Сериализация 3 взаимосвязанных реляционных моделей Django

Я пытаюсь написать набор сериализаторов для своих моделей. Я хочу, чтобы сериализатор для колоды выплюнул карты, соответствующие ID колоды в модели CardToDeck, а затем получил карту, соответствующую card_id в модели Card

models.py

from django.db import models

# Create your models here.

class CardToDeck(models.Model):
    deck_id = models.ForeignKey("Deck", related_name="card_to_deck", on_delete=models.CASCADE)
    card_id = models.ForeignKey("Card", related_name="card_to_deck", on_delete=models.CASCADE)

class Card(models.Model):
    id = models.AutoField(primary_key=True)
    multiverseid = models.IntegerField(unique=True) # Used to fetch the card from the API
    name = models.CharField(max_length=145)


class Deck(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=145)

serializers.py:

from .models import *
from rest_framework import serializers


class CardSerializer(serializers.ModelSerializer):
    class Meta:
        model = Card
        fields = ('id', 'name')

class CardToDeckSerializer(serializers.ModelSerializer):
    class Meta:
        model = CardToDeck
        fields = ('deck_id', 'card_id')

# Serializer for Deck that grabs the nested model references
class DeckSerializer(serializers.ModelSerializer):
    cards = serializers.PrimaryKeyRelatedField(queryset=CardToDeck.objects.all(), many=True)
    class Meta:
        model = Deck
        depth = 2
        fields = ('name', 'cards')

Что бы я хотел, чтобы JSON выглядел следующим образом:

{
    "name": "deckNameGoHere",
    "cards": [{"id":1, "name":"cardNameGoHere", "quantity":3},{"id":2, "name":"cardNameGoHere", "quantity":2}]
}

Я только что потратил последние 4 часа, пытаясь разобраться в этом, и чувствую себя довольно тупым, любая помощь будет оценена по достоинству. Я заглянул в доки, но не смог найти нужных мне ресурсов.

Предполагая, что quantity находится в CardToDeck, вы можете сделать что-то вроде этого:

class CardToDeckSerializer(serializers.ModelSerializer):
    id = serializers.CharField(source='card_id.id')
    name = serializers.CharField(source='card_id.name')

    class Meta:
        model = CardToDeck
        fields = ('id', 'name', 'quantity')


class DeckSerializer(serializers.ModelSerializer):
    cards = CardToDeckSerializer(source='card_to_deck' many=True)
    class Meta:
        model = Deck
        fields = ('name', 'cards')

Согласно документам DRF:

PrimaryKeyRelatedField может использоваться для представления цели отношения отношения используя его первичный ключ.

Вы можете использовать CardToDeckSerializer как поле DeckSerializer без PrimeryKeyRelated и как объект сериализатора, если вы хотите прочитать данные и вернуть их обратно:

from .models import *
from rest_framework import serializers


class CardSerializer(serializers.ModelSerializer):
    class Meta:
        model = Card
        fields = ('id', 'name')

class CardToDeckSerializer(serializers.ModelSerializer):
    class Meta:
        model = CardToDeck
        fields = ('deck_id', 'card_id')

# Serializer for Deck that grabs the nested model references
class DeckSerializer(serializers.ModelSerializer):
    # if not intended to use bulk action it's better to keep the "many" fields as read only
    cards = CardToDeckSerializer(many=True, read_only=True)
    class Meta:
        model = Deck
        depth = 2
        fields = ('name', 'cards')

Если вы хотите показать список связанных ссылок, вы можете использовать следующее:

HyperlinkedRelatedField

Я настоятельно рекомендую прочитать документ DRF о вложенных сериализаторах

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