【问题标题】:DRF + SerializerMethodField with Foreign KeyDRF + SerializerMethodField 与外键
【发布时间】:2021-08-30 10:28:50
【问题描述】:

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)),
]

【问题讨论】:

  • 分享urls.py
  • 我把它加到第一个帖子里了。
  • 对不起,我没有正确理解。您希望能够在artist 字段中读写吗?如果是这样,您应该将这两个作为两个序列化程序分开
  • 我想要一个 DRF HTML API 中所有艺术家的下拉列表,我可以在其中选择一个进行更新。现在GET 正确返回艺术家,但如果我想更新它,我需要一个所有艺术家的列表,例如从九寸钉移动专辑 -> Nirvana。

标签: django django-rest-framework django-serializer


【解决方案1】:

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

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

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

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

【讨论】:

  • 啊好吧...我确信它可以轻松完成。例如,如果我只使用您的示例,我会得到两个字符串输入“name”和“note”,而不是下拉列表 - 额外的 DB 查询是我在 tbh 之前没有考虑的参数。我有点期待 DRF 会在“幕后”执行此操作。
猜你喜欢
  • 2019-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
  • 2019-12-22
相关资源
最近更新 更多