Django Rest Framework 嵌套序列化器字段 many=false

Django RestFramework nested serializer field 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工作正常:

{
    "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) 但我收到以下错误:

create() argument after ** must be a mapping, not str

型号:

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 on this other post: Django Rest Framework: AttributeError when Serializer many=False, but not when many=True

的评论找到了解决方案

如果您在模型上使用 ForeignKey 关系,您似乎需要将 (many=True) 添加到您的序列化程序,因为 DRF 创建一个基于 OneToMany 关系的列表。如果您只需要 POST 一个对象,则需要在模型中使用 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