1. 程式人生 > >rest-framework框架 -- 解析器、分頁、路由

rest-framework框架 -- 解析器、分頁、路由

表示 color 組件 elf post data ... rest art rmp

解析器

:reqest.data取值的時候才執行

對請求的數據進行解析:是針對請求體進行解析的。表示服務器可以解析的數據格式的種類

django中的發送請求

#如果是這樣的格式發送的數據,在POST裏面有值
Content-Type: application/url-encoding.....
    request.body
    request.POST
    
#如果是發送的json的格式,在POST裏面是沒有值的,在body裏面有值,可通過decode,然後loads取值        
Content-Type: application/json.....
    request.body
    request.POST
關於decode、encode

瀏覽器發送過來是字節需要先解碼  --->  decode

如:s=中文
如果是在utf8的文件中,該字符串就是utf8編碼,如果是在gb2312的文件中,則其編碼為gb2312。這種情況下,要進行編碼轉換,都需要先用
decode方法將其轉換成unicode編碼,再使用encode方法將其轉換成其他編碼。通常,在沒有指定特定的編碼方式時,都是使用的系統默認編碼創建的代碼文件。
如下:
s.decode(utf-8).encode(utf-8)
decode():是解碼  --->把字節變成字符串
encode()是編碼---->把字符串變成字節

django只解析兩種形式

1:導入django的類
from django.core.handlers.wsgi import WSGIRequest

2class WSGIRequest(http.HttpRequest):
    def _get_post(self):
        if not hasattr(self, _post):
            self._load_post_and_files()
        return self._post
3#   self._load_post_and_files()從這裏找到django解析的方法
def _load_post_and_files(self): """Populate self._post and self._files if the content-type is a form type""" if self.method != POST: self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict() return if self._read_started and not hasattr(self, _body): self._mark_post_parse_error() return if self.content_type == multipart/form-data: if hasattr(self, _body): # Use already read data data = BytesIO(self._body) else: data = self try: self._post, self._files = self.parse_file_upload(self.META, data) except MultiPartParserError: # An error occurred while parsing POST data. Since when # formatting the error the request handler might access # self.POST, set self._post and self._file to prevent # attempts to parse POST data again. # Mark that an error occurred. This allows self.__repr__ to # be explicit about it instead of simply representing an # empty POST self._mark_post_parse_error() raise elif self.content_type == application/x-www-form-urlencoded: self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict() else: self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict() 從上面的 if self.content_type == ‘multipart/form-data‘:和 self.content_type == ‘application/x-www-form-urlencoded‘: 可以知道django只解析urlencoded‘和form-data這兩種類型

傳json數據默認為urlencoded這種解析
到request。body取原數據過來json數據時,django解析步驟---->需要我們自己操作
1:取到的數據是字節
需要先解碼decode():是解碼 --->把字節變成字符串
request。body。decode("utf8")
json.loads(request。body。decode("utf8"))

為了這種情況下每次都要decode,loads,顯得麻煩,所以才有的解析器。彌補了django的缺點

技術分享圖片
客戶端:
            Content-Type: application/json
            {"name":"alex","age":123}
        
        服務端接收:
            讀取客戶端發送的Content-Type的值 application/json
            
            parser_classes = [JSONParser,FormParser]  #表示服務器可以解析的數據格式的種類
            media_type_list = [application/json,application/x-www-form-urlencoded]
        
            如果客戶端的Content-Type的值和 application/json 匹配:JSONParser處理數據
            如果客戶端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser處理數據
        
        
        配置:
            單視圖:
            class UsersView(APIView):
                parser_classes = [JSONParser,]
                
            全局配置:
                REST_FRAMEWORK = {
                    VERSION_PARAM:version,
                    DEFAULT_VERSION:v1,
                    ALLOWED_VERSIONS:[v1,v2],
                    # ‘DEFAULT_VERSIONING_CLASS‘:"rest_framework.versioning.HostNameVersioning"
                    DEFAULT_VERSIONING_CLASS:"rest_framework.versioning.URLPathVersioning",
                    DEFAULT_PARSER_CLASSES:[
                        rest_framework.parsers.JSONParser,
                        rest_framework.parsers.FormParser,
                    ]
                }
                
                class UserView(APIView):
                    def get(self,request,*args,**kwargs):
                        return Response(ok)
                    def post(self,request,*args,**kwargs):
                        print(request.data)  #以後取值就在這裏面去取值
                        return Response(...)

具體講解
具體講解

rest-framework

在rest-framework中 是以利用Request類進行數據解析

1:找到apiview
class APIView(View):
    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES        #  解析器

2:找api_settings沒有定義找默認
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES

3:.
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)

4:DEFAULTS

DEFAULTS = {
    # Base API policies     #  自帶的解析器
    DEFAULT_PARSER_CLASSES: (
        rest_framework.parsers.JSONParser,    # 解析json數據
        rest_framework.parsers.FormParser,    # from數據
        rest_framework.parsers.MultiPartParser  # 多數據
    ),

例如

# 利用rest-framework的解析器
from  rest_framework.parsers import JSONParser, FormParser

class PublishView(generics.ListCreateAPIView):
    parser_classes = [FormParser]    #  自定義用哪些解析器來解析數據
    queryset = Publish.objects.all()
    serializer_class = PublishSerializers

技術分享圖片

技術分享圖片

全局視圖

REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
    "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",],
    "DEFAULT_THROTTLE_RATES":{
        "visit_rate":"5/m",
    },
    "DEFAULT_PARSER_CLASSES":[rest_framework.parsers.FormParser,]
}

分頁

試問如果當數據量特別大的時候,你是怎麽解決分頁的?

  • 方式a、記錄當前訪問頁數的數據id
  • 方式b、最多顯示120頁等
  • 方式c、只顯示上一頁,下一頁,不讓選擇頁碼,對頁碼進行加密

1:全局分頁

view。py:
class PublishView(generics.ListCreateAPIView):
    # parser_classes = [FormParser]    #  自定義用哪些解析器來解析數據
    queryset = Publish.objects.all()
    serializer_class = PublishSerializers  # 序列化

    def get(self,request,*args,**kwargs):
        publish_list = Publish.objects.all()
        # 構建分頁器對象
        pnp = PageNumberPagination()
        # 分完頁的數據
        pager_pulisher = pnp.paginate_queryset(queryset=publish_list,request=request,view=self)
        print(pager_pulisher)

        ps = PublishSerializers(pager_pulisher,many=True)
        return Response(ps.data)

setting:
REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["api.service.auth.MyAuthentication"],  # 認證組件
    "DEFAULT_PERMISSION_CLASSES":["api.service.permission.SVIPPermission"],  # 權限組件
    "DEFAULT_THROTTLE_CLASSES":["api.service.throttles.VisitThrottle"],      # 頻率組件

#     SimpleRateThrottle
    "DEFAULT_THROTTLE_RATES":{
        "visit_rate":"5/m,"
    },

#     分頁器參數
    "PAGE_SIZE":2  #每頁顯示的數據
}

技術分享圖片

局部及部分參數

# 自定義局部分頁
class MyPageNumberPagination(PageNumberPagination):
    page_size = 2   # 每頁顯示2條數據
    page_query_param = "page_num"  # http://127.0.0.1:8000/publishes/?page_num=2
    size = 3  # 從參數控制每頁顯示幾條數據
    max_page_size = 5   # 最多顯示5條數據

class PublishView(generics.ListCreateAPIView):
    # parser_classes = [FormParser]    #  自定義用哪些解析器來解析數據
    queryset = Publish.objects.all()
    serializer_class = PublishSerializers  # 序列化

    def get(self,request,*args,**kwargs):
        publish_list = Publish.objects.all()
        # 構建分頁器對象
        pnp = PageNumberPagination()
        # 分完頁的數據
        pager_pulisher = pnp.paginate_queryset(queryset=publish_list,request=request,view=self)
        print(pager_pulisher)

        ps = PublishSerializers(pager_pulisher,many=True)
        return Response(ps.data)

rest-framework框架 -- 解析器、分頁、路由