Django RestFramework вложенное поле сериализатора many=false

как я могу создать вложенное поле сериализатора без использования (many=True)? Следующий код работает нормально:

from music.models import Track, Album
from rest_framework import serializers

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ['order', 'title', 'duration']

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True)

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

    def create(self, validated_data):
        tracks_data = validated_data.pop('tracks')
        album = Album.objects.create(**validated_data)
        for track_data in tracks_data:
            Track.objects.create(album=album, **track_data)
        return album

Однако я не могу изменить полезную нагрузку json, поскольку она приходит из приложения третьей части, и поле "tracks" в примере должно быть "track" и POST только один объект.

Этот json работает нормально:

{
    "album_name": "Black Album",
    "artist": "Metallica",
    "tracks": [
        {
            "order": 1,
            "title": "Enter Sandman",
            "duration": 245
        },
        {
            "order": 2,
            "title": "Sad but True",
            "duration": 264
        },
        {
            "order": 3,
            "title": "The Unforgiven",
            "duration": 159
        }
    ]
}

но мне нужно заставить работать этот json, один объект, без квадратных скобок []:

    {
        "album_name": "Black Album",
        "artist": "Metallica",
        "tracks": 
            {
                "order": 1,
                "title": "Enter Sandman",
                "duration": 245
            }
        }

Я пытался удалить (many=True), но получаю либо следующие ошибки:

Got AttributeError when attempting to get a value for field `order` on serializer `TrackSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `RelatedManager` instance.
Original exception text was: 'RelatedManager' object has no attribute 'order'.

модели:

from django.db import models

class Album(models.Model):
    album_name = models.CharField(max_length=100)
    artist = models.CharField(max_length=100)

class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
    order = models.IntegerField()
    title = models.CharField(max_length=100)
    duration = models.IntegerField()

    class Meta:
        unique_together = ['album', 'order']
        ordering = ['order']

    def __str__(self):
        return '%d: %s' % (self.order, self.title)

views.py

from rest_framework import viewsets
from music.serializers import AlbumSerializer
from music.models import Album


class STMusic(viewsets.ModelViewSet):

    serializer_class = AlbumSerializer
    queryset = Album.objects.all()

Как это исправить?

def create(self, validated_data):
    track_data = validated_data.pop('tracks')
    album = Album.objects.create(**validated_data)
    Track.objects.create(album=album, **track_data)
    return album

Ок Я нашел решение, основываясь на комментариях tsantor в этом другом посте: Django Rest Framework: AttributeError когда Serializer many=False, но не когда many=True

Похоже, если вы используете отношение ForeignKey в вашей модели, вам нужно добавить (many=True) в ваш сериализатор, поскольку DRF создает список на основе отношения OneToMany. Если вам нужно отправить только один объект, вам нужно использовать отношение OneToOne в вашей модели (что имеет смысл), чтобы DRF ожидал только один объект, а не список.

Итак, рабочий код таков:

models.py

from django.db import models

class Album(models.Model):
    album_name = models.CharField(max_length=100)
    artist = models.CharField(max_length=100)

class Track(models.Model):
    album = models.OneToOneField(Album, related_name='track', on_delete=models.CASCADE)
    order = models.IntegerField()
    title = models.CharField(max_length=100)
    duration = models.IntegerField()

    class Meta:
        unique_together = ['album', 'order']
        ordering = ['order']

    def __str__(self):
        return '%d: %s' % (self.order, self.title)

serializer.py

class AlbumSerializer(serializers.ModelSerializer):
    track = TrackSerializer()

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'track']

    def create(self, validated_data):
        track_data = validated_data.pop('tracks')
        album = Album.objects.create(**validated_data)
        Track.objects.create(album=album, **track_data)
        return album
Вернуться на верх