django restframework

APIView

1.restframework的APIView源码剖析

类的继承: 继承了原生View类并继承了as_view方法

方法重写:重写了dispatch方法

2.APIView的使用

pip install djangorestframework #下载djangorestframework

        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()

  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)

  4. url和视图函数之间的绑定关系建立完毕 { "login": view},等待用户请求

  5. 接收到用户请求:login,到建立好的绑定关系里面执行对应的视图函数:view(request)

  6. 视图函数的执行结果是什么就返回给用户什么:self.dispatch(), self.dispatch()的执行结果是什么,就返回给用户什么

  7. 此时的self代表的是LoginView的实例化对象

  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]

 

原文地址:https://www.cnblogs.com/luxiangyu111/p/10099390.html