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。
我有以下 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。