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
如何在不使用 (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