簡體   English   中英

如何在同一模型中使用兩個不同的模型序列化器?

[英]How Can I Use Two Different Model Serializers With the Same Model?

我正在使用django-rest-framework。 我有一個有關系的模型。 我只想在用戶點擊/modelname/ URL時顯示相關項的計數,但是當用戶點擊/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。

您可以通過重寫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

我認為解決此問題的一個簡單方法是使用基於類的通用視圖而不是視圖集。

您可以使用帶有serializer_class作為ShortDataSetSerializer的列表創建api視圖。 因此,當您獲得數據列表時,它將具有修訂計數。 另外,如果您希望發布請求在相同的url上工作,則必須重寫get_serializer_class方法以根據請求類型設置serializer_class。

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

在DRF文檔網站上簽出通用視圖api指南。

此外,您可以覆蓋列表並在視圖集上檢索方法,但是我更喜歡使用基於類的視圖,因為DRF在請求函數(如get,put等)(或列表,詳細信息)上附加了許多附加功能,並且它最好不要覆蓋它們。

謝謝你,本傑明。 那沒有做我一直在尋找的東西。 最終,我要做的是(使用與上述相同的序列化器):

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'})),

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM