DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)...
| url控制 |
第二種寫法(只要繼承了ViewSetMixin)
url(r'^pub/$',views.Pub.as_view({'get':'list','post':'create'})), #獲取所有記得路由后面加$結束符 #pub/?format=jsonurl(r'^pub\.(?P<format>\w+)$',views.Pub.as_view({'get':'list','post':'create'})), #pub.jsonurl(r'^pub/(?P<pk>\d+)$',views.Pub.as_view({'get':'retrieve','put':'update','delete':'destroy'})), #獲取一條第三種(自動生成路由,必須繼承ModelViewSet)
from django.conf.urls import url,includeSimpleRouter 自動生成兩條路由
from rest_framework.routers import SimpleRouter,DefaultRouter #路由控制 router = SimpleRouter() router.register('pub',views.Pub)urlpatterns = [url(r'^admin/', admin.site.urls),#其他路由 url(r'',include(router.urls)),]DefaultRouter自動生成四條路由
from rest_framework.routers import SimpleRouter,DefaultRouter #路由控制 router = DefaultRouter() router.register('pub',views.Pub)urlpatterns = [url(r'^admin/', admin.site.urls),#其他路由url(r'',include(router.urls)),]?
| 解析器(一般不需要動,項目最開始全局配置一下就可以了) |
作用:控制視圖類能夠解析前端傳過來的格式是什么樣的 (默認配置三種都有)?有application/json,x-www-form-urlencoded,form-data等格式
全局使用:在settings中配置:
REST_FRAMEWORK = {"DEFAULT_PARSER_CLASSES":['rest_framework.parsers.JSONParser',] }局部使用:
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser#json字典 urlencoded form-data 文件在視圖類中
parser_classes=[JSONParser,]源碼流程
當調用request.data的時候去執行解析方法
-->根據傳過來的編碼方式選擇一個解析器對象
--->調用解析器對象的parser方法完成解析
?
?
在調用request.data時,才進行解析,由此入手@propertydef data(self):if not _hasattr(self, '_full_data'):self._load_data_and_files()return self._full_data 查看self._load_data_and_files()方法---->self._data, self._files = self._parse()def _parse(self):#用戶請求頭里content_type的值media_type = self.content_type#self.parsers 就是用戶配置的parser_classes = [FileUploadParser,FormParser ]#self里就有content_type,傳入此函數parser = self.negotiator.select_parser(self, self.parsers) 查看self.negotiator.select_parser(self, self.parsers)def select_parser(self, request, parsers):#同過media_type和request.content_type比較,來返回解析器,然后調用解析器的解析方法#每個解析器都有media_type = 'multipart/form-data'屬性for parser in parsers:if media_type_matches(parser.media_type, request.content_type):return parserreturn None 最終調用parser的解析方法來解析parsed = parser.parse(stream, media_type, self.parser_context) 源碼注釋 Request實例化,parsers=self.get_parsers()Request(request,parsers=self.get_parsers(),authenticators=self.get_authenticators(),negotiator=self.get_content_negotiator(),parser_context=parser_context) get_parsers方法,循環實例化出self.parser_classes中類對象def get_parsers(self):return [parser() for parser in self.parser_classes] self.parser_classes 先從類本身找,找不到去父類找即APIVIew 中的parser_classes = api_settings.DEFAULT_PARSER_CLASSES api_settings是一個對象,對象里找DEFAULT_PARSER_CLASSES屬性,找不到,會到getattr方法def __getattr__(self, attr):if attr not in self.defaults:raise AttributeError("Invalid API setting: '%s'" % attr)try:#調用self.user_settings方法,返回一個字典,字典再取attr屬性val = self.user_settings[attr]except KeyError:# Fall back to defaultsval = self.defaults[attr]# Coerce import strings into classesif attr in self.import_strings:val = perform_import(val, attr)# Cache the result self._cached_attrs.add(attr)setattr(self, attr, val)return val user_settings方法 ,通過反射去setting配置文件里找REST_FRAMEWORK屬性,找不到,返回空字典@propertydef user_settings(self):if not hasattr(self, '_user_settings'):self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})return self._user_settings 源碼注釋2?
?
| 響應器 |
?解析成字符串 還是一個瀏覽器頁面
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer #解析成字符串 還是瀏覽器樣式的 # 不用動,就用全局配置即可默認配置中兩個都有全局使用
在settings中配置 settings默認配置中兩個都有
REST_FRAMEWORK = {'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser',],# 響應器 默認配置兩個都由 這個是全局使用 # 'DEFAULT_PARSER_CLASSES':[ 'rest_framework.renderers.JSONRenderer', # 'rest_framework.renderers.BrowsableAPIRenderer',] }局部使用
在試圖類中配置
renderer_classes = [JSONRenderer, BrowsableAPIRenderer]?
| 版本控制 |
?作用用于控制版本? ??視圖中 版本問題需要接受版本傳過來的參數 注意是單個沒有復數
內置版本控制
from rest_framework.versioning import QueryParameterVersioning,AcceptHeaderVersioning,NamespaceVersioning,URLPathVersioning#基于url的get傳參方式:QueryParameterVersioning------>如:/users?version=v1 #基于url的正則方式:URLPathVersioning------>/v1/users/ #基于 accept 請求頭方式:AcceptHeaderVersioning------>Accept: application/json; version=1.0 #基于主機名方法:HostNameVersioning------>v1.example.com #基于django路由系統的namespace:NamespaceVersioning------>example.com/v1/users/局部使用
#在CBV類中加入 versioning_class = URLPathVersioning url中需要寫 url(r'(?P<version>[v1|v2])/register/$',views.Register.as_view()),url(r'(?P<version>[v1|v2])/register\.(?P<format>\w+)$',views.Register.as_view()),url(r'(?P<version>[v1|v2])/register/(?P<pk>\d+)$',views.Register.as_view()),寫訪問路由的的時候要寫上版本
?
全局使用
在settings中配置
REST_FRAMEWORK = {"DEFAULT_PARSER_CLASSES":['rest_framework.parsers.JSONParser',],'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning','DEFAULT_VERSION': 'v1', # 默認版本(從request對象里取不到,顯示的默認值)'ALLOWED_VERSIONS': ['v1', 'v2'], # 允許的版本'VERSION_PARAM': 'version', # URL中獲取值的key }路由不要寫
url(r'register/$',views.Register.as_view()),?
但是訪問路由的時候需要寫上版本
?
在試圖類中就可以通過,request.vesrsion取出當前訪問哪個版本,相應的去執行相應版本的代碼
?
示例
基于正則的方式
from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'), ]url View Code from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import URLPathVersioningclass TestView(APIView):versioning_class = URLPathVersioningdef get(self, request, *args, **kwargs):# 獲取版本print(request.version)# 獲取版本管理的類print(request.versioning_scheme)# 反向生成URLreverse_url = request.versioning_scheme.reverse('test', request=request)print(reverse_url)return Response('GET請求,響應內容')views.py View.py # 基于django內置,反向生成urlfrom django.urls import reverseurl2=reverse(viewname='ttt',kwargs={'version':'v2'})print(url2) View Code?
源碼分析
#執行determine_version,返回兩個值,放到request對象里 version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, schemedef determine_version(self, request, *args, **kwargs):#當配置上版本類之后,就會實例化if self.versioning_class is None:return (None, None)scheme = self.versioning_class()return (scheme.determine_version(request, *args, **kwargs), scheme)?
| 分頁 |
?
?常規分頁 查看第n頁 每頁顯示多少條
#分頁 #常規分頁 偏移分頁 cursor游標分頁 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPaginationclass PublishView(APIView):versioning_class = URLPathVersioningparser_classes = [JSONRenderer,] #解析器def get(self,request,*args,**kwargs):#第一種方法,普通分頁'''查詢出所有數據實例化產生一個普通分頁對象每頁顯示多少條查詢指定查詢那一頁的key值'''ret= models.Publish.objects.all()page = PageNumberPagination()page.page_size = 3 #每頁顯示多少條 page.page_query_param = 'page' #按照page名詞顯示那一頁# 前端控制每頁顯示多少條的查看key值必然要size=9,表示一頁顯示9條page.page_size_query_param = 'size'#控制每頁最大顯示多少,size如果傳100,最多也是顯示10page.max_page_size = 10ret_page = page.paginate_queryset(ret,request,self)#序列化pub_ser = PublishSerlizers(ret_page,many=True)#去settings中配置每頁顯示多少條 這個是全局配置的話 局部配置全局可以不配置return Response(pub_ser.data)settings中配置
REST_FRAMEWORK = {# 每頁顯示兩條'PAGE_SIZE':2 }路由
url(r'^(?P<version>[v1|v2]+)/publish/',views.PublishView.as_view())serializer
from rest_framework.serializers import ModelSerializer from app01 import models class PublishSerlizers(ModelSerializer):class Meta:model = models.Publishfields = '__all__'?
偏移分頁? 在第n個位置向前向后查詢第n個位置
#分頁 #常規分頁 偏移分頁 cursor游標分頁 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPaginationclass PublishView(APIView):versioning_class = URLPathVersioningparser_classes = [JSONRenderer,] #解析器def get(self,request,*args,**kwargs): #偏移分頁ret = models.Publish.objects.all()#實例化產生一個偏移分頁對象page= LimitOffsetPagination()# 四個參數:# 從標桿位置往后取幾個,默認取3個,可以指定page.default_limit = 3# 每條取得條數page.limit_query_param ='limit'# 標桿值,現象偏移到那個位置,如果offset=6, 表示當前在第6條位置上,往后取page.offset_query_param = 'offset'# 最大取10條page.max_limit = 10ret_page = page.paginate_queryset(ret,request,self)#序列化pub_ser= PublishSerlizers(ret_page,many=True)#取settings中配置每頁顯示多少條return page.get_paginated_response(pub_ser.data)?
?cursor游標分頁
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class PublishView(APIView):versioning_class = URLPathVersioningparser_classes=[JSONParser,]def get(self, request, *args, **kwargs):ret = models.Publish.objects.all()# 實例化產生一個偏移分頁對象page = CursorPagination()#三個參數:#每頁顯示的大小page.page_size=3#查詢的key值page.cursor_query_param='cursor'# 按什么排序page.ordering='id'ret_page = page.paginate_queryset(ret, request, self)# 序列化pub_ser = serializer.PublishSerializers(ret_page, many=True)# 去setting中配置每頁顯示多少條return page.get_paginated_response(pub_ser.data)?
轉載于:https://www.cnblogs.com/lakei/p/11143411.html
總結
以上是生活随笔為你收集整理的DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)...的全部內容,希望文章能夠幫你解決所遇到的問題。