(生鲜项目)18. 用户手机号注册

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

(生鲜项目)18. 用户手机号注册

渱尘   2019-12-28 我要评论

第一步: 前期分析

 

 

可见, 前端会POST过来三个字段, 所以这里我们应该使用 mixins.CreateModelMixin

由于我们自定义的Userprofile中只有name是必填字段(注意:django自带的user中username是必填字段), 所以我们可以在serializers.py中使用 serializers.ModelSerializer

code的验证需要单独的validate_code()方法

  • 并没有向手机号发送验证码, 用户随便输入的   
  • 有发送过验证码, 但是超过了5分钟过期限制
  • 有发送过验证码, 但是用户输错了
  • 如果发送了多条验证码, 应该只核对用户收到的最新的那个验证码

但是有一个问题, 传过来的code是我们Userprofile中没有的字段, 怎么使用ModelSerializer时将code验证并过滤掉?  答:先增加一个code字段, 然后使用全局钩子删掉code这个字段

注意: 上面这个页面, Vue前端post过来的手机号码放在username属性里的,  所以我们在取手机号码的时候, 应该用来self.initial_data["username"]取, 然后我们自己将其复制到mobile属性中去

这里我们还需要学会自定义错误提示信息 error_messages, 

虽然在发送验证码阶段, 已经验证了手机号码是否存在,但在这里由于前端post的是用户名,所以也要对用户名进行去重验证 UniqueValidator,校验是否已经存在

 

 

第二步: 写代码

1.首先写UserSerializer, 专门来处理code的验证, 和Username去重的验证

from rest_framework import serializers
from django.contrib.auth import get_user_model
from rest_framework.validators import UniqueValidator  # 给username字段做查重用

User = get_user_model()  # 可以获取数据库的userprofile表

# 验证码校验
class UserRegSerializer(serializers.ModelSerializer):
    # 由于userprofile并没有code字段,所以先加进来
    code = serializers.CharField(required=True, max_length=4, min_length=4,
                                 # 自定义的错误提示信息
                                 error_messages={
                                     "blank":"你的验证码哪儿去了",  # blank针对的是有字段名,但没有字段值
                                     "required":"请输入验证码",  # required针对的是连字段名都没有
                                     "max_length":"验证码长度错误",
                                     "min_length":"验证码长度错误",
                                 },
                                 help_text="验证码")

    # 虽然在发送验证码阶段, 已经验证了手机号码是否存在,但在这里由于前端post的是用户名,所以也要对用户名进行验证,校验是否已经存在
    username = serializers.CharField(required=True,allow_blank=False,
                                     validators=[UniqueValidator(queryset=User.objects.all(),message="用户已经存在")])

    # 局部钩子, 只对code进行校验
    def validate_code(self, code):
        # POST过来的数据封装在self.initial_data里, 且传递过来手机号的key是username
        # 一定要按时间排序,因为我们只会取最后一条code来验证
        verify_records = VerifyCode.objects.filter(mobile=self.initial_data["username"]).order_by("add_time")

        # 如果验证码存在
        if verify_records:
            # 取最新的那一条验证码
            last_records = verify_records[0]

            # 验证码有效期为5min
            five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)
            if five_minute_ago < last_records.add_time:
                raise serializers.ValidationError("验证码过期")

            # 验证码核对
            if last_records.code != code:
                raise serializers.ValidationError("验证码错误")

        # 如果验证码不存在, 则直接报错
        else:
            raise serializers.ValidationError("验证码错误")

    # 全局钩子, 目的是过滤掉code字段(code其实只用于验证,而不用存在userprofile表中)
    # attrs是局部钩子清洗后的所有字段的dict
    def validate(self, attrs):
        attrs["mobile"] = attrs["username"]
        del attrs["code"]
        return attrs

    class Meta:
        model = User
        fields = ("username", "code", "mobile")

然后是views.UserViewset

# 用户注册逻辑
class UserViewset(CreateModelMixin,viewsets.GenericViewSet):
    serializer_class=UserRegSerializer

别忘记配置url

# 用户注册接口(包含code验证,username去重验证)
router.register(r'users', UserViewset, basename="users")

 

 2. 最后去浏览器验证

 

 

 

 

第三步: 'UserProfile' object has no attribute 'code' 异常处理

1.  现在我们人为往数据库中添加一个手机号和验证码(省钱), 然后尝试着去POST, 最后的结果就是提示userprofile表没有code字段, 前面我们明明已经做的那么好了, 甚至还刻意删掉了code字段, 为什么还是报错???

 

 

 

 

 

 

2. 主要问题处在REST自带的 CreateModelMixin 上, 见下图

 

 

 

 

 

 

 

 

 

---  君子处其实,不处其华;治其内,不治其外   张居正  ----

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们