drf基础配置
版本:
Django 3.2
djangorestframework 3.13.1
纯净版配置:
INSTALLED_APPS = [
# 'django.contrib.admin',
# 'django.contrib.auth',
# 'django.contrib.contenttypes',
# 'django.contrib.sessions',
# 'django.contrib.messages',
'django.contrib.staticfiles',
'api.apps.ApiConfig',
'rest_framework'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
# 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
# 'django.contrib.auth.middleware.AuthenticationMiddleware',
# 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
# 'django.contrib.auth.context_processors.auth',
# 'django.contrib.messages.context_processors.messages',
],
},
},
]
REST_FRAMEWORK = {
"UNAUTHENTICATED_USER": None
}
路由
from django.contrib import admin
from django.urls import path
from api import views
urlpatterns = [
# path('admin/', admin.site.urls),
path('users/', views.UserView.as_view()),
]```
###视图
```python
from rest_framework.views import APIView
from rest_framework.response import Response
class UserView(APIView):
def get(self, request):
return Response("...")
request参数:
路径参数
# urls.py
urlpatterns = [
path('users/<str:version>/<int:pid>/',views.UserView.as_view())
]
# views.py
class UserView(APIView):
def get(self, request,version,pid):
print(version,pid)
print(self.kwargs) #{version:'v1','pid':123}
return Response("ok")
drf request对象获取参数示例:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
class MyView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
# 获取路径参数
item_id = kwargs.get('item_id')
# 获取查询参数
search_query = request.query_params.get('search', '')
# 获取请求头
auth_token = request.headers.get('Authorization')
# 获取表单或 JSON 数据
data_field = request.data.get('data_field')
# 获取文件
uploaded_file = request.FILES.get('file')
# 获取用户信息
user = request.user
return Response({
"item_id": item_id,
"search_query": search_query,
"auth_token": auth_token,
"data_field": data_field,
"uploaded_file_name": uploaded_file.name if uploaded_file else None,
"user": {"username": user.username, "email": user.email},
})
认证
#基础类,定义一个认证类,需要实现如下基础类两个方法
class BaseAuthentication:
def authenticate(self, request):
raise NotImplementedError(".authenticate() must be overridden.")
def authenticate_header(self, request):
pass
# 简单实现示例:
from rest_framework.authentication import BaseAuthentication
from api.models import User
class MyAuthentication(BaseAuthentication):
def authenticate(self, request):
token=request.headers.get('token')
user=User.objects.filter(token=token).first()
if user:
return user,token
return None,None
def authenticate_header(self, request):
return 'Token'
源码路径
APIView,dispatch方法会调用self.initial(request, *args, **kwargs)
self.initial会依次调用下面三个方法分别为认证、权限、限流
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
下面我们先看下认证源码,上述的self都是APIView的子类对象, self.perform_authentication(request)调用request.user进入Request对象,调用Request如下方法,self.authenticators是配置在settings.REST_FRAMEWORK下的DEFAULT_AUTHENTICATION_CLASSES属性或者APIView子类的authentication_classes属性配置里,优先取view类里配置的,没有再取settings公共的
def _authenticate(self):
for authenticator in self.authenticators:
try:
user_auth_tuple = authenticator.authenticate(self)
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()
备注:认证类默认前一个未认证会继续下一个,有一个认证成功就会终止认证继续后面逻辑,若认证抛出异常也会终止认证并返回,所有认证都没通过也会继续执行后面逻辑
权限
#自定义权限类,限制某个角色才能访问
from rest_framework.permissions import BasePermission
class PermissionA(BasePermission):
message = {"code": 1003, 'data': "无权访问"}
def has_permission(self, request, view):
if request.user.role == 2:
return True
return False
# 暂时先这么写
def has_object_permission(self, request, view, obj):
return True
源码简单分析:读取当前View类(如:UserView)配置的permission_classes,若未配置则取APIView默认配置settings.REST_FRAMEWORK的DEFAULT_PERMISSION_CLASSES属性
def check_permissions(self, request):
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(
request,
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)
备注:权限类默认有一个失败就返回异常,若想定制满足任意权限,可在APIView子类修改check_permission方法
def check_permissions(self, request):
for permission in self.get_permissions():
if permission.has_permission(request, self):
return #有任一权限返回
#无任何权限通过走此逻辑
self.permission_denied(
request,
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)
限流
class MyRateThrottle(SimpleRateThrottle):
cache = default_cache # 访问记录存放在django的缓存中(需设置缓存)
scope = "user" # 构造缓存中的key
cache_format = 'throttle_%(scope)s_%(ident)s'
'''设置访问频率,例如:1分钟允许访问10次,可在settings全局定义
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES":["xxx.xxx.xx.限流类", ],
"DEFAULT_THROTTLE_RATES": {
"user": "10/m", #与scope对应,没有值会抛出异常
"xx":"100/h"
}
}'''
THROTTLE_RATES = {"user": "10/s"}#没有定义会去全局定义里取
def get_cache_key(self, request, view):
if request.user:
ident = request.user.pk # 用户ID
else:
ident = self.get_ident(request) # 获取请求用户IP(去request中找请求头)
#throttle_user_11.11.11.11
return self.cache_format % {'scope': self.scope, 'ident': ident}
def throttle_failure(self):
wait = self.wait()
detail = {
"code": 1005,
"data": "访问频率限制",
'detail': "需等待{}s才能访问".format(int(wait))
}
raise ThrottledException(detail)
使用限流需要使用django-redis,安装pip install django-redis
# cache缓存配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://192.168.31.125:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100},
'decode_responses': True,
"PASSWORD": "xxxx",
},
}
}
标签:permission,--,self,request,django,限流,user,def
From: https://www.cnblogs.com/liuzhiyangz/p/18653853