路飞项目第五天
- 今天我们来做注册
- 在index里引一下路径
- 获取验证码按钮也做一下
今天我们来做注册
先在components文件夹下创建一个组件Register
Register代码
<template><div class="box"><img src="../../static/image/Loginbg.3377d0c.jpg" alt=""><div class="register"><div class="register_box"><div class="register-title">注册路飞学城</div><div class="inp"><input v-model = "mobile" type="text" placeholder="手机号码" class="user"><input v-model = "password" type="password" placeholder="登录密码" class="user"><input v-model = "sms_code" type="text" placeholder="输入验证码" class="user"><!-- <div id="geetest"></div>滑动验证这里我就不加了 --><button class="register_btn" >注册</button><p class="go_login" >已有账号 <router-link to="/user/login">直接登录</router-link></p></div></div></div></div>
</template><script>
export default {name: 'Register',data(){return {sms_code:"",mobile:"",password:"",validateResult:false,}},created(){},methods:{},};
</script><style scoped>
.box{width: 100%;height: 100%;position: relative;overflow: hidden;
}
.box img{width: 100%;min-height: 100%;
}
.box .register {position: absolute;width: 500px;height: 400px;top: 0;left: 0;margin: auto;right: 0;bottom: 0;top: -120px;
}
.register .register-title{width: 100%;font-size: 24px;text-align: center;padding-top: 30px;padding-bottom: 30px;color: #4a4a4a;letter-spacing: .39px;
}
.register-title img{width: 190px;height: auto;
}
.register-title p{font-family: PingFangSC-Regular;font-size: 18px;color: #fff;letter-spacing: .29px;padding-top: 10px;padding-bottom: 50px;
}
.register_box{width: 400px;height: auto;background: #fff;box-shadow: 0 2px 4px 0 rgba(0,0,0,.5);border-radius: 4px;margin: 0 auto;padding-bottom: 40px;
}
.register_box .title{font-size: 20px;color: #9b9b9b;letter-spacing: .32px;border-bottom: 1px solid #e6e6e6;display: flex;justify-content: space-around;padding: 50px 60px 0 60px;margin-bottom: 20px;cursor: pointer;
}
.register_box .title span:nth-of-type(1){color: #4a4a4a;border-bottom: 2px solid #84cc39;
}.inp{width: 350px;margin: 0 auto;
}
.inp input{border: 0;outline: 0;width: 100%;height: 45px;border-radius: 4px;border: 1px solid #d9d9d9;text-indent: 20px;font-size: 14px;background: #fff !important;
}
.inp input.user{margin-bottom: 16px;
}
.inp .rember{display: flex;justify-content: space-between;align-items: center;position: relative;margin-top: 10px;
}
.inp .rember p:first-of-type{font-size: 12px;color: #4a4a4a;letter-spacing: .19px;margin-left: 22px;display: -ms-flexbox;display: flex;-ms-flex-align: center;align-items: center;/*position: relative;*/
}
.inp .rember p:nth-of-type(2){font-size: 14px;color: #9b9b9b;letter-spacing: .19px;cursor: pointer;
}.inp .rember input{outline: 0;width: 30px;height: 45px;border-radius: 4px;border: 1px solid #d9d9d9;text-indent: 20px;font-size: 14px;background: #fff !important;
}.inp .rember p span{display: inline-block;font-size: 12px;width: 100px;/*position: absolute;*/
/*left: 20px;*/}
#geetest{margin-top: 20px;
}
.register_btn{width: 100%;height: 45px;background: #84cc39;border-radius: 5px;font-size: 16px;color: #fff;letter-spacing: .26px;margin-top: 30px;
}
.inp .go_login{text-align: center;font-size: 14px;color: #9b9b9b;letter-spacing: .26px;padding-top: 20px;
}
.inp .go_login span{color: #84cc39;cursor: pointer;
}
</style>
在index里引一下路径
Login.vue里设置一下路径
Register.vue也是
获取验证码按钮也做一下
去element-ui上找一些样式
相互嵌套一下
效果
接下来校验一下用户输入的手机号
前端先写个点击事件
后端先写一个路由
users/views代码
from django.shortcuts import render# Create your views here.from rest_framework_jwt.views import JSONWebTokenAPIView
from .serializers import CustomJSONWebTokenSerializer
from rest_framework.views import APIViewclass LoginView(JSONWebTokenAPIView):serializer_class = CustomJSONWebTokenSerializerimport re
from rest_framework.response import Response
from rest_framework import status
from .utils import get_user_by_account
class CheckPhoneView(APIView):def post(self,request):phone = request.data.get('phone')# 格式校验if not re.match('1\d{10}',phone):return Response({'error':'手机号码格式有误'},status=status.HTTP_400_BAD_REQUEST)# 校验手机号唯一性ret = get_user_by_account(phone)if ret:return Response({'error': '手机号已被注册'}, status=status.HTTP_400_BAD_REQUEST)return Response({'msg':'ok'})
看看效果
接下来后台要写注册逻辑
先写个路由
再写个视图,users/views代码
from django.shortcuts import render# Create your views here.from rest_framework_jwt.views import JSONWebTokenAPIView
from .serializers import CustomJSONWebTokenSerializer
from rest_framework.views import APIView
from . import modelsclass LoginView(JSONWebTokenAPIView):serializer_class = CustomJSONWebTokenSerializerimport re
from rest_framework.response import Response
from rest_framework import status
from .utils import get_user_by_account
class CheckPhoneView(APIView):def post(self,request):phone = request.data.get('phone')# 格式校验if not re.match('1\d{10}',phone):return Response({'error':'手机号码格式有误'},status=status.HTTP_400_BAD_REQUEST)# 校验手机号唯一性ret = get_user_by_account(phone)if ret:return Response({'error': '手机号已被注册'}, status=status.HTTP_400_BAD_REQUEST)return Response({'msg':'ok'})from rest_framework.generics import CreateAPIView
from .serializers import RegisterModelSerializer
class RegisterView(CreateAPIView):queryset = models.User.objects.all()serializer_class = RegisterModelSerializer
写个序列化器
users/serializers代码
from django.contrib.auth import authenticate, get_user_model
from django.utils.translation import ugettext as _
from rest_framework import serializers
from rest_framework_jwt.compat import Serializerfrom rest_framework_jwt.settings import api_settings
from rest_framework_jwt.compat import get_username_field, PasswordField
import re
from .utils import get_user_by_accountfrom django.contrib.auth.hashers import make_password
from .models import UserUser = get_user_model()
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
jwt_get_username_from_payload = api_settings.JWT_PAYLOAD_GET_USERNAME_HANDLERclass CustomJSONWebTokenSerializer(Serializer):def __init__(self, *args, **kwargs):"""Dynamically add the USERNAME_FIELD to self.fields."""super(CustomJSONWebTokenSerializer, self).__init__(*args, **kwargs)self.fields[self.username_field] = serializers.CharField()self.fields['password'] = PasswordField(write_only=True)self.fields['ticket'] = PasswordField(write_only=True)self.fields['randstr'] = PasswordField(write_only=True)@propertydef username_field(self):return get_username_field()def validate(self, attrs):credentials = {self.username_field: attrs.get(self.username_field),'password': attrs.get('password'),'ticket': attrs.get('ticket'),'randstr': attrs.get('randstr'),}if all(credentials.values()):user = authenticate(self.context['request'], **credentials)if user:if not user.is_active:msg = _('User account is disabled.')raise serializers.ValidationError(msg)payload = jwt_payload_handler(user)return {'token': jwt_encode_handler(payload),'user': user}else:msg = _('Unable to log in with provided credentials.')raise serializers.ValidationError(msg)else:msg = _('Must include "{username_field}" and "password".')msg = msg.format(username_field=self.username_field)raise serializers.ValidationError(msg)# 注册的序列化器
class RegisterModelSerializer(serializers.ModelSerializer):sms_code = serializers.CharField(max_length=6, min_length=4,write_only=True)token = serializers.CharField(max_length=256,read_only=True)class Meta:model = Userfields = ['id','username','phone','password','sms_code','token']extra_kwargs = {'password': {'write_only':True,},'phone': {'write_only': True,},'username':{'read_only': True,},'id':{'read_only': True,}}def validate_phone(self,phone):# 手机号格式校验if not re.match('1\d{10}', phone):raise serializers.ValidationError('手机号格式有误!')# 手机号唯一性校验ret = get_user_by_account(phone)if ret:raise serializers.ValidationError('手机号已经被注册啦!!')return phonedef create(self,validated_data):password = validated_data.get('password')hash_password = make_password(password)user = User.objects.create(**{'phone': validated_data.get('phone'),'password': hash_password,'username': validated_data.get('phone'),})from rest_framework_jwt.settings import api_settingsjwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLERjwt_encode_handler = api_settings.JWT_ENCODE_HANDLERpayload = jwt_payload_handler(user)token = jwt_encode_handler(payload)user.token = token # 给user对象赋属性return user
我们测试一下接口,发现没问题
数据都保存了,接下来该让它注册成功后跳转到首页
前端Register先写个方法
绑定一个点击事件
注册完账户自动登录跳转到首页了
手机号也注册进去了
接下来做一下真正的短信验证码
后台要生成验证码,所以我们先写一个接口
先写个路由
安装一下redis客户端django-redis
pip install django-redis
接下来去dev配置一下让django能连接我们的redis服务端
# 设置redis缓存
CACHES = {# 默认缓存"default": {"BACKEND": "django_redis.cache.RedisCache",# 项目上线时,需要调整这里的路径"LOCATION": "redis://127.0.0.1:6379/0", "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}},# 提供给xadmin或者admin的session存储"session": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379/1","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}},# 提供存储短信验证码"sms_code":{"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379/2","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}}
}# 设置xadmin用户登录时,登录信息session保存到redis
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"