首页 > 解决方案 > DRF + SerializerMethodField 与外键

问题描述

这个问题不同,我不仅想从我的数据中读取数据,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 视图中看不到艺术家的下拉菜单。

网址.py:

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

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

标签: djangodjango-rest-frameworkdjango-serializer

解决方案


您不能使用 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 的 save 方法,以便在嵌套序列化程序上进行写入工作。查看文档以获取更多信息

从 API 获取数据工作得很好,但是在调用 api/nevermind 时,我看到了所有专辑数据,但在 DRF 的可浏览 API 视图中看不到艺术家的下拉菜单。

我很确定您将看不到嵌套序列化程序甚至与 slug/pk 相关的字段的任何类型的下拉列表。这将要求 Django 向服务器/数据库发出额外的请求以获取数据。

不确定我是否可以提出这样的下拉菜单的好方法,我只考虑丑陋的方法。


推荐阅读