设为首页 收藏本站
查看: 345|回复: 0

drf实现登录和注册功能

[复制链接]
累计签到:503 天
连续签到:2 天
发表于 2023-2-23 00:46:20 | 显示全部楼层 |阅读模式
# 1、频率限制类()
继承SimpleRateThrottle,scope,重写get_cache_key方法:返回什么就医什么作为key限制,setting中配置
# 2、手机号验证码登录,手机号和验证码
[视图类代码]
class LoginView(ViewSet):
    #
多方式登录,手机,名字,邮箱
    @action(methods=['POST'],detail=False)
    def login(self,request,*args,**kwargs):
        ser=serializer.UserSerializer(data=request.data)
        if ser.is_valid():
            token=ser.context
['token']
            username=ser.context['user'].username# ser.context['user'] 拿到user对象
            return APIResponse(token=token,username=username)
        else:
            return APIResponse(code=0,msg=ser.errors)
    #
单纯校验手机号是否合法,不是登录功能
    @action(methods=['GET'],detail=False) # POST请求也可以,因为装饰器的路径不一样,但是为了练一下get的请求方法
    def check_telephone(self,request,*args,**kwargs):
        telephone=request.query_parms.get('telephone')
        if not re.match('^1
[3-9][0-9]{9}$',telephone):
           return APIResponse(code=0,msg='
手机号不合法')
        try:
            models.User.objects.get(telephone=telephone)
            return APIResponse(result=True)
        except:
            return APIResponse(result='
当前手机号不存在') # APIResponse中我们设置了result如果没有就不会添加到dicdata字段了
    # 非密码,验证码登录
    @action(methods=['POST'],detail=False)
    def code_login(self,request,*args,**kwargs):
        ser=serializer.CodeUserSerializer(data=request.data)
        if ser.is_valid():
            token=ser.context
['token']
            username=ser.context.username
            return APIResponse(token=token,username=username)
        else:
            return APIResponse(code=0,msg=ser.errors)
-----------------------------------------------------------------------------------------------------------------------
[序列化代码(主要逻辑)]
class UserSerializer(serializers.ModelSerializer):
    username=serializers.CharField()
    class Meta:
        model =models.User
        fields=
['username','password','id']
        extra_kwargs={
            'id':{'read_only':True},
            'password':{'write_only':True},
        }
    def validate(self, attrs):
        user=self._get_user(attrs)
        #
签发token
        token =self._get_token(user)
        #
放到context中可以在视图类中取出来
        self.context['token']=token
        self.context
['user']=user

    def _get_user(self,attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        # 多种登录方式
        import re
        if re.match('^1[3-9][0-9]{9}$', username):
            user = models.User.objects.filter(telephone=username).first()
        elif re.match('^.+@.+$', username):  # 邮箱登录
            user = models.User.objects.filter(email=username).first()
        else:
            user = models.User.objects.filter(username=username).first()
        if user:
            ret = user.check_password(password)
            if ret:
                return user
            else:
                raise ValidationError('密码错误')
        else:
            raise ValidationError('用户名不存在')

    def _get_token(self,user):
        from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler
        payload=jwt_payload_handler(user) # 通过user对象获得payload(字典)
        token=jwt_encode_handler(payload)# 通过payload获得token
        return token


class CodeUserSerializer(serializers.ModelSerializer):
    code=serializers.CharField()
    class Meta:
        model =models.User
        fields=
['telephone','code']

    def validate(self, attrs):
        user=self._get_user(attrs)
        # 签发token
        token =self._get_token(user)
        # 放到context中可以在视图类中取出来
        self.context['token']=token
        self.context['user']=user
        return attrs

    def _get_user(self,attrs):
        telephone = attrs.get('telephone')
        code = attrs.get('code')
        # 取出原来的code
        cache_code=cache.get(settings.PHONE_CAHCE_KEY%telephone)
        if cache_code==code:
            if re.match('^1[3-9][0-9]{9}$', telephone):
                user = models.User.objects.filter(telephone=telephone).first()
                if user:
                    # 把使用过的验证码删除
                    cache.set(settings.PHONE_CAHCE_KEY%telephone,'')
                    return user
                else:
                    raise ValidationError('用户不存在')
            else:
                raise ValidationError('手机号不合法')
        else:
            raise ValidationError('验证码错误')

    def _get_token(self,user):
        from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler
        payload=jwt_payload_handler(user) # 通过user对象获得payload(字典)
        token=jwt_encode_handler(payload)# 通过payload获得token
        return token
-----------------------------------------------------------------------------------------------------------------------
# 3、注册接口:
    -1、为什么继承了GenericViewSetCreateModelMixin分析
        -1、首先是注册接口要保存数据所以是要Create方法
        -2、要操作数据库和序列化器保存数据所以是GenericAPIView
        -3、又想让路由可以自动注册所以变成GenericAPIView→GenericViewSet
    -2、一定要写querysetserializer_class
    -3、序列化类=》校验字段
        -class Meta(传给前端的字段)=》注意传给前端不想让前端看到的字段可以携程write_only
        -def validate(字段的校验,全局好写一点)
            -取缓存,校验验证码(可以自己写个验证码)
    -4、重写create,因为model继承的是AbstractUser,存密码的时候是明文,所以要重写create方法
    -5、在序列化类中可以重写create方法,可以控制注册接口返回的参数
        -调用父类的super().create
        -返回的是序列化字段对应的字典
            -username=response.data.get('key')
            -return
[试图类代码实现]
class RegisterView(GenericViewSet,CreateModelMixin):
    queryset = models.User.objects.all()
    serializer_class =serializer.UserRegisterSerializer

    # 为了自定义响应的报文信息,重写create方法(CreateModelMixin方法的)
    def create(self, request, *args, **kwargs):  # 原生父类的create方法
        ser=self.get_serializer(date=request.data)
        if ser.is_valid():
            ser.save()
            return APIResponse(code=1,msg='注册成功',username=ser.data.get('username'))
        else:
            return APIResponse(code=0,msg=ser.errors
[序列化类代码(侏罗纪)]
class UserRegisterSerializer(serializers.ModelSerializer):
    code=serializers.CharField(max_length=4,min_length=4,write_only=True) #
因为code不是系统的字段所以需要重写序列化给前端
    class Meta:
        model =models.User
        fields=
['telephone','code','password']
        extra_kwargs={
            'password':{'max_length':18,'min_length':8}
        }

    def validate(self, attrs):
        telephone=attrs.get('telephone')
        code=attrs.get('code')
        if code==cache.get(settings.PHONE_CAHCE_KEY%telephone):
            # 验证码通过
            if re.match('^1[3-9][0-9]{9}$',telephone):
                attrs['username']=telephone # 把手机号设置为默认名字
                attrs.pop('code') # 把验证码字段去掉,方便保存
                return attrs
            else:
                raise ValidationError('手机号非法')
        else:
            raise ValidationError('验证码错误')

    # 为了加密密码
    def create(self,validated_data):
        user=models.User.objects.create_user(**validated_data) # 重写create方法把密码变成密文,视图类中的save方法保存create是明文的
        return user
# 4redis:应用简介
    -5大数据类型:
    -strhash(接口缓存,hash可以转换类型因为本身是字典),
    -list(分布式):同步调用和异步调用、爬虫一个装地址,一个装信息,实现分布式
    -set,zset(去重、排行榜,热搜,销量,音乐排行榜、评论总量、计算)
    -redis-server 以某个配置文件启动 启动(windows右键管理服务找到也行)
    -redis-cli -h -p

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-1003592-1-1.html 上篇帖子: Django核心(drf总结+代码思路) 下篇帖子: 深度刨析Flask请求上下文
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表