-
新建一个项目:
# 进入git工程目录 django-admin startproject demo_drf
-
使用pycharm打开新建的项目
-
安装drf依赖包
pip install djangorestframework==3.12.1 pip install djangorestframework-jwt==1.11.0 pip install django_filter==2.4.0
-
跨域配置
INSTALLED_APPS = [ ... 'corsheaders', # 跨域 ... ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 跨域 ... ] # 允许所有网站可以访问项目接口 CORS_ORIGIN_ALLOW_ALL = True # CORS跨域请求白名单设置, 只有在白名单中的网站才能访问接口 # CORS_ORIGIN_WHITELIST = ( # 'http://127.0.0.1:8080', # 'http://localhost:8080', # 'http://127.0.0.1:8081', # 'http://localhost:8081', # 'http://0.0.0.0:8080', # 'http://mysyl.com:8080', # ) # 允许携带cookie # CORS_ALLOW_CREDENTIALS = True
-
配置drf的settings
# 过滤器 # 1,安装 django-filter # 2,注册应用 # 3,配置settings, 在view里配置可过滤的字段 # 4,使用 查询字符串携带过滤信息 REST_FRAMEWORK = { # 文档报错: AttributeError: ‘AutoSchema’ object has no attribute ‘get_link’ # 用下面的设置可以解决 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema', # 默认设置是: # 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema', # 异常处理器 # 'EXCEPTION_HANDLER': 'user.utils.exception_handler', # 用户登陆认证方式 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication', # 使用session时的认证器, drfweb页面的认证方式 # 'rest_framework.authentication.BasicAuthentication' # 提交表单时的认证器 ], # 权限配置, 顺序靠上的严格 'DEFAULT_PERMISSION_CLASSES': [ # 'rest_framework.permissions.IsAdminUser', # 管理员可以访问 'rest_framework.permissions.IsAuthenticated', # 认证用户可以访问 # 'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 认证用户可以访问, 否则只能读取 # 'rest_framework.permissions.AllowAny', # 所有用户都可以访问 ], # 限流 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle', ], # 限流策略 'DEFAULT_THROTTLE_RATES': { 'user': '1000/hour', 'anon': '300/day', }, # 全局分页器, 例如 省市区的数据自定义分页器, 不需要分页 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', # 每页返回数量 'PAGE_SIZE': 10, # 默认 None # 过滤器后端 'DEFAULT_FILTER_BACKENDS': [ 'django_filters.rest_framework.DjangoFilterBackend', # 'django_filters.rest_framework.backends.DjangoFilterBackend', 包路径有变化 ], # Filtering 过滤排序 'SEARCH_PARAM': 'search', 'ORDERING_PARAM': 'ordering', # Authentication 认证 # 未认证用户使用的用户类型 'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser', # 未认证用户使用的Token值 'UNAUTHENTICATED_TOKEN': None, } # jwt载荷中的有效期设置 JWT_AUTH = { 'JWT_PAYLOAD_HANDLER': 'rest_framework_jwt.utils.jwt_payload_handler', # headers中 Authorization 值的前缀 'JWT_AUTH_HEADER_PREFIX': 'JWT', # token 有效期 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), 'JWT_ALLOW_REFRESH': True, # token在24小时内过期, 可续期token 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24), # 自定义返回格式,需要手工创建 'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler', }
-
创建book子应用
python manage.py startapp app_book 1. 创建路由 2. 注册路由 3. 注册应用
-
编写模型类
from django.db import models # Create your models here. from django.db import models # 定义图书模型类BookInfo class BookInfo(models.Model): btitle = models.CharField(max_length=20, verbose_name='名称') bpub_date = models.DateField(verbose_name='发布日期') bread = models.IntegerField(default=0, verbose_name='阅读量') bcomment = models.IntegerField(default=0, verbose_name='评论量') is_delete = models.BooleanField(default=False, verbose_name='逻辑删除') class Meta: db_table = 'tb_books' # 指明数据库表名 verbose_name = '图书' # 在admin站点中显示的名称 verbose_name_plural = verbose_name # 显示的复数名称 def __str__(self): """定义每个数据对象的显示信息""" return self.btitle # 定义英雄模型类HeroInfo class HeroInfo(models.Model): GENDER_CHOICES = ( (0, 'female'), (1, 'male') ) hname = models.CharField(max_length=20, verbose_name='名称') hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别') hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息') hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键 is_delete = models.BooleanField(default=False, verbose_name='逻辑删除') class Meta: db_table = 'tb_heros' verbose_name = '英雄' verbose_name_plural = verbose_name def __str__(self): return self.hname
-
迁移生成数据库
python manage.py makemigrations python manage.py migrate
-
使用视图集:modelviewset, 生成接口
1. 编写序列化器 from rest_framework import serializers from app_book.models import BookInfo, HeroInfo # 书籍序列化器 class BookInfoSerializer(serializers.ModelSerializer): class Meta: model = BookInfo # fields = ('id', ) fields = '__all__' # 所有字段 # exclude = ['password'] # 排除 id 字段 # 英雄序列化器 class HeroInfoSerializer(serializers.ModelSerializer): class Meta: model = HeroInfo # fields = ('id', ) fields = '__all__' # 所有字段 # exclude = ['password'] # 排除 id 字段 2. 编写视图集 class BookViewSet(viewsets.ModelViewSet): """ 完成书籍的增删改查 """ queryset = BookInfo.objects.all() # 视图集可以处理的数据 serializer_class = BookInfoSerializer # 处理数据的工具 class HeroViewSet(viewsets.ModelViewSet): """ 完成英雄的增删改查 """ queryset = HeroInfo.objects.all() # 视图集可以处理的数据 serializer_class = HeroInfoSerializer # 处理数据的工具 3. 生成路由 from django.urls import path, re_path, include from app_book import views # 自动生成路由方法, 必须使用视图集 from rest_framework.routers import DefaultRouter router = DefaultRouter() # 有根路由 router.register(r'book', views.BookViewSet) router.register(r'hero', views.HeroViewSet) urlpatterns = [ # 认证地址 path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), ] urlpatterns += router.urls # 把drf生成的路由, 注册到系统路由中
-
创建第一个超级用户(超级管理员)
python manage.py createsuperuser
-
drf界面使用
-
打开 http://127.0.0.1:8001/
-
登录用户
-
3. 访问接口:
4. 各种功能测试
-
给接口增加过滤排序功能
class BookViewSet(viewsets.ModelViewSet): ... # 指定顾虑的处理器, 哪个方法来处理过滤这个事情 # 指定过滤方法类, 排序方法类, 一个或多个 # from django_filters.rest_framework import DjangoFilterBackend # from rest_framework.filters import OrderingFilter filter_backends = (DjangoFilterBackend, OrderingFilter) # 同时支持过滤和排序 # 可以排序的字段有哪些, 指定排序字段, 不设置, 排序功能不起效 ordering_fields = ('id', 'bpub_date') # 可以过滤的字段指定过滤字段, 不设置, 过滤功能不起效 filter_fields = ('btitle', 'is_delete')
前端界面测试过滤排序
-
给接口增加分页功能
# 自定义分页器 class PageNum(PageNumberPagination): # /?page=1 => 进行分页, 取第一页, page_size_query_param = 'page_size' # 如果你写了 /?page_size=5 => 每页5条 page_size = 2 # 默认每页2条 class BookViewSet(viewsets.ModelViewSet): .... # 自定义分页器 覆盖全局配置 pagination_class = PageNum
页面测试分页功能:
-
认证&权限
- 认证: 从前端传回来的 jwt或者 session中, 取到用户信息, 用户id, 1. 取到用户id, 把user保存到了request.user 中, 2.没有取到用户id=>匿名用户
- 权限: 从request 中取user, 然后判断user的类型, adminuser, 认证用户, 还是职员用户, 还是…
-
限流
- 认证用户限流: 按照uid计数(认证用户, 用ip计数, 不准确, )
- 未认证用户限流: 按照ip计数
-
序列化器:
- 一对多序列化
- 一对多反序列化
# 序列化器, 两个方向, 读写 # 序列化数据, 结构化数据 # json 是什么序列化数据 # model, 一行数据, 结构化数据 # 序列化, model=>json 读 # 反序列化, json=>model 写 # 1. 读方向 # 根据前端发送的id, 根据id获取数据库中的数据, 绑定到模型(用数据实例化一个模型), 用序列化器把模型序列化成json # 然后返回给前端. # 2. 写方向 # 前端发送json数据给接口, 接口取到json后, 先用序列号器进行验证, # 验证通过, 进行反序列化, 转换成模型, 根据模型, 更新到数据库
浏览器页面(1, 资源获取 通常是标签获取, 2. form表单推送数据)
js(3. ajax请求)
django view, classView 自己解析数据
前后端分离开发, 推送数据的请求全部变为ajax,
apiview来处理ajax请求, 针对 api接口请求的特点(程序发出的请求, ), 认证, 权限, 限流.
一般而言, ajax发出的数据的都是 json数据, apiview中, 处理了 body中的json数据, 放在了 request.data中.方便使用. Response对象, 一般也是返回json数据, Response接收一个 字典, 转成json后返回.
很多请求都是针对模型进行增删改查, 于是就有了restfull,
获取一个数据, GET /user/pk/ 通过这个访问方式和地址, 就能获取一个 数据的内容
获取一些数据, GET /user/?name=lisi&orderby=age&page=2&page_size=5 就能获取一系列数据
增加一个数据, POST /user/ body:{“name”:“zs”,“age”:18} 就能增加一个数据
修改一个数据, PUT /user/pk/ body:{“name”:“zs”,“age”:19} 就能修改 pk 对应的数据
删除一个数据, DELETE /user/pk/ 就能删除pk对应的数据.
viewset(get, getlist, post, put, delete )
自动识别请求方式, 自动获取路由中的pk, 自动获取body中的数据,
modelViewSet/genricViewset
路由: GET /user/pk/unactive/
get+pk => retrv…
Get /user/pk/unactive/ => unactive
get => list
post => create
put => update
delete => destory