JAVA网络爬虫
HttpClient

导航

 

注册有两种逻辑

  1. 注册以后自己去登入
  2. 注册以后我们帮他直接登入

这里讲解的是第二种, 第一种直接把我第二种添加的代码删除掉就行

  • 前端代码-vue—注册是登入需要name和token–不想注册时直接登入把then下的三行代码删除掉, 留着跳转哪行代码就行

    <input class="btn btn-green" id="jsMobileRegBtn" @click="isRegister" type="button" value="注册并登录">
    
    // isRegister实在methods里的
    isRegister(){
                var that = this;
                register({
                    password:that.password,
                    username:that.mobile ,
                    code:that.code,
                }).then((response)=> {
                  // 我们这种模式是注册以后直接帮他登入了, 如果你想注册以后让他自己登入, 就把下面3行代码注释掉, 留着跳转页面哪行代码就行
                  cookie.setCookie('name',response.data.username,7);
                  cookie.setCookie('token',response.data.token,7)
                  //存储在store
                  // 更新store数据
                  that.$store.dispatch('setInfo');
                  //跳转到首页页面
                  this.$router.push({ name: 'index'})
    
              })
              .catch(function (error) {
                that.error.mobile = error.username?error.username[0]:'';
                that.error.password = error.password?error.password[0]:'';
                that.error.username = error.mobile?error.mobile[0]:'';
                that.error.code = error.code?error.code[0]:'';
              });
            }
    
  • views–不想注册时就登入就把我重写的方法全部删除掉就行了–留着queryset和serializer_class就行

    from django.contrib.auth import get_user_model
    
    from rest_framework.mixins import CreateModelMixin
    from rest_framework import viewsets
    # 返回的响应体
    from rest_framework.response import Response
    # 状态码
    from rest_framework import status
    
    # jwt_payload_handler 是生成payload的
    # jwt_encode_handler 是生成token的
    from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler
    
    from .serializers import UserRegSerializer
    
    # 获取用户模型类
    UserProfile = get_user_model()
    
    
    class UserViewSet(CreateModelMixin, viewsets.GenericViewSet):
        """
        用户注册
        """
        # 会调用ModelSerializer的create或者update方法,
        # 如果继承的是Serializer,就需要自己重载Serializer中的create或者update方法,或者修改mixins的create等方法的逻辑进行保存
        serializer_class = UserRegSerializer
        queryset = UserProfile.objects.all()
    
        # 因为我们是用户注册以后就直接帮用户登入, 所以我们要返回个token, 所以我们要重写create
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            # 我们这里要重载perform_create方法, 因为perform_create没有返回值
            user = self.perform_create(serializer)
    
            # 因为Response返回的是serializer.data, 所以我们应该把token放进去
            re_dict = serializer.data
    
            # 生成payload
            payload = jwt_payload_handler(user)
            # 生成user--JWT的token 并把token添加到serializer.data里, 这样我们Response返回就应该返回re_dict了
            # jwt_encode_handler(payload)生成token
            re_dict["token"] = jwt_encode_handler(payload)
    
            # 因为前端还需要个name
            re_dict["name"] = user.name if user.name else user.username
    
            headers = self.get_success_headers(serializer.data)
            return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
    
        def perform_create(self, serializer):
            # 返回的serializer关联的model对象
            return serializer.save()
    
    
    # 退出我们不用写接口, 因为JWT把token是放在客户端的, 前端只要清楚cookie就ok了
    
  • url

    from django.conf.urls import url, include
    
    from rest_framework.routers import DefaultRouter
    
    from users.views import UserViewSet
    
    # 生成一个注册器实例对象
    router = DefaultRouter()
    
    # 注册用户
    router.register(r'users', UserViewSet, base_name="users")
    
    urlpatterns = [
        # 自动生成url
        url(r"^", include(router.urls)),
    ]
    
    
  • serializer–这里是重写ModelSerializer里的create方法来加密用户密码的, 但是我这里把它注释了, 用的django信号机制解决的, 这样分离性更强

    from datetime import datetime
    from datetime import timedelta
    
    from rest_framework import serializers
    # 导入rest_framework的验证器
    from rest_framework.validators import UniqueValidator
    
    from django.contrib.auth import get_user_model
    
    from .models import VerifyCode
    
    UserProfile = get_user_model()
    
    
    class UserRegSerializer(serializers.ModelSerializer):
        # 因为UserProfile里面没有code字段, 所以我们要加个code字段
        # help_text = "验证码" 提示是验证码
        # label 一个简短的文本字符串,可用作HTML表单字段或其他描述性元素中字段的名称。
        # write_only 将其设置True为确保在更新或创建实例时可以使用该字段,但在序列化表示时不包括该字段。 默认为 False
        code = serializers.CharField(required=True, write_only=True, max_length=4, min_length=4, label="验证码",
                                     error_messages={
                                         # 设置每种错误的错误提示
                                         # blank是指为空
                                         "blank": "请输入验证码",
                                         # required是键都没有才会报这个错误
                                         "required": "请输入验证码",
                                         "max_length": "验证码过长",
                                         "min_length": "验证码过短"
                                     },
                                     help_text="验证码")
    
        # allow_blank=False表示不能为空
        username = serializers.CharField(required=True, allow_blank=False, label="用户名",
                                         validators=[UniqueValidator(queryset=UserProfile.objects.all(), message="用户已经存在")])
    
        # 这里的style把密码设置为密文的, 就像input标签type属性设置为password一样
        # write_only 将其设置True为确保在更新或创建实例时可以使用该字段,但在序列化表示时不包括该字段。 默认为 False
        password = serializers.CharField(
            style={'input_type': 'password'}, label="密码", write_only=True,
        )
    
        # def create(self, validated_data):
        #     # 获取到用户对象, 这个对象是继承了AbstractUser的用户对象
        #     user = super(UserRegSerializer, self).create(validated_data=validated_data)
        #     # 所以这里有set_password方法
        #     user.set_password(validated_data["password"])
        #     # ModelSerializer是有save()方法的, save()方法会调用create函数, 我们在这里重置了create函数, 我们在这里加入里密码设置
        #     user.save()
        #     return user
    
        def validate_code(self, code):
            """
            校验验证码
            :param code: 验证码
            :return: 验证码
            """
    
            # 在ModelSerializer前端传递过来的值都会放在initial_data里
    
            # 校验验证码是否存在, 这里一定要排序, 这样才能获取最后的那条记录 这里的username就是mobile
            verify_records = VerifyCode.objects.filter(code=code, mobile=self.initial_data["username"]).order_by("-add_time")
            if verify_records:
                # 获取到最后一条记录
                last_record = verify_records[0]
    
                # 校验验证码是否过期
                # 获取5分钟前的时间  验证码有效期为5分钟
                five_mintes_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)
    
                if five_mintes_ago > last_record.add_time:
                    raise serializers.ValidationError("验证码过期")
    
                if last_record.code != code:
                    raise serializers.ValidationError("验证码错误")
    
                # 因为code只做验证, 所以这里不用吧code return回来
            else:
                raise serializers.ValidationError("验证码错误")
    
        def validate(self, attrs):
            """
            校验所有的字段
            :param attrs:  attrs是所有字段组成的字典
            :return: attrs
            """
            # 因为mobile值就是username的值, 所以我们把username的值赋值给mobile
            attrs["mobile"] = attrs["username"]
            # 因为我们不需要code字段了, 所以这里可以直接删除
            del attrs["code"]
            return attrs
    
        class Meta:
            model = UserProfile
            # username必填, 因为UserProfile继承了AbstractUser
            # 模型类写了必填, 你序列化的字段写了这个字段的话, 那么前端必须传这个字段的数据
            fields = (
                "username",
                "code",
                "mobile",
                "password"
            )
    
    
  • signals–django型号机制

    # post_save Django中的model对象保存后,自动触发
    from django.db.models.signals import post_save
    from django.dispatch import receiver
    from django.contrib.auth import get_user_model
    
    # 获取用户模型类
    UserProfile = get_user_model()
    
    
    # sender谁传递过来的 接受UserProfile传递过来的
    @receiver(post_save, sender=UserProfile)
    # 在传递过来时它会不是是新建的, 因为update也会传递过来
    # 这里的instance就是我们的UserProfile的对象
    def create_auth_token(sender, instance=None, created=False, **kwargs):
        if created:
            # created为True就代表是新建的
            password = instance.password
            instance.set_password(password)
            instance.save()
    
  • 记住用了django信号机制, 记得在当前应用的apps下写ready方法把写信号机制的文件引入

    from django.apps import AppConfig
    
    
    class UsersConfig(AppConfig):
        name = 'users'
        verbose_name = "用户信息"
    
        def ready(self):
          	# 引入django信号机制所在模块
            import users.signals
    
posted on 2019-09-19 22:55  gmlgxx  阅读(100)  评论(0)    收藏  举报