Django丨REST framework

REST framework一、引入Django REST framework1.Web应用模式三级目录二、DRF工程搭建三、Serializer序列化器1.定义Serializer2.序列化使用3.反序列化使用4.模型类序列化器ModelSerializer四、视图五、其他功能一、引入Django REST framework1.Web应用模式三级目录二、DRF工程搭建三、Serializer序列化器1.定义Serializer2.序列化使用3.反序列化使用4.模型类序列化器ModelS
摘要由CSDN通过智能技术生成

一、引入Django REST framework

1.Web应用模式

在开发web应用中,有两种应用模式:前后端不分离和前后端分离。

  • 前后端不分离

    • 前端页面看到的效果都是由后端控制,由后端渲染页面或重定向。
    • 前端与后端的耦合度很高。
    • 比较适合纯网页应用,当后端对接App时,返回的网页接口不适用于前端App应用
  • 前后端分离

    • 由前端服务器返回静态文件,后端仅返回前端所需要的的数据,不再渲染HTML页面
    • 前端与后端的耦合度相对较低
    • 后端仅需要开发一套逻辑对外提供数据 ,可适用于网页和App的前端
    • 在前后端分离的应用模式中,将后端开发的每个视图都称为一个借口,或者API,前端通过访问接口来对数据进行增删改查。

前后端分离开发示例
获取图书数据 Web API

  • 请求方式:get
  • 请求路径:book/1
  • 请求参数:图书id 1
  • 请求结果:json {‘books’:[{‘name’:‘西游记’,‘bread’:20},{‘name’:‘三国’,‘bread’:30}]}

前端

<ul>
	<li v-for="book in data">
		{
   {
   book.name}}
		{
   {
   book.bread}}
	</li>
</ul>

axios.get('http:\\127.0.0.1:8000/book/1')
	# 200系列状态码,执行then
	.then(response => {
   
		this.data = response.data.books
	})	
	# 返回400/500状态码,执行catch
	.catch(response = >{
   
		response.data.error
	})

后端

url(r'book/(?P<pk>\d+)',views.BookView.as_view())

class BookView(View):
	def get(self,request,pk):
		# 1.获取数据
		# 2.查询数据
		try:
			book = Book.object.get(id=pk)
		except:
			return HttpResponse()
		data = {
   "name":book.name, "bread":book.bread}
		return JsonResponse(data)
		

2.RESTful

在前后端分离的应用模式里,API接口普遍采用RESTful设计风格

  • 1.域名:应该尽量将API部署在专有域名之下
    https://api.example.com
    如京东:https://shouji.jd.com/
    如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下
    https:example.org/api/

  • 2.版本:应该将API的版本号放入url
    http://www.example.com/app/1.0/foo
    http://www.example.com/app/1.1/foo
    http://www.example.com/app/2.0/foo
    另一种做法是将版本号放在HTTP头信息中,因为不同的版本可以理解成同一种资源的不同表现形式,所以应该采用同一种url,版本号可以放在HTTP请求头信息的Accept字段中进行区分。
    Accept: vnd.example-com.foo+json; version=1.0
    Accept: vnd.example-com.foo+json; version=1.1
    Accept: vnd.example-com.foo+json; version=2.0

  • 3.路径
    路径又称“终点”,表示API的具体网址,每个网址代表一种资源。

    • (1) 资源作为网址,只能有名词,不能有动词,所用名词往往与数据库的表名对应;此外,利用HTTP方法可以分离网址中的资源名称的操作。
      如:
      GET /products :将返回所有产品清单
      POST /products :将产品新建到集合
      GET /products/4 :将获取产品 4
      PATCH(或)PUT /products/4 :将更新产品 4
    • (2) API中的名词 应该使用复数,无论子资源还是所有资源
      如:
      获取单个产品:http://127.0.0.1:8080/AppName/rest/products/1
      获取所有产品: http://127.0.0.1:8080/AppName/rest/products
  • 4.HTTP动词
    对于资源的具体操作类型,由HTTP动词表示,常用的HTTP动词有下面四个。
    GET:从服务器取出资源(一项或多项)。
    POST:在服务器新建一个资源。
    PUT:在服务器更新资源(客户端提供改变后的完整资源)。
    DELETE:从服务器删除资源。
    如:
    GET /zoos:列出所有动物园
    POST /zoos:新建一个动物园(上传文件)
    GET /zoos/ID:获取某个指定动物园的信息
    PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
    PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
    DELETE /zoos/ID:删除某个动物园
    GET /zoos/ID/animals:列出某个指定动物园的所有动物
    DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

  • 5.过滤信息以查询字符串进行
    如果记录数量很多,API应该提供参数,过滤返回结果。
    下面是一些常见的参数:

    ?limit=10:指定返回记录的数量
    ?offset=10:指定返回记录的开始位置。
    ?page=2&per_page=100:指定第几页,以及每页的记录数。
    ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
    ?animal_type_id=1:指定

  • 6.状态码
    后端执行成功或失败以状态码的形式告诉前端,处理成功返回200系列状态码,执行前端then里面的代码;处理失败返回400/500系列状态码,执行catch里面的代码。

  • 200 OK :服务器成功返回用户请求的数据
  • 201 CREATED :用户新建或修改数据成功。
  • 202 Accepted :表示一个请求已经进入后台排队(异步任务)
  • 204 NO CONTENT :用户删除数据成功。
  • 400 INVALID REQUEST :用户发出的请求有错误,服务器没有进行新建或修改数据的操作
  • 401 Unauthorized :表示用户没有权限(令牌、用户名、密码错误)。
  • 403 Forbidden :表示用户得到授权(与401错误相对),但是访问是被禁止的。
  • 404 NOT FOUND :用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
  • 406 Not Acceptable :用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
  • 410 Gone:用户请求的资源被永久删除,且不会再得到的。
  • 422 Unprocesable entity : 当创建一个对象时,发生一个验证错误。
  • 500 INTERNAL SERVER ERROR :服务器发生错误,用户将无法判断发出的请求是否成功
  • 7.错误处理
    如果状态码是4xx,服务器就应该向用户返回出错信息,一般来说,返回的信息中将error作为键名,出错信息作为键值。
{
   
	error:"出错信息"
}
  • 8.返回结果
    针对不同操作,服务器向用户返回的结果应该符合以下规范:
    • GET /collection:返回资源对象的列表(数组)
    • GET /collection/resource:返回单个资源对象
    • POST /collection:返回新生成的资源对象
    • PUT /collection/resource:返回完整的资源对象
    • PATCH /collection/resource:返回完整的资源对象
    • DELETE /collection/resource:返回一个空文档
  • 9.其他
    服务器返回的数据格式,应该尽量使用JSON,避免使用XML

3.使用Django开发REST接口示例

使用图书英雄案例来写一套支持图书数据增删改查的REST API接口
① 接口设计

  • 增加图书
请求方式 请求路径 请求参数 返回结果
POST books/ title、bpub_date (请求体json) 保存后的图书数据books=[{btitle:“西游记”,bpub_date:2017},{…}]
  • 删除图书
请求方式 请求路径 请求参数 返回结果
DELETE books/1 id (路径)
  • 修改图书
请求方式 请求路径 请求参数 返回结果
PUT books/1 修改字段内容(json)、id (路径) 更新后的图书数据 book={ btitle:“xxx”,bpub_date:“xxx”}
  • 查询图书

查询单一图书

请求方式 请求路径 请求参数 返回结果
GET books/1 id (路径) book={ btitle:“xxx”,bpub_date:“xxx”}

查询所有图书

请求方式 请求路径 请求参数 返回结果
GET books/1 books=[{btitle:“西游记”,bpub_date:2017},{…}]

② 后端代码实现

urlpatterns = [
	url(r'^books/$', views.BooksView.as_view()),
	url(r'^books/(?P<pk>\d+)/', views.BookView.as_view()),
]




from django.views import View
from django.http import JsonResponse
from book.models import BookInfo
import json


class BooksView(View):

	def get(self,request):
		"""获取所有图书""""
		books = BookInfo.objects.all()
		data = []
		for book in books:
			data.append({
   
				"id": book.id,
				"btitle": book.btitle,
				"bpub_date": book.bpub_date
			})
		# safe=False,是将列表[]转成json中的数组"[]"
		return JsonResponse(data, safe=False)
		
	def post(self,request):
		"""保存图书"""
		# 1、获取前端数据
		data = request.body.decode()
		data_dict = json.loads(data)
		btitle = data_dict.get("btitle")
		bpub_date = data_dict.get("bpub_date")
		# 2、验证数据
		if btitle == "python":
			return JsonResponse({
   "error": "错误的书名"},status=400)
		# 3、保存数据
		book = BookInfo.objects.create(btitle=btitle, bpub_date=bpub_date)
		# 4、返回结果
		return JsonResponse({
   
			"id": book.id,
			"bpub_date": book.bpub_date,
			"btitle": book.btitle
		})

class BookView(View):
	def get(self,request,pk):
		"""查询一本图书"""
		try:
			book = BookInfo.objects.get(id=pk)
		except:
			return JsonResponse({
   
				"id": book.id,
				"btitle": book.btitle,
				"bpub_date": book.bpub_date
			})
	def put(self,request,pk):
		"""修改一本图书"""
		# 1、获取数据
		data = request.body.decode()
		data_dict = json.loads(data)
		btitle = data_dict.get("btitle")
		bpub_date = data_dict.get("bpub_date")
		# 2、校验数据
		# 3、更新数据
		# 这种方法得到的并不是对象,而是得到更新数据的个数
		# book = BookInfo.objects.filter(id=pk).update(btitle=btitle,bpub_date=bpub_date)
		try:
			book = BookInfo.objects.get(id=pk)
		except:
			return JsonResponse({
   "error": "错误的id"},status=400)
		book.btitle = btitle
		book.bpub_date = bpub_date
		book.save()
		# 4、返回结果
		return JsonResponse({
   
			"id": book.id,
			"btitle": book.btitle,
			"bpub_date": book.bpub_date
		})
	def delete(self,request,pk):
		"""删除一本图书"""
		try:
			book = BookInfo.objects.get(id=pk)
		except:
			return JsonResponse({
   "error": "错误的id"}, status=400)
		
		book.delete()

4.序列化与反序列化

  • 序列化:将程序的一个数据结构类型转换成其他格式(字典、JSON、XML等),如,获取数据库中的数据对象所对应的字段数据转化为json的过程(从后端服务到前端服务)
  • 反序列化:将其他格式(字典、JSON、XML等)转换为程序中的数据,如,获取前端数据,验证数据到保存或更新数据获取新的数据对象的过程(从前端服务到后端服务)

5.Django REST framework简介

  • Django REST framework 框架是一个用于构建Web API的强大而又灵活的工具,通常简称为DRF框架或REST framework。
  • 特点:
    • 提供了定义序列化器Serializer的方法,可以快速根据Django ORM或者其他库自动序列化/反序列化。
    • 提供了各种丰富的类视图、Mixin扩展类,简化视图的编写
    • 丰富的定制层级:函数视图、类视图、视图集合到自动生成API,满足各种需要
    • 多种身份认证和权限认证方式的支持
    • 内置了限流系统
    • 直观的API web界面
    • 可扩展性,插件丰富
  • 官方文档

二、DRF工程搭建

环境安装与配置

  • 1.安装DRF
pip install djangorestframework
  • 2.添加rest_framework应用
    在settings.py的INSTALLED_APPS中添加’rest_framework’
INSTALLED_APPS = [
    ...
    'rest_framework',
]

三、Serializer序列化器

序列化器的作用:

  • 进行数据的校验
  • 对数据对象进行转换

1.定义Serializer

在应用的目录下创建serializers.py文件,Serializer使用类来定义,须继承自rest_framework.serializers.Serializer.

from rest_framework import serializers


class BookSerializer(serializers.Serializers):
	# 根据模型类字段进行定义字段
	btitle=serializers.CharField()
	bpub_date=serializers.DateField()

注:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义,serializer是独立于数据库之外的存在。

2.序列化使用

  • 1 基本使用
from book.serializers import BookSerializer

class BookView(View):
	def get(self,request,pk):
		"""查询一本图书"""
		try:
			# 查询出一个图书对象
			book = BookInfo.objects.get(id=pk)
		except:
			# return JsonResponse({"id": book.id,"btitle": book.btitle,"bpub_date": book.bpub_date})
			# 1.构造序列化器对象
			serializer = BookSerializer(book)
			# 2.通过data方法获取序列化数据 
			data = serializer.data
			return JsonResponse(data)
  • 2 返回多条数据,通过添加many=True参数
from book.serializers import BookSerializer


class BooksView(View):

	def get(self,request):
		"""获取所有图书""""
		books = BookInfo.objects.all()
		# data = []
		# for book in books:
			# data.append({"id": book.id,"btitle": book.btitle,"bpub_date": book.bpub_date})
		serializer = BookSerializer(books,many=True)
		return JsonResponse(serializer.data, safe=False)
  • 3 关联对象嵌套序列化
    如果需要序列化的数据包含有其他关联对象,则对关联对象数据的序列化需要指明。
    对于关联字段可以采用以下几种方式:
    • PrimaryKeyRelatedField
      此字段将被序列化为关联对象的主键,返回关联对象的id值
      heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True)
      注:read_only=True,该字段只能用于序列化操作,不能用于反序列化;write_only=True,只能用于反序列化操作,不能用于序列化操作;many=True,关联的对象数据可能包含多条数据。
      返回结果示例:
{
   "btitle":"天龙八部", "bpub_date": "1986-07-24", "heroinfo_set":[6,7,8,9]}
  • StringRelatedField
    此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值),返回模型类中__str__方法中返回的数据。
    <
  • 9
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值