DRF + 带外键的 SerializerMethodField

DRF + SerializerMethodField with Foreign Key

this question不同,我不仅要从我的SerializerMethodField读取数据,还要写入其中:

型号:

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 时我看到所有专辑数据,但在 DRF 的可浏览 API 视图中看不到艺术家的下拉列表。

urls.py:

router = routers.DefaultRouter() 
router.register('albums', views.AlbumViewSet, basename = "albums")             

urlpatterns = [
    path("", views.ListView.as_view(), name = 'index'),
    url('^api/', include(router.urls)),
]

不能使用 SerializerMethodField 进行写入。阅读 the doc 中的第一句话。

您需要在此处使用嵌套序列化程序。类似的东西:

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 的 save 方法,以便在嵌套序列化程序上进行写入。 Check the doc for more info.

Getting data from the API works just fine, but when calling api/nevermind I see all the album data but not the dropdown for artist in the browsable API view of DRF.

我很确定您将看不到嵌套序列化程序甚至 slug/pk-related 字段的任何类型的下拉菜单。这将需要 Django 向 server/DB 发出额外请求以获取数据。

不确定我是否可以提出像这样的下拉菜单的好方法,我脑子里只有丑陋的方法。