【问题标题】:django-rest-framework HyperlinkedIdentityField with multiple lookup args具有多个查找参数的 django-rest-framework HyperlinkedIdentityField
【发布时间】:2015-06-04 09:48:52
【问题描述】:

我的 urlpatterns 中有以下 URL:

url(r'^user/(?P<user_pk>[0-9]+)/device/(?P<uid>[0-9a-fA-F\-]+)$', views.UserDeviceDetailView.as_view(), name='user-device-detail'),

注意它有两个字段:user_pkuid。 URL 类似于:https://example.com/user/410/device/c7bda191-f485-4531-a2a7-37e18c2a252c

在此模型的详细视图中,我尝试填充将包含返回模型的链接的 url 字段。

在序列化器中,我有:

url = serializers.HyperlinkedIdentityField(view_name="user-device-detail", lookup_field='uid', read_only=True)

但是,我认为它失败了,因为 URL 有两个字段:

django.core.exceptions.ImproperlyConfigured:无法使用视图名称“user-device-detail”解析超链接关系的 URL。您可能未能在 API 中包含相关模型,或者在此字段上错误地配置了 lookup_field 属性。

当 URL 有两个或多个 URL 模板项时,如何使用 HyperlinkedIdentityField(或任何 Hyperlink*Field)? (查找字段)?

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    我不确定您是否已经解决了这个问题,但这可能对遇到此问题的其他人有用。除了覆盖 HyperlinkedIdentityField 并自己创建自定义序列化程序字段之外,您无能为力。这个问题的一个例子是在下面的 github 链接中(连同一些源代码来解决它):

    https://github.com/tomchristie/django-rest-framework/issues/1024

    那里指定的代码是这样的:

    from rest_framework.relations import HyperlinkedIdentityField
    from rest_framework.reverse import reverse
    
    class ParameterisedHyperlinkedIdentityField(HyperlinkedIdentityField):
        """
        Represents the instance, or a property on the instance, using hyperlinking.
    
        lookup_fields is a tuple of tuples of the form:
            ('model_field', 'url_parameter')
        """
        lookup_fields = (('pk', 'pk'),)
    
        def __init__(self, *args, **kwargs):
            self.lookup_fields = kwargs.pop('lookup_fields', self.lookup_fields)
            super(ParameterisedHyperlinkedIdentityField, self).__init__(*args, **kwargs)
    
        def get_url(self, obj, view_name, request, format):
            """
            Given an object, return the URL that hyperlinks to the object.
    
            May raise a `NoReverseMatch` if the `view_name` and `lookup_field`
            attributes are not configured to correctly match the URL conf.
            """
            kwargs = {}
            for model_field, url_param in self.lookup_fields:
                attr = obj
                for field in model_field.split('.'):
                    attr = getattr(attr,field)
                kwargs[url_param] = attr
    
            return reverse(view_name, kwargs=kwargs, request=request, format=format)
    

    这应该有效,在您的情况下,您可以这样称呼它:

    url = ParameterisedHyperlinkedIdentityField(view_name="user-device-detail", lookup_fields=(('<model_field_1>', 'user_pk'), ('<model_field_2>', 'uid')), read_only=True)
    

    &lt;model_field_1&gt;&lt;model_field_2&gt; 是模型字段,在您的情况下可能是“id”和“uid”。

    请注意,上述问题是 2 年前报告的,我不知道他们是否在较新版本的 DRF 中包含类似的内容(我还没有找到),但上面的代码对我有用。

    【讨论】:

    • 谢谢。我最终创建了自己的 HyperlinkedIdentityField 子类,就像它只覆盖了“to_representation()”方法:def to_representation(self, value): return reverse('user-device-detail', kwargs={'user_pk': value. owner_id, 'uid': value.uid}, request=self.context['request'])
    • 将其标记为已接受,即使我还没有尝试过。这似乎是一种处理问题的明智(和可扩展)方式。
    • 该解决方案仅在您可以从obj 中提取所有必要的密钥(直接间接)时才有效。不幸的是,在多对多依赖的情况下,这是不可能的。
    猜你喜欢
    • 2018-02-23
    • 1970-01-01
    • 2018-12-12
    • 2015-10-12
    • 2018-07-28
    • 2019-05-15
    • 2015-05-11
    • 1970-01-01
    • 2019-02-22
    相关资源
    最近更新 更多