在正常前后端分离开发中均使用DRF框架进行开发
快速开发Restful API接口,是对django的改进,更适用于前后端分离开发
myproject/
├── myproject/ 主文件目录(项目设置)
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── apps/ 模块化APP(接口与数据模型)
│ └── user/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── ddl/ 存储数据表创建sql脚本
├── utils/
│ ├── __init__.py
│ ├── serializers.py # 通用序列化器
│ ├── middleware.py # 中间件 JWT鉴权、日志等
│ ├── request_util.py # 获取请求IP JWT用户信息
│ ├── pagination.py # 自定义分页类
├── config.py 配置文件 填写数据库信息、oauth等配置信息,再在settings.py里调用
├── requirements.txt
├── nginx.conf
└── manage.py
1.安装与配置
pip install djangorestframework
全局设置引入
INSTALLED_APPS = [
'rest_framework',
]
2. 创建app
# 直接创建到项目根目录,再迁移到apps目录内
python manage.py startapp myapp
# 或者直接创建子文件项目到apps文件夹内,需要先创建好myapp文件夹
django-admin startapp myapp apps/myapp
注意:需要将setting.py和apps.py应用名均改为apps.myapp
INSTALLED_APPS = [
...
'rest_framework',
'apps.user',
]
from django.apps import AppConfig
class MyappConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.user'
3. 创建模型并迁移
3.1 基于已有数据库,生成数据库表模型(推荐)
- 设置default数据库mysql配置(其余配置参考文档, 也可以将数据库信息存入config.py,生产部署时再将敏感信息存入环境变量)
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "mydatabase",
"USER": "mydatabaseuser",
"PASSWORD": "mypassword",
"HOST": "127.0.0.1",
"PORT": "5432",
}
}
- 根据数据库自动生成数据模型_使用Django自带inspectdb实现,导出为指定文件_
python manage.py inspectdb > models.py
- 从models.py里复制对应的表数据模型到对应的app的models.py里
3.2 由django创建管理数据库表格(不推荐)
会产生冗余数据表格,由auth和contenttypes内置组件造成,但并不需要,故不推荐
from django.db import models
# Create your models here.
class User(models.Model):
username = models.CharField(max_length=100, unique=True)
email = models.EmailField(unique=True)
def __str__(self):
return self.username
python manage.py makemigrations
python manage.py migrate
3.3 自定义auth用户表(鉴权、权限管理)
若需要使用drf自带的auth鉴权与权限管理,可自定义用户数据表
注意:自定义用户数据表必须在数据库迁移前完成,若项目后期修改会增加大量工作量
- 自定义用户数据表模型
- 在setting中指定用户数据模型
4.序列化与反序列化
序列化: 将 查询集QuerySet (多个模型类的集合)与单个模型类的实例,通过序列化器转化为 json数据(字符串)。
反序列化: 将json格式的字符串数据,通过序列化器转换为Django中的模型类的对象。
4.1 定义序列化器
创建一个名为 serializers.py
序列化会对数据字段进行校验,例如post增加数据时,多格式不符合,则默认返回错误提示
4.1.1 写法1:ModelSerializer 写法
前提:必须已定义数据model,适用于orm连接的数据库
优势:简洁;当不需要自定义校验规则时,可只写meta
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from .models import User
class UserModelSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(),
username = serializers.CharField(max_length = 20),
email = serializers.EmailField(validators=[UniqueValidator(queryset=User.objects.all(),message='邮箱已被注册')])
class Meta:
model = User
fields = ['id', 'username', 'email']
# fields = '__all__'
4.1.2 写法2:serializer 写法(不常用)
优点:不需要设置好model,不需要在meta指定model,即不使用orm操作的数据库连接
class FiltersSerializer(serializers.Serializer):
fid = serializers.IntegerField(source='field_code')
key = serializers.CharField(source='field_en_name')
name = serializers.CharField(source='field_cn_name')
rename = serializers.CharField(source='field_rename')
business_type = serializers.CharField()
dim_data_type = serializers.CharField()
group_id = serializers.IntegerField()
level_index = serializers.IntegerField()
class Meta:
fields = '__all__'
def get_""
5.分页
drf分页共有三种类型默认分页:
- PageNumberPagination 简单分页器
查询方式:?page=3 或 ?page=3&size=10(需要)
参数:page, page_size, max_page_size
- LimitOffsetPagination 偏移分页器
查询方式:?limit=20&offset=100
参数:offset 查询数据起点;limit 每页展示最大数;max_limit 限制最大数量
- CursorPagination 加密分页器
按照给定的排序方式将数据分页,每一页的分界点是另一页中最后一个数据的主键值。这种方式可以实现更为灵活的分页,因为它不受 limit 的限制,可以方便的实现“_无限滚动式”或“加载更多”_式的交互
注:需要的模型有"created"这个字段,否则要手动指定ordering排序才能进行使用
5.1 自定义分页器
若需要实现?page=3&size=10以及自定义返回样式则需要自定义类
自定义类均存放在common/pagination.py内
from rest_framework.pagination import (
PageNumberPagination,
LimitOffsetPagination,
CursorPagination,
)
from rest_framework.response import Response
class CustomPageNumberPagination(PageNumberPagination):
"""重写PageNumberPagination, 实现ModelViewSet可调用、自定义返回样式、实现size控制"""
page_size = 10 # 设置默认每页返回数据量
page_size_query_param = "size" # 自定义page_size在链接中的参数名称
max_page_size = 50 # 设置每页最大数据返回量
# 重写数据分页返回样式
def get_paginated_response(self, data):
currentPage = int(self.get_page_number(self.request, self.page.paginator)) or 1
limit = int(self.get_page_size(self.request)) or 10
total = self.page.paginator.count if self.page else 0
return Response(
{
"page": currentPage,
"limit": limit,
"total": total,
"results": data,
"links": {
"next": self.get_next_link(),
"previous": self.get_previous_link(),
},
}
)
class CustomLimitOffsetPagination(LimitOffsetPagination):
default_limit = 10
limit_query_param = "limit"
offset_query_param = "offset"
max_limit = 50
class CustomCursorPagination(CursorPagination):
page_size = 10
page_size_query_param = "page_size"
cursor_query_param = "cursor"
ordering = "id" # 默认采用“created”进行排序,故自定义排序字段
6.ModelViewSet创建视图(常用)
该方法必须使用django自带orm操作方法,同时需要设置好model和序列化
modelvieset方法已经封装好了常用的方法直接封装成了action,默认action如下:
- list() 提供一组数据
- retrieve() 提供单个数据
- create() 创建数据
- update() 更新数据
- destroy() 删除数据
6.1 接口编写
仅需要配置好model和序列化器,就可直接使用已封装好的五个接口进行增删改查
from rest_framework.viewsets import ModelViewSet
from .models import User
from .serializers import UserModelSerializer
from utils.pagination import CustomPageNumberPagination, CustomLimitOffsetPagination, CustomCursorPagination
class UserModelView(ModelViewSet):
queryset = User.objects.all().order_by("id")
serializer_class = UserModelSerializer
pagination_class = CustomCursorPagination
# 自定义方法
def latest(self, request):
'''获取最后一条记录'''
# 获取模型数据
user = User.objects.latest('id')
# 获取序列化器对象
s = UserModelSerializer(instance=user)
return Response(s.data)
6.2 路由配置
由于每个接口只有一个get,故同时使用
urlpatterns = [
# 常规path
path('user', UserModelView.as_view({'get':'list', 'post': 'create'})),
# 正则path,匹配参数(ModelViewSet默认使用pk进行指定数据操作)
re_path(r'^user/(?P<pk>\d+)$', UserModelView.as_view({'get':'retrieve', 'put': 'update', 'delete': 'destroy'})),
# 自定义action的路由
url(r'^user/latest$', views.BookInfoListAPIView.as_view({'get':'latest'})),
]
7.APIView类视图(不常用)
编辑接口
# views.py
from rest_framework import status
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from rest_framework.views import APIView # 使用APIview进行接口开发
from .models import User
from .serializers import UserModelSerializer #调用序列化器
import json
class UserView(APIView):
"""用户查询、增加、修改、删除
"""
def get(self, request):
user_id = int(request.query_params.get('id'))
user = User.objects.get(pk=user_id)
serializer = UserModelSerializer(user)
return Response({
"status": "success",
"data": serializer.data,
"msg": "数据获取成功"
})
def post(self, request):
serializer = UserModelSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def put(self, request):
data = json.loads(request.body)
user = User.objects.get(pk=data['id'])
user.username = data['username']
user.email = data['email']
user.save()
return Response({
"status": "success",
"msg": "更新成功"
})
def delete(self, request):
user_id = int(request.query_params.get('id'))
user = User.objects.get(pk=user_id)
user.delete()
return Response({
"status": "success"
})
from django.urls import path
from .views import UserView
urlpatterns = [
path('users', UserView.as_view(), name='user'),
]
8.参数获取
body内容
data = json.loads(request.body)
args
request.query_params.get('id')
附录:
RESTful api 规范
1.请求方式分类
- 查询 GET
- 新增 POST
- 更新 PUT
- 删除 DELETE
2.设计规范
常见状态代码
1xx:信息性 - 请求已接收,继续处理
2xx:成功 - 请求已成功被服务器接收、理解并接受
3xx:重定向 - 需要进一步的操作以完成请求
4xx:客户端错误 - 请求有语法错误或请求无法实现
5xx:服务器错误 - 服务器在处理请求时发生了错误
常见的状态码包括:
- 200 OK:请求成功,服务器已经处理并返回了请求的内容。
- 201 Created:请求已经被实现,且有一个新的资源已经依据请求被创建。
- 204 No Content:服务器成功处理了请求,但没有返回任何内容。
- 400 Bad Request:服务器无法处理请求,因为它包含语法错误。
- 401 Unauthorized:请求需要用户验证。
- 403 Forbidden:服务器已经理解请求,但是拒绝执行它。
- 404 Not Found:请求失败,请求的资源在服务器上未找到。
- 500 Internal Server Error:服务器遇到了不知如何处理的情况。
- 503 Service Unavailable:服务器暂时无法处理请求,可能是因为超载或维护