Django REST Framework (DRF) 是一个用于构建 Web API 的高级、简洁且易于使用的Python库,它是基于著名的Web框架Django而创建的。DRF提供了一套强大的工具和约定,简化了处理HTTP请求和响应的过程,以及序列化数据到JSON格式。它支持常见的RESTful架构模式,如资源定义(Resources)、视图集(ViewSets)、序列化器(Serializers)、认证和授权等。
通过DRF,你可以快速地创建API端点、处理HTTP方法(GET、POST、PUT、DELETE等)、分页和过滤数据、处理文件上传,并且可以轻松集成各种验证策略。DRF还提供了自动化的文档生成,使得开发者和API使用者能够方便地了解API的功能和使用方法。
1.项目初始化
新建Django项目
使用指令构建项目 ------> python manage.py startapp studentweb
新建Python Package命名为app,并将上述指令生成的studentweb 文件夹拖拽到app中并将app文件夹设置为 Sources Root 类型
将项目注册到settings.py下的 INSTALLED_APPS中,并使系统可以定位到app文件夹
2.连接Mysql
安装pymysql ---> pip install pymysql -i https://mirrors.aliyun.com/pypi/simple/
在和settings.py同目录下的__init__.py文件中添加如下配置
import pymysql
pymysql.install_as_MySQLdb()
在settings.py配置Mysql连接信息如下
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '数据库名',
'USER': '用户名',
'PASSWORD': '密码',
'HOST': '地址',
'PORT': '端口'
}
}
3.定义models类
from django.db import models
# Create your models here.
class Faculty(models.Model):
name = models.CharField(verbose_name="学院名称",max_length=100,unique=True,null=False,blank=False)
class Meta:
managed = True
app_label = "studentweb"
db_table = "Stu_Faculty"
def __str__(self):
return "%s" % (self.name)
class Major(models.Model):
name = models.CharField(verbose_name="专业名称",max_length=100,null=False,blank=False)
faculty = models.ForeignKey(verbose_name="所属学院",to=Faculty,on_delete=models.PROTECT)
class Meta:
managed = True
app_label = "studentweb"
db_table = "Stu_Major"
def __str__(self):
return "%s" % (self.name)
class Student(models.Model):
sno = models.CharField(verbose_name="学号", max_length=100, primary_key=True, null=False, blank=False)
name = models.CharField(verbose_name="姓名", max_length=100, null=False, blank=False)
gender = models.CharField(verbose_name="性别", max_length=100, null=True, blank=True, default=None)
birthday = models.DateField(verbose_name="出生日期", null=True, blank=True, default=None)
major = models.ForeignKey(verbose_name="专业", to=Major, on_delete=models.PROTECT)
mobile = models.CharField(verbose_name="电话", max_length=100, null=True, blank=True, default=None)
email = models.CharField(verbose_name="邮箱", max_length=100, null=True, blank=True, default=None)
address = models.CharField(verbose_name="地址", max_length=100, null=True, blank=True, default=None)
image = models.CharField(verbose_name="照片", max_length=100, null=True, blank=True, default=None)
class Meta:
managed = True
app_label = "studentweb"
db_table = "Stu_Student"
def __str__(self):
return "%s" % (self.name)
同步本地至数据库
python manage.py makemigrations
python manage.py migrate
4.路由配置
在app文件下的项目目录中新建一个独立的urls.py,并在与项目名称同名的目录下的urls.py完成访问外部url的配置
# 与项目名称同名的urls.py
# 调用其他app下定义的 url
from django.contrib import admin
from django.urls import path
from django.urls import include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('项目名.urls')),
]
# app文件夹下项目中新建的urls.py
from django.urls import path
urlpatterns = [
]
5.restful接口规范
GET : 从服务器取出资源(一项或多项)
POST : 在服务器新建一个资源
PUT : 在服务器更新资源(客户端提供改变后的完整资源)
PATCH : 在服务器更新资源(客户端提供改变的属性)
DELETE : 从服务器删除资源
# ==================================
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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
# ===================================
针对不同的操作返回不同的结果。这些结果应该符合restful规范:
GET/collection: 返回资源对象的列表(数组)
GET/collection/resource: 返回单个资源对象
POST/collection: 返回新生成的资源对象
PUT/collection/resource: 返回更新后的完整的资源对象
PATCH/collection/resource: 返回更新后的完整资源对象
DELETE/collection/resource: 删除后返回一个空文档
6.DRF的安装与实现
# 安装
pip install djangorestframework==3.13.1 -i https://mirrors.aliyun.com/pypi/simpl
e/
# 注册到settings.py下的 INSTALLED_APPS中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'项目名',
'rest_framework'
]
序列化
- 负责 对象和json格式的相互转换
- 获取数据: 对象 -->Json 返回给前端
- 添加、修改:json --> 对象 存储在数据库中
# 新建serializer.py
# 导入模块
# models中的类与接口转换
from rest_framework import serializers
from studentweb.models import *
# 学院序列化类
class FacultySerializer(serializers.ModelSerializer):
class Meta:
model = Faculty
fields = '__all__'
# 专业序列化类
class MajorSerializer(serializers.ModelSerializer):
class Meta:
model = Major
fields = '__all__'
# 学生序列化类
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = '__all__'
视图
- 实现后台功能的核心早期:视图是基于函数--FBV
- DRF:视图基于类 ---CBV
# views.py定义视图
# 导入模块
# 封装完成的Modelviewset视图集
from rest_framework.viewsets import ModelViewSet
from studentweb.models import *
# 序列化的类
from studentweb.serializer import *
# 学院视图
class FacultyViewSet(ModelViewSet):
queryset = Faculty.objects.all()
serializer_class = FacultySerializer
# 专业视图
class MajorViewSet(ModelViewSet):
queryset = Major.objects.all()
serializer_class = MajorSerializer
# 学生视图
class StudentViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
路由的匹配
# apps中项目下的urls.py
from django.urls import path
from rest_framework.routers import DefaultRouter
from studentweb.views import FacultyViewSet,MajorViewSet,StudentViewSet
# 1.实例化 DefaultRouter
router = DefaultRouter()
# 2.注册 url
# 注册faculty对象
router.register('facultys',FacultyViewSet,basename='facultys')
router.register('majors',MajorViewSet,basename='majors')
router.register('students',StudentViewSet,basename='students')
urlpatterns = [
]
# 3.附加到urlpatterns集合中
urlpatterns += router.urls
运行项目查看效果 python manage.py runserver
7.DRF筛选搜索和分页实现
# 安装筛选插件
pip install django-filter==21.1 -i https://mirrors.aliyun.com/pypi/simple/
# 注册到settings.py下的 INSTALLED_APPS中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'studentweb',
'rest_framework',
'django_filters',
]
# 新建filter.py
# 导入模块
from django_filters import FilterSet,filters
from studentweb.models import Faculty,Major,Student
# Faculty的filter类
class FacultyFilter(FilterSet):
# 重写支持模糊匹配的字段
name = filters.CharFilter(field_name='name',lookup_expr='icontains')
class Meta:
model = Faculty
# 筛选的值为一个时元组中需加上 ','
fields = ('name', )
# Major的filter类
class MajorFilter(FilterSet):
# 重写支持模糊匹配的字段
name = filters.CharFilter(field_name='name', lookup_expr='icontains')
faculty = filters.CharFilter(field_name='faculty', lookup_expr='icontains')
class Meta:
model = Major
fields = ('name','faculty')
# Faculty的filter类
class StudentFilter(FilterSet):
# 重写支持模糊匹配的字段
sno = filters.CharFilter(field_name='sno', lookup_expr='icontains')
name = filters.CharFilter(field_name='name', lookup_expr='icontains')
mobile = filters.CharFilter(field_name='mobile', lookup_expr='icontains')
class Meta:
model = Student
fields = ('sno','name','mobile')
# settings.py 定义筛选的全局变量
# REST Framework 全局设置
REST_FRAMEWORK = {
# 设置全局filter_backends
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
],
}
# 添加到views.py中
# 导入模块
# 封装完成的Modelviewset视图集
from rest_framework.viewsets import ModelViewSet
from studentweb.models import *
from studentweb.serializer import *
# 实现筛选的后台模块
from django_filters.rest_framework import DjangoFilterBackend
# 导入筛选类
from studentweb.filter import FacultyFilter,MajorFilter,StudentFilter
# 学院视图
class FacultyViewSet(ModelViewSet):
queryset = Faculty.objects.all()
serializer_class = FacultySerializer
# 设定筛选的后台
# filter_backends = (DjangoFilterBackend, )
# 指定筛选的类
filter_class = FacultyFilter
# 专业视图
class MajorViewSet(ModelViewSet):
queryset = Major.objects.all()
serializer_class = MajorSerializer
# 设定筛选的后台
# filter_backends = (DjangoFilterBackend,)
# 指定筛选的类
filter_class = MajorFilter
# 学生视图
class StudentViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
# 设定筛选的后台
# filter_backends = (DjangoFilterBackend,)
# 指定筛选的类
filter_class = StudentFilter
效果如下
搜索实现
# settings.py 添加全局搜索配置
# REST Framework 全局设置
REST_FRAMEWORK = {
# 设置全局filter_backends
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
],
# 设置分页
'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE':10
}
# 导入模块
# 封装完成的Modelviewset视图集
from rest_framework.viewsets import ModelViewSet
from studentweb.models import *
from studentweb.serializer import *
# 实现筛选的后台模块
from django_filters.rest_framework import DjangoFilterBackend
# 导入筛选类
from studentweb.filter import FacultyFilter,MajorFilter,StudentFilter
# 导入分页
from studentweb.paginations import MyPageNumberPagination
# 学院视图
class FacultyViewSet(ModelViewSet):
queryset = Faculty.objects.all()
serializer_class = FacultySerializer
filter_class = FacultyFilter
# 专业视图
class MajorViewSet(ModelViewSet):
queryset = Major.objects.all()
serializer_class = MajorSerializer
# 指定筛选的类
filter_class = MajorFilter
# 学生视图
class StudentViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
# 指定筛选的类
filter_class = StudentFilter
# 指定查找匹配的字段
search_fields = ('sno','name')
效果如下
分页实现
方法一:全局配置
# settings.py 定义分页全局变量
# REST Framework 全局设置
REST_FRAMEWORK = {
# 设置全局filter_backends
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
],
# 设置分页
'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE':10
}
方法二:灵活自定义配置
# 新建 paginations.py
# 分页导入
from rest_framework.pagination import PageNumberPagination
class MyPageNumberPagination(PageNumberPagination):
page_size = 5
page_query_param = "page"
page_size_query_param = 'size'
max_page_size = 20
# 导入模块
# 封装完成的Modelviewset视图集
from rest_framework.viewsets import ModelViewSet
from studentweb.models import *
from studentweb.serializer import *
# 实现筛选的后台模块
from django_filters.rest_framework import DjangoFilterBackend
# 导入筛选类
from studentweb.filter import FacultyFilter,MajorFilter,StudentFilter
# 导入分页
from studentweb.paginations import MyPageNumberPagination
# 学院视图
class FacultyViewSet(ModelViewSet):
queryset = Faculty.objects.all()
serializer_class = FacultySerializer
filter_class = FacultyFilter
# 专业视图
class MajorViewSet(ModelViewSet):
queryset = Major.objects.all()
serializer_class = MajorSerializer
# 指定筛选的类
filter_class = MajorFilter
# 学生视图
class StudentViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
# 指定筛选的类
filter_class = StudentFilter
# 指定查找匹配的字段
search_fields = ('sno','name')
# 分页
pagination_class = MyPageNumberPagination
8.Swagger后台项目自动化文档实现
# 安装并注册
pip install drf-yasg -i https://mirrors.aliyun.com/pypi/simple/
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'studentweb',
'rest_framework',
'django_filters',
'drf_yasg'
]
# 与项目名同名的urls.py中配置
from django.contrib import admin
from django.urls import path
# 调用其他app下定义的 url
from django.urls import include
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="管理系统后台API接口文档平台", # 必传
default_version='v1', # 必传
description="这是一个接口文档",
terms_of_service="",
contact=openapi.Contact(email="email@163.com"),
license=openapi.License(name="BSD License"),
),
public=True,
# permission_classes=(permissions.AllowAny,), # 权限类py
)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include('studentweb.urls')),
path('docs/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
]
查看运行效果
# views.py 中定义自动化文档备注
# 导入模块
# 封装完成的Modelviewset视图集
from rest_framework.viewsets import ModelViewSet
from studentweb.models import *
from studentweb.serializer import *
# 实现筛选的后台模块
from django_filters.rest_framework import DjangoFilterBackend
# 导入筛选类
from studentweb.filter import FacultyFilter,MajorFilter,StudentFilter
# 导入搜索模块
from rest_framework.filters import SearchFilter
# 导入分页
from studentweb.paginations import MyPageNumberPagination
# 学院视图
class FacultyViewSet(ModelViewSet):
"""
create:
创建院系信息
retrieve:
获取院系信息详情数据
update:
完整更新院系信息
partial_update:
部分更新院系信息
destroy:
删除院系信息
list:
获取所有院系信息
"""
queryset = Faculty.objects.all()
serializer_class = FacultySerializer
# 设定筛选的后台
# filter_backends = (DjangoFilterBackend, )
# 指定筛选的类
filter_class = FacultyFilter
# 专业视图
class MajorViewSet(ModelViewSet):
"""
create:
创建专业信息
retrieve:
获取专业信息详情数据
update:
完整更新专业信息
partial_update:
部分更新专业信息
destroy:
删除专业信息
list:
获取所有专业信息
"""
queryset = Major.objects.all()
serializer_class = MajorSerializer
# 设定筛选的后台
# filter_backends = (DjangoFilterBackend,)
# 指定筛选的类
filter_class = MajorFilter
# 学生视图
class StudentViewSet(ModelViewSet):
"""
create:
创建院系信息
retrieve:
获取院系信息详情数据
update:
完整更新院系信息
partial_update:
部分更新院系信息
destroy:
删除院系信息
list:
获取所有院系信息
"""
queryset = Student.objects.all()
serializer_class = StudentSerializer
# 分页
pagination_class = MyPageNumberPagination
# 设定筛选的后台
# filter_backends = (DjangoFilterBackend,)
# 设定查找的后台
# filter_backends = (SearchFilter,)
# 指定筛选的类
filter_class = StudentFilter
# 指定查找匹配的字段
search_fields = ('sno','name')
最终效果