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