如何在 Django REST Framework 中从两个反向外键关系序列化单个 json 字段?

问题描述 投票:0回答:1

我需要什么

我想在 API 响应中获取一个 json 字段,其中列出了基于 two 反向外键关系的相关对象的标识符。下面给出了我的意思的简单例子。我非常希望在 Django REST Framework 序列化器级别上处理它,而不是必须以某种方式更改模型,但我几乎没有 DRF 经验,而且我一生都无法弄清楚如何实际执行它。

示例模型.py:

class Person(models.Model):

    id = models.AutoField(primary_key=True)

    first_name = models.CharField(max_length=50, blank=True, null=True)

    last_name = models.CharField(max_length=50, blank=True, null=True)

    father = models.ForeignKey(
        "self",
        related_name="children_as_father",
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
    )

    mother = models.ForeignKey(
        "self",
        related_name="children_as_mother",
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
    )

数据库数据示例:

id 名字 姓氏 妈妈 父亲
1 史密斯
2 约翰 史密斯
3 克拉伦斯 史密斯 1 2
4 托马斯 史密斯 1 2

我想获得的序列化 json 示例:

[
    {
        "pk": 1,
        "first_name": "Jane",
        "last_name": "Smith",
        "mother": null,
        "father": null,
        "children": [
            3,4
        ],
    },
    {
        "pk": 2,
        "first_name": "John",
        "last_name": "Smith",
        "mother": null,
        "father": null,
        "children": [
            3,4
        ],
    },
    {
        "pk": 3,
        "first_name": "Clarence",
        "last_name": "Smith",
        "mother": 1,
        "father": 2,
        "children": [],
    },
    {
        "pk": 4,
        "first_name": "Thomas",
        "last_name": "Smith",
        "mother": 1,
        "father": 2,
        "children": [],
    }
]

我尝试了什么

这就是我的实验所能得到的:

序列化器.py

from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField
from .models import Person

class FamilySerializer(ModelSerializer):

    children_as_mother = PrimaryKeyRelatedField(
        many=True, read_only=True, allow_null=True
    )

    children_as_father = PrimaryKeyRelatedField(
        many=True, read_only=True, allow_null=True
    )

    class Meta:
        model = Person
        fields = [
            "pk",
            "first_name",
            "last_name",
            "mother",
            "father",
            "children_as_mother",
            "children_as_father",
        ]

views.py

from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import ModelViewSet
from .models import Person
from .serializers import FamilySerializer

class FamilyViewSet(ModelViewSet):
    """
    API endpoint with family data
    """

    queryset = Person.objects.all()
    serializer_class = FamilySerializer
    permission_classes = [IsAuthenticated]

序列化json:

[
    {
        "pk": 1,
        "first_name": "Jane",
        "last_name": "Smith",
        "mother": null,
        "father": null,
        "children_as_mother": [
            3,4
        ],
        "children_as_father": [],
    },
    {
        "pk": 2,
        "first_name": "John",
        "last_name": "Smith",
        "mother": null,
        "father": null,
        "children_as_mother": [],
        "children_as_father": [
            3,4
        ],
    },
    {
        "pk": 3,
        "first_name": "Clarence",
        "last_name": "Smith",
        "mother": 1,
        "father": 2,
        "children_as_mother": [],
        "children_as_father": [],
    },
    {
        "pk": 4,
        "first_name": "Thomas",
        "last_name": "Smith",
        "mother": 1,
        "father": 2,
        "children_as_mother": [],
        "children_as_father": [],
    }
]

正如你所看到的,与第一个 json 示例相比,这并不完全是我想要的 - 我想要一个 json 字段来列出一个人的孩子标识符(“children”),而不是两个(“children_as_mother”,“children_as_father”) .

python json django rest django-rest-framework
1个回答
0
投票

我设法找到了一个可以接受的解决方案。以下是我如何通过重写 to_representation 函数来修改序列化器:

class FamilySerializer(ModelSerializer):

    children_as_mother = PrimaryKeyRelatedField(
        many=True, read_only=True, allow_null=True
    )

    children_as_father = PrimaryKeyRelatedField(
        many=True, read_only=True, allow_null=True
    )

    class Meta:
        model = Person
        fields = [
            "pk",
            "first_name",
            "last_name",
            "mother",
            "father",
            "children_as_mother",
            "children_as_father",
        ]

    def to_representation(self, instance):
        data = super(FamilySerializer, self).to_representation(instance)
        data["children"] = data["children_as_father"]+data["children_as_mother"]
        del data["children_as_mother"]
        del data["children_as_father"]        
        return data     

或者 to_representation 也可以像这样被覆盖,以获得与我的特定数据集相同的效果:

    def to_representation(self, instance):
        data = super(FamilySerializer, self).to_representation(instance)
        if data["children_as_father"]:
            data["children"] = data["children_as_father"]
        elif data["children_as_mother"]:
            data["children"] = data["children_as_mother"]
        else:
            data["children"]=[]
        del data["children_as_mother"]
        del data["children_as_father"]        
        return data

我会将问题留出几天,以防有人想到其他解决方案,之后我会将其标记为正确答案。

© www.soinside.com 2019 - 2024. All rights reserved.