Django API开发实战:前后端分离、Restful风格与DRF序列化器详解

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 一、基本概念
    • [1. 什么是前后端分离](#1. 什么是前后端分离)
    • [2. 什么是restful风格](#2. 什么是restful风格)
    • [3. 什么是接口及接口文档](#3. 什么是接口及接口文档)
    • [4. 如何阅读接口文档](#4. 如何阅读接口文档)
  • 二、DRF工程-django-restful-framework
    • [1. DRF工程搭建](#1. DRF工程搭建)
    • [2. DRF官方文档导读](#2. DRF官方文档导读)
  • 三、APIView
    • [1. APIView处理Request](#1. APIView处理Request)
    • [2. 视图的Response及json处理](#2. 视图的Response及json处理)
    • [3. 常见状态码及Response的状态码处理](#3. 常见状态码及Response的状态码处理)
  • 四、序列化

前言

在当今互联网开发中,前后端分离架构和Restful风格API成为主流。本文将深入探讨前后端分离、Restful风格、接口文档的概念,并重点介绍DRF(Django-Rest-Framework)的使用,包括APIView处理请求与响应的方法,以及序列化的重要性。


一、基本概念

1. 什么是前后端分离

传统的不分离:

用户在浏览器上发送请求,服务器端接收到请求,根据 Header 中的 token 进行用户鉴权,从数据库取出数据,处理后将结果数据填入 HTML 模板,返回给浏览器,浏览器将 HTML 展现给用户,不分离的核心就是模版,比如 Django 直接将返回数据到模版,通过模版表单将数据返回至后端

前后端不分离的特点:

  • 业务耦合较强
  • 职责划分不明确
  • 开发成本较高
  • 服务器压力较大
  • 可提高 SEO 速度,提高搜索引擎收录检索速度

现在的前后端分离:

数据渲染的工作在客户端浏览器,不需要服务端完成,服务端专注于提供数据 。那么这就要求Django 框架不需要返回一个模版页面,而是返回一套JSON 数据,而由于JSON 可以在多种语言中支持,是一种交互、兼容非常合适的语言格式,所以现在后台常返回的数据都为JSON 格式的,这个过程也称作序列化

前后端分离的特点:

  • 部署解耦
  • 业务划分清晰,职责更为明确
  • 开发成本较低,一套后台可以支持多套前端渲染
  • SEO 优化较差,需要引入一些页面静态化手段

2. 什么是restful风格

***    在前后端分离的应用模式里,API接口如何定义?是否存在一种统一的定义方式,被广大开发人员接受认可的方式呢?***

restful风格--指的是前后端交互的接口的格式定义

RestFul 规范建议:

1. 域名要有标识:
Restful 风格建议,Api 服务器的域名要尽量在专用域名之下

例如:百度面向用户的站点地址为 https://baidu.com

那么,其后端接口地址可以为:
https://api.baidu.comhttps://baidu.com/api/
2.路由中体现接口版本号
例如:
https://api.baidu.com/v1/
https://baidu.com/api/v1/
http://openapi.tuling123.com/openapi/api/v2
3. url 建议名词复数
例如:

/goods/ 获取所有商品

/infos/

/addresses/
path("news/", NewsView.as_well())
path("news/<int:id>", NewsView.as_well())
4.使用合理的请求方式
例如:

对应操作,应该返回操作后的资源结果,比如获取数据 ,那就应该使用GET 请求方式

如果是更新数据 ,那么建议使用PUTPATCH方法

  • GET:获取数据
  • POST:提交数据,创建数据
  • PUT:提交数据,更新数据
  • DELETE:删除数据

还有三个不常用的HTTP动词:

  • PATCH:在服务器更新(更新)资源

  • HEAD:获取资源的元数据

  • OPTIONS :获取信息,关于资源的哪些属性是客户端可以改变的


提供参数过滤数据:

如果数据较多,返回所有数据是不现实的,那么可以让API 提供参数,进行结果返回
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件
5.使用合理的状态码:(示例如下)

python 复制代码
200 OK - [GET] # 服务器成功返回用户请求的数据
201 CREATED - [POST/PUT/PATCH] # 用户新建或修改数据成功。
204 NO CONTENT - [DELETE] # 用户删除数据成功。
202 Accepted - [*] # 表示一个请求已经进入后台排队(异步任务)
----------------------------------------------------
400 INVALID REQUEST - [POST/PUT/PATCH] # 用户发出的请求有错误,服务器没有进行新建或修改数据的操作
401 Unauthorized - [*] # 表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] # 表示用户得到授权(与 401 错误相对),但是访问是被禁止的。
404 NOT FOUND - [*] # 用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
405 请求方式错误
406 Not Acceptable - [GET] # 用户请求的格式不可得(比如用户请求 JSON 格式,但是只有 XML 格式)。
410 Gone -[GET] # 用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] # 当创建一个对象时,发生一个验证错误。
---------------------------------------------------
500 INTERNAL SERVER ERROR - [*] # 服务器发生错误,用户将无法判断发出的请求是否成功

3. 什么是接口及接口文档

API,全称是Application Programming Interface,即应用程序编程接口 ,我们日常中习惯简称为"接口"。
比如我们要实现一个手机注册的功能,那么相应地后台工程师就需要提供一个手机注册的接口,前端开发人员在调用接口实现功能的时候,只需按照既定的规则进行请求即可,不需要去理解该功能的实现逻辑。有了这么一个机制,就使得开发人员间的协作变得非常简洁、高效。

所以,可以简单地理解为"接口决定了功能"。
接口文档又称为API文档,一般是由后台开发人员所编写的,用来描述系统所提供接口信息的文档。 大家都根据这个接口文档进行开发,并需要一直维护和遵守。

4. 如何阅读接口文档

API接口文档一般分为接口描述、接口地址、请求方法、请求参数、响应内容、错误代码、实例几个部分:
接口描述: 简单描述接口的逻辑和作用。例如说明这是一个发送消息的接口、查询天气的接口;
接口地址: 这个地址表示的是网络地址,即url,我们需要调用接口url,获取响应内容;
请求方法: 常见的请求方法为GET和POST;
请求参数: 用来传递信息的变量。即需要请求的字段名的名称和规则:都是哪些字段,字段的类型是什么,是否必填字段等等;
响应内容: 接口返回的字段名称和规则;
错误代码: 对接口的错误用代码进行归类,以便能快速找到错误原因,解决问题;
实例: 实际调用时的响应的内容。


二、DRF工程-django-restful-framework

1. DRF工程搭建

安装DRF框架

bash 复制代码
pip install djangorestframework -i https://pypi.tuna.tsinghua.edu.cn/simple

配置 settings.py

python 复制代码
INSTALLED_APPS = [
  ...
  'rest_framework',
]

2. DRF官方文档导读

这个框架封装了很多很多复用的功能:

  • 将请求的数据转换为模型类对象
  • 操作数据库
  • 将模型类对象转换为响应的数据如JSON格式
  • 视图封装DRF 统一封装了请求的数据为request.data 以及返回数据的Response方法
  • 序列化器DRF 提供了序列化器 可以统一便捷的进行序列化反序列化工作
  • 认证:对用户登陆 进行身份验证
  • 权限:对用户权限 进行认证,超级用户、普通用户、匿名用户啥的
  • 限流:对访问的用户流量进行限制减轻 接口的访问压力
  • 过滤:可以对列表数据进行字段过滤 ,并可以通过添加django-fitlter扩展来增强支持
  • 排序:来帮助我们快速指明数据按照指定字段进行排序
  • 分页:可以对数据集进行分页处理
  • 异常处理DRF 提供了异常处理,我们可以自定义异常处理函数
  • 接口文档生成DRF还可以自动生成接口文档

三、APIView

APIViewDjango REST framework中的一个类,用于处理HTTP请求并返回HTTP响应APIView提供了一种基于类的视图的方式,可以更方便地编写RESTful APIAPIView可以处理GET、POST、PUT、DELETE等HTTP请求,并根据请求的类型调用对应的方法,如get()、post()、put()、delete()等。通过APIView,开发者可以更加灵活地定义API的行为和逻辑。

django框架和drf框架对比:

django框架 django-drf框架
HttpRequest Request
HttpResponse Response
查询参数: request.GET request.query_params
路径参数:路由转换器 路由转换器
请求头: request.META request.headers
请求体-表单: request.POST request.data
请求体-非表单:request.body request.data
解析上传文件: request.FILES request.data
类视图: View APIView
JsonResponse Response
render Response

1. APIView处理Request

DRFrequest.POSTrequest.FILES ,request.body 的数据统一封装到了data属性中,其中包含了

  • 解析之后的文件非文件数据
  • POSTPUTPATCH 请求方式解析后的数据
  • 表单类型 数据、JSON类型数据
python 复制代码
# app/views.py
from rest_framework.views import APIView
class ExampleView(APIView):
  def post(self, request):
      data = request.data # json/form 提交的数据
      return Response({'received data': request.data})

DRF 为了更准确的表示这是从连接 里取得数据,从而把request.GET 的名字更换为了request.query_params ,其余操作与request.GET 一样,这里只是拼写更换

python 复制代码
# app/views.py
from rest_framework.views import APIView
class ExampleView(APIView):
    def get(self, request):
        data = request.query_params # get 的连接传参
        return Response({'received data': request.query_params})

2. 视图的Response及json处理

目前在DRF 中,我们所使用最多的就是Response 这个方法,经常使用已经序列化 好的数据结合Response返回

python 复制代码
Response(data=None, status=None, template_name=None, headers=None, exception=False, content_type=None)
'''
data: 需要返回的数据
status: 状态码
headers: 头部信息
content-type: 返回数据 MIME 类型,一般不要多余设置,drf 会自动根据数据进行设置
'''

需要注意的是,在Response 函数的第一个参数位置上,这个data 不能是复杂结构的数据,比如ORM 查询到的数据,ORM 的数据需要提取出来成为Python 的数据类型或者使用序列化方式将其加工才可以使用Response进行返回

3. 常见状态码及Response的状态码处理

bash 复制代码
200 OK - [GET] # 服务器成功返回用户请求的数据
201 CREATED - [POST/PUT/PATCH] # 用户新建或修改数据成功。
202 Accepted - [*] # 表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE] # 用户删除数据成功。

四、序列化

1. 什么是json

这一种在各个编程语言中流通的数据格式,可以在不同的编程语言中的进行数据传递交互
也就是用JSON 传输数据可以让不同语言之间可以跨越语言不同的鸿沟,虽然 python 无法和 js 进行通信,但是通过JSON,就可以让两者进行数据通信,所以现在常见的接口返回的数据都是JSON格式

2. 什么是序列化

序列化 :就是把模型层的数据返回为JSON 数据集--->将模型类对象转换为响应的数据如JSON格式
反序列化 :就是把前端发来的JSON数据,类字典数据,变为模型层的数据---> 前端json数据--转换成 模型对象

3.QuerySet如何进行Json处理

QuerySet对象是Django-ORM中查询数据返回的类似列表的多数据集合
详细介绍QuerySet 的一篇文章: 正在整理ing...

返回QuerySet的过滤器方法有:

python 复制代码
all     : 返回全部数据的QuerySet
filter  : 返回满足条件的QuerySet
exclude : 返回条件之外的QuerySet

对QuerySet进行手动处理:

python 复制代码
# 序列化
#query_set<[object, obj2]>
book_set = Book.objects.all()

books = []
#  遍历 每一个 模型对象
for book in book_set:
    books.append({
        'id': book.id,
        'btitle': book.btitle,
        'price': book.price,
        'bread': book.bread,
        'bcomment': book.bcomment
    })

反序列化 :django将前端传递的json格式的字符串数据接收并转换为模型对象,这个过程称之为反序列化

对获取的json数据,手动进行反序列化:

python 复制代码
#获取前端传递数据
json_dict = request.data
json_dict = {
    "btitle":"光年",
    "price":18.8,
    "bread":20,
    "bcomment":200
}

# 模型对象,将获取的json格式数据插入
obj = Book()
obj.btitle = json_dict['btitle']
obj.price = json_dict['price']
obj.bread = json_dict['bread']
obj.bcomment = json_dict['bcomment']
ojb.save()

4.DRF中的序列化器

DRF中,给我们提供了一个实现序列化的组件,也叫序列化器 ,就是serializers

serializers序列化组件:

  • 序列化过程 :可以把我们用ORM产生的QuerySet对象转换成json格式数据
  • 反序列化过程 :可以实现数据校验功能,并把客户端发送过来的数据(前端json格式字符串),经过request.data以后变成字典,再把字典转成模型,存到数据库;

序列化器特点:

1、将复杂的数据结构与python对象之间进行转换

2、可以根据输入和输出数据的需要进行多级嵌套

3、改变序列化输出数据的格式 可以通过指定字段的source来源,使用SerializerMethodField自定义方法以及使用嵌套序列化器。

4、支持可以自定义验证和转换方法 :反序列化时需要对客户端发送的数据进行验证。可以通过自定义validate方法进行字段或对象级别的验证,还可以使用自定义的validatorsDRF自带的验证器

5、当使用嵌套序列化器后,多个关联模型同时的创建和更新的行为并不明确,需要显示地重写create和update方法

普通序列化器(Serializer)代码示例:

python 复制代码
class BookSerializer(serializers.Serializer):
    btitle = serializers.CharField(max_length=20, label='图书名称')
    price = serializers.DecimalField(max_digits=7, decimal_places=2, label='单价')
    bread = serializers.IntegerField(default=0, required=False, label='阅读量')
    bcomment = serializers.IntegerField(default=0, required=False, label='评论量')
    img = serializers.ImageField(label='封面图片', required=False)

相关推荐
databook9 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar10 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805110 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_10 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机17 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机18 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机18 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机18 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i18 小时前
drf初步梳理
python·django
每日AI新事件18 小时前
python的异步函数
python