0801 RESTAPI设计,DRF 序列化
1.内容回顾
1.restframework serializer(序列化)的简单使用
QuereySet([obj,obj,obj]) --> JSON格式数据
安装和导入:
pip install djangorestframework
from rest_framework import serializer
1.创建一个类,类一定要继承serializer.Serializers
2.chocie字段和FK字段都可以通过source来获取对应的值
3.多对多字段可以通过使用serializer.SerializerMethod
声明序列化器:
def get_tag(self, obj):
tag_list = []
for i in obj.tag.all():
tag_list.append(i.name)
return tag_list
(比较麻烦)
2.使用 ModelSerializer(简单)
和ORM绑定的序列化
通过配置class Meta:
model = 表名
fields = ['字段', ...]
depth = 1
2. 今日内容
1. RESTful风格API介绍
一、什么是RESTful
REST -- REpresentational State Transfer,英语的直译就是“表现层状态转移”。如果看这个概念,估计没几个人能明白是什么意思。
那下面就让我来用一句人话解释一下什么是RESTful:URL定位资源,用HTTP动词(GET,POST,PUT,DELETE)描述操作。
Resource:资源,即数据。
Representational:某种表现形式,比如用JSON,XML,JPEG等;
State Transfer:状态变化。通过HTTP动词实现。
REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”。
REST从资源得角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态。
所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性。
二、RESTful API设计
API与用户的通信协议 总是使用HTTPs协议。 域名 https://api.example.com 尽量将API部署在专用域名 https://example.org/api/ API很简单 版本 1. 将版本信息放在URL中,如:https://api.example.com/v1/ 2. 将版本信息放在请求头中。 路径 视网络上任何东西都是资源,均使用名词表示(可复数) https://api.example.com/v1/zoos https://api.example.com/v1/animals https://api.example.com/v1/employees method GET :从服务器取出资源(一项或多项) POST :在服务器新建一个资源 PUT :在服务器更新资源(客户端提供改变后的完整资源) PATCH :在服务器更新资源(客户端提供改变的属性) DELETE :从服务器删除资源 过滤 通过在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:指定筛选条件 状态码 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
错误处理 状态码是4xx时,应返回错误信息,error当做key。 {
error: "Invalid API key"
}
返回结果 针对不同操作,服务器向用户返回的结果应该符合以下规范 GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 PATCH /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档
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" }} 更多内容,请参考:阮一峰的Blog
二、基于Django实现RESTful API
1.RESTful API之url设计
路由分发:
在原先的URL中添加:url(r'api/', include(app01_urls)), include表示导入py文件
在 app01下新建路径文件:app01_urls.py
from django.conf.urls import urlfrom app01 import views
urlpatterns = [
url(r'article/', views.Article.as_view()),
url(r'article/(?P<pk>\d+)', views.ArticleDetail.as_view(), name='article-detail'),
url(r'school/(?P<id>\d+)', views.SchoolDetail.as_view(), name='school-detail111'),
# 评论
# url(r'comment_list/', ),
# url(r'add_comment/', ),
# url(r'delete_comment/', ),
# url(r'edit_comment/', ),
url(r'comment/', views.Comment.as_view()),
]
2.RESTful API之urls视图
针对4种请求方式,使用FBV
def comment(request):
if request.method == "GET":
return HttpResponse("获取评论")
elif request.method == "POST":
return HttpResponse("创建新评论")
elif request.method == "PUT":
return HttpResponse("修改评论")
elif request.method == "DELETE":
return HttpResponse("删除评论")
这样写的话,一个4层if判断,就会有很冗长的代码。不利与维护,推荐使用CBV方式
CBV方式
from django import viewsclass Comment(views.View):
def get(self, request):
return HttpResponse("获取评论")
def post(self, request):
return HttpResponse("创建新评论")
def put(self, request):
return HttpResponse("修改评论")
def delete(self, request):
return HttpResponse("删除评论")
三、 APIView
from rest_framework import APIView
class Comment(views.View):
pass
-------- 之前的写法 ↑ ----------
class APIView(views.View):
扩展的功能
self.request = Resquest(
self._request = request(Django的request)
)
self.request.data 封装好的数据属性,POST\PUT请求携带的数据都可以从这里取
pass
class Comment(APIView):
pass
1. APIView与View的区别
- APIView是View的子类
- 传递给请求处理程序的request实例是REST框架的请求实例,而不是Django的HttpRequest实例
- 处理程序返回的基于REST框架的Response,而不是Django的HttpResponse,视图函数将会管理内容协商,然后设置正确的渲染方式
- 任何APIException将会被捕捉,然后转换成合适的response对象
- 接收到的请求首先被认证,然后赋予相应的权限,然后通过节流器分发给相应的请求处理函数,类似.get()和.post()
APIView是专门写API的视图函数,结合serializers,非常方便做序列化!
关于APIView的源码解析,请参考文章:
https://blog.csdn.net/u013210620/article/details/79857654
取数据
get:
request._request ( 原request )
request.GET == request._request.GET
post:
request.data ( 得到 json 数据,也可得到 urlencode 数据)
都是 rest_framework APIView 的功劳,
如果使用 View , request.post( 只能得到 urlencode 的数据,不能得到 json 数据,只能从 request.body 中取)
3. serializer
1. ModelSerializer
1. 基于APIView实现的GET和POST
2. POST过来的数据进行校验
3. 保存数据
在app01下面创建一个文件,专门放序列化的 from app01.models import Comment, Article, School from rest_framework import serializers from rest_framework.validators import ValidationError # 序列化评论的类
class CommentSerializer(serializers.ModelSerializer): # content = serializers.CharField(error_messages={"required": '内容不能为空'}) # article_detail = serializers.SerializerMethodField(read_only=True) # 用于做校验的钩子函数,类似于form组件的clean_字段名 def validate_content(self, value):
if '草' in value:
raise ValidationError('不符合社会主义核心价值观!')
else:
return value # 全局的钩子
# def validate(self, attrs):
# # self.validated_data # 经过校验的数据 类似于form组件中的cleaned_data
# # 全局钩子
# pass class Meta: model = Comment
fields = "__all__"
# depth = 1 # 定义额外的参数
extra_kwargs = {
"content": {
"error_messages": {
"required": '内容不能为空',
}
}, "article": {
"error_messages": {
"required": '文章不能为空'
}
}
} # 文章的序列化类
class ArticleModelSerializer(serializers.ModelSerializer): # type_str = serializers.CharField(source='get_type_display', read_only=True) class Meta: model = Article # 绑定的ORM类是哪一个 fields = "__all__" # ["id", "title", "type"] # depth = 1 # 官方推荐不超过10层 # 文章超链接序列化 class ArticleHyperLinkedSerializer(serializers.HyperlinkedModelSerializer): school = serializers.HyperlinkedIdentityField(view_name='school-detail111', lookup_url_kwarg='id') class Meta: model = Article # 绑定的ORM类是哪一个 fields = ["id", "title", "type", "school"] # 学校的序列化 class SchoolSerializer(serializers.ModelSerializer): class Meta: model = School fields = "__all__" 参数解释: source 表示来源 lookup_field 表示查找字段 lookup_url_kwarg 表示路由查找的参数,pk表示主键 view_name 它是指urls定义的name值,一定要一一对应。
models.py
from django.db import models
# 文章表
class Article(models.Model):
title = models.CharField(max_length=32, unique=True, error_messages={"unique": "文章标题不能重复"})
# 文章发布时间
# auto_now每次更新的时候会把当前时间保存
create_time = models.DateField(auto_now_add=True)
# auto_now_add 第一次创建的时候把当前时间保存
update_time = models.DateField(auto_now=True)
# 文章的类型
type = models.SmallIntegerField(
choices=((1, "原创"), (2, "转载")),
default=1
)
# 来源
school = models.ForeignKey(to='School', on_delete=models.CASCADE)
# 标签
tag = models.ManyToManyField(to='Tag')
# 文章来源表
class School(models.Model):
name = models.CharField(max_length=16)
# 文章标签表
class Tag(models.Model):
name = models.CharField(max_length=16)
# 评论表
class Comment(models.Model):
content = models.CharField(max_length=128)
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
GET:
class Comment(APIView):
def get(self, request):
res = {"code": 0}
# print(self.request) # rest framework封装好的request
# print(self.request.data)
# print(self.request._request.GET.get("age")) # Django原来的request对象
# 数据
all_comment = models.Comment.objects.all()
# 序列化
ser_obj = app01_serializers.CommentSerializer(all_comment, many=True)
res["data"] = ser_obj.data
return Response(res)
POST:
def post(self, request):
res = {"code": 0}
# 去提交的数据
comment_data = self.request.data
# 对用户提交的数据做校验
ser_obj = app01_serializers.CommentSerializer(data=comment_data)
if ser_obj.is_valid():
# 表示数据没问题,可以创建
ser_obj.save() #创建数据,写入数据库
else:
# 表示数据有问题
res["code"] = 1
res["error"] = ser_obj.errors
return Response(res)
return HttpResponse("创建新评论")
#文章CBV
class Article(APIView):
def get(self,request):
res={"code":0}
all_article = models.Article.object.all() #显示超链接的URL需要的参数,表示上下文
ser_obj = app01_serializers.ArticleHyperLinkedSerializer(all_article, many=True, context={'request': request})
res["data"] = ser_obj.data
return Response(res)
def post(self, request):
res = {"code": 0}
ser_obj = app01_serializers.ArticleModelSerializer(data=self.request.data)
if ser_obj.is_valid():
ser_obj.save()
else:
res["code"] = 1
res["error"] = ser_obj.errors
return Response(res)
# 文章详情CBV
class ArticleDetail(APIView):
def get(self, request, pk):
res = {"code": 0}
article_obj = models.Article.objects.filter(pk=pk).first()
# 序列化
ser_obj = app01_serializers.ArticleHyperLinkedSerializer(article_obj, context={'request': request})
res["data"] = ser_obj.data
return Response(res)
# 学校详情CBV
class SchoolDetail(APIView):
def get(self, request, id):
res = {"code": 0}
school_obj = models.School.objects.filter(pk=id).first()
ser_obj = app01_serializers.SchoolSerializer(school_obj, context={'request': request})
res["data"] = ser_obj.data
return Response(res)
Response:
配置之后:浏览器才可访问; rest_framework 是django的一个app!
可发 get / post 请求 !!
rest framework 引入了Response对象,它是一个TemplateResponse类型,并根据客户端需求正确返回需要的类型。
使用前,需要导入模块
from rest_framework.response import Response
语法:
return Response(data) # 根据客户端的需求返回不同的类型。
0801 RESTAPI设计,DRF 序列化的更多相关文章
- python 全栈开发,Day95(RESTful API介绍,基于Django实现RESTful API,DRF 序列化)
昨日内容回顾 1. rest framework serializer(序列化)的简单使用 QuerySet([ obj, obj, obj]) --> JSON格式数据 0. 安装和导入: p ...
- 揭开DRF序列化技术的神秘面纱
在RESTful API中,接口返回的是JSON,JSON的内容对应的是数据库中的数据,DRF是通过序列化(Serialization)的技术,把数据模型转换为JSON的,反之,叫做反序列化(dese ...
- DRF 序列化组件
Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...
- python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)
昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...
- Django的DRF序列化方法
安装rest_framework -- pip install djangorestframework -- 注册rest_framework序列化 -- Python--json -- 第一版 用v ...
- drf序列化器与反序列化
什么是序列化与反序列化 """ 序列化:对象转换为字符串用于传输 反序列化:字符串转换为对象用于使用 """ drf序列化与反序列化 &qu ...
- drf序列化及反序列化
假如把drf看做一个汉堡包,我们之前讲的模块属于汉堡包前面的盖盖(请求模块.渲染模块)和底底(异常模块.解析模块.响应模块),但是真正中间的夹心没有讲,那么今天我就和大家来看一下汉堡包的夹心(序列化及 ...
- drf序列化和反序列化
目录 drf序列化和反序列化 一.自定义序列化 1.1 设置国际化 二.通过视图类的序列化和反序列化 三.ModelSerializer类实现序列化和反序列化 drf序列化和反序列化 一.自定义序列化 ...
- DRF 序列化组件 模型层中参数补充
一. DRF序列化 django自带有序列化组件,但是相比rest_framework的序列化较差,所以这就不提django自带的序列化组件了. 首先rest_framework的序列化组件使用同fr ...
随机推荐
- linux 分卷压缩命令
linux 分卷压缩命令 1.使用tar分卷压缩 格式 tar cvzf - filedir | split -d -b 50m - filename 样例: tar cvzf - ./picture ...
- 关于dll的pdb文件的小贴士
.pdb文件最好与生成它的.dll文件放在一起,这样调试的时候才有可能跟踪进dll的内部函数里.
- C++ 虚析构(virtual destructor)原理
注意:本文仅为个人理解,可能有误! 先看一段代码: #include <iostream> using namespace std; class CBase{ public: CBase( ...
- PHP和Java 加解密
http://www.jb51.net/article/64961.htm http://www.jb51.net/article/129218.htm http://www.jb51.net/art ...
- A guide to analyzing Python performance
来源:http://www.huyng.com/posts/python-performance-analysis/ While it's not always the case that every ...
- iOS学习笔记(一)——ios搭建开发环境
好久就想试水IOS开发了,由于开发环境限制,一直局限于理论和虚拟机,近来入手了MacBook Pro,也来尝尝鲜,笔者也是现学现总结,如果有不足,请指正. IOS开发必备MAC OS X 另加一部iP ...
- NoSQL-MongoDB with python
前言: MongoDB,文档存储型数据库(document store).NoSQL数据库中,它独占鳌头,碾压其他的NoSQL数据库. 使用C++开发的,性能仅次C.与redis一样,开源.高扩展.高 ...
- 【BZOJ1811】[Ioi2005]mea 乱搞
[BZOJ1811][Ioi2005]mea Description 考虑一个非递减的整数序列 S1,....Sn+1(Si<=Si+1 1<=i<=n). 序列M1...Mn是定义 ...
- EasyNVR摄像机无插件直播按需RTSP拉流播放流程详解
1.背景需求 有许多客户现场,有许多设备但是不需要一直向设备端取视频流,因为在用户不观看的情况下,还在获取视频资源,一方面大大的浪费了网络带宽资源,一方面对设备服务器要求也较高,用户成本就要提高,这是 ...
- ActiveMQ5.10.2版本配置JMX
ActiveMQ的特性之一是很好的支持JMX.通过JMX MBeans可以很方便的监听和控制ActiveMQ的broker. 鉴于官方网站提供的JMX特性说明对于远程访问的配置流程不是很完整,笔者在实 ...