Сохранить pk из подробного маршрута в сериализаторе [django REST API]
Я задавал этот вопрос раньше, но с меньшей ясностью
Как сохранить id
внутри RelatedFiled
из ForeignKey
?
Я тестирую приложение на Django, у меня есть две модели:
class Album(models.Model):
album_id = models.IntegerField()
artist = models.CharField(max_length=260)
album_name = models.CharField(max_length=260)
class Song(models.Model):
album = models.ForeignKey(Album, related_name='song', blank=True, null=True) #foreign key
song_name = models.CharField(max_length=260)
с Song
содержащий внешний ключ к Album
Мой вопрос заключается в том, как автоматически хранить pk
или же id
из album
внутри этого внешнего ключа?
Я создал detail_route
и когда я печатаю album_id
Я получаю правильный адрес, к которому я пытаюсь получить доступ в URL.
например: album/101/song
распечатает album_id
как 101. Но в моем сериализаторе он не сохраняет RelatedField как 101. Как мне это исправить?
@detail_route(methods=['post', 'get'], serializer_class=SongSerialiser)
def get_so(self, request, album_id=None):
serializer = self.get_serializer(data=request.data, context={"album_id": album_id })
if serializer.is_valid():
print album_id # this works !
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response({"detail": serializer.errors,
"status_code": status.HTTP_400_BAD_REQUEST})
Сериализатор:
class SongSerialiser(serializers.Serializer):
album = serializers.RelatedField(many=True)
song_name = serializers.CharField(required=False)
def create(self, validated_data):
album_id = self.context.get("album_id")
print album_id # I expect this to print 101 or the related id
instance = Song.objects.create(**validated_data)
instance.save()
return instance
2 ответа
Оказывается, внутри сериализатора мне нужно использовать:
self.context.get("request").parser_context["kwargs"]["album_id"]
Вместо прохождения album_id
в context
, вы можете пройти album_id
с помощью serializer.save()
и DRF автоматически создаст Song
объект с album_id
поле.
Вам нужно внести некоторые изменения в свой код.
По вашему мнению, вам не нужно проходить context
к сериализатору. Вы должны вместо этого пройти album_id
в serializer.save()
,
@detail_route(methods=['post', 'get'], serializer_class=SongSerialiser)
def get_so(self, request, album_id=None):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
serializer.save(album_id=album_id) # pass album_id here
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response({"detail": serializer.errors,
"status_code": status.HTTP_400_BAD_REQUEST})
Во-вторых, вы можете конвертировать SongSerialiser
в ModelSerializer
имея только поле song_name
без добавления create()
метод.
class SongSerialiser(serializers.ModelSerializer): # use modelserializer
class Meta:
model = Song
fields = ['song_name'] # only define song_name field
когда serializer.save()
называется, DRF создаст Song
объект с song_name
от request.data
а также album_id
из лишнего kwarg мы прошли в .save()
,