2014-02-21 94 views
1

我使用Django的REST的框架。我有一個關係模型。我想只顯示相關項目的數量,當用戶點擊URL /modelname/,但顯示的全組相關,當用戶在/modelname/1/點擊一個特定的模型實例。如何使用相同模型使用兩個不同的模型串行器?

我可以幾乎得到我想要的東西。

我有兩個串行器,像這樣:

class DataSetSerializer(serializers.ModelSerializer): 
    revisions = serializers.RelatedField(source='datasetrevision_set', many=True) 

    class Meta: 
     model = DataSet 
     fields = ('id', 'title', 'revisions') 

class ShortDataSetSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = DataSet 
     fields = ('id', 'title', 'revisions') 

如果我用的是短版,我得到的版本(這是一個計算字段)的數量。如果使用長版本,我會將相關項目的完整列表作爲「修訂」。

簡稱:

[{"id": 1, "title": "My Data Set", "revisions": 0}] 

長:

[{"id": 1, "title": "My Data Set", "revisions": ["Data Set v1", "Data Set v2"]}] 

我想要做的就是能夠根據查詢參數(URL)在它們之間進行切換。我試圖在ID不存在時將serializer_class設置爲ShortDataSetSerializer,但它覆蓋了所有情況,而不僅僅是非ID情況。

class DataSetViewSet(viewsets.ModelViewSet): 
    serializer_class = DataSetSerializer 
    model = DataSet 

    def get_queryset(self): 
     try: 
      id = self.kwargs['id'] 
      queryset = DataSet.objects.filter(id=id) 
     except KeyError: 
      queryset = DataSet.objects.all() 
      # We want to only list all of the revision data if we're viewing a 
      # specific set, but this overrides for all cases, not just the one 
      # we want. 
      self.serializer_class = ShortDataSetSerializer 
     return queryset 

有沒有辦法讓這項工作?我意識到我可能以一種荒謬的方式來解決這個問題,但似乎應該有一個簡單的解決方案。

的數據例如我給了相當縮寫相比,我的工作的真實數據。最終目標是在列表視圖中顯示字段的子集,並在GET中顯示特定ID的每個字段。這是一個只讀的API,所以我不需要擔心POST/PUT/DELETE。

+0

簡單但更冗餘的答案是隻使用兩個視圖集。 –

+0

您是否嘗試重寫'get_serializer_class'方法? –

回答

3

你可以通過重寫get_serializer_class方法做到這一點:

class DataSetViewSet(viewsets.ModelViewSet): 
    model = DataSet 

    def get_queryset(self): 
     queryset = DataSet.objects.all() 
     if self.kwargs.get('id'): 
      queryset = queryset.filter(pk=self.kwargs.get('id')) 
     return queryset 

    def get_serializer_class(self): 
     return DataSetSerializer if 'id' in self.kwargs else ShortDataSetSerializer 
0

謝謝你,本傑明。那不是我想要的。最終,我所要做的就是這個(具有相同的串行如上):

class DataSetViewSet(viewsets.ModelViewSet): 
    model = DataSet 

    def list(self, request): 
     queryset = DataSet.objects.all() 
     serializer = ShortDataSetSerializer(queryset, many=True) 
     return Response(serializer.data) 

    def detail(self, request, id=None): 
     queryset = DataSet.objects.get(id=id) 
     serializer = DataSetSerializer(queryset) 
     return Response(serializer.data) 

而在urls.py:

url(r'^sets/$', views.DataSetViewSet.as_view({'get': 'list'})), 
url(r'^sets/(?P<id>\d+)/$', views.DataSetViewSet.as_view({'get': 'detail'})), 
+1

ModelViewSet是一個GenericViewSet。這裏最好的解決方案是重寫'get_serializer_class'或'get_serializer',因爲通過重載'list'或'detail'重複已經存在於'ModelViewSet'中的功能(並且刪除了過濾器和權限後端等功能) 。 對於您在urls.py中的代碼,您可以使用DRF路由器(SimpleRouter,DefaultRouter) –

1

我想對於這個問題的一個簡單的解決方案是使用基於類的通用視圖而不是視圖集。

您可以使用列表創建serializer_class爲ShortDataSetSerializer API視圖。所以當你得到數據清單時,它會有修改數量。此外,如果你想POST請求在同一網址工作,你便要重寫get_serializer_class方法來設置基於請求類型的serializer_class。

對於檢索視圖,您可以使用serializer_class作爲DataSetSerializer。它將有一個修訂列表而不是計數。

在DRF文檔網站上籤出通用視圖API指南。因爲DRF有很多額外的功能附加到請求函數,比如get,put等(或者列表,列表等等),所以我們可以使用基於類的視圖。細節),最好不要重寫它們。

相關問題