Django Restful Framework

摘要:
返回JSON数据Django源代码解释图TDA[Route matching to book]-->D{在HTTP请求中}D->JsonResolve可用于验证从数据返回的Json数据的访问频率。当使用列表转换时,应该使用safety=FalseRestful规范。1.使用API与用户通信。//API.example。com尽可能将API部署到私有域名(可能存在跨域问题)https:
你在浏览器中输入了一个地址的时候发生了什么事情?
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源码解读

Django Restful Framework第3张

request类中实现的其他方法

Django Restful Framework第4张

总结

现在我们可以在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:序列化时,不显示
		

反序列化

Django Restful Framework第5张

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团队开发的企业级应用前端集成解决方案。

免责声明:文章转载自《Django Restful Framework》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇通过MacOS的ssh远程打开linux的firefox(通过X11协议实现图形化显示)Vim Clutch | 面向脚踏板编程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

sqlserver 多行转一行

sql 例子: SELECT STUFF((SELECT ',' + CONVERT(VARCHAR, b.SCsinfoSourceId) FROM PZDataCsinfo b WHERE b.DId = a.PFId FOR XML PATH ('')), 1, 1, '') AS cids, *FROM PZFocusImg a WHERE a.P...

USB转UART相关芯片

CP210X 系类官网地址 CP2102参考外围电路 CP2102 Pin Definitions Name Pin # Type Description  说明 VDD 6 Power In Power Out 3.0–3.6 V Power Supply Voltage Input. 3.3 V Voltage Regulator...

【转载】 tensorflow gfile文件操作详解

 原文地址: https://zhuanlan.zhihu.com/p/31536538 ------------------------------------------------------------------------------- 一、gfile模块是什么 gfile模块定义在tensorflow/python/platform/gfil...

iptables raw表

参考文档:http://blog.chinaunix.net/uid-10915175-id-3381754.html iptables 5链:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING 4表:优先级由高到低raw-->mangle-->nat-->filter 如果PRROUTING链上既有...

JS 全自动检测禁止输入特定字符

项目中输入域,特别是文本输入域,一般都会禁用某些特殊字符,基于这个需求,实现了一个全局设置禁止输入特别字符的方法,核心代码: Array.from(document.querySelectorAll('input')).map(function(item){ // 检索所有输入域,使用者可以修订别的选择器 var excludes = ['"',"...

iOS/Android 浏览器(h5)及微信中唤起本地APP

在移动互联网,链接是比较重要的传播媒质,但很多时候我们又希望用户能够回到APP中,这就要求APP可以通过浏览器或在微信中被方便地唤起。 这是一个既直观又很好的用户体验,但在实现过程中会遇到各种问题: 如何解决未安装APP时的做好引导页 如何在微信中唤醒APP 在iOS9中如何处理universal link被用户误关的情况 如何解决Android各种机型...