视图集回顾
-GenericAPIView+5个视图扩展类的组合
-ListAPIView,CreateAPIView,DestroyAPIView,RetrieveAPIView,UpdateAPIView
-ListCreateAPIView
-RetrieveDestroyAPIView,RetrieveUpdateAPIView,RetrieveUpdateDestroyAPIView
-class TestView(ListAPIView):
queryset
serializer_calss
-ModelViewSet:GenericViewSet+5个视图扩展类
-路由写法变了的5个接口
-PublishView.as_view({'get':'list','post':'create'})
-自动生成路由:本质:把get和list对应,把post和create对应
-可以重写父类方法,完成自己的定制
-ReadOnlyModelViewSet:2个接口,只读的
-ViewSet:ViewSetMixin+APIView
-GenericViewSet:ViewSetMixin+GenericAPIView
-ViewSetMixin:重写了as_view 路由写法变了
ViewSetMixin+ListAPIView---》自动生成路由
-自动生成路由步骤
-action装饰器---》/publish/被装饰函数名字/ post请求就会执行
- @action(methods=['POST'], detail=False)
class TestView(GenericViewSet):
def list(self, request):
return Response('sdafs')
1 认证组件
1.1 登录功能
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import ViewSetMixin, ViewSet
from rest_framework.response import Response
from rest_framework.decorators import action
from .models import User, UserToken
import uuid
class UserView(ViewSet):
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(username=username, password=password).first()
if user:
token = str(uuid.uuid4())
UserToken.objects.update_or_create(defaults={'token': token}, user=user)
return Response({'code': 100, 'msg': '登录成功', 'token': token, 'username': user.username})
else:
return Response({'code': 101, 'msg': '用户名或密码错误'})
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('user', UserView, 'user')
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(router.urls)),
]
1.2 认证组件
-一些接口,想限制登录后才能访问,没登录不能访问
-做登录认证,限制如果没登录,不允许访问该接口
class BookView(ViewSet):
authentication_classes = [LoginAuth]
request.user
1.2.1 auth.py
from .models import UserToken
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
token = request.query_params.get('token')
user_token = UserToken.objects.filter(token=token).first()
if user_token:
return user_token.user, token
else:
raise AuthenticationFailed('您没有登录')
1.2.2 视图类
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import ViewSetMixin, ViewSet
from rest_framework.response import Response
from rest_framework.decorators import action
from .models import User, UserToken
import uuid
from .auth import LoginAuth
class UserView(ViewSet):
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(username=username, password=password).first()
if user:
token = str(uuid.uuid4())
UserToken.objects.update_or_create(defaults={'token': token}, user=user)
return Response({'code': 100, 'msg': '登录成功', 'token': token, 'username': user.username})
else:
return Response({'code': 101, 'msg': '用户名或密码错误'})
class BookView(ViewSet):
authentication_classes = [LoginAuth]
def list(self, request):
print(request.user.username)
return Response("你好:%s,你看到了好多书啊"%request.user.username)
1.2.3 路由
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('user', UserView, 'user')
router.register('books', BookView, 'books')
urlpatterns = [
path('', include(router.urls)),
]
1.3 小结
-配置在视图类上---》局部使用
-配置文件中配置--》全局使用---》所有接口都必须登录后才能用
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'app01.auth.LoginAuth'
],
}
-局部禁用:
class UserView(ViewSet):
authentication_classes = []
-后端定的,我们这个项目是从请求地址中取
-还可以从请求头或请求体中取
2 权限组件
-由于它的执行是在认证之后,所有从request.user中取出当前等用户,判断权限
class PublishView(ViewSet):
permission_classes = [UserPermission]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'app01.auth.LoginAuth'
],
'DEFAULT_PERMISSION_CLASSES': [
'app01.permissions.UserPermission',
],
}
from rest_framework.permissions import BasePermission
class UserPermission(BasePermission):
def has_permission(self, request, view):
if request.user.user_type == 3:
return True
else:
self.message = '您的用户类型是:%s,您没有权限操作' % (request.user.get_user_type_display())
return False
2.1 django项目国际化
INSTALLED_APPS = [
'rest_framework'
]
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
3 频率组件
'''
'DEFAULT_THROTTLE_RATES': {
'drf_day08': '3/m', # 一分钟访问三次 5/s,m,h,d
},
'''
class PublishView(ViewSet):
throttle_classes = [IPRateThrottle]
'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.IPRateThrottle'],
from rest_framework.throttling import SimpleRateThrottle
'''
'DEFAULT_THROTTLE_RATES': {
'drf_day08': '3/m', # 一分钟访问三次
},
'''
class IPRateThrottle(SimpleRateThrottle):
scope = 'drf_day08'
def get_cache_key(self, request, view):
print(request.META)
return request.META.get('REMOTE_ADDR')
4 排序
- 1 必须写在继承:GenericAPIView 类的视图类中才行
-2 配置类属性:
filter_backends = [OrderingFilter]
ordering_fields=['id','user_type']
-3 使用:规定必须使用ordering 降序带负号
http://127.0.0.1:8000/user/?ordering=user_type
http://127.0.0.1:8000/user/?ordering=-user_type
http://127.0.0.1:8000/user/?ordering=user_type,-id
代码展示
from rest_framework.viewsets import GenericViewSet
from rest_framework.generics import ListAPIView
from rest_framework.mixins import ListModelMixin
from rest_framework.filters import OrderingFilter
from .models import User
from .serializer import UserSerializer
class UserView(GenericViewSet, ListModelMixin):
authentication_classes = []
permission_classes = []
throttle_classes = []
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['id', 'user_type']
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(username=username, password=password).first()
if user:
token = str(uuid.uuid4())
UserToken.objects.update_or_create(defaults={'token': token, 'user': user})
return Response({'code': 100, 'msg': '登录成功', 'token': token})
return Response({'code': 101, 'msg': '用户名或密码错误'})