django restframework

 

APIView

1.restframework的APIView源碼剖析

類的繼承: 繼承了原生View類並繼承了as_view方法django

方法重寫:重寫了dispatch方法api

2.APIView的使用

pip install djangorestframework #下載djangorestframeworkapp

  from rest_framework.views import APIView
class LoginView(APIView):
def get(self, request):
   pass

解析器組件

1.使用示例
class LoginView(APIView):
def get(self, request):
   pass
   def post(self, request):
       request.data  # 新的request對象 @property
       return
2.部分重要關鍵源碼
class APIView(View):
@classmethod
def as_view(cls, **initkwargs):
   pass
super(APIView, cls).as_view(**initkwargs)

def initialize_request(self, request, *args, **kwargs):

from rest_framework.request import Request

return Request(
request,  # 原生request對象
parsers=self.get_parsers(), #
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)

def dispatch(self):
   pass
request = self.initialize_request(request, *args, **kwargs)
   self.request = request

def get_parsers(self):

return [parser() for parser in self.parser_classes]
3.實現流程
  1. views.LoginView.as_view()ide

  2. LoginView裏面沒有as_view方法,到父類APIView去找函數

  3. 執行View裏面的as_view()方法,返回view函數 def view(request, *args, kwargs): ​ self = cls(initkwargs) ​ if hasattr(self, 'get') and not hasattr(self, 'head'): ​ self.head = self.get ​ self.request = request ​ self.args = args ​ self.kwargs = kwargs ​ return self.dispatch(request, *args, **kwargs)post

  4. url和視圖函數之間的綁定關係創建完畢 { "login": view},等待用戶請求優化

  5. 接收到用戶請求:login,到創建好的綁定關係裏面執行對應的視圖函數:view(request)ui

  6. 視圖函數的執行結果是什麼就返回給用戶什麼:self.dispatch(), self.dispatch()的執行結果是什麼,就返回給用戶什麼url

  7. 此時的self表明的是LoginView的實例化對象spa

  8. 開始找dispatch方法,self裏面沒有,LoginView裏面也沒有,在APIView裏面有

  9. 開始執行APIView裏面的dispatch

  10. 最後找到http方法(GET,POST,PUT,DELETE),根據請求類型查找(request.method.lower())

  11. 開始執行找到的方法(GET),self.get(), self此時表明LoginView的實例化對象 11.1 假設接收到的是POST請求, 執行request.data 11.2 根據分析,全部的解析工做都在request.data裏面實現,且data是一個方法(被裝飾後的) 11.2 開始執行request.data @property def data(self): if not hasattr(self, 'full_data'): self.load_data_and_files() return self.full_data 11.3 執行self.load_data_and_files 11.4 執行self.data, self.files = self.parse() 11.5 parser = self.negotiator.select_parser(self, self.parsers) 11.5.1 開始找self.parsers 11.5.2 self.get_parses() [ parse() for parse in self.parser_classes ] 11.5.3 parser_classes = api_settings.DEFAULT_PARSER_CLASSES 11.5.4 from rest_framework import api_settings 11.5.5 api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) 11.5.6 class APISettings():pass

    ​ 11.5.7 找不到DEFAULT_PARSER_CLASSES,getattr 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser' ),

    11.5.8 首先找程序的settings

    11.5.9 而後找rest_framework的settings

    11.6 self.data就是咱們想要的數據 11.7 DRF將self.data = data 11.8 request.data

  12. 在LoginView裏面找到了對應的方法,執行該方法,最後返回給用戶

    • DRF的全部功能都是在as_view()和dispatch裏面重寫的

    • 而解析器組件在dispatch方法裏面重寫了,具體是在從新封裝的Request對象裏面

序列化組件

1.經過序列化組件進行get接口設計

GET 127.0.0.1:8000/books/ # 獲取全部數據,返回值: [{}, {}]

GET 127.0.0.1:8000/books/{id} # 獲取一條數據,返回值:{}

POST 127.0.0.1:8000/books/ # 新增一條數據,返回值:{}

PUT 127.0.0.1:8000/books/{id} # 修改數據,返回值:{}

DELETE 127.0.0.1:8000/books/{id} # 刪除數據,返回空

導入模塊:from rest_framework import serializers

創建一個序列化類:

 class BookSerializer(serializers.Serializer):
publish_name = serializers.CharField(read_only=True, source="publish.name")
authors_list = serializers.SerializerMethodField()

def get_authors_list(self, book_obj):
pass

開始序列化:

class BookView(APIView):
   def get(self, request):
       origin_data = Book.objects.all() #獲取queryset
       serialized_data = BookSerializer(origin_data, many=True) #開始序列化
       #book_obj = Book.objects.all()
       #serialized_data = BookSerializer(book_obj, many=False) get單條數據接口設計
       return Response(serialized_data.data) #獲取序列化後的數據,返回給客戶端

 

2.post接口設計
def post(self, request):
verified_data = BookSerializer(data=request.data)
if verified_data.is_valid():
book = verified_data.save()
authors=Author.objects.filter(nid__in=request.data
['authors'])
book.authors.add(*authors)
return Response(verified_data.data)
else:
return Response(verified_data.errors)

3.put接口設計
def put(self, request, nid):
book_obj = Book.objects.get(pk=nid)
verified_data = BookSerializer(data=request.data, instance=book_obj)
if verified_data.is_valid():
verified_data.save()
return Response(verified_data.data)
else:
return Response(verified_data.errors)

視圖組件

1. 使用視圖組件的mixin進行接口邏輯優化
a.導入mixin
from rest_framework.mixinx import (

ListModelMix,

CreateModelMixin,

DestroyModelMixin,

UpdateModelMixin,

RetrieveModelMixin

)

from rest_framework.generics import GenericAPIView

 

b.定義序列化類
class BookSerializer(serializers.ModelSerializer):
   class Meata:
       model = Book
       fields = ('field_name', )
       extra_kwargs = {"publish": {"write_only": True}, }

       publish_name = serializers.CharField(read_only=True, source="publish.name")
       authors = serializers.SerializerMethodField()

       def get_authors(self, book_obj):
           pass
c.導入序列化類

from .app_serializers import BookSerializer

d.定義視圖類
class BookView(ListModelMix, CreateModelMixin, GenericAPIView):
 #queryset和serializer_class是固定的寫法
     queryset = Book.objects.all()
     serializer_class = BookSerializer

     def get():
       return self.list()

     def post():
       return self.create()


class BookFilterView(RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin, GenericAPIView):
   queryset = Book.objects.all()
serializer_class = BookSerializer
def get():
   return self.retrieve()

def delete():
   return self.destroy()

def put():
   return self.update()
 
#注意:單條數據操做的url是這樣的:re_path(r'books/(?P<pk>\d+)/$, views.BookFilterView.as_view())



2.使用視圖組件的view進行接口邏輯優化
a.導入模塊
from rest_framework import generics
b.寫視圖類
class BookView(generics.ListCreateAPIView)
   queryset = Book.objects.all()
   serializer_class = BookSerializer

class BookFilterView(generics.RetrieveUpdateDestroyAPIView):
   queryset = Book.objects.all()
   serializer_class = BookSerializer
3.使用視圖組件的viewset進行接口邏輯優化
a.導入模塊
from rest_framework.viewsets import ModelViewSet
b.設計url
re_path(r'books/$', views.BookView.as_view({
   'get': 'list',
   'post': 'create'
})),
re_path(r'books/(?P<pk>\d+)/$', views.BookView.as_view({
   'get': 'retrieve',
   'delete': 'destroy',
   'put': 'update'
}))
c.設計視圖類
class BookView(ModelViewSet):
   queryset = Book.objects.all()
   serializer_class = BookSerializer

 

認證組件

1.使用方法
a.定義認證類
class UserAuth():
   def authenticate_header(self, request):
       pass

   def authenticate(self, request):
       pass
b.在須要認證的數據接口裏面指定認證類
class BookView(ModelViewSet):
   authentication_classes = [UserAuth]
   queryset = Book.objects.all()
   serializer_class = BookSerializer
2.全局認證

在settings文件裏面指定:

 REST_FRAMEWORK = {
"DEFAULT_PARSER_CLASSES": (JsonParser, FormParser),
"DEFAULT_AUTHENTICATION_CLASSES": ("serializer.utils.app_authes.UserAuth",)
}
3.源碼剖析
- self.dispatch() # self BookView的實例化對象
- self.initial() # self BookView的實例化對象
- self.perform_authentication()  # self BookView的實例化對象
- request.user    # self Request的實例化對象
- self._authenticate() # self Request的實例化對象
self.user = xxx

 

權限組件

1.權限組件的使用
a.定義一個權限類
    class UserPerm():
       def has_permission(self, request, view):
           if 有權限:
               return True
           else:
               return False
b.指定權限類
class BookView(APIView):
   permission_classes = [UserPerm]

 

頻率組件

1.頻率組件的使用
a.定義一個頻率類
class RateThrottle():
   def allow_request(request, self):
       if 沒有超過限制:
      return True
       else:
      return False

   def wait(self):
  return 10
b.指定頻率類
class BookView(APIView):
throttle_classes = [RateThrottle]
2.使用DRF的簡單頻率控制來控制用戶訪問頻率(局部)
  -導入模塊
from rest_framework.throttling import SimpleRateThrottle
- 定義並繼承SimpleRateThrottle
   class RateThrottle(SimpleRateThrottle):
   # 指定訪問頻率
   rate = '5/m'

# 指定經過什麼方式來區分用戶
def get_cache_key(self, request, view):
   return self.get_ident(request)

- 指定頻率類
   class BookView(APIView):
   throttle_classes = [RateThrottle]
3.使用DRF的簡單頻率控制來控制用戶訪問頻率(全局)
 -導入模塊
from rest_framework.throttling import SimpleRateThrottle

- 定義並繼承SimpleRateThrottle
   class RateThrottle(SimpleRateThrottle):
   # 指定訪問頻率
   scope = 'visit_rate'

# 指定經過什麼方式來區分用戶
def get_cache_key(self, request, view):
   return self.get_ident(request)

- 在settings裏面指定頻率類和訪問頻率
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": ('serializer.utils.app_throttles.RateThrottle',),
"DEFAULT_THROTTLE_RATES": {
"visit_rate": "5/m"
}
}

 

url註冊器組件

1.url註冊器組件的使用
a.導入模塊
from django.urls import re_path, include  
from .serializer import views
from rest_framework import routers
b.生成一個註冊器示例對象
router = routers.DefaultRouter()

 

c.將須要自動生成url的接口註冊
router.register(r"books", views.BookView)

 

d.開始自動生成url
urlpatterns = [
   re_path('^', include(router.urls)),
]

 

分頁器組件

1.使用方法​
 - 導入模塊
  from rest_framework.pagination import PageNumberPagination
   
- 獲取數據
   books = Book.objects.all()

- 建立一個分頁器對象
   paginater = PageNumberPagination()

- 開始分頁
paged_books = paginater.paginate_queryset(books, request)

- 開始序列化
   serialized_books = BookSerializer(paged_books, many=True)

- 返回數據
   return Response(serialized_books.data)
2.局部實現
 - 導入模塊
  from rest_framework.pagination import PageNumberPagination
 
- 自定義一個分頁類並集成PageNumberPagination
class MyPagination(PageNumberPagination):
   page_size = 2
page_query_param = 'p'
page_size_query_param = 'size'
max_page_size = 5

- 實例化一個分頁類對象
paginater = MyPagination()

- 開始分頁
paged_books = paginater.paginate_queryset(books, request)

- 開始序列化
   serialized_books = BookSerializer(paged_books, many=True)

- 返回數據
   return Response(serialized_books.data)

響應器組件

a.導入模塊
 from rest_framework.renderers import JsonRender

 

b.指定返回類
  class BookView(APIView):
       render_classes = [JsonRender]
相關文章
相關標籤/搜索