3 回答

TA貢獻(xiàn)1875條經(jīng)驗(yàn) 獲得超3個(gè)贊
對(duì)此的答案取決于您使用的是什么類型的視圖,但最重要的是您不要這樣做,因?yàn)間et_queryset您在請(qǐng)求類型的方法中執(zhí)行此操作。
因?yàn)槿绻闶褂玫氖抢鏡etrieveAPIView應(yīng)覆蓋retrieve從方法RetrieveModelMixin像這樣:
class MyAPIView(RetrieveAPIView):
queryset = MyModel.objects.all()
serializer_class = MySerializer
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
data = {
"collection": {
"data": serializer.data
},
"statusCode": 200,
"version": "1.0"
}
return Response(data)
如果您使用的是 ListAPIView 之類的其他東西,那么您希望查看相關(guān)方法中使用的內(nèi)容并覆蓋它以包裝您的數(shù)據(jù)。
這里要意識(shí)到的主要事情是它與獲取查詢集無關(guān) - 這只是從數(shù)據(jù)庫中獲取數(shù)據(jù)。這是關(guān)于在發(fā)回響應(yīng)時(shí)將數(shù)據(jù)轉(zhuǎn)換為正確的格式。因此,工作應(yīng)該在做出響應(yīng)時(shí)完成。

TA貢獻(xiàn)1803條經(jīng)驗(yàn) 獲得超6個(gè)贊
在這里實(shí)現(xiàn)自定義渲染器似乎是一種方法。
您可以讓來自 android 客戶端的請(qǐng)求在Accept標(biāo)頭中包含一種向渲染器標(biāo)識(shí)客戶端的方法。1 例如
Accept: application/json; android=true
然后使用JSONRenderer該類編寫渲染器,為您的 Android 客戶端提供格式。
# ./formatters/android_format.py
from rest_framework.renderers import JSONRenderer, BaseRenderer
from django.http.multipartparser import parse_header
class AndroidV1FormatRenderer(BaseRenderer):
media_type = 'application/json'
format = 'json'
json_renderer = JSONRenderer()
def android(self, accepted_media_type):
base_media_type, params = parse_header(accepted_media_type.encode('ascii'))
return 'android' in params
def render(self, data, accepted_media_type=None, renderer_context=None):
response = renderer_context['response']
android = self.android(accepted_media_type)
if android:
data = {
"collection": {"data": data},
"statusCode": response.status_code,
"version": "1.0"
}
return json_renderer.render(
wrapped_data, accepted_media_type, renderer_context)
在這里你需要響應(yīng)格式化使用此方法然后可以使用renderer_classes你的屬性APIView。2

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超8個(gè)贊
這個(gè)問題有幾種可能的解決方案。NDevox 已經(jīng)提到我們?nèi)绾胃采w我們的retrive函數(shù)并獲得我們預(yù)期的響應(yīng)。但是如果我們希望這將在每個(gè)api端點(diǎn)的每個(gè)響應(yīng)中完成,如果我們這樣做,我們需要覆蓋每個(gè)函數(shù),那么它的負(fù)擔(dān)很大,DRY我們應(yīng)該盡可能避免這種情況。引入中間件或覆蓋的可能方法之一,Response以便我們可以在不顯式覆蓋每個(gè)功能的情況下獲得每個(gè) API 端點(diǎn)的通用響應(yīng)。
可能的解決方案一
正如我們?cè)贒RF這里使用的那樣,我們可以添加我們自己的各種媒體類型的返回響應(yīng),比如 for application/json。
首先我們需要添加我們的settings.py
REST_FRAMEWORK = {
...
'DEFAULT_RENDERER_CLASSES': (
'app_name.renderers.ApiRenderer', # our own render middleware
),
...
}
在我們的自定義渲染中間件中
from rest_framework.renderers import BaseRenderer
from rest_framework.utils import json
class ApiRenderer(BaseRenderer):
def render(self, data, accepted_media_type=None, renderer_context=None):
our_response_dict = {
'version': '1.0'
'data': {},
'message': '',
}
if data.get('data'):
our_response_dict['data'] = data.get('data')
if data.get('status'):
our_response_dict['statusCode'] = data.get('status')
if data.get('message'):
our_response_dict['message'] = data.get('message')
data = our_response_dict
return json.dumps(data)
參考鏈接
可能的解決方案二
如果我們正在使用,ModelViewset那么還有另一種方法可以實(shí)現(xiàn)這一目標(biāo)。說我們的 Views.py 如下
class A(serializer.ModelSerializer):
........
class B(serializer.ModelSerializer):
........
class C(serializer.ModelSerializer):
........
我們的目標(biāo)是覆蓋ModelViewset的 to_representation 函數(shù)并返回我們的自定義結(jié)果。這將如下所示
from collections import OrderedDict
class OurParentViewset(serializer.ModelSerializer):
......
def to_representation(self, instance):
data = super(serializers.ModelSerializer, self).to_representation(instance)
result = OrderedDict()
result['data'] = data
result['version'] = '1.0'
result['statusCode'] = '2xx' # i am not fully sure how to customize this
return result
class A(OurParentViewset):
........
class B(OurParentViewset):
........
class C(OurParentViewset):
........
添加回答
舉報(bào)