2013-11-04 68 views
7

我有兩個模型:用戶票務有一個用戶用戶有許多門票Django Rest Framework,超鏈接嵌套關係

我已經做到了這一點,當我去到URL /用戶/ 1 /票,我得到用戶的票證列表。

我想使用超鏈接關係,這裏是我在我的用戶模型表現看:

"tickets": [ 
    "http://127.0.0.1:8000/tickets/5/", 
    "http://127.0.0.1:8000/tickets/6/" 
] 

但我希望它像

"tickets": "http://127.0.0.1:8000/users/1/tickets" 

有沒有辦法做到與DRF?

的網址:

url(r'^users/(?P<user_pk>\d+)/tickets/$', 
    views.TicketsByUserList.as_view(), 
    name='myuser-tickets'), 

的視圖:

class TicketsByUserList(generics.ListAPIView): 
    model = Ticket 
    serializer_class = TicketSerializer 

    def get_queryset(self): 
     user_pk = self.kwargs.get('user_pk', None) 
     if user_pk is not None: 
      return Ticket.objects.filter(user=user_pk) 
     return [] 

用戶串行器(我試圖與門票字段定義播放,改變的類型,VIEW_NAME,但沒有效果):

class UserSerializer(serializers.HyperlinkedModelSerializer): 
    tickets = serializers.HyperlinkedRelatedField(many=True, view_name='ticket-detail') 

    class Meta: 
     model = MyUser 
     fields = ('id', 'nickname', 'email', 'tickets') 

Ticket serializer:

class TicketSerializer(serializers.HyperlinkedModelSerializer): 
    user = serializers.HyperlinkedRelatedField(view_name='myuser-detail') 
    liked = serializers.Field(source='liked') 

    class Meta: 
     model = Ticket 
     fields = ('id', 'user', 'word', 'transcription', 'translation', 'liked', 'created', 'updated') 

回答

15

您可以使用SerializerMethodField進行自定義。事情是這樣的:

class UserSerializer(serializers.HyperlinkedModelSerializer): 
    tickets = serializers.SerializerMethodField('get_tickets') 

    def get_tickets(self, obj): 
     return "http://127.0.0.1:8000/users/%d/tickets" % obj.id 

    class Meta: 
     model = MyUser 
     fields = ('id', 'nickname', 'email', 'tickets') 

我硬連接的URL在那裏爲簡潔,但你可以做一個反向查找一樣好。這基本上只是告訴它調用get_tickets方法,而不是超類中的默認行爲。

+0

在試圖實現您的解決方案,我意識到,我必須請求對象某種方式傳遞到串行,通過它來反轉功能,獲得絕對的網址。我通過將查詢「dispatch」方法中的請求對象傳遞到序列化程序中的字段來解決此問題。但是我覺得每次我希望在序列化程序中都有請求對象時,重寫一個調度方法並不是一個好主意。在串行器中獲取請求的最佳方式是什麼? – optimistiks

+1

有一種方法可以[爲序列化程序提供額外的上下文](http://django-rest-framework.org/api-guide/serializers.html#including-extra-context)。文檔以示例用例展示您的確切情況。 –

+2

在'get_tickets'方法中,您可以通過'request = self.context.get('request')'獲得請求對象,然後照常調用'reverse'。 – Cartucho

0

爲了記錄在案,這裏是根據喬·霍洛威的答案的完整解決方案的一個例子:

class WorkProjectSerializer(serializers.CustomSerializer): 
    issues = drf_serializers.SerializerMethodField() 

    def get_issues(self, obj): 
     request = self.context.get('request') 
     return request.build_absolute_uri(reverse('project-issue-list', kwargs={'project_id': obj.id})) 

    class Meta: 
     model = WorkProject 
     fields = '__all__' 
相關問題