一、 用户注册
注册流程:
1. 注册序列化器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
class RegisterSerializer(serializers.ModelSerializer): admin_code = serializers.CharField(default='')
class Meta: model = User fields = ['username', 'password', 'email', 'phone', 'realname', 'admin_code']
def validate(self, attrs): if attrs['admin_code'] and attrs['admin_code'] != 'sqpt': raise ValidationError('错误的admin_code') return attrs
def register(self): in_param = self.data if in_param['admin_code']: in_param.pop('admin_code') user = User.objects.create_superuser(**in_param) else: in_param.pop('admin_code') user = User.objects.create_user(**in_param) return user
|
2. 注册视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@api_view(['POST']) def register(request): serializer = RegisterSerializer(data=request.data) if serializer.is_valid(): user = serializer.register() auth.login(request, user) return Response(status=status.HTTP_201_CREATED,data={'msg': 'reister success', 'retcode': 201,'is_admin': user.is_superuser}) return Response(status=400,data={'msg': 'error', 'error': serializer.errors,'retcode': 400})
|
3. 注册 URL
1
| path('register/', views.register),
|
二、 用户登录
登录流程:
1. 登录序列化器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
class LoginSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['username', 'password',]
def validate(self, attrs): position_params = ['username', 'password'] for param in position_params: if param not in attrs: raise ValidationError(f'缺少参数:{param}') user = auth.authenticate(**attrs) if not user: raise ValidationError('用户名或密码错误') return user
|
2. 登录视图
1 2 3 4 5 6 7 8 9 10 11 12
|
@api_view(['POST']) def login(request): serializer = LoginSerializer(data=request.data) user = serializer.validate(request.data) if user: auth.login(request, user) return Response(status=302, data={'msg': 'success', 'to': 'index.html'}) return Response(status=status.400,data={'msg': 'error', 'error': serializer.errors, 'retcode': status.400})
|
3. 登录 url
1
| path('login/', views.login),
|
4. 渲染器-异常捕获重写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
from rest_framework.exceptions import ValidationError from rest_framework.views import exception_handler
def my_exception_handler(exc, context): response = exception_handler(exc, context) if response: if isinstance(exc, ValidationError): error_msg = exc.detail[0] else: error_msg = exc
response.data = {'msg': 'error', 'retcode': response.status_code, 'error': str(error_msg)}
return response
|
三、 用户登出
流程图:
1. 登出视图
1 2 3 4 5 6 7 8
|
@api_view(['GET']) def logout(request): if request.user.is_authenticated: auth.logout(request) return Response(status=302, data={'msg': 'logout success', 'retcode': 302, 'to': 'login.html'})
|
2. 登出 url
1
| path('logout/', views.logout),
|
3. 获取当前用户信息视图
前后端分离的系统前端部分需要同步后端的访问状态,因此构造一个请求用于检查是否登录
1 2 3 4 5 6 7 8 9 10 11 12
|
@api_view(['GET']) def current_user(request): if request.user.is_authenticated: serializer = UserSerializer(request.user) return Response(serializer.data) return Response(status=status.HTTP_403_FORBIDDEN,data={'retcode':403,'msg':'未登录', 'to': 'login.html'})
|
四、 用户状态效验
1. Django 默认方式
django默认的用户信息存储方案为session机制,有内置的装饰器可以验证当前请求是否携带用户认证信息,
1 2 3 4 5 6
| from django.contrib.auth.decorators import login_required @login_required def list_user(request): ...
|
2. DRF 设置认证方案
可以使用 DEFAULT_AUTHENTICATION_CLASSES
设置全局的默认身份验证方案
1 2 3 4 5 6 7 8 9
|
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ), }
|
①. 基于 APIView 类视图的方式 :
1 2 3 4 5 6 7 8 9 10 11 12 13
|
from rest_framework.authentication import SessionAuthentication,BasicAuthentication from rest_framework.permissions import IsAuthenticated
class ProjectViewSet(viewsets.ModelViewSet): queryset = Project.objects.all() serializer_class = ProjectSerializer authentication_classes = (SessionAuthentication, BasicAuthentication) permission_classes = (IsAuthenticated, IsProjectAdmin)
|
②. 基于函数的视图
1 2 3 4 5 6 7 8 9 10 11 12 13
|
from rest_framework.authentication import SessionAuthentication,BasicAuthentication from rest_framework.permissions import IsAuthenticated
@api_view(['GET']) @authentication_classes((SessionAuthentication, BasicAuthentication)) @permission_classes((IsAuthenticated,)) def user_lest(request): query_set = User.objects.all() serializer = UserSerializer(query_set, many=True) return Response(serializer.data)
|
3. DRF权限方案
①. 定义权限
sqpt/permissions.py
1 2 3 4 5 6 7 8 9 10 11 12
|
from rest_framework import permissions
class IsProjectAdmin(permissions.BasePermission): def has_object_permission(self, request, view, obj): if request.method in permissions.SAFE_METHODS: return True return obj.admin == request.user
|
②. 加入权限
1 2 3 4 5 6 7 8 9 10 11 12
|
from rest_framework.authentication import SessionAuthentication,BasicAuthentication from rest_framework.permissions import IsAuthenticated
class ProjectViewSet(viewsets.ModelViewSet): queryset = Project.objects.all() serializer_class = ProjectSerializer authentication_classes = (SessionAuthentication, BasicAuthentication) permission_classes = (IsAuthenticated, IsProjectAdmin)
|