Django Rest-Framework
Django Rest Framework
1、特点
- 提供了定义序列化器Serializer的方法,可快速根据Django ORM或其他库自动化序列化/反序列化。
- 提供了丰富的类视图,MiXin扩展类,简化视图的编写。
- 丰富的定制层级:函数视图、类视图、视图集合到自动生成API,满足各种需求。
- 多种身份认证和权限认证方式的支持。JWT
- 内置了限流系统
- 直观的API WEB页面
- 可扩展性、插件丰富
2、DRF依赖
Django:1.10、1.11、2.0
Python:2.7、3.2-3.6
测试版本
drf==3.12.2
django==2.2
3、django添加drf配置
# settings.py
INSTALLED_APPS=[
...
'rest_framework',
]
# 报错解决
*AttributeError: 'str' object has no attribute 'decode'*
146行新增:query = query.encode()
4、简单示例
models.py
from django.db import models
class Users(models.Model):
"""models 模型"""
name = models.CharField(max_length=10, null=False, verbose_name='用户名', help_text='提示文本,不能为空')
age = models.IntegerField(verbose_name='年龄')
sex = models.BooleanField(default=1, verbose_name='性别')
user_num = models.CharField(null=True, verbose_name='用户编号', max_length=5)
description = models.TextField(null=True, max_length=1000, verbose_name='个性签名')
class Meta:
db_table = 'tb_users'
verbose_name = '用户'
verbose_name_plural = verbose_name
serializer.py
from rest_framework.serializers import ModelSerializer
from app01 import models
class UsersSerilizer(ModelSerializer):
"""序列化器类"""
class Meta:
model = models.Users
fields = '__all__'
views.py
from django.views import View
from app01 import models
from app01.serialize import UsersSerilizer
from django.http import JsonResponse
class UsersView(View):
"""视图"""
def get(self, request):
users = models.Users.objects.all()
ser_obj = UsersSerilizer(instance=users, many=True)
print(users, '--', type(ser_obj), '--', ser_obj)
return JsonResponse(ser_obj.data, safe=False) # JsonResponse非字典,需要加safe=False
urls.py
url(r'users/', views.UsersView.as_view(), name='users'),
5、序列化器类
1、基础序列化器类Serializer
# 1、models.py
from django.db import models
class Users(models.Model):
name = models.CharField(max_length=10, null=False, verbose_name='用户名', help_text='提示文本,不能为空')
age = models.IntegerField(verbose_name='年龄')
sex = models.BooleanField(default=1, verbose_name='性别')
user_num = models.CharField(null=True, verbose_name='用户编号', max_length=5)
description = models.TextField(null=True, max_length=1000, verbose_name='个性签名')
class Meta:
db_table = 'tb_users02'
verbose_name = '用户02'
verbose_name_plural = verbose_name
# 2、serializer.py
from rest_framework import serializers
class UsersSerializer(serializers.Serializer): # 基础序列化器类Serializer
# 可删减字段
id = serializers.IntegerField()
# name = serializers.CharField()
sex = serializers.BooleanField()
user_num = serializers.CharField()
description = serializers.CharField()
age = serializers.IntegerField()
# 3、urls.py
url(r'index/', views.UsersViews.as_view(), name='index'),
# 4、views.py
from django.http import JsonResponse
from django.views import View
from app02.models import *
from app02.serializer import UsersSerializer
class UsersViews(View):
def get(self, request):
users = Users.objects.all()
ser_obj = UsersSerializer(many=True, instance=users)
print(ser_obj.data, type(ser_obj))
return JsonResponse(ser_obj.data, safe=False, json_dumps_params={'ensure_ascii': False})
2、序列化单条数据
class UsersViews(View):
def get(self, request):
u1 = Users.objects.get(id=1)
ser_obj = UsersSerializer(instance=u1) # 取消 many=True
print(u1, ser_obj.data)
return JsonResponse(ser_obj.data, safe=False, json_dumps_params={'ensure_ascii': False})
3、ModelViewSet
可在页面查询和新增数据。但是不常用。

views.py
from rest_framework.viewsets import ModelViewSet
class UsersView(ModelViewSet): # 继承ModelViewSet 增删改查都包含进去,不需要单独写函数
queryset = models.Users.objects.all()
serializer_class = UsersSerilizer
urls.py
from . import views
from rest_framework.routers import DefaultRouter
urlpatterns = [
]
url_obj = DefaultRouter()
url_obj.register('users1', views.UsersView)
urlpatterns += url_obj.urls
http://127.0.0.1:8000/users1/ # 查询全部
http://127.0.0.1:8000/users1/1/ # 查询id为1
页面查询出来,下面即可修改和删除。

4、序列化器类的【反序列化】功能
进行反序列化的时候,需要对数据进行验证。
APIView 用于前端返回的是json数据,django无法解析。
# models.py
class UsersSerializer2(serializers.Serializer): # 基础序列化器类Serializer
# 可删减拉取的字段
# id = serializers.IntegerField()
name = serializers.CharField(max_length=10, min_length=3)
sex = serializers.BooleanField() # 1、默认约束:required=True 默认有数据 表明必须提交此字段
user_num = serializers.CharField(allow_blank=False) # 是否允许为空(空字符串)
description = serializers.CharField() # allow_null 表示是否允许传入None,默认False
age = serializers.IntegerField(error_messages={'max-length':'太长了','required':'不能没有'})
# 2、多传的参数,序列化器类不会校验,除非在此添加名称
# 3、允许字段为空加上allow_null=True和allow_blank=True
# 4、不管传不传 required=False
# views.py
from app02.serializer import UsersSerializer2
from rest_framework.views import APIView
class UsersViews(APIView):
# get写法不变
def post(self, request):
ser_obj = UsersSerializer2(data=request.data) # 由于用户提交的数据可能是json数据,django无法解析,所以使用drf来解析,需要继承APIView
print(request.POST)
if ser_obj.is_valid(): # 所有字段校验没问题,返回True,其中一个字段校验失败,都会返回False。
print('校验成功之后的数据', ser_obj.validated_data)
return JsonResponse(ser_obj.validated_data)
else:
print('校验失败', ser_obj.error_messages)
return JsonResponse({'errmsg': 'check failed', 'code': '555'})
raise_exception=True
ser_obj.is_valid(raise_exception=True)
is_valid方法还可以在校验失败的时候抛出异常,通过上面的参数开启。
drf抛出异常,向前端抛出HTTP 400 Bad Request。
此报错不够,可以使用自定义校验函数、全局钩子和局部钩子。
context额外参数
在构造serializer对象时,可以通过context添加额外数据。
seri_obj = UserSerializer('users',context={'request':request})
还可通过serializer对象的context属性获取。
例如想在全局钩子函数获取请求路径,也就是request里面的属性。
# 全局钩子
def validate(self, data):
req_path = self.context.get('request').path
5、字段选项参数
max_length 最大长度
min_length 最小长度
-allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最大值
min_value 最小值
# 通用参数
-read_only 表示该字段仅用于序列化,默认False
sex = serializers.BooleanField(read_only=True) # 只是序列化需要,反序列化不校验
-write_only 表示该字段仅用于反序列化,默认False
sex = serializers.BooleanField(write_only=True) # 该字段序列化阶段不会被提取出来,反序列化必须传值过来验证
-required 表示该字段在反序列化时,必须传入
default 反序列化的默认值
-allow_null 表示该字段是否允许传入None值,默认False
validators 该字段使用的验证器
-error_messages 包含错误编号与错误信息的字典
age = serializers.IntegerField(error_messages={'max-length':'太长了','required':'不能没有'})
label 用于html展示API页面时
help_text 用于html展示API页面时
区别:
allow_blank、allow_null、required
空字符串 null或None 传不传参数
6、read_only和write_only
序列化和反序列化可以写在一个class里,通过上面2个参数做区分。
在之后的view里面不需要分开序列化和反序列化,只需要给参数添加上面2个区分即可。
read_only用于序列化
write_only用于反序列化
7、自定义校验函数 validators
# serializers.py
def check_name(val):
"""自定义校验用户名函数"""
if not re.match('a', val):
raise serializers.ValidationError('用户名不是a开头')
return val
class UsersSerializer2(serializers.Serializer):
name = serializers.CharField(validators=[check_name, ]) # 使用自定义校验函数
sex = serializers.BooleanField()
user_num = serializers.CharField()
description = serializers.CharField()
age = serializers.IntegerField()
# views.py
def post(self, request):
ser_obj = UsersSerializer2(data=request.data)
print(request.data)
if ser_obj.is_valid():
return JsonResponse(ser_obj.validated_data)
else:
print('校验失败', ser_obj.errors) # 会打印校验失败的错误
return JsonResponse({'errmsg': 'check failed', 'code': '555'})
8、局部钩子和全局钩子
自定义校验函数无法做到获取额外参数功能。所以引入钩子。
局部钩子
反序列化,先进行参数校验,再进行寻找局部钩子校验。自动调用执行。
字段1参数校验、字段1局部钩子、字段2参数校验、字段2局部钩子,最后执行全局钩子。
class UsersSerializer2(serializers.Serializer):
name = serializers.CharField()
sex = serializers.BooleanField()
user_num = serializers.CharField()
description = serializers.CharField()
age = serializers.IntegerField()
# 局部钩子
def validate_name(self, data): # validate_属性名
if '666' in data:
raise serializers.ValidationError('不能包含666')
return data
def validate_age(self, data):
pass
全局钩子
对校验完成的字段所有字段进行校验。比如校验密码和再次输入密码校验等。
重写validate函数。
class UsersSerializer2(serializers.Serializer):
name = serializers.CharField()
sex = serializers.BooleanField()
user_num = serializers.CharField()
description = serializers.CharField()
age = serializers.IntegerField()
# 全局钩子
def validate(self, data):
p1 = data.pwd1
p2 = data.pwd2
if p1 != p2:
raise ValidationError('两次密码不一样')
return data
9、保存和更新数据
保存数据
# 保存方法1
# views.py
def post(self, request):
ser_obj = UsersSerializer2(data=request.data)
if ser_obj.is_valid(raise_exception=True):
print('校验成功之后的数据', ser_obj.validated_data)
# 1、直接保存
new_obj = Users.objects.create(**ser_obj.validated_data)
obj = UsersSerializer2(instance=new_obj)
return JsonResponse(obj.data)
else:
print('校验失败', ser_obj.errors)
return JsonResponse({'errmsg': 'check failed', 'code': '555'})
# 保存方法2
# views.py
def post(self, request):
ser_obj = UsersSerializer2(data=request.data)
if ser_obj.is_valid(raise_exception=True):
# 2、序列化器类对象可以触发对应的序列化器类的create方法
new_obj = ser_obj.save()
obj = UsersSerializer2(instance=new_obj)
return JsonResponse(obj.data)
else:
print('校验失败', ser_obj.errors)
return JsonResponse({'errmsg': 'check failed', 'code': '555'})
# serializer.py
class UsersSerializer2(serializers.Serializer):
def create(self, validated_data):
"""自定义的create方法"""
obj = Users.objects.create(**validated_data)
return obj
更新数据
# 更新 方式1
# views.py
def put(self, request):
"""更新数据"""
se_obj = UsersSerializer2(data=request.data, partial=True) # partial=True 部分字段校验,传递哪个字段就校验哪个字段,没传递,不校验,即便是必填的
if se_obj.is_valid():
id = request.data.get('id')
objs = Users.objects.filter(id=id)
objs.update(**se_obj.validated_data)
obj = objs.first()
obj = UsersSerializer2(instance=obj)
return JsonResponse(obj.data)
else:
print('校验失败', se_obj.errors)
# 更新 方式2
# views.py
def put(self, request):
"""更新数据"""
user_obj = Users.objects.filter(id=request.data.get('id'))[0]
se_obj = UsersSerializer2(data=request.data, partial=True, instance=user_obj)
if se_obj.is_valid():
# save方法更新
obj = se_obj.save()
obj = UsersSerializer2(instance=obj)
return JsonResponse(obj.data)
else:
print('校验失败', se_obj.errors)
# serializer.py
class UsersSerializer2(serializers.Serializer):
def update(self, instance, validated_data):
"""
:param instance: 是视图查询传递过来的原来对象
:param validated_data: 是用户传递过来需要更新的对象
:return: 返回修改完成的对象
"""
instance.description = validated_data.get('description') # 根据更新的值,来进行获取、最后save
instance.save()
return instance
8、modelSerializer 模型类序列化器类
serializer.py
# serializer.py
from rest_framework import serializers
from app02 import models
class UsersSerializers(serializers.ModelSerializer):
re_pwd = serializers.CharField()
class Meta:
model = models.Users
# fields = ['name', 'age','re_pwd']
fields = '__all__'
# read_only_fields = ('id',)
# write_only_fields = ('id',)
# exclude = ['name', 'age'] # 排除字段
extra_kwargs = { # 自定义
'id': {'read_only': True},
'name': {'max_length': 10,
'error_messages': { # 错误信息
'max_length': '用户名长度太长了'
},
'validators': [], # 自定义校验函数
},
}
def validate_name(self, data): # 局部钩子
pass
def validate(self, data): # 全局钩子
return data
views.py
from rest_framework.views import APIView
from app02 import models
from moapp import serializers
from django.http import JsonResponse
class UsersView(APIView):
def get(self, request):
all_user = models.Users.objects.all()
sobj = serializers.UsersSerializers(instance=all_user, many=True)
return JsonResponse(sobj.data, safe=False)
def post(self, request):
sobj = serializers.UsersSerializers(data=request.data)
if sobj.is_valid():
obj = sobj.save()
obj = serializers.UsersSerializers(instance=obj)
return JsonResponse(obj.data)
else:
print(sobj.errors)
return JsonResponse({'msg': '校验失败'})
6、视图
6.1、APIView 增删改查
class UsersSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
extra_kwargs = {
'id': {
'read_only': True
},
}
6.1.1、查询
6.1.1.1、查询所有
from rest_framework.views import APIView
from app02.models import Users
from vapp.serializer import UsersSerializer
from rest_framework.response import Response
class UsersView(APIView):
# 查询所有数据
def get(self, request):
# 1、request.query_params
# http://127.0.0.1:8000/vapp/users/?a=1&b=2&b=3
print(request.query_params) # url后面跟着?a=1&b=2 取值 ?a=1&b=2&b=3 多选传参
print(request.query_params.get('b')) # getlist('b') 取多值
us = Users.objects.all()
obj = UsersSerializer(instance=us, many=True)
# 2、Response 当浏览器访问时,默认页面效果
# 默认处理了obj
return Response(obj.data)
# Response解析
# Response(data=None, status=None,template_name=None, headers=None,exception=False, content_type=None)
status 响应状态吗 status=status.HTTP_400_BAD_REQUEST
template_name 响应的页面
6.1.1.2、查询单条
urls.py
url(r'users/(?P<pk>\d+)/', views.UsersView.as_view()), # 获取单条数据
views.py
class UsersView(APIView):
def get(self, request, pk):
u1 = Users.objects.get(id=pk)
obj = UsersSerializer(instance=u1)
return Response(obj.data)
6.1.2、新增
views.py
from rest_framework.views import APIView
from app02.models import Users
from vapp.serializer import UsersSerializer
from rest_framework.response import Response
class UsersView(APIView):
# 添加单条数据
def post(self, request):
ser_obj = UsersSerializer(data=request.data)
if ser_obj.is_valid(): # 校验数据
obj = Users.objects.create(**ser_obj.validated_data)
new_obj = UsersSerializer(instance=obj)
return JsonResponse(new_obj.data)
6.1.3、更新
urls.py
url(r'users/(?P<pk>\d+)/', views.UsersView.as_view()),
views.py
class UsersView(APIView):
def put(self, request, pk):
"""更新"""
u1 = Users.objects.get(id=pk)
r_data = request.data
ser_obj = UsersSerializer(instance=u1, data=r_data, partial=True)
# partial=True 会在更新数据时,取消校验,设置其他字段可为空
if ser_obj.is_valid():
instance = ser_obj.save()
obj = UsersSerializer(instance=instance)
return Response(obj.data)
else:
return Response({'error': '更新失败'})

6.1.4、删除
url(r'users/(?P<pk>\d+)/', views.UsersView.as_view()),
views.py
class UsersView(APIView):
def delete(self, request, pk):
"""删除数据"""
Users.objects.get(id=pk).delete()
return Response('', status=status.HTTP_200_OK)
6.2、GenericAPIView
GenericAPIView继承了APIView。实现了5个接口。
url(r'u1/$', views.UsersViewGenericApiView.as_view()),
url(r'u1/(?P<pk>\d+)/', views.UserDetailGenericAPIView.as_view()),
serializer.py
from app02.models import Users
from rest_framework import serializers
class UsersSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
extra_kwargs = {
'id': {
'read_only': True
},
}
views.py
class UsersViewGenericApiView(GenericAPIView):
# 查询全部
queryset = Users.objects # 可根据不同的model,直接修改Users即可
serializer_class = UsersSerializer # 同上
def get(self, request):
"""查询全部"""
user_list = self.get_queryset()
user_ser = self.get_serializer(user_list, many=True)
return Response(user_ser.data)
def post(self, request):
"""新增"""
user_ser = self.get_serializer(data=request.data)
if user_ser.is_valid():
user_ser.save()
return Response(user_ser.data)
else:
return Response({'msg': '新增失败'})
class UserDetailGenericAPIView(GenericAPIView):
queryset = Users.objects
serializer_class = UsersSerializer
def get(self, request, pk):
"""查询单条"""
user = self.get_object()
user_ser = self.get_serializer(user)
return Response(user_ser.data)
def put(self, request, pk):
"""更新单条"""
user = self.get_object()
ser_obj = self.get_serializer(instance=user, data=request.data)
if ser_obj.is_valid():
ser_obj.save()
return Response(ser_obj.data)
else:
return Response({'msg': '更新失败'})
def delete(self, request, pk):
"""删除单条"""
user = self.get_object().delete()
return Response({'msg': '删除成功'})
调用多个不同的序列化器类
get_serializer_class()
views.py
class UsersViewGenericApiView(GenericAPIView):
# 查询全部
queryset = Users.objects
def get_serializer_class(self): # 这里来分配不同的序列化器类
if self.request.method == 'GET':
return UsersSerializer
else:
return UsersSerializer2
def get(self, request):
"""查询全部"""
user_list = self.get_queryset()
user_ser = self.get_serializer(user_list, many=True)
return Response(user_ser.data)
def post(self, request):
user_ser = self.get_serializer(data=request.data)
if user_ser.is_valid():
user_ser.save()
return Response(user_ser.data)
else:
print(user_ser.errors)
return Response({'msg': '新增失败'})
serializer.py
class UsersSerializer(serializers.ModelSerializer):
"""校验所有字段"""
class Meta:
model = Users
fields = '__all__'
extra_kwargs = {
'id': {
'read_only': True
},
}
class UsersSerializer2(serializers.ModelSerializer):
# 校验指定字段
class Meta:
model = Users
fields = ['name', 'age']
extra_kwargs = {
'id': {
'read_only': True
},
}
6.3、视图扩展类接口
5个视图扩展类。
- ListModelMixin 查询全部
- CreateModelMixin 新增数据
- RetrieveModelMixin 查询单条
- UpdateModelMixin 更新单条
- DestroyModelMixin 删除单条
需要和GenericAPIView配合。
urls.py
url(r'u1/$', views.UsersViewGenericApiView.as_view()),
url(r'u1/(?P<pk>\d+)/', views.UserDetailGenericAPIView.as_view()),
views.py
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, \
DestroyModelMixin
class UsersViewGenericApiView(GenericAPIView, ListModelMixin, CreateModelMixin):
# 查询全部
queryset = Users.objects
serializer_class = UsersSerializer
def get(self, request):
"""查询全部"""
return self.list(request)
def post(self, request):
"""添加单条数据"""
return self.create(request)
class UserDetailGenericAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Users.objects
serializer_class = UsersSerializer
def get(self, request, pk):
"""查询单条"""
return self.retrieve(request, pk)
def patch(self, request, pk): # 使用put更新需要把所有数据提供过来,才可以更新
"""更新单条"""
return self.update(request, pk)
def delete(self, request, pk):
"""删除单条"""
return self.destroy(request, pk)
6.4、基于GenericAPIView视图子类的接口
from rest_framework.generics import ListAPIView, CreateAPIView, RetrieveAPIView, UpdateAPIView, DestroyAPIView
class UsersViewGenericApiView(ListAPIView, CreateAPIView):
queryset = Users.objects.all()
serializer_class = UsersSerializer
class UserDetailGenericAPIView(RetrieveAPIView, UpdateAPIView, DestroyAPIView):
queryset = Users.objects.all()
serializer_class = UsersSerializer
6.5、视图基类ViewSet
使用视图基类,可讲一系列相关参数放到一个类中。
- list() 提供一组数据
- retrieve() 提供单个数据
- create() 创建数据
- update() 更新数据
- destory 删除数据
ViewSet不再实现get、post等方法,而是实现动作action,如list()、create()等。视图只在使用as_view()方法,才将action动作与具体请求方式对应上。
好处:可以把所有方法写到一个类中,不用获取全部和获取单条都写在2个类中。
urls.py
url(r'u2/$', views.UsersViewGenericApiView.as_view({'get': 'get_all_users'})),
url(r'u2/(?P<pk>\d+)/', views.UsersViewGenericApiView.as_view({'get': 'get_single_user'})),
views.py
class UsersViewGenericApiView(ViewSet):
def get_all_users(self, request):
users = Users.objects.all()
us_obj = UsersSerializer(instance=users, many=True)
return Response(us_obj.data)
def get_single_user(self, request, pk):
u1 = Users.objects.get(id=pk)
obj = UsersSerializer(instance=u1)
return Response(obj.data)
def post(self,request):
pass
6.6、视图基类和视图扩展类合并
urls.py
url(r'u2/$', views.UsersViewGenericApiView.as_view({'get': 'list', 'post': 'create'})),
url(r'u2/(?P<pk>\d+)/',
views.UsersViewGenericApiView.as_view({'get': 'retrieve', 'delete': 'destory', 'patch': 'update'})),
views.py
class UsersViewGenericApiView(ViewSet, GenericAPIView, ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin,
DestroyModelMixin):
queryset = Users.objects.all()
serializer_class = UsersSerializer
# 进一步优化
class UsersViewGenericApiView(ModelViewSet):
queryset = Users.objects.all()
serializer_class = UsersSerializer
6.7、视图集中定义附加action动作
url(r'stu/login/',views.UserModelViewSet.as_view({'get':'login'}))
views.py
class UsersViewGenericApiView(ModelViewSet):
queryset = Users.objects.all()
serializer_class = UsersSerializer
def login(self,request):
pass
7、路由Routers
drf提供了2个router。
区别是没有APIRoot。统一路径入口。
7.1、SimpleRouter
urls.py
from rest_framework.routers import DefaultRouter, SimpleRouter
router = SimpleRouter()
router.register('users', views.UsersViewGenericApiView)
urlpatterns += router.urls
views.py
from rest_framework.viewsets import ModelViewSet
class UsersViewGenericApiView(ModelViewSet):
queryset = Users.objects.all()
serializer_class = UsersSerializer
7.2、DefaultRouter
常用。
urls.py
from rest_framework.routers import DefaultRouter, SimpleRouter
router = DefaultRouter()
router.register('users', views.UsersViewGenericApiView)
urlpatterns += router.urls
views.py
from rest_framework.viewsets import ModelViewSet
class UsersViewGenericApiView(ModelViewSet):
queryset = Users.objects.all()
serializer_class = UsersSerializer
7.2.1、defaultrouter附加action动作
需要处理业务数据,单独定义函数。
urls.py
from . import views
from rest_framework.routers import DefaultRouter, SimpleRouter
urlpatterns = []
router = DefaultRouter()
router.register('users', views.UsersViewGenericApiView)
urlpatterns += router.urls
views.py
from rest_framework.decorators import action
class UsersViewGenericApiView(ModelViewSet):
queryset = Users.objects.all()
serializer_class = UsersSerializer
@action(methods=['get'], detail=False) # detail=True是处理单条数据 其他情况都是False
def books(self, request):
return Response({'msg': 'xxx'})
8、认证Authentication
和admin一样,使用的是一套session认证。
默认全局认证,每个请求都需要认证,需要添加白名单。
全局认证类
# settings.py
REST_FRAMEWORK = {
# 认证
'DEFAULT_AUTHENTICATION_CLASSES': [
'chapp.utils.my_auth.Auth', # 自定义认证类
'rest_framework.authentication.SessionAuthentication', # 基于session认证
'rest_framework.authentication.BasicAuthentication', # 基础认证
],
}
# my_auth.py 自定义认证方法
from rest_framework.authentication import BasicAuthentication
from rest_framework.exceptions import AuthenticationFailed
class Auth(BasicAuthentication):
def authenticate(self, request):
if 1 == 1:
return 'request.user', 'request.auth' # 返回用户信息 认证信息
else:
raise AuthenticationFailed('认证失败')
# views.py
class UUU(APIView):
def get(self, request):
print(request.user) # 调用认证返回的用户信息 调用返回认证信息
print(request.auth)
return Response({'msg': 'ok'})
局部认证类
# views.py
class UUU(APIView):
authentication_classes = [Auth,] # 指定认证类
def get(self, request):
print(request.user)
print(request.auth)
return Response({'msg': 'ok'})
9、权限 Permissions
权限控制可以限制用户对于视图的访问和对于具体的数据对象的访问。
- 在执行视图的dispatch()方法前,对视图访问权限进行判断
- 在通过get_object()获取具体对象时,对模型对象访问权限进行判断
提供的权限
- AllowAny
- IsAuthenticated 仅通过认证的用户。只能简单的判断用户是否为注册用户而无法进行更细致的判断。
# my_prom.py 自定义权限类
from rest_framework.permissions import BasePermission
class Prom(BasePermission):
def has_permission(self, request, view):
print('这是promission')
return True
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'chapp.utils.my_promiss.Prom', # 自定义权限配置 全局组件
'rest_framework.permissions.AllowAny', # 默认权限
],
}
# views.py
class UUU(APIView):
permission_classes = (IsAuthenticated, Prom) # 权限 Prom自定义用户权限 局部权限
def get(self, request):
print(request.user)
print(request.auth)
return Response({'msg': 'ok'})
10、限流 Throttling
对接口的访问频次进行限制,减轻服务器压力。
一般用于付费购买次数。
settings.py 全局配置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'', # 可自定义限流类
'rest_framework.throttling.AnonRateThrottle', # 匿名用户,未登录的
'rest_framework.throttling.UserRateThrottle', # 登录之后的用户
),
'DEFAULT_THROTTLE_RATES': { # 可使用second、minute、hour或者day[smhd]
'anon': '100/day', # 或100/m
'user': '100/day'
}
}
views.py 局部类配置
from rest_framework.throttling import UserRateThrottle
class UUU(APIView):
throttle_classes = (UserRateThrottle,)
def get(self, request):
return Response({'msg': 'ok'})
可选限流类
AnonRateThrottle
限制所有匿名未认证用户,使用IP区分。
UserRateThrottle
限制认证用户,使用user id来区分。
自定义限流类
import time
from rest_framework.throttling import BaseThrottle
visit_recode = {}
class MySelfBaseThrottling(BaseThrottle):
"""10秒之内只能访问3次"""
# 限制访问时间
VISIT_TIME = 10
# 访问次数
VISIT_COUNT = 3
def allow_request(self, request, view):
id = request.META.get('REMOTE_ADDR') # 获取IP
self.now = time.time() # 现在时间
if id not in visit_recode:
visit_recode[id] = []
self.history = visit_recode[id] # 访问历史
# 限制访问时间 要求上次访问时间-这次访问时间 >10s
while self.history and self.now - self.history[-1] > self.VISIT_TIME:
self.history.pop() # 删除最后一条上次登录记录
if len(self.history) >= self.VISIT_COUNT:
return False
else:
self.history.insert(0, self.now)
return True
def wait(self):
return self.history[-1] + self.VISIT_TIME - self.now
11、过滤 Filtering
使用django-filter增强支持。
pip install django-filter
settings.py
INSTALLED_APPS = [
...
'django_filters',
]
REST_FRAMEWORK={
...,
'DEFAULT_FILTER_BACKENDS':('django_filter.rest_framework.DjangoFilterBackend',)
}
views.py
class StudentListView(ListAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer()
filter_fields = ('age', 'sex')
url
127.0.0.1:8000/app01/students/?sex=1
12、排序
对于排序,drf提供了OrderingFilter过滤器来帮助进行指定字段进行排序。
class StudentListView(ListAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer()
filter_backends = [OrderingFilter]
ordering_fields = ('id','age')
url
127.0.0.1:8000/app01/students/?ordering=-age
-age 降叙
age 升序
过滤之后再排序
class StudentListView(ListAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer()
filter_fields = ('age','sex')
# 由于filterbackend是局部过滤,局部过滤会覆盖全局过滤,需要过滤组件核心类再次声明。
filter_backends = (OrderingFilter,DjangoFilterBackend)
ordering_fields= ('id','age')
url
127.0.0.1:8000/students/?sex=18&ordering=-age
13、分页 Pagination
settings.py
# 全局分页 一旦设置了全局分页 drf视图扩展类里面的list方法提供的列表页都会产生分页的数量,一般不用全局
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100
自定义分页类
# 自定义分页类
class CusPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'size' # 可控制每页获取多少条数据
page_query_param = 'page_size'
max_page_size = 100 # 一页最多显示多少条
# 视图
class UsersListView(RetrieveAPIView):
queryset = Users.objects.all()
serializer_class = UsersSerializer()
pagination_class = CusPagination
# pagination_class = None # 关闭分页
127.0.0.1:8000/users/?page_size1=10
LimitOffsetPagination
通过偏移量获取数据

14、异常处理
统一异常处理。
settings.py
REST_FRAMEWORK={
# 自定义配置
'EXCEPTION_HANDLER':'chapp.utils.exceptions.create_exception_handler'
# 默认配置 rest_framework.views.exception_handler
}
create_exception_handler.py
from rest_framework.views import exception_handler
from chapp.utils.my_excep import APIError
def create_exception_handler(exc, context): # 自定义错误处理函数
"""
:param exc: 错误处理对象
:param context: 异常发生的上下文信息
:return:
"""
# 先调用drf默认异常处理方法,获得标准的错误响应对象
response = exception_handler(exc, context) # 此函数提供了一些错误,如果无法处理,他会返回None,则需要我们自己处理错误
if response is None:
view = context['view'] # 出错的方法或者函数名称
if isinstance(exc, APIError):
# 记录错误信息,一般记录到文件中,可以使用日志系统来记录
return Response({'msg':'自定义API错误'},status=500)
if isinstance(exc, DatabaseError):
return Response({'msg':'服务器内部错误'},status=status.HTTP_507_INSUFFICENT_STORAGE)
else:
return response
return response
class APIError(Exception):
pass
15、自动生成接口文档
需要 coreapi 库支持。
pip install coreapi
设置接口文档访问路径
在总路由中添加接口文档路径。
文档路由对应的视图配置为 rest_framework.documentation.include_docs_urls
from rest_framework.documentation import include_docs_urls
urlpatterns = [
url('docs/',include_docs_urls(title='站点页面标题'))
]
错误信息:AutoSchema object has no attribute get link
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS':'rest_framework.schemas.AutoSchema'
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现