django-rest-framework
目录
频率限制
# 新建频率类继承SimpleRateThrottle以重写其内部的get_cache_key方法,并标明配置名称
from rest_framework.throttling import SimpleRateThrottle
class MyThrottle(SimpleRateThrottle):
scope = 'xxx'
def get_cache_key(self, request, view):# return结果是频率限制的key
return request.META.get('REMOTE_ADDR')
# 局部配置或者全局配置频率类
class BookView(ListAPIView):
throttle_classes = [MyThrottle]
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
pagination_class = MYLimitOffsetPagination
# 全局配置对应名称的频率值限制
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'xxx': '3/m',
},
}
自定义频率
from rest_framework.throttling import BaseThrottle
# 自定义频率类,需要重写两个方法,即allow_request、wait
class IPThrottle(BaseThrottle):
visit_dict = {}
def __init__(self):
self.history_list = []
def allow_request(self, request, view):
ip = request.META.get('REMOTE_ADDR')
ctime = time.time()
if ip not in self.visit_dict:
self.visit_dict[ip] = [ctime,]
return True
self.history_list = self.visit_dict[ip]
while True:
if ctime-self.history_list[-1]>60:
self.history_list.pop()
else:
break
if len(self.history_list)<2: # 配置一个周期内的频次限制
self.history_list.insert(0,ctime)
return True
else:
return False
def wait(self):
ctime = time.time()
return 60 - (ctime-self.history_list[-1])
from utils.throttle1 import IPThrottle
class BookView(ListAPIView):
throttle_classes = [IPThrottle]
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
pagination_class = MYLimitOffsetPagination
JWT
Json Web Token
header+payload+signature
djangorestframework-jwt模块的使用
在继承AbstractUser的用户表模型下使用
# 安装模块
# 新建模型类继承AbstractUser
# settings中配置认证用户模型
AUTH_USER_MODEL = 'api.user'
# 创建超级用户
# 配置路由,在登录入口签发token
from rest_framework_jwt.views import ObtainJSONWebToken
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', ObtainJSONWebToken.as_view()),
]
# 以上是简单使用,如果要在自定义视图类中使用,可以在类中配置:
from rest_framework.permissions import IsAuthenticated
authentication_classes = [JSONWebTokenAuthentication,]
permission_classes = [IsAuthenticated,]
# 如果请求头中没有jwt标准格式的数据或者token不正确,则request.user为空,IsAuthenticated返回False,所以这里是组合使用才能生效
自定义登录接口返回数据(由于之前是使用ObtainJSONWebToken类)
1.自写登录接口
2.用内置
# 源码
def jwt_response_payload_handler(token, user=None, request=None):
"""
Returns the response data for both the login and refresh views.
Override to return a custom response such as including the
serialized representation of the User.
Example:
def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user': UserSerializer(user, context={'request': request}).data
}
"""
return {
'token': token
}
# 重写jwt_response_payload_handler
def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'msg': '成功',
'status': 100
}
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER':'api.auth.jwt_response_payload_handler'
} # settings配置
自定义认证(继承BaseJSONWebTokenAuthentication)
# 新建认证类
from rest_framework import exceptions
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication, jwt_decode_handler
class MyToken(BaseJSONWebTokenAuthentication):
def authenticate(self, request):
token = str(request.META.get('HTTP_AUTHORIZATION')) # 取出token
try:
payload = jwt_decode_handler(token) # 校验是否过期,是否合法,是就返回荷载
except Exception:
raise exceptions.AuthenticationFailed('认证失败')
user = self.authenticate_credentials(payload)
return user, token
# 局部配置
class BookView(APIView):
authentication_classes = [MyToken,]
def get(self, request):
return Response('123')
# 测试,在GET请求头配置key:AUTHORIZATION
# 自定义认证类的返回元组将作为request对象的两个属性
base64编解码
base64.b64encode(bytes)
base64.b64decode(bytes)
开放media
from django.views.static import serve
from django.conf import settings
re_path('media/(?P<path>.*)',serve,{'document_root':settings.MEDIA_ROOT}) # serve即内置视图函数
手动签发token,完成多方式登录
# 自定义序列化器
class LoginModelSerializer(serializers.ModelSerializer):
username = serializers.CharField(max_length=16) # 覆盖数据库字段,避免字段校验
class Meta:
model = models.User
fields = ['username','password']
def validate(self,attrs):
username = attrs.get('username')
password = attrs.get('password')
if re.match('^1[3-9][0-9]{9}$',username):
user=models.User.objects.filter(mobile=username).first()
elif re.match('^.+@.+',username):
user=models.User.objects.filter(email=username).first()
else:
user=models.User.objects.filter(name=username).first()
if user:
if user.check_password(password):
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
self.context['token'] = token
return attrs
else:
raise ValidationError('密码错误')
else:
raise ValidationError('用户不存在')
# 新建登录视图类
class LoginView(ViewSet):
def login(self,request,*args,**kwargs):
login_ser = ser.LoginModelSerializer(data=request.data,context={})
login_ser.is_valid(raise_exception=True)
token = login_ser.context.get('token')
return Response({'status':100,'msg':'登录成功','token':token})
序列化多条(many=True)时,自定义ListSerializer
# 自定义类继承ListSerializer
class MyListSerializer(ListSerializer):
def update(self, instance, validated_data):
l = []
for i in range(len(instance)):
l.append(self.child.update(instance=instance[i],validated_data=validated_data[i]))
return l
# 在序列化器类中配置list_serializer_class
class BookModelSerializer(serializers.ModelSerializer):
# publish = serializers.CharField(source='publish.name') # 反序列化会有问题
class Meta:
list_serializer_class = MyListSerializer
model = models.Book
fields = ('name', 'price', 'authors', 'authors_list', 'publish', 'publish_name', )
# depth = 0
extra_kwargs = {
'publish': {'write_only': True, },
'publish_name': {'read_only': True, },
'authors': {'write_only': True, },
'authors_list': {'read_only': True, },
}
# 视图类中调用
instance_list = [models.Book.objects.filter(id=i.pop('id')).first() for i in request.data]
book_ser = BookModelSerializer(instance=instance_list,data=request.data,many=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return Response(data=book_ser.data)
视图函数给序列化类传数据
book_ser = BookModelSerializer(instance=instance_list,data=request.data,many=True,context={'request':request})
认证组件:校验用户是否登录
写类继承BaseAuthentication,重写authenticate方法,内部写认证逻辑,认证通过,返回两个值一个值给request.user,另一个值给request.auth,认证失败,抛出AuthenticationFailed异常
class MyAuthentication(BaseAuthentication):
def authenticate(self, request):
token = request.META.get('HTTP_TOKEN')
if token:
user = UserToken.objects.filter(token=token).first().user
if user:
return user,'ok'
else:
raise AuthenticationFailed('登录信息校验失败')
else:
raise AuthenticationFailed('未登录')
# 全局使用
from app01.Myauth import MyAuthentication
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'MyAuthentication',
],
}
# 在具体视图类中定义authentica_classes为空列表可以局部禁用
# 局部使用
# 在视图类中定义authentication_classes=[]
权限:校验用户是否有权限进行后续操作
写类继承BasePermission,重写has_permission方法,返回布尔值
# 定义权限类
from rest_framework.permissions import BasePermission
class UserAdminPermission(BasePermission):
def has_permission(self, request, view):
user = request.user
# print(user.get_permissions_display())
if user.permissions == 1: # 超级用户
return True
else:
return False
# 局部使用
class NewBooksView(ListAPIView, CreateAPIView):
permission_classes = [UserAdminPermission]
queryset = Book.objects.all()
serializer_class = NewBookModelSerializer
# 全局使用
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'app01.123.UserAdminPermission',
],
}
# 局部禁用
permission_classes = []
参考
频率:限制用户访问频率
写类继承SimpleRateThrottle,具体见上详述
解析器:即前段传的编码格式能不能解析,默认全配,全部可以解析
响应器:响应格式指定或者自动
过滤器:使用三方模块django-filter
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!