一.前后端分离及drf实现序列化的原理
为什么要进行前后端分离
- 可pc、app、pad多端适应
- SPA开发模式的流行--单页web应用(只有一html页面)
- 可实现前后端开发职责清(不分离时,前端是通过后端给的变量并渲染出来方式拿到数据!!后端是通过前端准备好的模版,并替换其中变量方式传数据)
- 不分时开发效率问题,前后端相互等待
- 不分时前端一直配合着后端,能力受限制
- 不分时后端开发语言和模板高度耦合,导致开发语言依赖严重--现在可把语言和模板分离开
前后端分离缺点
- 前后端学习门槛增加
- 数据依赖导致文档重要性增加
- 前端工作量加大
- SEO难度加大
- 后端开发迁移成本增加
restfull api目前是前后端分离的最佳实践
- 轻量的,直接通过http方式进行数据交互,不需要额外的协议,支持post/get/put/delete操作
- 面向资源,一面了然,具有自解释性
- 数据描述简单,一般是通过json或者xml做数据通信(后端准备好数据以json形式返回给前端,前端拿到的就是直接可用的对象)
理解RESTful架构:概念参考http://www.ruanyifeng.com/blog/2011/09/restful.html
实战参考http://www.ruanyifeng.com/blog/2014/05/restful_api.html

二.开始drf
1.项目准备
开始项目:
(python36env) [vagrant@CentOS7 devops]$ python manage.py startapp idcs
新建项目目录下apps包用于放将来很多的app--idcs也放其中。
(1)urls.py:--注意为了让其能识别idcs/urls有两方式:
从pycharm上识别:点击apps包右键--mark as--source root(意思是以apps目录为查找模块的目录)
从代码层面识别:把apps目录加到全局path路径BASE_DIR中,
import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,os.path.join(BASE_DIR, "apps"))
--sys.path中存着django所有可搜索加载的目录,并插到最开始的地方所以用insert(0)。并加在django项目下。
激活app:
INSTALLED_APPS = [
.......
'idcs'
]
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^idcs', include("idcs.urls")),
]
(2)idcs/urls.py: 定义一空变量即可
from django.conf.urls import include, url
urlpatterns = [ ]
2.drf安装及配置:
(python36env) [vagrant@CentOS7 devops]$ pip install djangorestframework
INSTALLED_APPS = (
......
'rest_framework'
)
然后重启pycharm重新同步远程环境。
3.序列化模型
(1)准备模型models.py:
from django.db import models class Idc(models.Model):
name = models.CharField("机房名",max_length=32)
address = models.CharField("机房地址",max_length=200)
phone = models.CharField("机房联系电话",max_length=15)
email = models.EmailField("机房联系email")
letter = models.CharField("idc字母简称",max_length=5)
def __str__(self):
return self.name
class Meta:
db_table = 'resources_idc'
同步数据:
(python36env) [vagrant@CentOS7 devops]$ python manage.py makemigrations idcs
(python36env) [vagrant@CentOS7 devops]$ python manage.py migrate idcs
(2)序列化模型:在idcs下新建serializers.py
from rest_framework import serializers class IdcSerializer(serializers.Serializer):
"""
Idc 序列化类
"""
id = serializers.IntegerField()
name = serializers.CharField()
address = serializers.CharField()
phone = serializers.CharField()
email = serializers.EmailField()
letter = serializers.CharField()
a.把模型中的所有字段和id字段都拿过来--定义它的变量类型(根据模型的字段类型定义序列化--是为了返回给前端什么样的字段/数据类型)
b.使用序列化
为了测试,所以先手动往库中添加点记录(添加到idc模型中)。
(python36env) [vagrant@CentOS7 devops]$ python manage.py shell
In [1]: from idcs.models import Idc
In [2]: idc = Idc()
In [3]: idc.name = "昆明机房"
In [4]: idc.address = "昆明"
In [5]: idc.phone = ""
In [6]: idc.email = "rock@51reboot.com"
In [7]: idc.letter = "km"
In [8]: idc.save()
In [9]: idc.id = None
In [10]: idc.name = "大理机房"
In [11]: idc.address = "大理"
In [12]: idc.letter = "dl"
In [13]: idc.save()
In [14]: Idc.objects.all() 查询如下有两条记录了
Out[14]: <QuerySet [<Idc: 昆明机房>, <Idc: 大理机房>]>
先导入idc序列化类,并准备一条记录,然后序列化类(要实例化类--把记录传给它)并保存在一变量中,
把此实例化后的对象用data属性一打印出来就直接是json格式的数据了:
In [16]: from idcs.serializers import IdcSerializer
In [17]: idc = Idc.objects.get(pk=1)
In [18]: idc
Out[18]: <Idc: 昆明机房>
In [19]: serializer = IdcSerializer(idc)
In [20]: serializer
Out[20]:
IdcSerializer(<Idc: 昆明机房>):
id = IntegerField()
name = CharField()
address = CharField()
phone = CharField()
email = EmailField()
letter = CharField()
In [21]: serializer.data
Out[21]: {'id': 1, 'name': '昆明机房', 'address': '昆明', 'phone': '', 'email': 'rock@51reboot.com', 'letter': 'km'}
In [22]: a = serializer.data
In [23]: type(a)
Out[23]: rest_framework.utils.serializer_helpers.ReturnDict
但它是rest字典类型的数据,所以要给它转成json,且用rest提供的方法转(不能用json.dumps):
先实例化JSONRenderer方法,并给它传一数据----如下结果中,这才是标准的返回给前端的数据
In [25]: from rest_framework.renderers import JSONRenderer
In [26]: jr = JSONRenderer()
In [27]: jr.render(serializer.data)
Out[27]: b'{"id":1,"name":"\xe6\x98\x86\xe6\x98\x8e\xe6\x9c\xba\xe6\x88\xbf","address":"\xe6\x98\x86\xe6\x98\x8e","phone":"1234568","email":"rock@51reboot.com","letter":"km"}'
In [28]: content = jr.render(serializer.data) 保存到一变量中,就可直接通过httpresponse对象直接返回给前端
c.用序列化做字段的简单验证serializers.py:
from rest_framework import serializers
class IdcSerializer(serializers.Serializer):
"""
Idc 序列化类
"""
id = serializers.IntegerField(read_only=True) #只读的,即忽略可不传
name = serializers.CharField(required=True,max_length=32) #意思是提交数据时此字段必须填且不能为空
address = serializers.CharField(required=True,max_length=256)
phone = serializers.CharField(required=True,max_length=15)
email = serializers.EmailField(required=True)
letter = serializers.CharField(required=True,max_length=5)
d.怎样把前端提交过来的数据content插入到数据库中---反序列化(即把bytes类型转成模型对象)
首先它是一byte类型,是一种流
In [31]: from django.utils.six import BytesIO
In [32]: stream = BytesIO(content)
In [33]: stream
Out[33]: <_io.BytesIO at 0x7fe29ac4b410>
In [35]: from rest_framework.parsers import JSONParser 后可看到如下中是标准的json了
In [36]: data = JSONParser().parse(stream)
In [37]: data
Out[37]:
{'id': 1,
'name': '昆明机房',
'address': '昆明',
'phone': '',
'email': 'rock@51reboot.com',
'letter': 'km'}
In [38]: serializer = IdcSerializer(data=data) 反序列化后如下就生成标准的原始数据了
In [39]: serializer
IdcSerializer(data={'id': 1, 'name': '昆明机房', 'address': '昆明', 'phone': '1234568', 'email': 'rock@51reboot.com', 'letter': 'km'}):
id = IntegerField()
name = CharField()
address = CharField()
phone = CharField()
email = EmailField()
letter = CharField()
但是可以看到上述所有字段中都没有规则,所以得让其重新生效一次--要重新加载IdcSerializer类(因为这个类我已经修改过了,加了验证规则),而上述拿到的序列类它是没有验证规则
先退出django shell,再重新进入
In [1]: from idcs.serializers import IdcSerializer
In [2]: data = {'id': 1, 这是前端传过来的数据
...: 'name': '昆明机房',
...: 'address': '昆明',
...: 'phone': '',
...: 'email': 'rock@51reboot.com',
...: 'letter': 'km'} In [3]: serializer = IdcSerializer(data=data) 反序列化 后如下中可看到有验证规则了 In [4]: serializer
Out[4]:
IdcSerializer(data={'id': 1, 'name': '昆明机房', 'address': '昆明', 'phone': '', 'email': 'rock@51reboot.com', 'letter': 'km'}):
id = IntegerField(read_only=True)
name = CharField(max_length=32, required=True)
address = CharField(max_length=256, required=True)
phone = CharField(max_length=15, required=True)
email = EmailField(required=True)
letter = CharField(max_length=5, required=True)
In [5]: serializer.is_valid() 进行验证
Out[5]: True
e.此时数据已准备好,验证规则也有了,也验证完了,此时我需要拿到干净的数据(不等于前端传过来的数据)
In [6]: serializer.validated_data 此时就拿到了干净的数据
Out[6]:
OrderedDict([('name', '昆明机房'),
('address', '昆明'),
('phone', ''),
('email', 'rock@51reboot.com'),
('letter', 'km')])
f.拿到干净的数据后要想保存得重写create方法,并把已经验证过的数据给它再返回
serializer.py中加入如下代码:
from rest_framework import serializers
from .models import Idc
class .....
def create(self, validated_data):
return Idc.objects.create(**validated_data)
退出django shell再进入并再把前端传的数据拿过来且把id去掉,就表示新建(没有传id django认为是创建数据,有传id表示认为修改数据),--因为有save方法时它会自动判断你是调用create还是update方法
所以对数据进行序列化--验证---保存,如下所示一条记录就保存了且做了验证
In [2]: from idcs.serializers import IdcSerializer
In [3]: data = {'id': 1,
...: 'name': '昆明机房',
...: 'address': '昆明',
...: 'phone': '',
...: 'email': 'rock@51reboot.com',
...: 'letter': 'km'}
In [4]: del data["id"]
In [5]: serializer = IdcSerializer(data=data)
In [6]: serializer.is_valid()
Out[6]: True
In [7]: serializer.save()
Out[7]: <Idc: 昆明机房>
In [8]: from idcs.models import Idc 测试有无验证成功,如下有三条记录说明成功了
In [9]: Idc.objects.all()
Out[9]: <QuerySet [<Idc: 昆明机房>, <Idc: 大理机房>, <Idc: 昆明机房>]>
g.我上述所有操作都是只序列化一条记录,那如何序列化多条记录
给它传一queryset即可(Idc.objects.all(), many=True)表示有多条。
In [11]: data = IdcSerializer(Idc.objects.all(), many=True) In [12]: data
Out[12]:
IdcSerializer(<QuerySet [<Idc: 昆明机房>, <Idc: 大理机房>, <Idc: 昆明机房>]>, many=True):
id = IntegerField(read_only=True)
name = CharField(max_length=32, required=True)
address = CharField(max_length=256, required=True)
phone = CharField(max_length=15, required=True)
email = EmailField(required=True)
letter = CharField(max_length=5, required=True) 那如何拿到数据?--通过JSONRenderer,并传给它上述的data数据,且它是序列化类所以用data属性,最终如下它就是一多标准数据的列表了
In [14]: from rest_framework.renderers import JSONRenderer
In [15]: content = JSONRenderer().render(data.data)
In [16]: content
Out[16]: b'[{"id":1,"name":"\xe6\x98\x86\xe6\x98\x8e\xe6\x9c\xba\xe6\x88\xbf","address":"\xe6\x98\x86\xe6\x98\x8e","phone":"1234568","email":"rock@51reboot.com","letter":"km"},{"id":2,"name":"\xe5\xa4\xa7\xe7\x90\x86\xe6\x9c\xba\xe6\x88\xbf","address":"\xe5\xa4\xa7\xe7\x90\x86","phone":"1234568","email":"rock@51reboot.com","letter":"dl"},{"id":3,"name":"\xe6\x98\x86\xe6\x98\x8e\xe6\x9c\xba\xe6\x88\xbf","address":"\xe6\x98\x86\xe6\x98\x8e","phone":"1234568","email":"rock@51reboot.com","letter":"km"}]'
扩展:update方法
class.....
def create(self, validated_data):
return Idc.objects.create(**validated_data)
def update(self, instance, validated_data): #对已经验证过的非常干净的数据进行修改,instance是当前的对象
instance.name = validated_data.get("name", instance.name) #哪些字段可以修改,且默认名是
instance.address = validated_data.get("address", instance.address)
instance.phone = validated_data.get("phone", instance.phone)
instance.email = validated_data.get("email", instance.email)
instance.save() #保存
return instance #返回
一.前后端分离及drf实现序列化的原理的更多相关文章
- 前后端分离之DRF——1
1. 作用 1. 序列化,序列化器会把模型对象转成字典,经过 response 以后变成 json 字符串 2. 反序列化,把客户端发送过来的数据,经过 request 以后变成字典,序列化器可以把字 ...
- 前后端分离djangorestframework——序列化与反序列化数据
我们写好后端的代码,要把数据交给前端的展示的,这个数据以什么类型给前端呢?学到这里,我们已经知道这个数据最好是json字符串才行,因为网络间的传输,只认字符串或者二进制,字符串就是我们的数据,二进制就 ...
- python drf+xadmin+react+dva+react-native+sentry+nginx 搭建前后端分离的博客完整平台
前言: 经过差不多半年的开发,搭建从前端到服务器,实现了前后端分离的一个集PC端.移动端的多端应用,实属不易,今天得空,好好写篇文章,记录这些天的成果.同时也做个分享. 演示网站地址: http:// ...
- 前后端分离djangorestframework——分页组件
Pagination 为什么要分页也不用多说了,大家都懂,DRF也自带了分页组件 这次用 前后端分离djangorestframework——序列化与反序列化数据 文章里用到的数据,数据库用的my ...
- 前后端分离djangorestframework——视图组件
CBV与FBV CBV之前说过就是在view.py里写视图类,在序列化时用过,FBV就是常用的视图函数,两者的功能都可以实现功能,但是在restful规范方面的话,CBV更方便,FBV还要用reque ...
- 前后端分离和restful开发规范
一.web开发的两种模式 1.前后端不分离 在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高. 这种应用模式比 ...
- 【转】从MVC到前后端分离
1. 理解MVC MVC是一种经典的设计模式,全名为Model-View-Controller,即模型-视图-控制器. 其中,模型是用于封装数据的载体,例如,在Java中一般通过一个简单的POJO(P ...
- 从MVC到前后端分离
摘要:MVC模式早在上个世纪70年代就诞生了,直到今天它依然存在,可见生命力相当之强.MVC模式最早用于Smalltalk语言中,最后在其它许多开发语言中都得到了很好的应用,例如,Java中的Stru ...
- dotnetcore vue+elementUI 前后端分离架二(后端篇)
前言 最近几年前后端分离架构大行其道,而且各种框架也是层出不穷.本文通过dotnetcore +vue 来介绍 前后端分离架构实战. 涉及的技术栈 服务端技术 mysql 本项目使用mysql 作为持 ...
随机推荐
- Java实现 洛谷 P1049 装箱问题
题目描述 有一个箱子容量为V(正整数0≤V≤20000),同时有n个物品(0<n≤30,每个物品有一个体积(正整数). 要求nn个物品中,任取若干个装入箱内,使箱子的剩余空间为最小. 输入输出格 ...
- Java实现 LeetCode 739 每日温度(暴力循环)
739. 每日温度 根据每日 气温 列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数.如果之后都不会升高,请在该位置用 0 来代替. 例如,给定一个列表 temper ...
- Java实现 蓝桥杯VIP 算法训练 快速排序
import java.util.Scanner; public class 快速排序 { public static void main(String[] args){ Scanner sc=new ...
- Java实现第八届蓝桥杯纸牌三角形
纸牌三角形 题目描述 A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算).要求每个边的和相等. 下图就是一种排法(如有对齐问题,参看p1.png). A 9 6 4 8 3 ...
- js事件的一些兼容写法
事件兼容 事件对象的兼容 获取键码兼容 默认行为兼容 阻止事件冒泡兼容 事件监听兼容 ---- 封装 删除事件监听兼容 ---- 封装 事件委托->获取事件源兼容
- 初学python笔记
一.关于python ① 由荷兰人Guido van Rossum(龟叔)于1989年圣诞节为打发无聊时间所编写的编程语言. ② python的特点:优雅 明确 简单.代码量少,运行速度快. 缺点:运 ...
- vim编辑器添加插件NERDTree
0x01 首先在 http://www.vim.org/scripts/script.php?script_id=1658 下载插件 (可能要爬梯,也可以在https://github.com/scr ...
- neo4j导入csv文件
neo4j导入csv文件 关于neo4j的安装 官网和网上博客提供了n中安装的方法,这里不再赘述: 普通安装: https://cloud.tencent.com/developer/article/ ...
- python基础001----Python+pycharm环境搭建
一.Python下载安装 1.python下载-----下载地址:https://www.python.org/downloads/windows/ 在python的官网下载python版本,需要下载 ...
- Nginx配置rewrite过程介绍
创建rewrite语句 vi conf/vhost/www.abc.com.conf #vi编辑虚拟主机配置文件 文件内容 server { listen 80; server_name abc.co ...