Как сериализовать одно json-поле из двух обратных отношений внешних ключей в Django REST Framework?

Я хотел бы получить в ответе API одно json-поле, в котором перечислены идентификаторы связанных объектов на основе двух обратных внешних ключевых отношений. Простой пример того, что я имею в виду, представлен ниже. Я бы предпочел, чтобы это было сделано на уровне сериализатора Django REST Framework, а не пришлось бы как-то менять модель, но у меня очень мало опыта работы с DRF, и я не могу понять, как это сделать.

Пример models.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 first_name last_name mother father
1 Jane Smith
2 John Smith
3 Clarence Smith 1 2
4 Thomas Smith 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": [],
    }
]

Это то, чего удалось достичь в моих экспериментах, и, как вы можете видеть по сравнению с примером выше, это не совсем то, что я хочу - я хотел бы иметь одно json-поле для детей, а не два:

serializers.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": [],
    }
]

Мне удалось найти приемлемое решение. Вот как я модифицировал сериализатор, переопределив функцию 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

Я оставлю вопрос на несколько дней, если у кого-то есть другое решение, после чего отмечу этот как правильный ответ.

class PersonSerializer(serializers.ModelSerializer):
    children = serializers.SerializerMethodField()

    class Meta:
        model = Person
        fields = ['id', 'first_name', 'last_name', 'mother', 'father', 'children']

    def get_children(self, obj):
        # Get all children of the demo
        children_as_father = obj.children_as_father.values_list('id', flat=True)
        children_as_mother = obj.children_as_mother.values_list('id', flat=True)
        return list(children_as_father) + list(children_as_mother)

https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

Вернуться на верх