一个Django项目(注册逻辑)

商城项目

  • 登录注册页面
    • view.py中书写处理代码
    • urls.py跳转逻辑,注意项目下的urls.py也需要对应的配置
    • 新建一个serializers.py写检验逻辑
    • 用jq输写注册页面的js内容
    • 注册用户并存入数据库
    • urls.py配置路径
    • 新建一个serializers.py自定义校验内容:

此项目是为了实现注册页面的一些基本功能,只要是看看后端如何实现和前后端如何交互的

登录注册页面

想要登入注册页面并且交互,需要分别开启前后端服务器,这里我们通过live_server来开启前端页面(关于前端服务器的安装详细内容,请点击了解)https://blog.csdn.net/weixin_43158056/article/details/90757939

这里注册页面的HTML和CSS不是重点,后端的实现才是重点
一个Django项目(注册逻辑)_第1张图片
主要内容:显示图片验证码点击时图片验证码能够自动切换和判断验证码对错,并且会通过手机接收短信验证码
首先,在django项目中建立一个image模块,此模块用来实现一些验证码的操作

view.py中书写处理代码

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from django.http import HttpResponse
from rest_framework.response import Response
from shanghui.libs.captcha.captcha import captcha
import random
from shanghui.libs.yuntongxun.sms import CCP



from . import constants
from .serializers import ImageTextSerializers
import redis
from django_redis import get_redis_connection




# Create your views here.
class ImageView(APIView):
    def get(self, request, image_id):
        # 1.生成图片验证码
        text,image = captcha.generate_captcha()
        print('============')
        print(text)
        #print(image)
        # 2.要保存验证码上面的文字部分
        #配置redis数据库
        #conn = redis.Redis( host='localhost', port=6379,db=2)
        #保存数据
        #conn.set(image_id ,text,1000)


        #todo 2.1连接校验专用的redis数据库
        redis_con_obj = get_redis_connection('verification_code')
        #todo 2.2插入数据到redis,但需要设置过期时间
        redis_con_obj.setex(image_id,constants.IMAGE_UUID_REDIS_EXPIRES,text)

        # 3.返回图片验证码
        return HttpResponse(image,content_type='image/jpg')

class MsgView(GenericAPIView):
    #serializer_class指明使用序列化器
    serializer_class = ImageTextSerializers
    def get(self,request):
        # 1.校验图片验证码
        print(request.query_params)
        #获取查询的参数
        query_dict = request.query_params
        # 获取serializer_class指定的序列化器对象,并且进行序列化的实例化
        serializer = self.get_serializer(data=query_dict)
        #进行校验
        serializer.is_valid(raise_exception=True)


        # 2.在5分钟不在重复发送(利用redis可以设置过期时间的特点,将表示在5分钟内发送短信个的标志设置放入redis)
        # redis中标志的例子 13111111111 flag:1
        # 3.生成短信验证码
        msg = '%04d'%random.randint(0,9999)
        print('生成的短信验证码',msg)
        # 4.保存短信验证码
        #todo 2.1连接校验专用的redis数据库
        redis_con_obj = get_redis_connection('verification_code')
        #todo 2.2插入数据到redis,但是需要设置过期时间
        phone = query_dict['phone']
        redis_con_obj.setex('%s_msg'%phone,constants.PHONE_FLAG_CODE_EXPIRES,msg)
        redis_con_obj.setex('%s_flag'%phone,constants.PHONE_FLAG_CODE_EXPIRES,1)
        # todo 5.发送短信
        ccp = CCP()
        ret_data=ccp.send_template_sms(phone,[msg,constants.PHONE_FLAG_CODE_EXPIRES],1)
        #send_template_sms(self, to, datas, temp_id):
        # @param datas 内容数据 格式为数组 例如:{'12','34'},如不需替换请填 ''
        print('=====================================================')
        print(ret_data)

        # 6.返回相应的响应数据
        return Response('123123ok')

urls.py跳转逻辑,注意项目下的urls.py也需要对应的配置

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^image_code/(?P[\w-]+)/$',views.ImageView.as_view()),
    url(r'^msg_code/',views.MsgView.as_view()),

]

新建一个serializers.py写检验逻辑

from rest_framework import serializers
from django_redis import get_redis_connection


class ImageTextSerializers(serializers.Serializer):
    image_id = serializers.UUIDField()
    image_text = serializers.CharField(max_length=4, min_length=4)
    phone = serializers.CharField(min_length=11, max_length=11)

    def validate(self, attrs):
        print('********************************************')
        print(attrs)
        image_id_uuid = attrs['image_id']
        image_input_text = attrs['image_text']
        phone = attrs['phone']
        print(image_id_uuid)
        print(image_input_text)
        print(phone)

        # 验证用户输入的图片验证码的文字
        # todo 从redis数据库中取出正确的验证码文字
        redis_con_obj = get_redis_connection('verification_code')
        print(image_id_uuid)
        # '%s'%image_id_uuid 将uuid的数据类型bytes转成string
        correct_image_text = redis_con_obj.get('%s' % image_id_uuid)
        # 注意点:从redis里面取出的数据是bytes类型的
        print('真正的验证码文字', correct_image_text)

        # todo 将用户输入的验证码与真实的验证码对比
        correct_image_text = correct_image_text.decode()

        if correct_image_text.lower() != image_input_text.lower():
            raise serializers.ValidationError('图片验证码错误')

        # todo 取出该手机号码对应的发送标志,如果能取到,说明已经在5分钟内发送过了
        # 获取手机号
        flag = redis_con_obj.get('%s_flag' % phone)
        if flag:
            raise serializers.ValidationError('在5分钟内请勿重复发送')

        return attrs


用jq输写注册页面的js内容

新建一个register.js页面

function uuid() {
    /*这是生成uuid的函数*/
    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";

    var uuid = s.join("");
    return uuid;
};

    var current_id = '';

function getImageCode() {
    //这个函数生成新的uuid,并且在前端中将验证码对应的src替换掉
    var uuid_data = uuid();
    current_id = uuid_data;
    $('#img_code').attr('src', 'http://127.0.0.1:8000/image/image_code/' + uuid_data + '/')



  }

$(function () {
    getImageCode();//ajaxPostfunc();
    $('#msg_req').click(function () {
        //1.请求路径
        // 获取uuid的输入的文字验证码,电话号码
        image_id = current_id;
        image_text = $('#mytext').val();
        phone = $('#phone').val();


        // 获取的数据进行正则的校验
        reg_uuid =/^[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}$/;
        reg_text =/^[\w]{4}$/;
        reg_phone =/^1[3456789]\d{9}$/;
        console.log(reg_uuid.exec(image_id));
        alert(image_id);
        console.log(reg_uuid.test(image_id));

        //利用正则进行校验,如果校验不通过,则返回弹窗
        if (!reg_uuid.test(image_id)){
            alert('图片地址校验未通过');
            return
        }
        if (!reg_text.test(image_text)){
            alert('验证码校验未通过');
            return
        }
        if (!reg_phone.test(phone)){
            alert('手机号码校验未通过');
            return
        }
        //拼接的是向后端提交申请短信验证码的请求路径
        msgurl = 'http://127.0.0.1:8000/image/msg_code/?image_id='+image_id+'&image_text='+image_text+'&phone='+phone
        console.log(msgurl);

    //2.发送AJAX请求
        $.ajax({
            url:msgurl,
            type:'GET',
            contentType:'application/json',
            success:function (data) {
                alert('请求成功');
                console.log(data);
                },
            error:function (data) {
                 alert('发送失败');
                console.log(data)
            }

            });

    });


    //给注册按钮书写单击事件,先后端提交数据
    $('#ajaxPost').click(function () {
        //alert('ok')
        //todo 获取到所有需要提交的数据
        //获取用户名
        username = $('#username').val();
        //密码
        pas = $('#password').val();
        //确认密码
        cpas = $('#cpassword').val();
        //手机号码
        phone = $('#phone').val();
        //邮箱
        email = $('#email').val();
        //短信验证码
        msg_code = $('#msg_code').val();

        //获取勾选值
         checkbox = $('#checkbox2').prop('checked');
         console.log(msg_code)
        //是否同意用户隐私
       if (!checkbox){
            alert('你需要同意用户隐私协议');
            return
        }
        //todo 将获取的数据进行校验
        //校验用户名
        if (!username){
            alert('用户名不能为空');
            return
        }
        //校验密码是否相同
        if(pas!=cpas){
            alert('您输入的两次密码不一致')
            return
        }
         if (!phone){
            alert('手机号码不能为空');
            return
        }
         if (!email){
            alert('邮箱不能为空');
            return
        }
         if (!msg_code){
            alert('短信验证码不能为空');
            return
        }
        if (!checkbox){
            alert('你需要同意用户隐私协议');
            return
        }


        //todo 将获取到的数据拼接成json数据(前后端交互一般使用json形式) 
        var data= {
            'username':username,
            'password':pas,
            'cpas':cpas,
            'phone':phone,
            'email':email,
            'msg_code':msg_code,
            'checkbox':checkbox
        };
        console.log('object');
        console.log(data);
        // alert(data);
        //todo 拼接object 对象为json数据
        var data_json = JSON.stringify(data);
        console.log(data_json);
        console.log(typeof (data_json));

        //todo 使用ajax提交POST请求
        $.ajax({
            url:'http://127.0.0.1:8000/user/register/',
            type:'POST',
            data:data_json,
            contentType:'application/json',
            dataType:'json',
            success:function (data) {
                alert('注册成功');
                console.log(data);
                //object
                console.log(typeof (data));
                 //取值
                token = data['token'];
                //清空本地token
                localStorage.clear();
                //基于浏览器的连接情况
                //sessionStorage
                //长期有效
                localStorage.token = token;

                alert('注册成功')
                //location.href='http://127.0.0.1:8000';
                },
            error:function (data) {
                 alert('注册失败');
                console.log(data);
                console.log(token)
            }
            });

    })
    });

注册用户并存入数据库

前端用ajax发送,内容在上面js文件:
用之前创建好的users模块,之前配置过users.models来使用,现在在views.py使用三级APIview视图会非常方便:

from rest_framework.generics import *
from .serializers import RegisterUserSerialize
from .models import Users


class UserRegisterView(CreateAPIView):
    # serializer_class---->指明使用序列化器
    serializer_class = serializers.RegisterUserSerialize

urls.py配置路径

from django.conf.urls import url
from . import views
from rest_framework import routers

urlpatterns = [
    url(r'^register/',views.UserRegisterView.as_view()),
    
]

新建一个serializers.py自定义校验内容:

前后端都需要检验格式以及内容对错,因为可能绕过前端直接发送请求到后端

from rest_framework import serializers
from . import models
from rest_framework_jwt.settings import api_settings
from django.conf import settings
from itsdangerous import TimedJSONWebSignatureSerializer as ts
from celery_tasks.email.tasks import send_email


class RegisterUserSerialize(serializers.ModelSerializer):

    #声明序列化程序
    cpas = serializers.CharField(label='确认密码',write_only=True)
    msg_code = serializers.CharField(label='手机验证码',write_only=True)
    checkbox = serializers.BooleanField(label='同意隐私内容',write_only=True)
    token = serializers.CharField(label='令牌JWT-TOKEN',read_only=True)
    #创建序列化器
    class Meta:

        # 补充说明
        extra_kwargs = {
            'username': {
                'min_length': 6,
                'max_length': 8,
                'error_messages': {
                    'min_length': '6个字符',
                    'max_length': '16个字符',
                }
            },
            'password': {
                'help_text': '这是密码,6~16位'
            }
        }
        model = models.User
        fields = ('id','username','email','password','phone','cpas','msg_code','checkbox','token',)

    #检验数据
    def validate(self, attrs):
        print('=========vvvvv===========')
        
        if len(attrs['username']) < 6:
             raise serializers.ValidationError("用户名太短了")
        
         if not re.match('^[\w]{8,16}$',attrs['password']):
             raise serializers.ValidationError("密码长度为8~16位")
        
         if attrs['password'] != attrs['cpas']:
             raise serializers.ValidationError("两次密码不一样")
        
         if not re.match('^1[3-9][0-9]{9}$',attrs['phone']):
             raise serializers.ValidationError("手机号不符合规则")
        
         if not re.match('^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$',attrs['email']):
             raise serializers.ValidationError("邮箱不符合规则")
        
         if not re.match('^[\d]{4}$', attrs['msg_code']):
             raise serializers.ValidationError("短信验证码不符合规则")
        
         if attrs['checkbox']==0:
             raise serializers.ValidationError("没有勾选隐私协议")
        return attrs

    #创建保存序列化数据
    def create(self, validated_data):
        print('=============cccccccccc===========')
        print(validated_data)

        #此时的validated_data已经是字典
        del validated_data['cpas']
        del validated_data['msg_code']
        del validated_data['checkbox']

        print('===========del_after==================')
        print(validated_data)

        #user = models.User.objects.create(**validated_data)
        user = super().create(validated_data)
        user.set_password(validated_data['password'])
        user.save()

        #JWT加密 手动创建新令牌
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        print('payload',payload)
        token = jwt_encode_handler(payload)
        print('token',token)

        #todo 将令牌传递给前端,给对象动态增加属性方式
        user.token = token

        return user

你可能感兴趣的:(框架)