Django REST Framework

WEB 应用模式

前后端不分离
depended_frontend_backend.png
  • 前端页面效果由后端控制(后端渲染页面或重定向) 前端的静态文件(css,js)和后端的django框架都部署在一个服务器上
  • 此模式适合纯网页应用,当后端对接APP时,后端返回的网页接口不再适用于前端APP应用
前后端分离
indepent_frontend_backend.png
  • 后端只返回前端所需要的数据,不再渲染HTML页面
  • 前端的静态文件和后端的django框架部署在不同的服务器上
在静态文件夹内开启静态服务器
python3 -m http.server 端口号
django框架开启后端应用服务器
实现一台物理主机,开启多个服务器功能
  • 浏览器先请求部署Nginx的静态服务器,请求的内容不在Nginx中,由Nginx转发请求到部署uwisg的后端应用服务器,进行处理响应,将相应的结果返回给Nginx,再由Nginx返回给浏览器
  • 前后端分离模式中,后端的每个视图都为一个接口或API, 前端通过访问接口对数据进行增删改查

RESTful设计方法

域名
  • 尽量将API部署在专用域名之下
  • 若API很简单,不会再扩展,可放在主域名下
版本
  • API的版本号放入URL,路径参数
  • 不同的版本,为同一种资源的不同表现形式,采用同一个URL,版本号在HTTP请求头信息的Accept字段中进行区分
路径

路径又称"终点"(endpoint),表示API的具体网址,每个网址代表一种资源(resource)

  • 资源作为网址,只能有名词,不能有动词,而且所用的名词往往与数据库的表名对应
  • API中的名词应该使用复数。无论子资源或者所有资源
HTTP动词
  • GET(SELECT):从服务器取出资源(一项或多项)
  • POST(CREATE):在服务器新建一个资源
  • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)
  • DELETE(DELETE):从服务器删除资源
过滤信息(filtering)

使用查询字符串参数对信息进行过滤

状态码(status codes)
200 OK - [GET]:服务器成功返回用户请求的数据
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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
错误处理

状态码是4xx,服务器向用户返回出错信息,返回的信息中将error作为键名,出错信息作为键值。

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

服务器返回的数据格式,应该尽量使用JSON,避免使用XML

使用django开发REST接口

  • 接口设计
  1. 请求方式(GET/POST/PUT/DELETE)
  2. 请求路径
  3. 请求参数(路径参数/字符串参数/表单/json)
  4. 返回结果
  • 开发REST API时,视图中做的三件事:
  1. 将请求的数据(如JSON格式)转换成模型类对象,将前端发送的数据反序列化为模型类对象,并保存到数据库中
  2. 操作数据库
  3. 将模型类对象转化成响应的数据(如JSON格式),将数据库数据序列化为前端所需要的格式,并返回
  • 序列化 将程序中的数据结构类型转换成其他格式(字典,JSON,XML等)
  • 反序列化 将其他格式(字典,JSON,XML等)转换成程序中的数据

DRF

Django REST framework可以简化以下两部分的代码编写,提高REST API的开发速度

  • 在序列化与反序列化时,虽然操作的数据不同,但执行的过程却是相似的,这部分代码是可以复用简化编写的
  • 在开发REST API的视图中,每个视图具体操作的数据不同,但增、删、改、查的实现流程基本套路化,这部分代码也是可以复用简化编写的:
  1. 增:校验请求数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
  2. 删:判断要删除的数据是否存在 -> 执行数据库删除
  3. 改:判断要修改的数据是否存在 -> 校验请求的数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
  4. 查:查询数据库 -> 将数据序列化并返回

DRF工程搭建

  1. 安装DRF
pip install djangorestframework
  1. 在settings.py的INSTALLED_APPS中添加rest_framework

序列化器

  • 序列化器的作用
    • 进行数据的校验
    • 对数据对象进行转换
  • serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义

定义序列化器Serializer

  1. 新建serializers.py,该文件用来定义序列化器类,DRF中的Serializer使用类来定义, 继承自rest_framework.serializers.Serializer
from rest_framework import serializers
from book.models import BookInfo, HeroInfo

class BookSerializers1(serializers.Serializer):
    btitle = serializers.CharField()
    bpub_date = serializers.DateField()
  1. 创建的序列化器中的字段参考模型类中的字段
  • 字段中的常用参数
常用参数 参数说明
read_only 该字段仅用于序列化输出,默认False
write_only 该字段仅用于反序列化输入,默认False
required 该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
  1. 在serializers.py中定义好类后,在视图中创建序列化器对象
Serializer(instance=None, data=empty, **kwarg)
  • 序列化时,将模型类对象传入instance参数
  • 反序列化时,将要被反序列化的数据传入data参数

序列化使用

在django shell 中使用序列化器

python manage.py shell
  • 基本使用
    • 模型类查询数据库 ,获取查询对象
    • 把查询对象当作参数,进行序列化器实例化对象
    • 序列化器对象通过data属性获取序列化后的数据
    • 被序列化的是包含多条数据的查询集QuerySet,通过添加many=True参数补充说明
from booktest.models import BookInfo
from booktest.serializers import BookInfoSerializer
#获取单个数据
book = BookInfo.objects.get(id=2)
serializer = BookInfoSerializer(book)
serializer.data
# {'id': 2, 'btitle': '天龙八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None}
#获取多条数据
book_qs = BookInfo.objects.all()
serializer = BookInfoSerializer(book_qs, many=True)
serializer.data
# [OrderedDict([('id', 2), ('btitle', '天龙八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bcomment', 40), ('image', N]), OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image'ne)]), ]
  • 关联对象嵌套序列化
关联字段方式 说明
PrimaryKeyRelatedField 被序列化为关联对象的主键
StringRelatedField 被序列化为关联对象的字符串(str方法的返回值)
关联对象的序列化器 关联对象的序列化器
  1. 主表嵌套副表
#一对多,关联多个对象数据,使用many=True参数
heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True)
heroinfo_set =serializers.StringRelatedField(read_only=True,many=True)
heroinfo_set = HeroSerialzier(many=True)
  1. 副表嵌套主表
#多对一,关联单个对象数据
hbook = serializers.PrimaryKeyRelatedField(read_only=True)
hbook = serializers.StringRelatedField(read_only=True)
hbook = BookHeroSerialzer()

反序列化使用

反序列化:对前端请求来的参数进行验证,保存或更新,需要在序列化类中指明哪些字段进行反序列化验证

  1. 验证
#视图中
ser = BookSerializer(instance,date_dict)
ser.is_valid(raise_exception=True)
ser.errors
#序列化器类中
#指定字段验证
def validate_btitle(self,value):
    if value =='python':
            return serializers.ValidationError("报错信息")
    return value
#多个字段验证
def validate(self,attrs):
    if attrs['btitle'] =='python':
            return serializers.ValidationError("报错信息")
    return attrs
  1. 保存/更新
#视图中,反序列化保存更新,save选择保存还是更新由初始化反序列器时有没有传入instance决定
ser.save()
#序列化器中
#保存使用create
def create(self,validated_date)
#更新使用update
def update(self,instance,validate_date)

模型类序列化器ModelSerializer

  • ModelSerializer提供:
    • 基于模型类自动生成一系列字段
    • 基于模型类自动为Serializer生成validators,比如unique_together
    • 包含默认的create()和update()的实现
class BookModelSerialize(serializers.ModelSerializer):
    #显示指明字段
    bcomment = serializers.IntegerField(max_value=200, min_value=20)

    class Meta:
        model = BookInfo  #指定根据哪个模型类生成字段
        fields = '__all__'  #所有字段
        # fields = ('id','btitle') #指定字段
        # exclude = ('bread', )  #字段取反
        read_only_fields = ('bcomment', )  #指定参与序列化的字段
        extra_kwargs = {'is_delete': {'default': True}}

class HeroModelSerialize(serializers.ModelSerializer):
    #显示指明字段
    bcomment = serializers.IntegerField(max_value=200, min_value=20)

    class Meta:
        model = HeroInfo  #指定根据哪个模型类生成字段
        fields = '__all__'  #所有字段
        read_only_fields = ('hcomment', )  #指定参与序列化的字段
        extra_kwargs = {'is_delete': {'default': True}}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容