DRF + SerializerMethodField с внешним ключом

Unlike this question I do not only want to read the data from my SerializerMethodField but also write in it:

Модель:

class Artist(models.Model):
    name = models.CharField("name", max_length = 34)
    note = models.CharField("additional info", max_length = 128, blank = True, null = True)

class Album(models.Model):
    name = models.CharField("name", max_length = 34)
    artist = models.ForeignKey(Artist, on_delete=models.CASCADE)

Сериализатор:

class AlbumSerializer(serializers.ModelSerializer):
    artist = serializers.SerializerMethodField("get_artist")

    def get_artist(self, obj):
        return [obj.artist.pk, obj.artist.name, obj.artist.note]

    class Meta:
        model = Album
        lookup_field = "name"
        fields = ["name", "artist",]
        read_only_fields = ["name",]

Видовой набор:

class AlbumViewSet(RetrieveModelMixin, ListModelMixin, GenericViewSet):
    serializer_class = AlbumSerializer
    lookup_field = "name"

    def get_queryset(self):
        return Album.objects.all()

    def retrieve(self, request, artist = None):
        query = Album.objects.filter(artist = artist)
        results = AlbumSerializer(data = query, many = True)
        results.is_valid()
        return Response(results.data)

    def put(self, request, name):
        print("------->", name, request)
        return Response("test")

Получение данных из API работает нормально, но при вызове api/nevermind я вижу все данные об альбомах, но не выпадающий список исполнителей в просматриваемом API представлении DRF.

Вы не можете использовать SerializerMethodField для записи. Прочитайте первое предложение в доке.

Здесь нужно использовать вложенный сериализатор. Что-то вроде этого:

class ArtistSerializer(serializers.ModelSerializer):
    class Meta:
        model = Artist
        fields = ["id", "name", "note"]
        

class AlbumSerializer(serializers.ModelSerializer):
    artist = ArtistSerializer()

    class Meta:
        model = Album
        lookup_field = "name"
        fields = ["name", "artist",]
        read_only_fields = ["name",]

Обратите внимание, что для работы записи на вложенном сериализаторе необходимо переписать метод сохранения AlbumSerializer. Проверьте документацию для получения дополнительной информации.

Получение данных из API работает нормально, но при вызове api/nevermind я вижу все данные об альбомах, но не выпадающий список исполнителей в просматриваемом API представлении DRF.

Я уверен, что вы не сможете увидеть никаких выпадающих полей для вложенных сериализаторов или даже для полей, связанных со slug/pk. Это потребует от Django сделать дополнительный запрос к серверу/БД, чтобы получить данные.

Не уверен, что могу предложить хорошие способы такого выпадающего списка, у меня на уме только уродливые.

Вернуться на верх