DRF Serializer 如何序列化我的数据并显示

DRF Serializer How do I serialize my data and display

我有以下 Serializer 我在 Json 序列化时遇到问题。我有一个名为 daniel james 的用户,他有多个学科,比如数学科学,我提供嵌套序列化程序来填充所有学科,但基于学科用户名也在下面重复,更具体 qsn

这是我的模型。

class Result(BaseModel):
    semester_choices = (
        ('first', 'First'),
        ('second', 'Second'),
        ('third', 'Third'),
        ('fourth', 'Fourth'),
        ('fifth', 'Fifth'),
        ('sixth', 'Sixth'),
        ('seventh', 'Seventh'),
        ('eight', 'Eight'),
        ('all', 'All'),
    )
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    registration_number = models.CharField(null=True, blank=True, max_length=20)
    semester = models.CharField(max_length=50, choices=semester_choices, null=True, blank=True)
    gpa = models.CharField(max_length=20)
    subject = models.CharField(max_length=50)

serializers.py

 class ResultSerializer(serializers.ModelSerializer):
    class Meta:
        model = Result
        fields = '__all__'

class ListResultSerializer(ResultSerializer):
    user = serializers.CharField()
    semester = serializers.CharField()
    subject = serializers.SerializerMethodField()

class Meta(ResultSerializer.Meta):
    fields = (
        'user',
        'semester',
        'subject',
    )

def get_subject(self, instance):
    return SubjectSerializer(instance).data

这是我的SubjectSerializer

class SubjectSerializer(ResultSerializer):
    class Meta(ResultSerializer.Meta):
        fields = (
            'gpa',
            'subject'
        )

在我的 views.py 中,我已经这样做了。

class ListResultView(rest_generics.ListAPIView, UserMixin):
    serializer_class = serializers.ListResultSerializer
    permission_classes = (AllowAny,)

    def get_object(self):
        return self.get_user()

    def get_queryset(self):
        return usecases.ListResultUseCase(
            user=self.get_user()
        ).execute()

我用usecases.py过滤数据这里是进一步的代码

class ListResultUseCase:
    def __init__(self, user: User):
        self._user = user

    def execute(self):
        self._factory()
        return self._result

    def _factory(self):
        self._result = Result.objects.filter(user=self._user)

现在这是我从上面的代码中得到的 Json。

[
    {
        "user": "daniel james",
        "semester": "first",
        "subject": {
            "gpa": "a+",
            "subject": "maths"
        }
    },
    {
        "user": "daniel james",
        "semester": "first",
        "subject": {
            "gpa": "A",
            "subject": "data structures"
        }
    }
]

我希望我的json采用这种格式

 [
  {
    "user": "daniel james",
    "semester": "first",
    "subject": [
      {
        "gpa": "a+",
        "subject": "maths"
      },
      {
        "gpa": "A",
        "subject": "data structures"
      }
    ]
  }
]

序列化器有什么帮助吗?

您可以为您的用户创建一个序列化程序,并添加一个方法字段来检索用户的所有主题。

def get_subjects(self,instace):
    subjects = Subject.objects.filter(user=instance)
    return SubjectSerializer(subjects, many=True)

您可以创建一个单独的序列化程序以与嵌套序列化程序一起使用。

class SubjectNestedSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subject
        exclude = ['user']

P.S

试着像这样改变你的模型

class Semester(BaseModel):
    semester_choices = (
        ('first', 'First'),
        ('second', 'Second'),
        ('third', 'Third'),
        ('fourth', 'Fourth'),
        ('fifth', 'Fifth'),
        ('sixth', 'Sixth'),
        ('seventh', 'Seventh'),
        ('eight', 'Eight'),
        ('all', 'All'),
    )
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='semesters')
    registration_number = models.CharField(null=True, blank=True, max_length=20)
    semester = models.CharField(max_length=50, choices=semester_choices, null=True, blank=True)

class Subject(BaseModel):
    semester = models.ForeignKey(Semester, on_delete=models.CASCADE, related_name='semester_subjects')
    gpa = models.CharField(max_length=20)
    subject = models.CharField(max_length=50)

您想要的是现有数据的聚合,以便为前端提供更有意义的结果。我宁愿生成自己的响应也不愿为此使用序列化程序。

这是一个简单的例子。

假设您想要多个用户的结果。 (如果你想要一个用户就更容易了)

def get_item_with_attribute_from_list(items, attribute, attribute_value):
"""
This is just a utility function that I use occasionally
"""
    if items is None or len(items) == 0:
        return None

    if isinstance(items[0], dict):
        for item in items:
            if item.get(attribute) == attribute_value:
                return item
    else:
        for item in items:
            if getattr(item, attribute, None) == attribute_value:
                return item

results = Result.objects.all().select_related('user')

response = []
for result in results:
    user_dict = get_item_with_attribute_from_list(response, "user", result.user.name)
    subject = {"gpa": "A", "subject": "data structures"}
    if user_dict:
        semester_list = user_dict['semesters']
        semester = get_item_with_attribute_from_list(semester_list, 'semester_name', result.semester)
        if semester:
            semester['subjects'].append(subject)
        else:
            semester_list.append({'subjects': [subject]})
    else:
        response.append({'user': result.user.name, 'semesters': [{'semester_name': result.semester, 'subjects': [subject]}]})

结果 JSON 将是这样的。

[
  {
    "user": "daniel james",
    "semesters": [
        {
            "semester_name": "first",
            "subjects": [
                
                {
                    "gpa": "a+",
                    "subject": "maths"
                },
                {
                    "gpa": "A",
                    "subject": "data structures"
                }
            ]
        },
        {
            "semester_name": "second",
            "subjects": [
                
                {
                    "gpa": "b+",
                    "subject": "geometry"
                },
                {
                    "gpa": "C",
                    "subject": "chemistry"
                }
            ]
        }
    ]
  },
  ... # Other user's data
]

这样,您将拥有更多结构化数据,您将能够轻松计算每个学期的 SPA。