django-rest-framework具有多个查询参数的HyperlinkedIdentityField [英] django-rest-framework HyperlinkedIdentityField with multiple lookup args

查看:1377
本文介绍了django-rest-framework具有多个查询参数的HyperlinkedIdentityField的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的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_pk ,和 uid 。该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有两个字段,因为URL有两个字段:


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


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

解决方案

我不知道你是否已经解决了这个问题,但是这对于任何有这个问题的人。除了超越HyperlinkedIdentityField并自己创建自定义序列化器字段之外,您还可以做很多工作。这个问题的一个例子是下面的github链接(以及一些源代码来解决):



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



在此指定的代码是:

  from rest_framework.relations import HyperlinkedIdentityField 
来自rest_framework.reverse import reverse

class ParameterisedHyperlinkedIdentityField(HyperlinkedIdentityField):

表示实例或实例上的一个属性,使用超链接

lookup_fields是以下形式的元组元组:
('model_field','url_parameter')

lookup_fields =(('pk','pk' )

def __init __(self,* args,** kwargs):
self.lookup_fields = kwargs.pop('lookup_fields',self.lookup_fields)
super(Parameter isedHyperlinkedIdentityField,self).__ init __(* args,** kwargs)

def get_url(self,obj,view_name,request,format):

给定一个对象,返回超链接到该对象的URL。

如果`view_name`和`lookup_field'
属性未配置为正确匹配URL conf,则可以引发NoReverseMatch。

kwargs = {}
for model_field,url_param in self.lookup_fields:
attr = obj
for model 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 

其中 ; model_field_1> < model_field_2> 是您的案例中的模型字段,可能是id和uid。



注意上述问题是在2年前报告的,我不知道他们是否在ne更好的DRF版本(我还没有找到),但上面的代码对我有用。


I have the following URL in my urlpatterns:

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

notice it has two fields: user_pk, and uid. The URL would look something like: https://example.com/user/410/device/c7bda191-f485-4531-a2a7-37e18c2a252c.

In the detail view for this model, I'm trying to populate a url field that will contain the link back to the model.

In the serializer, I have:

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

however, it's failing I think because the URL has two fields:

django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "user-device-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_field attribute on this field.

How do you use a HyperlinkedIdentityField (or any of the Hyperlink*Field) when the URL has two or more URL template items? (lookup fields)?

解决方案

I'm not sure if you've solved this problem yet, but this may be useful for anyone else who has this issue. There isn't much you can do apart from overriding HyperlinkedIdentityField and creating a custom serializer field yourself. An example of this issue is in the github link below (along with some source code to get around it):

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

The code that is specified there is this:

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)

This should work, in your case you would call it like this:

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

Where <model_field_1> and <model_field_2> are the model fields, probably 'id' and 'uid' in your case.

Note the above issue was reported 2 years ago, I have no idea if they've included something like that in newer versions of DRF (I haven't found any) but the above code works for me.

这篇关于django-rest-framework具有多个查询参数的HyperlinkedIdentityField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆