【Django开发】0到1美多商城项目md教程第3篇:用户注册业务实现,1. 用户注册页面绑定Vue数据【附代码文档】

news/2025/2/19 10:20:09

美多商城完整教程(附代码资料)主要内容讲述:欢迎来到美多商城!,项目准备。展示用户注册页面,创建用户模块子应用。用户注册业务实现,用户注册前端逻辑。图形验证码,图形验证码接口设计和定义。短信验证码,避免频繁发送短信验证码。账号登录,用户名登录。登录,登录开发文档。用户基本信息,查询并渲染用户基本信息。收货地址,省市区三级联动。收货地址,展示地址前后端逻辑。商品数据库表设计,SPU和SKU。准备商品数据,容器化方案Docker。首页广告,展示首页商品频道分类。商品列表页,列表页面包屑导航。商品搜索,Haystack扩展建立索引。商品详情页,统计分类商品访问量。购物车管理,添加购物车。购物车管理,删除购物车。订单,结算订单。提交订单,使用乐观锁并发下单。对接系统,订单支付功能。页面静态化,首页广告页面静态化。MySQL读写分离,MySQL主从同步。

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~


全套教程部分目录:


部分文件图片:

用户注册业务实现

用户注册前端逻辑

为了学会使用Vue.js的双向绑定实现用户的交互和页面局部刷新效果。

1. 用户注册页面绑定Vue数据

1.准备div盒子标签

<div id="app">
    <body>
    ......
    </body>
</div>

2.register.html

  • 绑定内容:变量、事件、错误提示等
<form method="post" class="register_form" @submit="on_submit" v-cloak>
    {{ csrf_input }}
    <ul>
        <li>
            <label>用户名:</label>
            <input type="text" v-model="username" @blur="check_username" name="username" id="user_name">
            <span class="error_tip" v-show="error_name">[[ error_name_message ]]</span>
        </li>
        <li>
            <label>密码:</label>
            <input type="password" v-model="password" @blur="check_password" name="password" id="pwd">
            <span class="error_tip" v-show="error_password">请输入8-20位的密码</span>
        </li>
        <li>
            <label>确认密码:</label>
            <input type="password" v-model="password2" @blur="check_password2" name="password2" id="cpwd">
            <span class="error_tip" v-show="error_password2">两次输入的密码不一致</span>
        </li>
        <li>
            <label>手机号:</label>
            <input type="text" v-model="mobile" @blur="check_mobile" name="mobile" id="phone">
            <span class="error_tip" v-show="error_mobile">[[ error_mobile_message ]]</span>
        </li>
        <li>
            <label>图形验证码:</label>
            <input type="text" name="image_code" id="pic_code" class="msg_input">
            <img src="{{ static('images/pic_code.jpg') }}" alt="图形验证码" class="pic_code">
            <span class="error_tip">请填写图形验证码</span>
        </li>
        <li>
            <label>短信验证码:</label>
            <input type="text" name="sms_code" id="msg_code" class="msg_input">
            <a href="javascript:;" class="get_msg_code">获取短信验证码</a>
            <span class="error_tip">请填写短信验证码</span>
        </li>
        <li class="agreement">
            <input type="checkbox" v-model="allow" @change="check_allow" name="allow" id="allow">
            <label>同意”美多商城用户使用协议“</label>
            <span class="error_tip2" v-show="error_allow">请勾选用户协议</span>
        </li>
        <li class="reg_sub">
            <input type="submit" value="注 册">
        </li>
    </ul>
</form>

2. 用户注册JS文件实现用户交互

1.导入Vue.js库和ajax请求的库

<script type="text/javascript" src="{{ static('js/vue-2.5.16.js') }}"></script>
<script type="text/javascript" src="{{ static('js/axios-0.18.0.min.js') }}"></script>

2.准备register.js文件

<script type="text/javascript" src="{{ static('js/register.js') }}"></script>

绑定内容:变量、事件、错误提示等

let vm = new Vue({
    el: '#app',
    // 修改Vue读取变量的语法
    delimiters: ['[[', ']]'],
    data: {
        username: '',
        password: '',
        password2: '',
        mobile: '',
        allow: '',

        error_name: false,
        error_password: false,
        error_password2: false,
        error_mobile: false,
        error_allow: false,

        error_name_message: '',
        error_mobile_message: '',
    },
    methods: {
        // 校验用户名
        check_username(){
        },
        // 校验密码
        check_password(){
        },
        // 校验确认密码
        check_password2(){
        },
        // 校验手机号
        check_mobile(){
        },
        // 校验是否勾选协议
        check_allow(){
        },
        // 监听表单提交事件
        on_submit(){
        },
    }
});

3.用户交互事件实现

methods: {
    // 校验用户名
    check_username(){
        let re = /^[a-zA-Z0-9_-]{5,20}$/;
        if (re.test(this.username)) {
            this.error_name = false;
        } else {
            this.error_name_message = '请输入5-20个字符的用户名';
            this.error_name = true;
        }
    },
    // 校验密码
    check_password(){
        let re = /^[0-9A-Za-z]{8,20}$/;
        if (re.test(this.password)) {
            this.error_password = false;
        } else {
            this.error_password = true;
        }
    },
    // 校验确认密码
    check_password2(){
        if(this.password != this.password2) {
            this.error_password2 = true;
        } else {
            this.error_password2 = false;
        }
    },
    // 校验手机号
    check_mobile(){
        let re = /^1[3-9]\d{9}$/;
        if(re.test(this.mobile)) {
            this.error_mobile = false;
        } else {
            this.error_mobile_message = '您输入的手机号格式不正确';
            this.error_mobile = true;
        }
    },
    // 校验是否勾选协议
    check_allow(){
        if(!this.allow) {
            this.error_allow = true;
        } else {
            this.error_allow = false;
        }
    },
    // 监听表单提交事件
    on_submit(){
        this.check_username();
        this.check_password();
        this.check_password2();
        this.check_mobile();
        this.check_allow();

        if(this.error_name == true || this.error_password == true || this.error_password2 == true
            || this.error_mobile == true || this.error_allow == true) {
            // 禁用表单的提交
            window.event.returnValue = false;
        }
    },
}

4. 知识要点

  1. Vue绑定页面的套路

    • 导入Vue.js库和ajax请求的库
    • 准备div盒子标签
    • 准备js文件
    • html页面绑定变量、事件等
    • js文件定义变量、事件等
  2. 错误提示

    • 如果错误提示信息是固定的,可以把错误提示信息写死,再通过v-show控制是否展示
    • 如果错误提示信息不是固定的,可以使用绑定的变量动态的展示错误提示信息,再通过v-show控制是否展示
  3. 修改Vue变量的读取语法,避免和Django模板语法冲突

    • delimiters: ['[[', ']]']
  4. 后续的页面中如果有类似的交互和刷新效果,也可按照此套路实现

用户注册后端逻辑

1. 接收参数

提示:用户注册数据是从注册表单发送过来的,所以使用**request.POST**来提取。

python">username = request.POST.get('username')
password = request.POST.get('password')
password2 = request.POST.get('password2')
mobile = request.POST.get('mobile')
allow = request.POST.get('allow')

2. 校验参数

前端校验过的后端也要校验,后端的校验和前端的校验是一致的

python">  
  
# 判断参数是否齐全
  
  
  
  
# 判断用户名是否是5-20个字符
  
  
  
  
# 判断密码是否是8-20个数字
  
  
  
  
# 判断两次密码是否一致
  
  
  
  
# 判断手机号是否合法
  
  
  
  
# 判断是否勾选用户协议
  
  
python">  
  
# 判断参数是否齐全
  
  
if not all([username, password, password2, mobile, allow]):
    return http.HttpResponseForbidden('缺少必传参数')
  
  
# 判断用户名是否是5-20个字符
  
  
if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
    return http.HttpResponseForbidden('请输入5-20个字符的用户名')
  
  
# 判断密码是否是8-20个数字
  
  
if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
    return http.HttpResponseForbidden('请输入8-20位的密码')
  
  
# 判断两次密码是否一致
  
  
if password != password2:
    return http.HttpResponseForbidden('两次输入的密码不一致')
  
  
# 判断手机号是否合法
  
  
if not re.match(r'^1[3-9]\d{9}$', mobile):
    return http.HttpResponseForbidden('请输入正确的手机号码')
  
  
# 判断是否勾选用户协议
  
  
if allow != 'on':
    return http.HttpResponseForbidden('请勾选用户协议')

提示:这里校验的参数,前端已经校验过,如果此时参数还是出错,说明该请求是非正常渠道发送的,所以直接禁止本次请求。

3. 保存注册数据

  • 这里使用Django认证系统用户模型类提供的 create_user() 方法创建新的用户。
  • 这里 create_user() 方法中封装了 set_password() 方法加密密码。
python">  
  
# 保存注册数据
  
  
try:
    User.objects.create_user(username=username, password=password, mobile=mobile)
except DatabaseError:
    return render(request, 'register.html', {'register_errmsg': '注册失败'})

  
  
# 响应注册结果
  
  
return http.HttpResponse('注册成功,重定向到首页')

如果注册失败,我们需要在页面上渲染出注册失败的提示信息。

{% if register_errmsg %}
    <span class="error_tip2">{{ register_errmsg }}</span>
{% endif %}

4. 响应注册结果

  • 重要提示:注册成功,重定向到首页

1.创建首页广告应用:contents

$ cd ~/projects/meiduo_project/meiduo_mall/meiduo_mall/apps
$ python ../../manage.py startapp contents

2.定义首页广告视图:IndexView

python">class IndexView(View):
    """首页广告"""

    def get(self, request):
        """提供首页广告界面"""
        return render(request, 'index.html')

3.配置首页广告路由:绑定命名空间

python">  
  
# contents
  
  
url(r'^', include('contents.urls', namespace='contents')),
python">  
  
# 首页广告
  
  
url(r'^$', views.IndexView.as_view(), name='index'),

4.测试首页广告是否可以正常访问

python">

5.响应注册结果:重定向到首页

python">  
  
# 响应注册结果
  
  
return redirect(reverse('contents:index'))

5. 知识要点

  1. 后端逻辑编写套路:

    • 业务逻辑分析
    • 接口设计和定义
    • 接收和校验参数
    • 实现主体业务逻辑
    • 响应结果
  2. 注册业务逻辑核心思想:

    • 保存用户注册数据

状态保持

说明:

  • 如果需求是注册成功后即表示用户登入成功,那么此时可以在注册成功后实现状态保持
  • 如果需求是注册成功后不表示用户登入成功,那么此时不用在注册成功后实现状态保持

美多商城的需求是:注册成功后即表示用户登入成功

1. login()方法介绍

  1. 用户登入本质:

    • 状态保持
    • 将通过认证的用户的唯一标识信息(比如:用户ID)写入到当前浏览器的 cookie 和服务端的 session 中。
  2. login()方法:

    • Django用户认证系统提供了login()方法。
    • 封装了写入session的操作,帮助我们快速登入一个用户,并实现状态保持。
  3. login()位置:

    • django.contrib.auth.__init__.py文件中。
    python">

login(request, user, backend=None)





4. 状态保持 session 数据存储的位置:**Redis数据库的1号库**
```python
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

2. login()方法登入用户

python">  
  
# 保存注册数据
  
  
try:
    user = User.objects.create_user(username=username, password=password, mobile=mobile)
except DatabaseError:
    return render(request, 'register.html', {'register_errmsg': '注册失败'})

  
  
# 登入用户,实现状态保持
  
  
login(request, user)

  
  
# 响应注册结果
  
  
return redirect(reverse('contents:index'))

3. 查看状态保持结果

4. 知识要点

  1. 登入用户,并实现状态保持的方式:login(request, user, backend=None)

用户名重复注册

1. 用户名重复注册逻辑分析

2. 用户名重复注册接口设计和定义

1.请求方式

选项方案
请求方法GET
请求地址/usernames/(?P[a-zA-Z0-9_-]{5,20})/count/

2.请求参数:路径参数

参数名类型是否必传说明
usernamestring用户名

3.响应结果:JSON

响应结果响应内容
code状态码
errmsg错误信息
count记录该用户名的个数

3. 用户名重复注册后端逻辑

python">class UsernameCountView(View):
    """判断用户名是否重复注册"""

    def get(self, request, username):
        """
        :param request: 请求对象
        :param username: 用户名
        :return: JSON
        """
        count = User.objects.filter(username=username).count()
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})

4. 用户名重复注册前端逻辑

if (this.error_name == false) {
    let url = '/usernames/' + this.username + '/count/';
    axios.get(url,{
        responseType: 'json'
    })
        .then(response => {
            if (response.data.count == 1) {
                this.error_name_message = '用户名已存在';
                this.error_name = true;
            } else {
                this.error_name = false;
            }
        })
        .catch(error => {
            console.log(error.response);
        })
}

5. 知识要点

  1. 判断用户名重复注册的核心思想:

    • 使用用户名查询该用户名对应的记录是否存在,如果存在,表示重复注册了,反之,没有重复注册。
  2. axios发送异步请求套路:

    • 处理用户交互
    • 收集请求参数
    • 准备请求地址
    • 发送异步请求
    • 得到服务器响应
    • 控制界面展示效果

手机号重复注册

1. 手机号重复注册逻辑分析

2. 手机号重复注册接口设计和定义

1.请求方式

选项方案
请求方法GET
请求地址/mobiles/(?P1[3-9]\d{9})/count/

2.请求参数:路径参数

参数名类型是否必传说明
mobilestring手机号

3.响应结果:JSON

响应结果响应内容
code状态码
errmsg错误信息
count记录该用户名的个数

3. 手机号重复注册后端逻辑

python">class MobileCountView(View):
    """判断手机号是否重复注册"""

    def get(self, request, mobile):
        """
        :param request: 请求对象
        :param mobile: 手机号
        :return: JSON
        """
        count = User.objects.filter(mobile=mobile).count()
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})

4. 手机号重复注册前端逻辑

if (this.error_mobile == false) {
    let url = '/mobiles/'+ this.mobile + '/count/';
    axios.get(url, {
        responseType: 'json'
    })
        .then(response => {
            if (response.data.count == 1) {
                this.error_mobile_message = '手机号已存在';
                this.error_mobile = true;
            } else {
                this.error_mobile = false;
            }
        })
        .catch(error => {
            console.log(error.response);
        })
}

验证码

图形验证码

图形验证码逻辑分析

需要新建应用verifications

知识要点

  1. 将图形验证码的文字信息保存到Redis数据库,为短信验证码做准备。
  2. UUID 用于唯一区分该图形验证码属于哪个用户,也可使用其他唯一标识信息来实现。

未完待续, 同学们请等待下一期

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~

文章来源:https://blog.csdn.net/m0_72919230/article/details/136991835
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.niftyadmin.cn/n/5456518.html

相关文章

cookie,sessionStorage,localStorage的区别及应用场景、http状态码含义、使用token登录、无感登录

浏览器的缓存机制提供了可以将用户数据存储在客户端上的方式&#xff0c;可以利用cookie&#xff0c;session等跟服务端进行数据交互。 浏览器的存储方式有哪些&#xff1f; 1.cookiesH5标准前的本地存储方式兼容性好&#xff0c;请求头自带cookie存储量小&#xff0c;资源浪费…

微信小程序修改checkbox和radio的样式

我们在开发小程序的时候&#xff0c;有时候需要修改小程序中checkbox和radio的原生样式&#xff0c;如何修改呢&#xff1f;这里给大家提供了一份代码&#xff0c;大家可以试试。 首先是修改checkbox样式的代码&#xff1a; /* 重写 checkbox 样式 */ /* 未选中的 背景样式 *…

Python数据结构与算法——排序(希尔、计数、桶、基数排序)

目录 希尔排序 计数排序 桶排序 基数排序 希尔排序 希尔排序是一种分组插入排序算法 步骤&#xff1a; 首先取一个整数d1 n/2&#xff0c;将元素分为d1个组&#xff0c;每组相邻量元素之间距离为d1&#xff0c;在各组内进行直接插入排序&#xff1b; 取第二个整数d2 …

题目:要求输出国际象棋棋盘。

题目&#xff1a;要求输出国际象棋棋盘。 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should lea…

基于SwinTransformer和Unet的自适应多类别分割

1、介绍 transformer的基于全局信息的把握&#xff0c;使得对图像的处理成为了可能 swin-transformer在图像分类应用的成功&#xff0c;证明了transformer比传统的cnn卷积网络可以更好的提取图像特征。因为图像分割也是基于特征信息的融合&#xff0c;将不同尺度下的信息拼接…

EfficientVMamba:Atrous Selective Scan for LightWeightVisualMamba

摘要 https://arxiv.org/pdf/2403.09977.pdf 先前的轻量级模型开发努力主要集中在基于CNN和Transformer的设计上&#xff0c;但仍面临持续的挑战。CNN擅长局部特征提取&#xff0c;但会牺牲分辨率&#xff0c;而Transformer提供了全局范围&#xff0c;但会加剧计算需求 O ( N…

OceanBase中NOT EXISTS是否需要被改写

作者简介 张瑞远&#xff0c;曾经从事银行、证券数仓设计、开发、优化类工作&#xff0c;现主要从事电信级IT系统及数据库的规划设计、架构设计、运维实施、运维服务、故障处理、性能优化等工作。 持有Orale OCM,MySQL OCP及国产代表数据库认证。 获得的专业技能与认证包括 Oce…

Yocto - 如何在配方文件中输出log

官方文档里有输出调试信息的方法。包含两种&#xff0c;一种是调用python的&#xff0c;一种是bash的。 另外&#xff0c;在python 函数里&#xff0c;调用python的log输出&#xff1b;在bash 函数里调用bash的log输出&#xff1b;不然会出错。 输出log的语句直接写在bb脚本里…