• Django drf:cbv源码、resful规范及接口、drf使用、response源码、序列化


     本文目录:

    一、cbv源码分析

    二、resful规范

    三、django中写resful的接口

    四、drf写resful的接口及APIVIew源码分析

    五、drf之序列化

    一、cbv源码分析

      -CBV和FBV

        1.在views中写一个类,继承views里面写get方法,post方法

        2.在路由中配置:url(r'^test/',views.Test.as_view()),实际上上第二个参数位置,放的还是一个函数内存地址

        3.当请求来了,就会执行第二个参数(request,参数),本质上执行views()

        4.views内部调用了dispatch()方法

        5.dispatch分发方法,根据请求方式不同,执行的方法不同

    二、resful规范

      -什么是restful?

        1.REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”

        2.REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态

        3.所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性

        4.对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture

      

      -10个规范

        1:与后台做交互,通常使用https

        2:域名:

          https://api.baidu.com(存在跨域问题)

          https://baidu.com/api/

        3:版本:

            -https://www.baidu.com/api/v1
            -https://www.baidu.com/api/v2

        4.路径:视网上任何东西都是资源,全使用名词表示(可复数)

          -https://api.example.com/v1/books
          不是:https://api.example.com/v1/delete_one_book

        5.method:

          -https://api.example.com/v1/books  get请求,获取所有书
               -https://api.example.com/v1/books  post请求,新增一本书
               -https://api.example.com/v1/book/1  delete请求,删除一本书
               -https://api.example.com/v1/book/1  delete请求,获取id为1的这本书
               -https://api.example.com/v1/book/1  put/patch请求,修改id为1的这本书

        6.过滤,通过在url上传参的形式的传递搜索条件

          -https://api.example.com/v1/books?limit=10:只拿前10本
               -https://api.example.com/v1/books?price=10:只拿价格为10的书

        7.状态码:

    200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
    201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    204 NO CONTENT - [DELETE]:用户删除数据成功。
    400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
    401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
    404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
    406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
    410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
    422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
    500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    
    更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

        8.错误处理,应返回错误信息,error当做key

          {
               status:101,
                          errors:'您没有权限操作这个事'
                          }

        9.返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范

          GET/collection:返回资源对象的列表(数组)

          GET/collection/resource:返回单个资源对象

          POST/collection:返回新生成的资源对象

          PUT/collection/resource:返回完整的资源对象

          PATH/collection/resource:返回完整的资源对象

          DELETE/collection/resource:返回一个空文档

        10.返回结果中提供链接(获取一本书)

          {
                id:1
                name:lxx
                price:12
                  publish:www.xx.com/api/v1/publish/1
                }

    三、django中写resful的接口

      -请求地址带反斜杠出现的问题(中间件)

        -如果请求地址是/user,路由中配置成‘/user/’,匹配不上,中间件会自动在后面加/,再去匹配,能匹配成功,重定向到/user/,加了 / 还匹配不上,就报错

        -django.middleware.common.CommonMiddleware

      -基于Django实现

    #路由

    urlpatterns = [
        url(r'^users/$', views.Users.as_view()),
        url(r'^users2/$', views.user2),
    
    ]

    #视图函数

    import json
    
    def  user2(request):
        if request.method=='GET':
            dic = {'status':200,'name': 'lqz2', 'age': 18}
            return HttpResponse(json.dumps(dic))
        elif request.method=='POST':
            dic = {'status': 200, 'msg': '修改成功'}
            return JsonResponse(dic)
    
    class Users(View):
        def get(self, request):
            dic = {'status':200,'name': 'lqz', 'age': 18}
            return HttpResponse(json.dumps(dic))
    
        def post(self, request):
            dic = {'status': 200, 'msg': '修改成功'}
            return JsonResponse(dic)

    四、drf写resful的接口及APIVIew源码分析

      1.先安装,pip3 install djangorestframework    

        方式一:pip3 install djangorestframework

        方式二:pycharm图形化界面安装

        方式三:pycharm命令行下安装(装在当前工程所用的解释器下)

      2.djangorestframework的APIView分析

     @classmethod
        def as_view(cls, **initkwargs):
            """
            Store the original class on the view function.
    
            This allows us to discover information about the view when we do URL
            reverse lookups.  Used for breadcrumb generation.
            """
            if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
                def force_evaluation():
                    raise RuntimeError(
                        'Do not evaluate the `.queryset` attribute directly, '
                        'as the result will be cached and reused between requests. '
                        'Use `.all()` or call `.get_queryset()` instead.'
                    )
                cls.queryset._fetch_all = force_evaluation
    
            view = super(APIView, cls).as_view(**initkwargs)
            view.cls = cls
            view.initkwargs = initkwargs
    
            # Note: session based authentication is explicitly CSRF validated,
            # all other authentication is CSRF exempt.
            return csrf_exempt(view)
    as_view方法
     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
    dispatch
        def initialize_request(self, request, *args, **kwargs):
            """
            Returns the initial request object.
            """
            parser_context = self.get_parser_context(request)
    
            return Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
    initialize_request
        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)
    initial方法(内部调用认证,权限和频率)

      

      3.djangorestframework的Request对象简单介绍

      

      4.基于drf写接口,写cbv

    # 基于drf写接口,写cbv
    class DrfTest(APIView):
        def get(self, request, *args, **kwargs):
            # request是封装之后的request了,原来的request是request._request
            print(type(request._request))
            print(type(request))
            # 问:当前request对象并没有这些属性,但是能打印出来,为什么?
            # getattr
            print(request.method)
            print(request.POST)
            print(request.GET)
            # 就相当于:
            print(request.query_params)
            print(request._request.GET)
            response = {'status': 100, 'errors': None}
            response['users'] = user_list
            # 用drf的Response,可以通过请求客户端来判断返回数据格式是什么样的
            return Response(response)
            # return JsonResponse(response)
    
        def post(self, request, *args, **kwargs):
            # post 提交的数据,urlencode,formdate,json格式,都能从data中取出来
            name = request.data.get('name')
            # request.FILES
            print(name)
            return HttpResponse('ok')

    五、drf之序列化

      干什么用的?把python中的对象,转成json格式字符串

      1.写一个类继承

    from rest_framework import serializers
    
    
    class BookSerializer(serializers.Serializer):
        id = serializers.CharField()
        name = serializers.CharField(source='title')
        price = serializers.CharField()
        publish_name = serializers.CharField(source='publish')
        author_name = serializers.CharField(source='authors')
        def get_author_name(self,obj):
            return {'name':obj.name,'age':obj.age}

      2.路由配置

    from django.conf.urls import url
    from django.contrib import admin
    from app import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^books/', views.Books.as_view()),
        url(r'^book/(?P<id>d+)', views.Book.as_view()),
    ]

      3.views视图函数

    from django.shortcuts import render
    
    # Create your views here.
    
    from app.MySer import BookSerializer
    from django.views import View
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app import models
    
    class Books(APIView):
        def get(self, request, *args, **kwargs):
            response = {'status': 100, 'msg': '成功'}
            book_list = models.Book.objects.all()
            # 第一个参数是要序列化的queryset对象,如果序列化多条,必须指定many=True
            # 问?什么情况下many=False,instance=单个对象的时候
            book_ser = BookSerializer(book_list, many=True)
            print(book_ser.data)
            response['books'] = book_ser.data
            return Response(response)
    
    
    class Book(APIView):
        def get(self,request, id):
            response = {'status':100,'msg':'成功'}
            book = models.Book.objects.filter(pk=id).first()
            book_ser = BookSerializer(book,many=False)
            response['book'] = book_ser.data
            return Response(response)

    -总结:
       # 1 变量名和source指定的值不能一样
       # 2 source='publish.name'还支持继续 .
       # 3 source 还支持方法(没用)
       # 4 支持写方法,如下

     #方法一定传一个参数,是当前book对象
     publish_dic=serializers.SerializerMethodField()
         def get_publish_dic(self,obj):
         # 猜,这个obj应该是谁,当前book对象
         return {'id':obj.publish.pk,'name':obj.publish.name}

    补充点:在线格式化json ==> https://www.json.cn/

  • 相关阅读:
    日记
    没有起得晚的周末,希望今天能做一些什么
    怎么就这么喜欢测软件呢?—— Google Calendar农历问题
    Sharepoint带自定义属性的FieldType
    自己使用Outlook 2003 的一些小技巧
    Xml名称空间
    c# jingtailei 静态成员
    select count
    varchar nvarchar(转)
    linq 笔记(1)
  • 原文地址:https://www.cnblogs.com/wuzhengzheng/p/10408905.html
Copyright © 2020-2023  润新知