django - DRF多对一反向查询

标签 django django-rest-framework

我有一个API端点,返回宠物及其主人。

  • 每个所有者都有一个名字和一个或多个宠物
  • 每只宠物都有一个名字和一个所有者

  • Django模型示例:
    class Owner(models.Model):
        name = models.CharField(max_length=200)
    
    class Pet(models.Model):
        owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
        name = models.CharField(max_length=200)
    

    我已经将我的API配置为返回JSON数据,如下所示:
    [
        {
            "id": 2,
            "name": "Scotch",
            "owner": {
                "id": 2,
                "name": "Ben"
            }
        },
        {
            "id": 3,
            "name": "Fluffy",
            "owner": {
                "id": 1,
                "name": "Fred"
            }
        },
        {
            "id": 1,
            "name": "Spot",
            "owner": {
                "id": 1,
                "name": "Fred"
            }
        }
    ]
    

    DRF序列化器示例:
    class OwnerSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = Owner
            fields = ("id", "name")
    
    class PetSerializer(serializers.HyperlinkedModelSerializer):
        owner = OwnerSerializer()
        class Meta:
            model = Pet
            fields = ("id", "name", "owner")
    

    尽管这一切都很好,但我实际上想要一个可以返回所有者及其宠物列表的终结点。因此,我将获得以下数据:
    [
        {
            "id": 1,
            "name": "Fred",
            "pets": [
                { "id": 1, "name": "Spot" },
                { "id": 3, "name": "Fluffy" }
            ]
        },
        {
            "id": 2,
            "name": "Ben",
            "pets": [
                { "id": 2, "name": "Scotch" }
            ]
        }
    ]
    

    如何获得该输出?

    最佳答案

    您需要像这样将pet_set字段添加到OwnerSerializer:

    class PetSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = Pet
            fields = ("id", "name")
    
    class OwnerSerializer(serializers.HyperlinkedModelSerializer):
        pet_set = PetSerializer(many=True, read_only=True)
        class Meta:
            model = Owner
            fields = ("id", "name", "pet_set")
    

    这将起作用,因为在您的情况下,多对一关系默认反向查找名称是<model>_setpet_set。您可以使用related_name进行更改:
    class Pet(models.Model):
        owner = models.ForeignKey(Owner, related_name='pets', on_delete=models.CASCADE)
    

    在这种情况下,您可以在序列化程序中使用pets名称:
    class OwnerSerializer(serializers.HyperlinkedModelSerializer):
        pets = PetSerializer(many=True, read_only=True)
    

    现在在OwnerListView中,您可以使用此新的序列化器:
    class OwnerListView(ListAPIView):
        queryset = Owner.objects.all()
        serializer_class = OwnerSerializer
    

    关于django - DRF多对一反向查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48413143/

    相关文章:

    python - 覆盖 django-rest-auth 中的 UserDetailsS​​erializer

    python - 迭代数据库对象并将它们渲染到模板

    python - NoReverseMatch at/sitemap.xml Django 与来自 app.urls 的 StaticViewSitemap

    django - Wagtail Streamblock 模板渲染

    python - 具有多个嵌套对象的 Django Rest Framework 可写嵌套序列化程序

    python - 序列化器: Customising nested relationships

    python - Django 按年分页

    python - 使用 south 重构具有继承的 Django 模型

    java - 如何访问DRF服务器端的请求主体模型字段?

    django - 将根元素添加到 json 响应 (django-rest-framework)