【问题标题】:Understanding the requirement for the related field to provide a queryset了解相关字段提供查询集的要求
【发布时间】:2021-11-01 11:31:25
【问题描述】:

考虑:

class CouponSerializer(serializers.ModelSerializer):
    courses = serializers.PrimaryKeyRelatedField(
        many=True, read_only=True)
    class Meta:
        model = Coupon
        exclude = ['users']

如果我删除 read_only=True,我会收到错误:

AssertionError: Relational field must provide a `queryset` argument, override `get_queryset`, or set read_only=`True`.

documentation 声明:

验证字段输入时用于模型实例查找的查询集。关系必须明确设置查询集,或设置 read_only=True

这个要求背后的逻辑是什么?为什么StringRelatedField没有这个要求?

【问题讨论】:

    标签: django django-rest-framework django-serializer


    【解决方案1】:

    如果用户在请求中发送的数字有效,Django Rest Framework 必须知道要查找哪个查询集。

    假设用户向使用此序列化程序的视图发送 POST 请求。使用这样的有效负载:

    {
       "courses": [1, 2, 3]
    }
    

    因此,我们希望创建一个 Coupon 的实例,其中包含字段 courses 以填充 ID 为 1、2 和 3 的 Course 实例。

    DRF 将验证此请求以确保模型 Course 中存在主键 1、2 和 3。如果我们不添加queryset = Course.objects.all(),那么 DRF 不知道要查看哪个模型。

    您不必添加到StringRelatedField 的原因是因为这种字段默认为只读。

    编辑:

    如果您使用read_only=True,则 DRF 将在您在序列化程序中定义的相同字段名称上签入模型。在您的示例序列化器中,您已将字段命名为 courses,因此 DRF 将检查模型以查找名为 courses 的字段,并且它知道这是一个多对多字段,因此它将从中获取所有主键。

    您可能会问自己,为什么 DRF 在写入时不做同样的事情。那就是使用序列化程序中的字段名称来找出该字段在模型中引用的模型。但是,我对此没有很好的答案。

    【讨论】:

    • 糟糕,我没有注意到相关字段没有指定模型。现在我真的很困惑。即,考虑一个列表视图,我们只在其中读取,以便我们可以使用read_only=True。基于此序列化程序的列表视图如何知道从哪个模型获取课程(它们的 PK 或字符串表示形式)?
    • 我添加了对您问题的后续回答的编辑。
    【解决方案2】:

    如果您只是使用此序列化程序查看数据,则需要添加 ready_only,如果您想保存数据,则需要使用 queryset 参数,这让序列化程序在将数据保存到数据库之前验证数据

    例子

    class CouponSerializer(serializers.ModelSerializer):
        courses = serializers.PrimaryKeyRelatedField(
            many=True, queryset = Course.objects.all() )
        class Meta:
            model = Coupon
            exclude = ['users']
    

    如果您的课程列表中没有课程,则在验证数据时会引发错误

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-01
      • 1970-01-01
      • 2013-02-26
      相关资源
      最近更新 更多