REST-framework快速构建API--源码解析

作者:@skyflask
转载本文请注明出处:https://www.cnblogs.com/skyflask/p/10422335.html


目录

一、APIView
二、ModelView
三、认证、权限、频率源码

一、APIView

通过APIView实现API的过程如下:

urls.py

1
2
url(r'^books/$', views.BookView.as_view(),name="books"),
 url(r'^books/(\d+)/$', views.BookDetailView.as_view(),name="detailbook"),

 

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        bs = BookModelSerializers(book_list, many=True, context={'request': request})
        return Response(bs.data)
 
    def post(self, request):
        # post请求的数据
        bs = BookModelSerializers(data=request.data)
        if bs.is_valid():
            print(bs.validated_data)
            bs.save()  # create方法
            return Response(bs.data)
        else:
            return Response(bs.errors)
 
 
class BookDetailView(APIView):
 
    def get(self, request, id):
 
        book = Book.objects.filter(pk=id).first()
        bs = BookModelSerializers(book, context={'request': request})
        return Response(bs.data)
 
    def put(self, request, id):
        book = Book.objects.filter(pk=id).first()
        bs = BookModelSerializers(book, data=request.data, context={'request': request})
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)
 
    def delete(self, request, id):
        Book.objects.filter(pk=id).delete()
 
        return Response()
1
 

 

urls中,定义了两个url的请求方式:

  • 通过URL:http://127.0.0.1/books/   GET/POST数据

  • 通过URL:http://127.0.0.1/books/id/   GET/PUT/DELETE数据

第一种,url(r'^books/$', views.BookView.as_view(),name="books"),调用过程如下:

views.BookView.as_view()

  1、APIView.as_view(),返回view,实际上是执行View.as_view()

    2、View中的as_view()返回disptch()函数

      3、self会从View类往上找dispatch(),在APIView类中有找到dispatch()

        4、dispatch()会找get、post、put、delete等方法

          5、在当前View下,BookView类下定义了get、post,BookDetailView类下定义了get、put、delete

            6、执行当前类下的对应方法

第二种URL执行过程一样。

二、ModelView

通过ModelView实现API过程如下:

urls.py

1
2
url(r'^authors/$', views.AuthorModelView.as_view({'get':'list','post':'create'}),name="authors"),
url(r'^authors/$', views.AuthorModelView.as_view({'get':'retrieve','post':'update','delete':'destory'}),name="authors"),

views.py

1
2
3
4
class AuthorModelView(viewsets.ModelViewSet):
    queryset = Author.objects.all()
    serializer_class = AuthorModelSerializers
  

执行过程如下:

1、当前类下没有as_view方法,从父类ModelViewSet中查找

1
 
1
2
3
4
5
6
7
8
9
10
11
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass
1
 

2、ModeViewSet在mixins中没有as_view,从GenericViewSet往上找

1
 
1
2
3
4
5
6
7
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    """
    The GenericViewSet class does not provide any actions by default,
    but does include the base set of generic view behavior, such as
    the `get_object` and `get_queryset` methods.
    """
    pass
1
 

3、从ViewSetMixin中找到了as_view(),实际上返回了dispatch()

ViewSetMixin==>generics.GenericAPIView==>views.APIView==>dispatch()

4、执行dispatch(),实际上是找get、post、put、delete等方法

5、在当前类下找到对应的方法

 

 

三、认证、权限、频率源码

 通过ModelView方式实现认证,

局部应用:

1
2
3
4
5
6
class AuthorModelView(viewsets.ModelViewSet):
 
    authentication_classes = [TokenAuth, ]
    queryset = Author.objects.all()
    serializer_class = AuthorModelSerializers
    pagination_class = StandardResultsSetPagination

  

  

全局应用:

1
2
3
4
REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.utils.TokenAuth",],
  
}

  

源码实现过程:

服务端以authors为例:

 1、在AuthorModelView中查找as_view(),在本类中找不到,往上查找;

 2、父类:viewsets.ModelViewSet

1
2
3
4
5
6
7
8
9
10
11
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass

  3、其他几个父类没有as_view()和祖父类了,只能从GenericViewSet往上找;

1
2
3
4
5
6
7
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    """
    The GenericViewSet class does not provide any actions by default,
    but does include the base set of generic view behavior, such as
    the `get_object` and `get_queryset` methods.
    """
    pass

  4、最左边父类ViewSetMixin查找as_view(),找到了

  5、ViewSetMixin中的as_veiw()实际上返回了dispatch()

  6、再查找dispatch()方法,顺序:generics.GenericAPIView==>APIView==>dispatch()

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def dispatch(self, request, *args, **kwargs):
    """
    `.dispatch()` is pretty much the same as Django's regular dispatch,
    but with extra hooks for startup, finalize, and exception handling.
    """
    self.args = args
    self.kwargs = kwargs
    request = self.initialize_request(request, *args, **kwargs)
    self.request = request
    self.headers = self.default_response_headers  # deprecate?
 
    try:
        self.initial(request, *args, **kwargs)
 
        # Get the appropriate handler method
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(),
                              self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
 
        response = handler(request, *args, **kwargs)
 
    except Exception as exc:
        response = self.handle_exception(exc)
 
    self.response = self.finalize_response(request, response, *args, **kwargs)
    return self.response

  7、dispatch()中,先会执行self.initial()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def initial(self, request, *args, **kwargs):
    """
    Runs anything that needs to occur prior to calling the method handler.
    """
    self.format_kwarg = self.get_format_suffix(**kwargs)
 
    # Perform content negotiation and store the accepted info on the request
    neg = self.perform_content_negotiation(request)
    request.accepted_renderer, request.accepted_media_type = neg
 
    # Determine the API version, if versioning is in use.
    version, scheme = self.determine_version(request, *args, **kwargs)
    request.version, request.versioning_scheme = version, scheme
 
    # Ensure that the incoming request is permitted
    self.perform_authentication(request)
    self.check_permissions(request)
    self.check_throttles(request)

  8、initial()中会对过来的请求进行认证、授权、频率检测。

 

图标流程如下:

  

posted @   skyflask  阅读(303)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示