2015-03-31 44 views
7

我在urlpatterns的以下網址:user_pk,並uid:它有兩個字段Django的休息框架HyperlinkedIdentityField與多個查找ARGS

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

通知。該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」的超鏈接關係。您可能未能在API中包含相關模型,或在此字段上錯誤地配置了lookup_field屬性。

你如何使用HyperlinkedIdentityField(或任何Hyperlink*Field的)當URL擁有兩個或多個網址模板項目? (查找字段)?

回答

5

我不確定你是否已經解決了這個問題,但這可能對有此問題的其他人有用。除了重寫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) 

<model_field_1><model_field_2>是示範田,大概'id'和'uid'在你的情況下。

注意上面的問題在2年前報道過,我不知道他們是否在新版本的DRF中包含類似的內容(我還沒有找到),但上面的代碼適用於我。

+0

謝謝。我最終創建了自己的HyperlinkedIdentityField的子類,就像它只覆蓋了「to_representation()」方法:def to_repreationation(self,value): return reverse('user-device-detail', kwargs = {'user_pk': value.owner_id,'uid':value.uid}, request = self.context ['request']) – SuperDuperTango 2015-07-01 16:23:10

+0

將此標記爲已接受,即使我沒有嘗試過。這似乎是處理這個問題的一種合理的(可擴展的)方式。 – SuperDuperTango 2015-07-01 16:24:29

+0

該解決方案僅適用於從'obj'(直接間接)提取所有必需的密鑰。不幸的是,在多對多依賴的情況下,這是不可能的。 – prokher 2017-11-05 18:11:12