簡體   English   中英

DRF 查詢集返回特定字段

[英]DRF queryset to return specific field

我正在使用這種結構創建一個 django rest 框架應用程序(假設導入是正確的,所以我從下面的代碼中省略了它們。

模型.py:

class Door(models.Model):
  type = models.CharField(max_length=40)
  color = models.CharField(max_length=40)

序列化程序.py:

class DoorSerializer(serializers.ModelSerializer):
  class Meta:
    model = Door
    fields = ['type', 'color']

視圖.py:

class DoorViewSet(viewsets.ModelViewSet):
  serializer_class = DoorSerializer
  queryset = Door.objects.all()
  def get_queryset(self, *args, **kwargs):
    queryset = Door.objects.all()
    parameter = self.request.query_params.get('type', '')
    if parameter:
      return queryset.filter(type=parameter)
    else:
      return queryset

到目前為止,這符合預期,當我對localhost/Doors進行 api 調用時,它會列出所有門。 當我對localhost/Doors/?type=big進行 api 調用時,它會列出在其“類型”字段中具有“大”值的所有門。

我想做的補充是另一個參數檢查,它將返回數據庫中存在的所有唯一門類型的列表。 這可以通過使用以下方法在 manage.py shell 中實現: Door.objects.all().values('type').distinct()

我的嘗試是對views.py進行以下修改:

...
parameter = self.request.query.params.get('type', '')
unique = self.request.query.params.get('unique', '')
if parameter:
  ...
elif unique:
  return Door.objects.all().values('type').distinct()
...

我的假設是,當我調用localhost/Doors/?unique=whatever時,這將返回與Door.objects.all().values('type').distinct()相同的結果

但是我收到錯誤消息:“嘗試獲取序列化程序 DoorSerializer 上的字段color值時DoorSerializer 。\n序列化程序字段可能命名不正確,並且與dict實例上的任何屬性或鍵都不匹配。\n原始異常文本為:'顏色'。”

我假設這意味着序列化程序需要一個 object 或包含相應 model 的所有字段的對象列表。

有什么方法可以通過修復視圖來規避這個問題,還是應該創建一個不同的序列化程序? 無論哪種情況,由於我對 DRF / django 差異感到非常困惑,並且我可能無法遵循抽象說明,您能否提供解決該問題的代碼解決方案? 此外,在很可能我的假設完全不成立的情況下,您能否解釋一下導致問題的原因? 感謝您的時間!

編輯以澄清所需的結果:

假設我的數據庫有 4 個門,它們是:

{
  "id": 1,
  "type": "big",
  "color": "blue"
},
{
  "id": 2,
  "type": "big",
  "color": "yellow"
},
{
  "id": 3,
  "type": "small",
  "color": "green"
},
{
  "id": 4,
  "type": "big",
  "color": "red"
},

我想向某些 url 發出get請求,例如localhost/Doors/?unique=Yes並讓 api 返回給我列表{"big", "small}

  1. 編寫自己的視圖:返回類型列表的簡短視圖。 您需要在此處設置新路徑。 對於此選項,我個人會選擇 go,因為您期望的響應與您視圖中的 rest 的響應完全不同。
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view()
def Unique_door_types(request):
   types = Door.objects.values_list('type', flat=True).distinct()
   return Response({"types": list(types)})
  1. 沒有其他視圖:

無需額外的視圖或序列化程序。 覆蓋list方法。 請注意,這更像是一種技巧,而不是一種好的編程方式。

from rest_framework.response import Response

class DoorViewSet(viewsets.ModelViewSet):
    serializer_class = DoorSerializer
    
    def get_queryset(self, *args, **kwargs):
        queryset = Door.objects.all()
        parameter = self.request.query_params.get('type', '')
        if parameter:
            return queryset.filter(type=parameter)
        else:
            return queryset

    def list(self, request):
        unique = self.request.query_params.get('unique', '')
        if unique:
            types = Door.objects.values_list('type', flat=True).distinct()
            return Response({"types": list(types)})
        return super().list()

我的建議是創建一個單獨的路線,例如/doors/types/ 為此,您可以使用@action裝飾器向DoorViewSet class 添加一個方法。 有關如何執行此操作的更多詳細信息,請參閱https://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing

暫無
暫無

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

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