一:drf中视图集
视图集 | 说明 |
---|---|
ViewSetMixin | 路由写法可以是第二种和第三种 |
GenericViewSet | ViewSetMixin+GenericViewSet 需要和数据库打交道 |
ViewSet | ViewSetMixin+APIView 不需要和数据库打交道的 |
ModelViewSet | GenericViewSet+5个视图扩展类 |
ReadOnlyModelViewSet | GenericViewSet+2个视图扩展类 |
补充
如果不跟数据库打交道:继承APIView
如果想自动生成路由:继承ViewSetMixin
二:登录功能知识点补充
1.如何获取请求头中的数据?
-
从request.META中取 统一:HTTP_请求头大写
-
request.META.get(“HTTP_TOKEN”)
三:权限类的使用
1.思路:
- 1.写一个类,继承BasePermission
- 2.重写has_permission方法
- 3.在方法中校验用户是否有权限(request.user就是当前登录的用户)
- 4.如果有权限,返回True,没有权限,返回False
- 5.self.message 给前端的提示信息
- 6.局部使用,全局使用,局部禁用
from rest_framework.permissions import BasePermission
class UserTypePermission(BasePermission):
def has_permission(self, request, view):
if request.user.user_type == 1:
return True
else:
self.message = '普通用户没有权限'
return False
四:频率类的使用
1.思路:
- 1.写一个类继承SimpleRateThrottle
- 2.重写get_cache_key方法,返回唯一的字符串,会以这个字符串做频率限制
- 3.写一个类属性:scope=‘随便写’, 必须要跟配置文件对象
- 4.在配置文件中写
- ‘DEFAULT_THROTTLE_RATES’:{ ’ 随便写’: ‘3/m’}
- 5.局部配置,全局配置,局部禁用
from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
class MyThrottling(SimpleRateThrottle):
scope='me'
def get_cache_key(self, request, view):
# 返回什么,频率就是什么
return request.META.get('REMOTE_ADDR')
全局配置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES':['app01.throttling.MyThrottling'],
'DEFAULT_THROTTLE_RATES': {
'luffy': '3/m'
}
}
五.认证源码分析:
- 1.入口:APIView的dispatch
self.initial(request, *args, **kwargs)
- 2.APIView的initial中分别是:认证,权限,频率
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
- 3.读认证类源码:APIView的perform_authentication(request)
def perform_authentication(self, request):
request.user # 新的request
- 4.request是新的request—》Request类中找user属性(方法),是个方法包装成了数据属性
来到Request类中找
def user(self):
if not hasattr(self, '_user'): # Request类的对象中反射_user
with wrap_attributeerrors():
self._authenticate() # 第一次会走这个代码
return self._user
- 5.Request的self._authenticate()
def _authenticate(self):
for authenticator in self.authenticators: # 配置在视图类中所有的认证类的对象
try:
#(user_token.user, token)
user_auth_tuple = authenticator.authenticate(self) # 调用认证类对象的authenticate
except exceptions.APIException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator # 忽略
self.user, self.auth = user_auth_tuple # 解压赋值
return
# 认证类可以配置多个,但是如果有一个返回了两个值,后续的就不执行了
self._not_authenticated()
总结:认证类,要重写authenticate方法,认证通过返回两个值或None,认证不通过抛AuthenticationFailed(APIException)异常
六.权限源码分析
- 1.APIView的check_permissions(request)
def check_permissions(self, request):
for permission in self.get_permissions():
# permission是咱们配置在视图类中权限类的对象,对象调用它的绑定方法has_permission
# 对象调用自己的绑定方法会把自己传入(权限类的对象,request,视图类的对象)
if not permission.has_permission(request, self):
self.permission_denied(
request,
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)
- 2.APIVIew的self.get_permissions()
return [permission() for permission in self.permission_classes]
self.permission_classes 就是咱们在视图类中配的权限类的列表
所以这个get_permissions返回的是 咱们在视图类中配的权限类的对象列表[UserTypePermession(),]
总结:重写has_permission方法,有三个参数,为什么一定要return True/False,以及message作用
七:鸭子类型
1.定义:
指的是面向对象中,子类不需要显示继承某个类,只要有某个类中的方法和属性,那就属于这个类
2.推导
假设有个鸭子类,里面有两个方法:run,speak,正统的鸭子类型就是:只有继承了这个鸭子类,就属于这个鸭子类型,不继承的画就不属于这种鸭子类型
但是python不推崇,它推崇的鸭子类型是:不需要显示继承了某个类,只要类中有run和speak方法,这个类就是鸭子类型
使用python中的鸭子类型的写法,方法可能会写错,这样的话就不属于鸭子类型了,python给出了两种解决方案:
- 1.abc模块,装饰后,必须重写方法,补充些将报错
- 2.drf源码中使用的:父类中写这个方法,但没有具体实现,直接抛异常