1.RESTful
1.1 定义
REST(Representational State Transfer)与技术无关,代表一种软件架构风格,中文为表征状态转移。
1.2 RESTful API设计
- API与用户的通信协议,总是使用HTTPS协议
- 域名
- https://api.example.com 尽量将API部署在专用域名(会存在跨域问题)
- https://example.org/api/ API在路径上,简单
- 版本
- URL 如:https://api.example.com/v1/ 代表v1版本的API
- 路径,网络上的任何东西都是资源,均使用名词表示(可复数)
- method
- GET :从服务器取出资源(一项或多项)
- POST:在服务器新建一个资源
- PUT:在服务器更新资源(客户端提供改变后的完整资源)
- PATCH:在服务器更新资源(客户端提供改变属性)
- DELETE:从服务器删除资源
- 过滤,通过在url上传递参数的形式传递过滤条件
- 状态码
常见状态码:
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。 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当做key
{ error:"Invalid API key" }
- 返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范
GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 PATCH /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档
2.Django Rest Framework 框架
Django Rest Framework帮助我们快速构建符合RESTful的数据。通常用于前后端分离项目之间的数据资源传输。
2.1 Serializer的简单使用
serializers序列化器,帮助我们快速序列化在数据库中查询到的数据。
下面通过一个小例子来简单看一下Serializer的使用
表结构model.py
from django.db import models
# Create your models here.
class Publisher(models.Model):
name = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32, )
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=6, decimal_places=2)
pub_date = models.DateTimeField()
pub = models.ForeignKey('Publisher', on_delete=models.CASCADE)
authors = models.ManyToManyField('Author')
路由urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^books/', views.BookListView.as_view()),
]
2.1.1 通过json模块手动序列化
views.py文件
from django.shortcuts import render, HttpResponse
from django.views import View
import json
#使用json模块序列化,时间类型需要单独转成字符串再序列化
class BookListView(View):
def get(self, request, *args, **kwargs):
obj_list = models.Book.objects.all().values('title', 'pub', 'pub_date')
return HttpResponse(json.dumps(list(obj_list), ensure_ascii=False)) # pub_date为日期类型无法json序列化
通过json手动序列化,当数据中有时间类型时,序要单独处理成字符串类型,才能进行序列化。
2.1.2 通过django的JsonResponse
views.py文件
from django.http.response import JsonResponse
#使用JsonResponse对象序列化,可以直接处理时间类型
class BookListView(View):
def get(self, request, *args, **kwargs):
obj_list = models.Book.objects.all().values('title', 'pub', 'pub_date')
return JsonResponse(list(obj_list), safe=False, json_dumps_params={
'ensure_ascii': False}) # safe参数为False:当最外层不为字典时也可序列化,json_dumps_params参数:设置json序列化的参数
JsonResponse类不能对查询到的query_set对象直接序列化,对外键等字段关联对象数据不好处理。
2.1.3 使用django自带的序列化器
views.py文件
#使用django自带的序列化器
from django.core import serializers
class BookListView(View):
def get(self, request, *args, **kwargs):
""" 获取所有的数据 返回所有的书籍数据 json格式"""
# 1. 从数据库获取所有数据
all_books = models.Book.objects.all()
data = serializers.serialize('json', all_books)
return HttpResponse(data)
序列化后的数据格式
[
{
"model": "app01.book",
"pk": 1,
"fields": {
"title": "\u4e5d\u9634\u771f\u7ecf",
"price": "9.99",
"pub_date": "2019-06-04T07:15:56Z",
"pub": 1,
"authors": [
1,2
]
}
},
{
"model": "app01.book",
"pk": 2,
"fields": {
"title": "\u4e5d\u9633\u771f\u7ecf",
"price": "98.30",
"pub_date": "2019-04-16T07:16:39Z",
"pub": 1,
"authors": [
1
]
}
},
{
"model": "app01.book",
"pk": 3,
"fields": {
"title": "\u8475\u82b1\u5b9d\u5178",
"price": "65.50",
"pub_date": "2019-07-25T07:17:09Z",
"pub": 2,
"authors": [
2
]
}
}
]
2.1.4 使用Rest Framework的Response对象
views.py文件
#使用RestFramework 的response对象
from rest_framework.views import APIView
from rest_framework.response import Response
class BookListView(APIView):
def get(self, request, *args, **kwargs):
all_books = models.Book.objects.all().values('title', 'authors__name','pub_date')
print(all_books)
return Response(all_books)
数据格式
[
{
"title": "九阴真经",
"authors__name": "沙和尚",
"pub_date": "2019-06-04T07:15:56Z"
},
{
"title": "九阴真经",
"authors__name": "猪悟能",
"pub_date": "2019-06-04T07:15:56Z"
},
{
"title": "九阳真经",
"authors__name": "沙和尚",
"pub_date": "2019-04-16T07:16:39Z"
},
{
"title": "葵花宝典",
"authors__name": "猪悟能",
"pub_date": "2019-07-25T07:17:09Z"
}
]
2.1.5 使用Rest Framework的序列化器
首先要创建一个序列化器
serializer.py文件
from rest_framework import serializers
class AuthorSerializer(serializers.Serializer): #Author表的序列化器
name = serializers.CharField()
class PublisherSerializer(serializers.Serializer): #Publisher表的序列化器
name = serializers.CharField()
class BookSerializer(serializers.Serializer): #Book表的序列化器
title = serializers.CharField() #普通字段类型和数据库类型相同即可,字段名也要相同
price = serializers.DecimalField(max_digits=6,decimal_places=2)
pub_date = serializers.DateTimeField()
pub = PublisherSerializer() #外键使用,使用定义的序列化器实例化
authors = serializers.SerializerMethodField() #多对多字段,定义get_字段名方法
def get_authors(self,obj): #obj当前表的对象
data_obj = AuthorSerializer(obj.authors.all(),many=True) #多条数据要设置many为True
return data_obj.data #返回对象的data
views.py文件
class BookListView(APIView):
def get(self, request, *args, **kwargs):
all_books = models.Book.objects.all()
ser_obj = BookSerializer(all_books, many=True)#多条数据要设置many为True
return Response(ser_obj.data)#返回对象的data
数据格式:
[
{
"title": "九阴真经",
"price": "9.99",
"pub_date": "2019-06-04T07:15:56Z",
"pub": {
"name": "沙和尚出版社"
},
"authors": [
{
"name": "沙和尚"
},
{
"name": "猪悟能"
}
]
},
{
"title": "九阳真经",
"price": "98.30",
"pub_date": "2019-04-16T07:16:39Z",
"pub": {
"name": "沙和尚出版社"
},
"authors": [
{
"name": "沙和尚"
}
]
},
{
"title": "葵花宝典",
"price": "65.50",
"pub_date": "2019-07-25T07:17:09Z",
"pub": {
"name": "二师兄出版社"
},
"authors": [
{
"name": "猪悟能"
}
]
}
]
2.2 使用Serializer实现简单的增删改
urls.py文件
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^books/', views.BookListView.as_view()), #获取多条数据和添加数据
url(r'^book/(\d+)/', views.BookView.as_view()), #获取单条数据,编辑和删除数据
]
2.2.1 获取多条数据和添加数据
serializer.py文件
from rest_framework import serializers
from app01 import models
class AuthorSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField()
class PublisherSerializer(serializers.Serializer):
name = serializers.CharField()
class BookSerializer(serializers.Serializer):
title = serializers.CharField()
price = serializers.DecimalField(max_digits=6, decimal_places=2)
pub_date = serializers.DateTimeField()
pub = PublisherSerializer(read_only=True) #GET请求时需要的数据设置为只读,POST时可为空
authors = serializers.SerializerMethodField(read_only=True)
post_pub = serializers.IntegerField(write_only=True) #POST和PUT时的数据只写,GET时可为空
post_authors = serializers.ListField(write_only=True)
def get_authors(self, obj):
data_obj = AuthorSerializer(obj.authors.all(), many=True) #多个对象需要many为True
return data_obj.data
def create(self, validated_data): #create方法用于添加数据,validated_data校验完的数据
book_obj = models.Book.objects.create(
title=validated_data.get('title'),
price=validated_data.get('price'),
pub_date=validated_data.get('pub_date'),
pub_id=validated_data.get('post_pub'),
)
book_obj.authors.set(validated_data.get('post_authors'))
return book_obj # 将book对象返回
view.py文件
from app01.serializer import BookSerializer
class BookListView(APIView):
def get(self, request, *args, **kwargs):
all_books = models.Book.objects.all()
obj = BookSerializer(all_books,many=True)
return Response(obj.data)
def post(self,request,*args,**kwargs):
print(request.data)
obj = BookSerializer(data=request.data)
if obj.is_valid(): #对数据进行校验,貌似序列化器里的多对多不会校验
obj.save() #会去序列化器里找create()方法
return Response(obj.data) #校验成功返回添加的数据
return Response({'error': obj.errors}) #校验失败返回错误信息
POST的数据
{
"title": "葵花宝典续集",
"price": "65.50",
"pub_date": "2019-07-25T07:17:09Z",
"post_pub": 1,
"post_authors": [
1
]
}
返回的数据
{
"title": "葵花宝典续集",
"price": "65.50",
"pub_date": "2019-07-25T07:17:09Z",
"pub": {
"name": "沙和尚出版社"
},
"authors": [
{
"id": 1,
"name": "沙和尚"
}
]
}
2.2.2 获取单条数据、编辑和修改
serializer.py文件
class BookSerializer(serializers.Serializer):
title = serializers.CharField()
price = serializers.DecimalField(max_digits=6, decimal_places=2)
pub_date = serializers.DateTimeField()
pub = PublisherSerializer(read_only=True)
authors = serializers.SerializerMethodField(read_only=True)
post_pub = serializers.IntegerField(write_only=True)
post_authors = serializers.ListField(write_only=True)
def get_authors(self, obj):
data_obj = AuthorSerializer(obj.authors.all(), many=True)
return data_obj.data
def create(self, validated_data): # validated_data校验完的数据
book_obj = models.Book.objects.create(
title=validated_data.get('title'),
price=validated_data.get('price'),
pub_date=validated_data.get('pub_date'),
pub_id=validated_data.get('post_pub'),
)
book_obj.authors.set(validated_data.get('post_authors'))
return book_obj # 将book对象返回
def update(self, instance, validated_data): # 修改数据时调用update方法,instance当前要求改的数据对象
instance.title = validated_data.get('title', instance.title)
instance.price = validated_data.get('price', instance.price)
instance.pub_date = validated_data.get('pub_date', instance.pub_date)
instance.pub_id = validated_data.get('post_pub', instance.title)
instance.save()
instance.authors.set(validated_data.get('post_authors',instance.authors.all()))
return instance #返回修改后的数据对象
view.py文件
class BookView(APIView):
def get(self, request,pk, *args, **kwargs):
book = models.Book.objects.filter(pk=pk).first()
obj = BookSerializer(book)
return Response(obj.data)
def put(self,request,pk,*args,**kwargs): #修改资源
book = models.Book.objects.filter(pk=pk).first()
obj = BookSerializer(data=request.data,instance=book)
if obj.is_valid():
obj.save() #保存时会调用序列化器定义好的update()方法
return Response(obj.data) #校验成功返回修改后的对象
return Response(obj.errors)
def delete(self,request,pk,*args,**kwargs): #删除资源
book = models.Book.objects.filter(pk=pk).first()
if book:
book.delete()
return Response({'info':'删除成功'})
return Response({'info': '数据不存在'})
PUT的数据
{
"title": "葵花宝典1",
"price": "63.50",
"pub_date": "2019-07-25T07:17:09Z",
"post_pub": 1,
"post_authors": [
1
]
}
返回的数据
{
"title": "葵花宝典1",
"price": "63.50",
"pub_date": "2019-07-25T07:17:09Z",
"pub": {
"name": "沙和尚出版社"
},
"authors": [
{
"id": 1,
"name": "沙和尚"
}
]
}
原文地址:https://www.cnblogs.com/wang-kai-xuan/p/11247496.html
时间: 2024-10-28 03:38:03