具有多个查找参数的 django-rest-framework HyperlinkedIdentityField
django-rest-framework HyperlinkedIdentityField with multiple lookup args
我的 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
字段,它将包含 link 回到模型。
在序列化器中,我有:
url = serializers.HyperlinkedIdentityField(view_name="user-device-detail", lookup_field='uid', read_only=True)
但是,我认为它失败了,因为 URL 有两个字段:
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.
当 URL 有两个或更多 URL 模板项时,如何使用 HyperlinkedIdentityField
(或任何 Hyperlink*Field
)? (查找字段)?
我不确定您是否已经解决了这个问题,但这可能对其他遇到此问题的人有用。除了覆盖 HyperlinkedIdentityField 和自己创建自定义序列化程序字段之外,您无能为力。这个问题的一个例子在下面的 github link 中(连同一些源代码来解决它):
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)
其中 <model_field_1>
和 <model_field_2>
是模型字段,在您的情况下可能是 'id' 和 'uid'。
请注意,上述问题是 2 年前报告的,我不知道他们是否在较新版本的 DRF 中包含类似的东西(我还没有找到),但上面的代码对我有用。
我的 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
字段,它将包含 link 回到模型。
在序列化器中,我有:
url = serializers.HyperlinkedIdentityField(view_name="user-device-detail", lookup_field='uid', read_only=True)
但是,我认为它失败了,因为 URL 有两个字段:
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.
当 URL 有两个或更多 URL 模板项时,如何使用 HyperlinkedIdentityField
(或任何 Hyperlink*Field
)? (查找字段)?
我不确定您是否已经解决了这个问题,但这可能对其他遇到此问题的人有用。除了覆盖 HyperlinkedIdentityField 和自己创建自定义序列化程序字段之外,您无能为力。这个问题的一个例子在下面的 github link 中(连同一些源代码来解决它):
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)
其中 <model_field_1>
和 <model_field_2>
是模型字段,在您的情况下可能是 'id' 和 'uid'。
请注意,上述问题是 2 年前报告的,我不知道他们是否在较新版本的 DRF 中包含类似的东西(我还没有找到),但上面的代码对我有用。