了解相关字段提供查询集的要求

Understanding the requirement for the related field to provide a queryset

考虑:

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 状态:

The queryset used for model instance lookups when validating the field input. Relationships must either set a queryset explicitly, or set read_only=True

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

你需要添加ready_only如果你只是想使用这个序列化器来查看数据或者如果你想保存数据使用queryset参数,这让序列化器在将数据保存到数据库之前验证数据

例子

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

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

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

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

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

因此,我们要创建一个 Coupon 的实例,字段 courses 将填充 Course 的实例,id 为 1、2 和 3。

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

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

编辑:

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

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