restful规范 drf初识 序列化
前后端分离
前后端分离并非仅仅是一种开发模式,而是一种架构模式(前后端分离架构)。千万不要以为只有在写代码的时候把前端和后端分开就是前后端分离了,这样的理解太片面了。前后端分离是需要区分前后端项目的,即前端项目和后端项目是两个项目,放在两个不同的服务器,需要独立部署,两个不同的工程,两个不同的代码库,两组不同的开发人员。前后端开发工程师需要约定交互的接口,实现并行开发。而在开发结束之后,前端项目和后端项目都需要进行独立部署,前端通过AJAX来调用HTTP请求,调用后端的RESTFUL API。前端只需要关注页面的样式与动态数据的解析和渲染,不用关心数据是怎么产生的;后端则专注于具体的业务逻辑,返回前端展现所需要的业务数据即可。
什么是DRF?
DRF从本质上来讲, 它就是一个Django的App, 有了这样一个App, 我们就可以更好的设计出符合RESTful
DRF从本质上来讲, 它就是一个Django的App, 有了这样一个App, 我们就可以更好的设计出符合RESTful规范的web应用 实际上, 即便没有DRF, 我们也能够自行设计出符合RESTful规范的web应用,是一个框架
为什么要使用DRF?
DRF就是这样一个优秀的工具, 另外, 它不仅能够帮助我们快速的设计出符合RESTful规范的接口, 还提供了诸如 认证 , 权限 等等其他强大的功能.使用了drf之后,可以快速帮我们开发restful规范来开发接口
drf组件的功能:
+ 根据请求方式不同做不同操作 get/post/put/patch/delete
+ 视图,继承APIView(在内部apiview继承了django的View)
+ 解析器,解析请求体中的数据,将其变成我们想要的格式。request.data,query_params
+ 序列化,对对象或对象列表(queryset)进行序列化操作以及表单验证的功能。
+ 渲染器,渲染页面
记忆:请求到来之后,先执行视图的dispatch方法。
1. 视图
2. 版本处理
3. 认证
4. 权限
5. 节流(频率限制)
6. 解析器
7. 筛选器
8. 分页
9. 序列化
10. 渲染
DRF的应用场景
参与前后端分离项目、参与为app写接口时,用drf会比较方便。
restful规范
https://www.cnblogs.com/Erik_Xu/p/9011013.html
RESTful是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
REST是Representational State Transfer的缩写,是Roy Thomas Fielding在他2000年的博士论文中提出的。其提出的设计概念和准则为:
\1. 网络上的所有事物都可以抽象为资源
\2. 每个资源都应该有唯一的标识(identifier),对资源的操作不会改变标识
\3. 所有的操作都是无状态的
\4. 使用标准方法(GET、POST、PUT、PATCH、DELETE)操作资源
http://127.0.0.1:8000/info/
get,获取数据
post,添加
put,更新
delete,删除
基于django可以实现遵循restful规范的接口开发:
- FBV,可以实现比较麻烦。
- CBV,相比较简答根据method做的了不同的区分。
安装DRF
pip3 install djangorestframework
使用DRF步骤
先注册app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework'#注册app
]
写路由
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^drf/info/', views.DrfInfoView.as_view()),
]
写视图
from rest_framework.views import APIView#必须
from rest_framework.response import Response#必须
class DrfInfoView(APIView):
def get(self,request,*args,**kwargs):
data = [
{'id': 1, 'title': '震惊了...王阳居然...', 'content': '...'},
{'id': 2, 'title': '震惊了...王阳居然...', 'content': '...'},
]
return Response(data)
drf框架总结
不基于drf也可以实现restful规范来开发接口程序。
使用了drf之后,可以快速帮我们开发restful规范来开发接口。
利用postmam自己测试
用工具模拟前端发请求:postman
怎么用
利用drf对数据库增删改查
准备文章表
from django.db import models
class Category(models.Model):
"""
文章分类
"""
name = models.CharField(verbose_name='分类',max_length=32)
class Article(models.Model):
"""
文章表
"""
title = models.CharField(verbose_name='标题',max_length=32)
summary = models.CharField(verbose_name='简介',max_length=255)
content = models.TextField(verbose_name='文章内容')
category = models.ForeignKey(verbose_name='分类',to='Category')
x-www-urlencoded 键值对形式发送
request.body: name=alex&age=19&gender=12#发送过来的原始数据
request.POST: {'name': ['alex'], 'age': ['19'], 'gender': ['12']}#只会解析上面这个
json 形式发送
request.body: b'{"ID":1,"name":"Alex","age":19}'
request.POST: 没有值
注意 我们用restful规范 一般都是发json形式数据 所有我们用request.body
接收
注意我们接收的是字节 request.body: b'{"ID":1,"name":"Alex","age":19}'
drf 有一个方法 request.data
可以将字节 b'{"ID":1,"name":"Alex","age":19}'
转化为字典{"ID":1,"name":"Alex","age":19}
创建一个文章分类
url
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^drf/category/', views.DrfCategoryView.as_view()),
]
view
from api import models
class DrfCategoryView(APIView):
#前端发送的是json数据 request.data可以将其转化为字典
def post(self,request,*args,**kwargs):
"""增加一条分类信息"""
models.Category.objects.create(**request.data)
return Response('成功')
获取所有的文章分类
url
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^drf/category/', views.DrfCategoryView.as_view()),
]
因为是restful规范所以 url是一个
view
from api import models
class DrfCategoryView(APIView):
def get(self,request,*args,**kwargs):
"""获取所有文章分类"""
queryset = models.Category.objects.all().values('id','name')
data_list = list(queryset)#转化为列表
return Response(data_list)
获取一条文章分类的详细信息
url
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^drf/category/$', views.DrfCategoryView.as_view()),
url(r'^drf/category/(?P<pk>\d+)/$', views.DrfCategoryView.as_view()),
]
view
from api import models
from django.forms.models import model_to_dict#对象转字典用的
class DrfCategoryView(APIView):
def get(self,request,*args,**kwargs):
"""获取所有文章分类/单个文章分类"""
pk = kwargs.get('pk')
if not pk:
queryset = models.Category.objects.all().values('id','name')
data_list = list(queryset)
return Response(data_list)
else:#获取一条
category_object = models.Category.objects.filter(id=pk).first()
data = model_to_dict(category_object)#转化为字典
return Response(data)
文章分类的更新和删除
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^drf/category/$', views.DrfCategoryView.as_view()),
url(r'^drf/category/(?P<pk>\d+)/$', views.DrfCategoryView.as_view()),#nb
]
view
from api import models
from django.forms.models import model_to_dict
class DrfCategoryView(APIView):
def delete(self,request,*args,**kwargs):
"""删除"""
pk = kwargs.get('pk')
models.Category.objects.filter(id=pk).delete()
return Response('删除成功')
def put(self,request,*args,**kwargs):
"""更新"""
pk = kwargs.get('pk')
models.Category.objects.filter(id=pk).update(**request.data)
return Response('更新成功')
drf的序列化
序列化器作用:
1.进行数据的校验
2.对数据对象进行转换
序列化: 模型类对象 -----> python字典 用于输出, 返回给前端使用
反序列化: 前端传送的数据 -------> 经过验证 -----> python的字典 用于输入 接受前端数据时使用
序列化器作用: 帮助我们进行序列化, 反序列化
获取一条文章分类和所有
url
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^new/category/$', views.NewCategoryView.as_view()),
url(r'^new/category/(?P<pk>\d+)/$', views.NewCategoryView.as_view()),
]
url其实没什么变化
view
from rest_framework import serializers
class NewCategorySerializer(serializers.ModelSerializer):#必须要 用于序列化
class Meta:
model = models.Category
# fields = "__all__" #所有字段
fields = ['id','name']
class NewCategoryView(APIView):
def get(self,request,*args,**kwargs):
pk = kwargs.get('pk')
if not pk:
queryset = models.Category.objects.all()
ser = NewCategorySerializer(instance=queryset,many=True)
return Response(ser.data)
else:#单条many=False
model_object = models.Category.objects.filter(id=pk).first()
ser = NewCategorySerializer(instance=model_object, many=False)
return Response(ser.data)
ps有了序列化 我们就自己不要 转字典 转列表了 哈哈哈哈
以前获取所有文章 data_list = list(queryset)#转化为列表
现在不用了
文章分类的编辑和更新
drf还给了我们一个好功能 数据校验 在文章的编辑和更新可以看出来
from rest_framework import serializers
class NewCategorySerializer(serializers.ModelSerializer):
class Meta:
model = models.Category
# fields = "__all__"
fields = ['id','name']
class NewCategoryView(APIView):
#增加
def post(self,request,*args,**kwargs):
ser = NewCategorySerializer(data=request.data)#效验
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)#没事数据报错
#更新
def put(self,request,*args,**kwargs):
pk = kwargs.get('pk')
category_object = models.Category.objects.filter(id=pk).first()
ser = NewCategorySerializer(instance=category_object,data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)
文章分类的删除
from rest_framework import serializers
class NewCategorySerializer(serializers.ModelSerializer):
class Meta:
model = models.Category
# fields = "__all__"
fields = ['id','name']
class NewCategoryView(APIView):
def delete(self,request,*args,**kwargs):
pk = kwargs.get('pk')
models.Category.objects.filter(id=pk).delete()
return Response('删除成功')
总结
-
什么是前后端分离?
-
drf组件
帮助们在django框架基础上快速搭建遵循restful规范接口的程序。
-
drf组件的功能
- 解析器,解析请求体中的数据,将其变成我们想要的格式。request.data
- 序列化,对对象或对象列表(queryset)进行序列化操作以及表单验证的功能。
- 视图,继承APIView(在内部apiview继承了django的View)
-
postman
模拟浏览器进行发送请求
-
查找模板的顺序
优先根目录下:templates 根据app的注册顺序去每个app的templates目录中找。
-
在URL的最后添加终止符
练习对文章表的增删改查
查询所有文章 和单条
modul
from django.db import models
class Category(models.Model):
"""
文章分类
"""
name = models.CharField(verbose_name='分类',max_length=32)
class Article(models.Model):
"""
文章表
"""
status_choices = (
(1,'发布'),
(2,'删除'),
)
status = models.IntegerField(verbose_name='状态',choices=status_choices,default=1)
title = models.CharField(verbose_name='标题',max_length=32)
summary = models.CharField(verbose_name='简介',max_length=255)
content = models.TextField(verbose_name='文章内容')
category = models.ForeignKey(verbose_name='分类',to='Category')
tag = models.ManyToManyField(verbose_name='标签',to='Tag',null=True,blank=True)
class Tag(models.Model):
"""标签"""
title = models.CharField(verbose_name='标签',max_length=32)
注意ForeignKey
url 不变
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
# get获取列表
# post增加数据
url(r'^drf/article/$', views.ArticleView.as_view()),
url(r'^drf/article/(?P<pk>\d+)/$', views.ArticleView.as_view()),
]
效验模块 变了
效验模块 显示跨表内容 有3种方式
第一种不常用
from rest_framework import serializers
from api import models
class ArticleSerializer(serializers.ModelSerializer):
x2 = serializers.SerializerMethodField()
class Meta:
model = models.Article
fields = "__all__"
depth = 1
第2种 常用
source='category.name'
source代表源头
category
是字段
from rest_framework import serializers
from api import models
class ArticleSerializer(serializers.ModelSerializer):
category_txt = serializers.CharField(source='category.name',required=False)
status_txt = serializers.CharField(source='get_status_display',required=False)#get_字段_display()获取对应的value值
class Meta:
model = models.Article
# fields = "__all__"
fields = ['id','title','summary','content','category','category_txt','status_txt']
第3种
from rest_framework import serializers
from api import models
class ArticleSerializer(serializers.ModelSerializer):
x1 = serializers.SerializerMethodField()
x2 = serializers.SerializerMethodField()
class Meta:
model = models.Article
# fields = "__all__"
fields = ['id','title','summary','content','category','x1',]
def get_x1(self,obj):
return obj.category.name
view 没变
文件效验在其他文件 ArticleSerializer
class ArticleView(APIView):
def get(self,request,*args,**kwargs):
pk = kwargs.get('pk')
if not pk:
queryset = models.Article.objects.all()
ser = serializer.ArticleSerializer(instance=queryset,many=True)
return Response(ser.data)
article_object = models.Article.objects.filter(id=pk).first()
ser = serializer.ArticleSerializer(instance=article_object, many=False)
return Response(ser.data)
增加文章
class ArticleView(APIView):
def post(self,request,*args,**kwargs):
ser = serializer.ArticleSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)
编辑更新文章
class ArticleView(APIView):
def put(self,request,*args,**kwargs):
"""全部更新"""
pk = kwargs.get('pk')
article_object = models.Article.objects.filter(id=pk).first()
ser = serializer.ArticleSerializer(instance=article_object,data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)
局部更新
class ArticleView(APIView):
def patch(self,request,*args,**kwargs):
"""局部"""
pk = kwargs.get('pk')
article_object = models.Article.objects.filter(id=pk).first()
ser = serializer.ArticleSerializer(instance=article_object, data=request.data,partial=True)#partial=True加这个参数
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)
练习总结
对与跨表的
显示在效验那设置
如果要自己的 中文value值
get_字段_display()获取对应的value值