【问题标题】:Django Rest Framework – Custom Hyperlink field in serializerDjango Rest Framework – 序列化程序中的自定义超链接字段
【发布时间】:2016-02-22 06:08:45
【问题描述】:

如何在序列化程序中添加自定义超链接字段?我想在我的序列化程序中有一个超链接字段,其中包含查询参数。据我所知,由于无法从HyperlinkedRelatedFieldHyperlinkedIdentityField 传递查询参数,因此我尝试使用SerializerMethodField。但是,这只会序列化为字符串,当我通过浏览器访问 API 时,它不是可点击的 URL。我的代码如下所示:

class MySerializer(serializers.HyperlinkedModelSerializer):
    custom_field = serializers.SerializerMethodField()

    class Meta:
        model = MyModel
        fields = ('url', 'custom_field')

    def get_custom_field(self, obj):
        result = '{}?{}'.format(
            reverse('my-view'),
            urllib.urlencode({'param': 'foo'})
        )
        return result

另外,我无法理解 HyperlinkedRelatedFieldHyperlinkedIdentityField 之间的区别,因此我们将不胜感激。

【问题讨论】:

  • 您必须阅读.. django-rest-framework.org/tutorial/… 它可以帮助您。 :-)
  • 我看过了,里面没有讲自定义超链接
  • @b_pcakes - 如果我的回答符合您的期望,介意接受吗?谢谢!

标签: django serialization django-rest-framework


【解决方案1】:

这应该可以解决问题:

from rest_framework.reverse import reverse

class MySerializer(serializers.HyperlinkedModelSerializer):
    custom_field = serializers.SerializerMethodField()

    class Meta:
        model = MyModel
        fields = ('url', 'custom_field')

    def get_custom_field(self, obj):
        result = '{}?{}'.format(
            reverse('my-view', args=[obj.id], request=self.context['request']),
            'param=foo'
        )
        return result

rest_framework 中的 reverse 函数接受一个视图名称(您想链接到的任何视图)、一个 args 列表(在本例中为对象 id)或 kwargs,以及一个请求对象(可以在内部访问self.context['request'] 的序列化程序)。它还可以采用格式参数和您想要传递给它的任何额外参数(作为字典)。

然后,反向函数会为您构建一个漂亮的、格式完整的 URL。您可以通过简单地将尽可能多的?{}&{}&{} 添加到结果变量中来添加查询参数,然后使用您想要的任何其他参数填写format 函数内的“param = foo”下方的一系列查询参数。

HyperlinkedIdentityField 用于正在序列化的对象本身。因此,HyperlinkedIdentifyField 被用来代替 MyModel 上的主键字段,因为您使用的是 HyperlinkedModelSerializer,它为正在序列化的对象本身的 pk 创建了一个 HyperlinkedIdentityField

HyperlinkedRelatedField 用于定义与相关对象的超链接关系。因此,如果有一个 MySecondModelMyModel 具有外键关系,并且您希望在您的 MyModel 序列化程序上具有指向所有相关 MySecondModel 对象的超链接,您将使用 HyperlinkedRelatedField 像这样(记住将新字段添加到 Meta 中的 fields 属性):

class MySerializer(serializers.HyperlinkedModelSerializer):
    custom_field = serializers.SerializerMethodField()
    mysecondmodels = serializers.HyperlinkedRelatedField(
        many=True
        read_only=True,
        view_name='mysecondmodel-detail'
    )

    class Meta:
        model = MyModel
        fields = ('url', 'custom_field', 'mysecondmodels')

    def get_custom_field(self, obj):
        result = '{}?{}'.format(
            reverse('my-view', args=[obj.id], request=self.context['request']),
            'param=foo'
        )
        return result

如果它是 OneToOneField 而不是 MySecondModel 上的 ForeignKey 字段,那么您将设置 many=False。

希望这会有所帮助!

【讨论】:

  • 我收到密钥“请求”的 KeyError。如你所说,如何拥有 self.context['request']?
  • @mirek 在视图中使用序列化程序时,您需要添加上下文:MySerializer(MyModel, context={'request': request})。如果您使用的是ModelViewSet self.request 或覆盖get_serializer_context
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-28
  • 1970-01-01
  • 2023-02-08
  • 1970-01-01
  • 2017-06-07
  • 2013-08-03
  • 1970-01-01
相关资源
最近更新 更多