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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
from rest_framework import serializers from rest_framework import exceptions from django.conf import settings from django.core.cache import cache from . import models import re
class MobileLoginSerializer(serializers.ModelSerializer): # 覆盖 mobile = serializers.CharField(required=True, write_only=True) # 自定义 code = serializers.CharField(min_length=6, max_length=6, required=True, write_only=True) class Meta: model = models.User fields = ('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('手机号不存在') return value
def validate(self, attrs): # 验证码校验 - 需要验证码与手机号两者参与 mobile = self._check_code(attrs) # 多方式得到user user = self._get_user(mobile) # user签发token token = self._get_token(user) # token用context属性携带给视图类 self.context['token'] = token # 将登录用户对象直接传给视图 self.context['user'] = user return attrs
def _check_code(self, attrs): mobile = attrs.get('mobile') code = attrs.pop('code') old_code = cache.get(mobile) if code != old_code: raise exceptions.ValidationError({'code': '验证码不正确'}) else: # 验证码的时效性:一旦验证码验证通过,代表改验证码已使用,需要立即失效 # cache.set(settings.SMS_CACHE_KEY % {'mobile': mobile}, '', -1) return mobile
def _get_user(self, mobile): try: return models.User.objects.get(mobile=mobile) except: raise exceptions.ValidationError({'mobile': '手机号不存在'})
def _get_token(self, user): from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) return token
|