[英]Django rest framework, should be able to override get_queryset and not define queryset attribute?
[英]django-rest-framework override get_queryset and pass additional data to serializer along queryset
这是我面临的问题的一个玩具示例。 出于某种原因,我无法将预期的数据传递给我的序列化程序,这引发了以下错误。
/my-end-point/ 处的 AttributeError
尝试获取序列化ParentSerializer
main_data
上的字段main_data
的值时出现ParentSerializer
。 序列化器字段可能命名不正确,并且与str
实例上的任何属性或键都不匹配。 原始异常文本是:“str”对象没有属性“main_data”。
class MainModelSerializer(serializers.ModelSerializer):
class Meta:
model = MainModel
class ParentSerializer(serializers.Serializer):
main_data = MainModelSerializer(many=True)
extra_data = serializers.FloatField()
class View(ListCreateAPIView):
serializer = ParentSerializer
def get_queryset(self):
# extra_data would have some calculated value which would be a float
extra_data = some_calculated_value()
queryset = MainModel.objects.filter(some filters)
return {
'main_data': queryset,
'extra_data': extra_data
}
# expected data that is passed to the ParentSerializer
# {
# 'main_data': queryset,
# 'extra_data': extra_data
# }
看起来你有两个问题:
get_queryset
方法的返回值不正确至于第一个,您根本不应该覆盖该方法或返回查询集。 根据计算额外数据的方式,可以进行权衡,例如在查询集上注释值并在序列化器字段列表中指定它。
对于第二个 - 如果注释不是一个选项并且您想计算一个值,可能的解决方案是将额外的数据添加到序列化器上下文并将其用作序列化器方法 field 的返回值。 在这种情况下,额外的数据将与模型记录数据放在同一级别(每个模型记录的额外字段):
{
'model_field_1': 'value',
...
'extra_field': 'value',
}
或者,您可以通过覆盖list
(并create
,如果需要)继续使用嵌套关系的方法 - 只需将额外数据添加到序列化程序验证的数据中,结果将如下所示:
{
'extra_data': 'value',
'main_data': [
{'id': 1, 'field1': 'value', ...}
...
]
}
class View(ListCreateAPIView):
serializer = ParentSerializer
def list(self, request, *args, **kwargs):
# extra_data would have some calculated value which would be a float
extra_data = some_calculated_value()
qs = self.get_queryset()
data = self.get_serializer(qs, many=True).data
data['extra_data'] = extra_data
return Response({'data': data}, status=status.HTTP_200_OK, content_type = 'application/json' )
我认为您想要实现的是将一些额外的数据传递给ParentSerializer
,以便您的视图上的list action
返回。但是您的代码中存在多个问题:
get_queryset
仅用于返回models.QuerySet
的实例,用于确定允许视图对哪些模型对象执行任何类型的操作。get_queryset
不用于将数据传递给序列化程序,这是在Serializer
程序初始化期间完成的。ModelSerializer
但您没有在Meta
类上指定fields
属性,因为drf version 3.3
不再允许,您必须定义fields
属性或exclude
属性。至于实际上如何将额外数据传递给序列化程序,您可以通过多种方式做到这一点:
class ParentSerializer(serializers.Serializer):
main_data = MainDataSerializer(many=True)
extra_data = serializers.SerializerMethodField(method_name="some_calculated_value")
def some_calculated_value(self, obj):
# calculate value here
return value
请注意,此字段是只读字段。
class ParentSerializer(serializers.Serializer):
main_data = MainDataSerializer(many=True)
def validate(self, attrs):
attrs["extra_data"] = some_calculated_value()
return attrs
list
函数并更改传递给序列化程序的数据来实现。 我个人更喜欢选项 1,因为SerializerMethodField
符合目的,而validate
函数应该仅用于验证以遵守单一职责概念。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.