django-rest-framework 基础一 RESTful规范和DRF基本使用
django-rest-framework 基础一 RESTful规范和DRF基本使用
1. RESTful 架构
1.1 REST来源
REST全称是Representational State Transfer
,中文意思是表述性状态转移。 它首次出现在2000年Roy Fielding
的博士论文中。他对互联网软件的架构原则,定名为REST
.如果一个架构符合REST
原则,就称它为RESTful
架构。
RESTful
是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中。
RESTful架构原则:
- 每一个URI代表一种资源;
- 客户端和服务器之间,传递这种资源的某种表现层
- 客户端通过四个HTTP动词(GET、POST、PUT、DELETE),对服务器端资源进行操作,实现"表现层状态转化"
1.2 RESTful设计原则
1. 协议
API与用户的通信协议使用HTTPS
协议
2. 域名
API尽量部署在专用域名之下:
https://api.xxx.com
也可以写在主域名下:
https://www.xxx.com/api
3. 版本
把API的版本号放到URL中
https://api.xxx.com/v1/
https://api.xxx.com/v2/
也可以放在将版本号放在HTTP头信息中
# curl https://api.github.com/users/technoweenie -I
> HTTP/2 200
> X-GitHub-Media-Type: github.v3
4. 路径
API的具体网址
在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数。
https://api.xxx.com/v1/books # 获取书籍
https://api.xxx.com/v1/auth # 获取作者
https://api.xxx.com/v1/price # 获取书籍价钱
5. 资源的具体操作类型
对资源的具体操作类型,由HTTP动词表示, 常用的五个HTTP动词:
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源。
两个不常用的HTTP动词
- HEAD:获取资源的元数据。
- OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
示例:
GET https://api.xxx.com/books:列出所有书籍
POST https://api.xxx.com/book:新出一本书
GET https://api.xxx.com/books/ID:获取某个指定书籍的信息
PUT https://api.xxx.com/books/ID:更新某个指定书籍的信息 (提供该书籍的全部信息)
PATCH https://api.xxx.com/books/ID:更新某个指定书籍的信息(提供该书籍的部分信息)
DELETE https://api.xxx.com/books/ID:删除某本书籍
GET https://api.xxx.com/books/ID/price:列出某个指定书籍的价钱
6. 过滤信息
如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果
https://api.xxx.com/books?limit=10:指定返回记录的数量
https://api.xxx.com/books?offset=10:指定返回记录的开始位置。
https://api.xxx.com/books?page=2&per_page=100:指定第几页,以及每页的记录数。
https://api.xxx.com/books?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
https://api.xxx.com/books?book_type_id=1:指定筛选条件
参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复
7. 状态码
服务器向用户返回的状态码和提示信息.
在设计API时一般会自定义一些返回码,所以一般有两种,一种HTTP返回码,一个自定义返回码。
常见HTTP返回码:
1xx:请求正在处理
2xx:请求成功
3xx:重定向 (301永久和302临时)
4xx:客户端错误(404:地址不存在,403:禁止了)
5xx:服务端错误
自定义返回码:
响应体中返回json格式数据包含code或status返回码,返回码和对应信息都为自定义,如:
-1001 :用户名或密码错误
-1002 :没有权限
8.错误处理
如果有报错,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。
{
error: "Invalid API key"
}
9. 返回结果
针对不同操作,服务器向用户返回的结果应该符合以下规范。
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档
但公司不一定遵守这个规范
10. Hypermedia API
RESTful API返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。
{
url: 'https://example.com/onLogin',
data: {
code: res.code
}
}
11. 其他
- API的身份认证应该使用OAuth 2.0框架。
- 服务器返回的数据格式,应该尽量使用JSON,避免使用XML。
2. DRF的基础使用
DRF全称:Django REST framework
目前DRF支持的python
和Django
的版本:
- Python (3.6, 3.7, 3.8, 3.9, 3.10)
- Django (2.2, 3.0, 3.1, 3.2, 4.0)
2.1 安装DRF
使用pip安装:
pip3 install djangorestframework
2.2 Django配置DRF
添加 'rest_framework'
到setting.py
里面的 INSTALLED_APPS
INSTALLED_APPS = [
...
'rest_framework',
]
2.3 利用DRF写出RESTful规范的增删查改接口
models.py文件代码
from django.db import models
# Create your models here.
class Book(models.Model):
name = models.CharField(max_length=128)
auth = models.CharField(max_length=128)
price = models.DecimalField(decimal_places=2, max_digits=5)
"""
增加一个书籍表
数据库迁移:
python3 manage.py makemigrations
python3 manage.py migrate
"""
serializers.py
from rest_framework import serializers
from drftest.models import Book
# 从数据库中读出来的和前端提交过来的数据使用此类进行序列化
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
views.py文件代码
from rest_framework import viewsets, permissions
from drftest.serializers import UserSerializer, GroupSerializer, BookSerializer
from drftest.models import Book
class BookView(viewsets.ModelViewSet):
# 从数据库进出全部数据
queryset = Book.objects.all()
# 序列化的使用的类:BookSerializer
serializer_class = BookSerializer
urls.py
from django.contrib import admin
from django.urls import path
from drftest import views
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'books', views.BookView)
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += router.urls
测试:
使用get拿全部数据:
使用get拿其中某一条数据:
利用put修改数据:
发现需要填写其他的字段,所以put
用于更新全部
局部更新使用PACTH
新增使用POST
:
查看是否新增:
能查到,说明新增成功
删除delete
一条:
返回为空,可以查一下是否删除:
可以看到删除成功。
2.4 DRF request
不用 DRF
之前使用request
里面的post
请求只能接收form-urlencode
和form-data
格式的数据,而且只能是POST
方法
request.POST # Only handles form data. Only works for 'POST' method.
使用DRF里面的request
,可以接收任意数据,而且使用不但能接收POST
方法,还可以接收PUT
和PATCH
方法。
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.