注册功能接口

注册功能

# 前端传入的数据
	{手机号,验证码,密码}
# 后端要验证数据--->序列化类

#遇到的错误
	1 注册使用哪个序列化了:get_serializer_class
    2 配置文件中debug必须是True,因为咱们有万能验证码--->正常流程这个不需要
    3 把code,弹出来,加入用户名,你可以随机生成用户名
    4 重写create(可以不重写,把密码设为加密的密码),create_user
    5 如果你继承了CreateModelMixin,一定要注意,它会走序列化,所以code字段是只写的

视图类

重写get_serializer_class

class UserView(GenericViewSet, CreateModelMixin):
    serializer_class = LoginUserSerializer
    def get_serializer_class(self):
        if self.action == 'sms_login':
            return LoginUserSMSSerializer
        elif self.action == 'register' or self.action == 'create':
            return UserRegisterSerializer
        else:
            # return super().get_serializer_class()
            return self.serializer_class

方式一:自己写接口

    @action(methods=['POST'], detail=False)
    # 注册接口
    # 自己写的  访问:127.0.0.1:8000/api/v1/user/userinfo/register/   --->post请求即可
    def register(self,  request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return APIResponse(mag='注册成功')

方式二:继承CreateModelMixin

class UserView(GenericViewSet, CreateModelMixin):
# 访问:127.0.0.1:8000/api/v1/user/userinfo/ --->post请求
# 这样调用Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
# 只要调用serializer.data ,就会走序列化,只要走序列化,会把create返回的user对象 来使用UserRegisterSerializer类做序列化
# 就需要在序列化类中code加write_only
code = serializers.CharField(max_length=4, min_length=4, write_only=True)

方式三:继承CreateModelMixin,重写create方法

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data) # 第一个错误  UserRegisterSerializer
        serializer.is_valid(raise_exception=True) # 执行三个校验:字段自己,局部钩子,全局
        self.perform_create(serializer)
        return APIResponse(msg='注册成功') # 不走序列化了,序列类中得write_only 也就不用了

序列化类

# 注册序列化类,注册需要:1.反序列化保存, 2.校验数据, 3.序列化要不要?存疑
class UserRegisterSerializer(serializers.ModelSerializer):
    code = serializers.CharField(max_length=4, min_length=4)

    class Meta:
        model = User
        fields = ['mobile', 'password', 'code']  # code 不是数据库的字段,需要重写

    # 如果要限制密码强度,需要写个局部钩子
    def _check_code(self, attrs):
        mobile = attrs.get('mobile')
        code = attrs.get('code')
        old_code = cache.get('send_sms_code_%s' % mobile)
        if not (code == old_code or (settings.DEBUG and code == '8888')):  # 第二个错误:debug忘了设为True
            raise APIException("验证码错误")

    def _pre_save(self, attrs):  # {mobile:122222,code:8888,password:123}
        attrs.pop('code')
        attrs['username'] = attrs.get('mobile')  # 默认用户名就是手机号  可以随机生成用户名  随机生成有意义的名字( Faker)

    def validate(self, attrs):
        # 写逻辑
        # 1 校验验证码是否正确
        self._check_code(attrs)
        # 2 入口前准备 ---> code不是数据库字段,不能入库,username是数据库字段必填,这里没有,写成默认
        self._pre_save(attrs)
        return attrs

    def create(self, validated_data):  # {mobile:122222,password:123,username:名字}
        # 为什么要重写create? 因为密码人家是加密的,也可以在全局钩子中使用check_password将密码加密
        # User.objects.create(**validated_data)  # 密码是明文,必须重写
        user = User.objects.create_user(**validated_data)  # 保存成功,密码就是加密的
        return user
posted @ 2023-06-28 22:15  星空看海  阅读(16)  评论(0编辑  收藏  举报