zoukankan      html  css  js  c++  java
  • Django Restful Framework

    你在浏览器中输入了一个地址的时候发生了什么事情?

    1.HOST 
    2.DNS
    3.HTTP/HTTPS协议 发送一个协议
    4.进入了实现了WSGI协议的服务器(wsgiref uwsgi(C语言实现,多线程,多进程,PHP,TOMCAT))
    5.请求进入Django
    6. 前后端不分离:中间件->路由分发->对应的视图函数->找到模板,渲染数据-> 返回模板的字符串
    	前后端分析:中间件->路由分发->返回JSON数据
    

    Django源代码解读

    Django源码解读

    CBV的执行流程

    graph TD A[路由匹配到book]-->B(执行as_view) B --> C[执行dispath方法] C --> D{在HTTP请求中} D -->|是HTTP请求| E[利用反射获得该请求内存地址,并执行] D -->|不是HTTP请求| F[405错误方法不允许]

    应用

    我们也可以重写dispatch方法,做登陆验证,或者请求限制,做访问频率验证

    返回数据的Json数据时候可以使用JsonResonpe 使用列表转换的时候,要带上safe=False

    Restful规范

    1.使用API与用户通讯,总是使用https
    2.域名有区分

    3.版本
    可以放在URL地址中
    也可以放在请求头中(利用request.Meta进行取值)

    4.路径,路径上的任何参数都是资源,均使用名词
    5.通过METHOD区分不同的操作
    GET :从服务器取出资源(一项或多项)
    POST :在服务器新建一个资源
    PUT :在服务器更新资源(客户端提供改变后的完整资源)
    PATCH :在服务器更新资源(客户端提供改变的属性)
    DELETE :从服务器删除资源
    6.过滤,通过在url上传参的形式传递搜索条件
    https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
    https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
    https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
    https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
    https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件

    7.状态码

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

    8.错误处理,应该返回错误信息

    {
        ``error: ``"Invalid API key"
    }
    

    9.返回结果

    GET /collection:返回资源对象的列表(数组)
    GET /collection/resource:返回单个资源对象
    POST /collection:返回新生成的资源对象
    PUT /collection/resource:返回完整的资源对象
    PATCH /collection/resource:返回完整的资源对象
    DELETE /collection/resource:返回一个空文档
    

    10.Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么

    {"link": {
      "rel":   "collection https://www.example.com/zoos",
      "href":  "https://api.example.com/zoos",
      "title": "List of zoos",
      "type":  "application/vnd.yourformat+json"
    }}
    
    

    drf 应用

    ​ -安装:

    		-pip3 install djangorestframework
    
    
    

    使用

    		-第一步,再写视图,都写cbv
    			from rest_framework.views import  APIView
    			class Books(APIView):
    				pass
    		-在setting中配置
    			INSTALLED_APPS= [
    					。。。。。
    				'rest_framework'
    			]
    
    	-源码分析:
    		继承了APIView 之后:
    			-1 所有的请求都没有csrf的认证了
    			-2 在APIView中as_view本质还是调用了父类的as_view(View的as_view)
    			-3 as_view中调用dispatch  -----》这个dispatch是APIView的dispatch
    
    graph TD A[路由匹配到book]-->B(执行as_view) B --> C[执行dispath方法] C --> D{在HTTP请求中} D -->|是HTTP请求| E[利用反射获得该请求内存地址] D -->|不是HTTP请求| F[405错误方法不允许]

    DRF源码解读

    request类中实现的其他方法

    总结

    现在我们可以在views中一旦继承了drf的APIview可以调用

    		-1 原生的request是self._request
    		-2 取以post形式提交的数据,从request.data中取(urlencoded,formdata,json格式)
    		-3 query_params 就是原生request的GET的数据
    		-4 上传的文件是从FILES中取
    		-5 (重点)其他的属性,直接request.属性名(因为重写了__getattr__方法)
    

    序列化组件的使用

    		-使用drf的序列化组件
    			-1 新建一个序列化类继承Serializer
    			-2 在类中写要序列化的字段
    

    简单使用

    模型层

    from django.db import models
    
    
    # Create your models here.
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish_date = models.DateField(null=True)
        kind = models.IntegerField(choices=((0, '文学类'), (1, '情感类')), default=1, null=True)
        publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE, null=True)
        authors = models.ManyToManyField(to='Author')
    
        def __str__(self):
            return self.name
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
    
        def __str__(self):
            return self.name
    
    

    自定义序列化器

    from rest_framework import serializers
    
    
    class BookSerializer(serializers.Serializer):
        name = serializers.CharField()
        price = serializers.CharField()
    
    

    视图层

    # Create your views here.
    from rest_framework.response import Response
    from rest_framework.views import APIView
    
    from app01 import models
    from app01.app01serialier import BookSerializer
    
    
    class Books(APIView):
    
        def get(self, request):
            response = {'code': 100, 'msg': '查询成功'}
            books = models.Book.objects.all()
            # 如果序列化是多个,就要传入many=true,序列化一条可以不写
            bookser = BookSerializer(books, many=True)
            response['data'] = bookser.data
            return Response(response)
    
    

    序列化的高级用法

    souce,指定数据来源

    from rest_framework import serializers
    
    
    class BookSerializer(serializers.Serializer):
        book_name = serializers.CharField(source='book')
        price = serializers.CharField()
        publish = serializers.CharField(source='publish.name')
    
    
    HTTP 200 OK
    Allow: GET, HEAD, OPTIONS
    Content-Type: application/json
    Vary: Accept
    
    {
        "code": 100,
        "msg": "查询成功",
        "data": [
            {
                "book_name": "红楼梦",
                "price": "14.00",
                "publish": "北方出版社"
            },
            {
                "book_name": "水浒传",
                "price": "19.00",
                "publish": "南方出版社"
            }
        ]
    }
    

    source,指定方法名

    from rest_framework import serializers
    
    
    class BookSerializer(serializers.Serializer):
        book_name = serializers.CharField(source='book')
        price = serializers.CharField()
        publish = serializers.CharField(source='publish.name')
        book_class = serializers.CharField(source='get_kind_display')
    
    

    返回结果

    HTTP 200 OK
    Allow: GET, HEAD, OPTIONS
    Content-Type: application/json
    Vary: Accept
    
    {
        "code": 100,
        "msg": "查询成功",
        "data": [
            {
                "book_name": "红楼梦",
                "price": "14.00",
                "publish": "北方出版社",
                "book_class": "情感类"
            },
            {
                "book_name": "水浒传",
                "price": "19.00",
                "publish": "南方出版社",
                "book_class": "情感类"
            }
        ]
    }
    

    序列化中绑定方法

        publish_detail = serializers.SerializerMethodField()
    
        def get_publish_detail(self, obj):
            return {'name': 'obj.publish.name', 'city': 'obj.publish.city'}
    
    	-read_only:反序列化时,不传
    	-write_only:序列化时,不显示
    		
    

    反序列化

    instance 是我序列化的对象,data是要反序列化的数据,因此反序列化的时候要用关键字参数传值data = request.data

    如果要使用反序列化必须要重写create方法

        def create(self, validated_data):
            ret = models.Book.objects.create(**validated_data)
            return ret
    
        def post(self,request):
            bookser = BookSerializer(data=request.data)
            if bookser.is_valid():
                # 检验通过的数据才会放在
                ret = bookser.create(bookser.validated_data)
    

    根据表模型创建序列化器

    只要在序列化函数中定义一个meta类,在类中的字段是固定给的

    • model 指定要绑定的模型表
    • field 指定要绑定的字段,__all__代表全部字段
    • exclude 代表要排除的字段
    • depth 存在连表的情况下,要把几个表中的数据返回,返回的数据时列表中所有的数据

    序列化类

    
    class BookSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = models.Book
            fields = ('__all__')
            exclude = ('name')
            depth = 1 # 表的数据没有控制,会把所有的数据都拿出来
    

    视图层

    
    class Books(APIView):
    
        def get(self, request):
            response = {'code': 100, 'msg': '查询成功'}
            books = models.Book.objects.all()
            # 如果序列化是多个,就要传入many=true,序列化一条可以不写
            bookser = BookSerializer(books, many=True)
            response['data'] = bookser.data
            return Response(response)
        def post(self,request):
            bookser = BookSerializer(data=request.data)
            if bookser.is_valid():
                bookser.save()
    

    钩子函数

    局部钩子使用validate__表名定义

    全局钩子使用validata定义

    def validate_name(self,value):
    
            print(value)
            raise exceptions.ValidationError('不能以sb开头')
            # if value.startswith('sb'):
            #     raise ValidationError('不能以sb开头')
            # return value
    
        def validate(self,attrs):
            print(attrs)
            # if attrs.get('price')!=attrs.get('xx'):
            #     raise exceptions.ValidationError('name和price相等,不正常')
            return attrs
    

    代码折叠

    <details>
      <summary>什么是iuap design</summary>
      iuap design 是用友网络FED团队开发的企业级应用前端集成解决方案。
    </details>
    
    <details>
      <summary>什么是tinper</summary>
    
    `tinper`是开源前端技术平台。
    </details>
    
    什么是iuap design iuap design 是用友网络FED团队开发的企业级应用前端集成解决方案。
  • 相关阅读:
    Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型
    如何防止网站短信验证码被攻击
    JS和C#.NET获取客户端IP
    H5案例分享:移动端touch事件判断滑屏手势的方向
    防止asp.net连续点击按钮重复提交
    JS正则表达式验证手机号和邮箱
    sql server查询数据库的大小和各数据表的大小
    大型分布式网站架构技术总结
    一个高逼格开发者必须理解的大型分布式网站的几点概念
    C# 在程序中控制IIS服务或应用程序池关闭重启
  • 原文地址:https://www.cnblogs.com/ruhai/p/11123784.html
Copyright © 2011-2022 走看看