后台
urls.py
path('mobile/login/', views.MobileLoginViewSet.as_view({'post': 'login'})),
serializers.py
import re
from django.core.cache import cache
class MobileLoginSerializer(serializers.ModelSerializer):# 覆盖mobile = serializers.CharField(required=True, write_only=True)# 自定义code = serializers.CharField(min_length=4, max_length=4, required=True, write_only=True)class Meta:model = models.Userfields = ('id', 'username', 'icon', 'mobile', 'code')extra_kwargs = {'id': {'read_only': True,},'username': {'read_only': True,},'icon': {'read_only': True,},}# 手机号格式校验(手机号是否存在校验规则自己考量)def validate_mobile(self, value):if not re.match(r'^1[3-9][0-9]{9}$', value):raise exceptions.ValidationError('mobile field error')return valuedef validate(self, attrs):# 验证码校验 - 需要验证码与手机号两者参与mobile = self._check_code(attrs)# 多方式得到useruser = self._get_user(mobile)# user签发tokentoken = self._get_token(user)# token用context属性携带给视图类self.context['token'] = token# 将登录用户对象直接传给视图self.context['user'] = userreturn attrsdef _check_code(self, attrs):mobile = attrs.get('mobile')code = attrs.pop('code')old_code = cache.get(settings.SMS_CACHE_KEY % {'mobile': mobile})if code != old_code:raise exceptions.ValidationError({'code': 'double code error'})else:# 验证码的时效性:一旦验证码验证通过,代表改验证码已使用,需要立即失效# cache.set(settings.SMS_CACHE_KEY % {'mobile': mobile}, '', -1)passreturn mobiledef _get_user(self, mobile):try:return models.User.objects.get(mobile=mobile)except:raise exceptions.ValidationError({'mobile': 'user not exist'})def _get_token(self, user):from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handlerpayload = jwt_payload_handler(user)token = jwt_encode_handler(payload)return token
views.py
class MobileLoginViewSet(ViewSet):# 局部禁用认证、权限组件authentication_classes = ()permission_classes = ()def login(self, request, *args, **kwargs):serializer = serializers.MobileLoginSerializer(data=request.data, context={'request': request})if serializer.is_valid():token = serializer.context.get('token')# 拿到登录用户,直接走序列化过程,将要返回给前台的数据直接序列化好给前台user = serializer.context.get('user')# 返回给前台的数据结果:id,username,icon,tokenresult = serializers.MobileLoginSerializer(user, context={'request': request}).dataresult['token'] = tokenreturn APIResponse(result=result)return APIResponse(1, serializer.errors)