【Django开发】0到1开发美多shop项目:Celery短信和用户注册。全md文档笔记(附代码,已分享)

本系列文章md笔记(已分享)主要讨论django商城项目开发相关知识。本项目利用Django框架开发一套前后端不分离的商城项目(4.0版本)含代码和文档。功能包括前后端不分离,方便SEO。采用Django + Jinja2模板引擎 + Vue.js实现前后端逻辑,Nginx服务器(反向代理)Nginx服务器(静态首页、商品详情页、uwsgi服务器(美多商场业务场景),后端服务:MySQL、Redis、Celery、RabbitMQ、Docker、FastDFS、Elasticsearch、Crontab,外部接口:容联云、QQ互联、支付宝。

全套笔记和代码自取移步gitee仓库: gitee仓库获取完整文档和代码

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


共 11 章,63 子模块

用户部分

使用Celery完成发送短信

meiduo/meiduo_mall下创建celery_tasks用于保存celery异步任务。

在celery_tasks目录下创建config.py文件,用于保存celery的配置信息

python broker_url = "redis://127.0.0.1/14"

在celery_tasks目录下创建main.py文件,用于作为celery的启动文件

```python from celery import Celery

为celery使用django配置文件进行设置

import os if not os.getenv('DJANGO_SETTINGS_MODULE'): os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev'

创建celery应用

app = Celery('meiduo')

导入celery配置

app.config_from_object('celery_tasks.config')

自动注册celery任务

app.autodiscover_tasks(['celery_tasks.sms']) ```

在celery_tasks目录下创建sms目录,用于放置发送短信的异步任务相关代码。

将提供的发送短信的云通讯SDK放到celery_tasks/sms/目录下。

在celery_tasks/sms/目录下创建tasks.py文件,用于保存发送短信的异步任务

```python import logging

from celery_tasks.main import app from .yuntongxun.sms import CCP

logger = logging.getLogger("django")

验证码短信模板

SMS_CODE_TEMP_ID = 1

@app.task(name='send_sms_code') def send_sms_code(mobile, code, expires): """ 发送短信验证码 :param mobile: 手机号 :param code: 验证码 :param expires: 有效期 :return: None """

try:ccp = CCP()result = ccp.send_template_sms(mobile, [code, expires], SMS_CODE_TEMP_ID)
except Exception as e:logger.error("发送验证码短信[异常][ mobile: %s, message: %s ]" % (mobile, e))
else:if result == 0:logger.info("发送验证码短信[正常][ mobile: %s ]" % mobile)else:logger.warning("发送验证码短信[失败][ mobile: %s ]" % mobile)

```

在verifications/views.py中改写SMSCodeView视图,使用celery异步任务发送短信

```python from celery_tasks.sms import tasks as sms_tasks

class SMSCodeView(GenericAPIView): ... # 发送短信验证码 sms_code_expires = str(constants.SMS_CODE_REDIS_EXPIRES // 60) sms_tasks.send_sms_code.delay(mobile, sms_code, sms_code_expires)

    return Response({"message": "OK"})

```

判断帐号是否存在

1. 判断用户名是否存在

后端接口设计:

请求方式: GET usernames/(?P<username>\w{5,20})/count/

请求参数: 路径参数

|参数|类型|是否必传|说明| |---|---|---|---| |username|str|是|用户名|

返回数据: JSON

json { "username": "itcast", "count": "1" }

|返回值|类型|是否必须|说明| |---|---|---|---| |username|str|是|用户名| |count|int|是|数量|

后端实现

在users/views.py中定义视图

```python

url(r'^usernames/(?P \w{5,20})/count/$', views.UsernameCountView.as_view()),

class UsernameCountView(APIView): """ 用户名数量 """ def get(self, request, username): """ 获取指定用户名数量 """ count = User.objects.filter(username=username).count()

    data = {'username': username,'count': count}return Response(data)

```

前端实现

在js/register.js中修改

js // 检查用户名 check_username: function (){ var len = this.username.length; if(len<5||len>20) { this.error_name_message = '请输入5-20个字符的用户名'; this.error_name = true; } else { this.error_name = false; } // 检查重名 if (this.error_name == false) { axios.get(this.host + '/usernames/' + this.username + '/count/', { responseType: 'json' }) .then(response => { if (response.data.count > 0) { this.error_name_message = '用户名已存在'; this.error_name = true; } else { this.error_name = false; } }) .catch(error => { console.log(error.response.data); }) } },

2. 判断手机号是否存在:

后端接口设计:

请求方式: GET mobiles/(?P<mobile>1[3-9]\d{9})/count

请求参数: 路径参数

|参数|类型|是否必须|说明| |---|---|---|---| |mobile|str|是|手机号|

返回数据: JSON

json { "mobile": "18512345678", "count": 0 }

|返回值|类型|是否必须|说明| |---|---|---|---| |mobile|str|是|手机号| |count|int|是|数量|

后端实现

在users/views.py中定义视图

```python

url(r'^mobiles/(?P 1[3-9]\d{9})/count/$', views.MobileCountView.as_view()),

class MobileCountView(APIView): """ 手机号数量 """ def get(self, request, mobile): """ 获取指定手机号数量 """ count = User.objects.filter(mobile=mobile).count()

    data = {'mobile': mobile,'count': count}return Response(data)

```

前端实现

在js/register.js中修改

js // 检查手机号 check_phone: function (){ var re = /^1[345789]\d{9}$/; if(re.test(this.mobile)) { this.error_phone = false; } else { this.error_phone_message = '您输入的手机号格式不正确'; this.error_phone = true; } if (this.error_phone == false) { axios.get(this.host + '/mobiles/'+ this.mobile + '/count/', { responseType: 'json' }) .then(response => { if (response.data.count > 0) { this.error_phone_message = '手机号已存在'; this.error_phone = true; } else { this.error_phone = false; } }) .catch(error => { console.log(error.response.data); }) } },

注册

1. 后端接口设计:

请求方式: POST /users/

请求参数: JSON 或 表单

|参数名|类型|是否必须|说明| |---|---|---|---| |username|str|是|用户名| |password|str|是|密码| |password2|str|是|确认密码| |sms_code|str|是|短信验证码| |mobile|str|是|手机号| |allow|str|是|是否同意用户协议|

返回数据: JSON

json { "id": 9, "username": "python8", "mobile": "18512345678", }

|返回值|类型|是否必须|说明| |---|---|---|---| |id|int|是|用户id| |username|str|是|用户名| |mobile|str|是|手机号|

视图原型

```python

url(r'^users/$', views.UserView.as_view()),

class UserView(CreateAPIView): """ 用户注册 传入参数: username, password, password2, sms_code, mobile, allow """ pass ```

2. 后端实现

在users/serializers.py中创建序列化器对象

```python class CreateUserSerializer(serializers.ModelSerializer): """ 创建用户序列化器 """ password2 = serializers.CharField(label='确认密码', write_only=True) sms_code = serializers.CharField(label='短信验证码', write_only=True) allow = serializers.CharField(label='同意协议', write_only=True)

class Meta:model = Userfields = ('id', 'username', 'password', 'password2', 'sms_code', 'mobile', 'allow')extra_kwargs = {'username': {'min_length': 5,'max_length': 20,'error_messages': {'min_length': '仅允许5-20个字符的用户名','max_length': '仅允许5-20个字符的用户名',}},'password': {'write_only': True,'min_length': 8,'max_length': 20,'error_messages': {'min_length': '仅允许8-20个字符的密码','max_length': '仅允许8-20个字符的密码',}}}def validate_mobile(self, value):"""验证手机号"""if not re.match(r'^1[3-9]\d{9}$', value):raise serializers.ValidationError('手机号格式错误')return valuedef validate_allow(self, value):"""检验用户是否同意协议"""if value != 'true':raise serializers.ValidationError('请同意用户协议')return valuedef validate(self, data):# 判断两次密码if data['password'] != data['password2']:raise serializers.ValidationError('两次密码不一致')# 判断短信验证码redis_conn = get_redis_connection('verify_codes')mobile = data['mobile']real_sms_code = redis_conn.get('sms_%s' % mobile)if real_sms_code is None:raise serializers.ValidationError('无效的短信验证码')if data['sms_code'] != real_sms_code.decode():raise serializers.ValidationError('短信验证码错误')return datadef create(self, validated_data):"""创建用户"""# 移除数据库模型类中不存在的属性del validated_data['password2']del validated_data['sms_code']del validated_data['allow']user = super().create(validated_data)# 调用django的认证系统加密密码user.set_password(validated_data['password'])user.save()return user

```

在users/views.py中定义视图

python class UserView(CreateAPIView): """ 用户注册 """ serializer_class = serializers.CreateUserSerializer

3. 前端编写

修改js/register.js

```js // 注册 on_submit: function(){ this.check_username(); this.check_pwd(); this.check_cpwd(); this.check_phone(); this.check_sms_code(); this.check_allow();

        if(this.error_name == false && this.error_password == false && this.error_check_password == false && this.error_phone == false && this.error_sms_code == false && this.error_allow == false) {axios.post(this.host + '/users/', {username: this.username,password: this.password,password2: this.password2,mobile: this.mobile,sms_code: this.sms_code,allow: this.allow.toString()}, {responseType: 'json'}).then(response => {location.href = '/index.html';    }).catch(error=> {if (error.response.status == 400) {if ('non_field_errors' in error.response.data) {this.error_sms_code_message = error.response.data.non_field_errors[0];} else {this.error_sms_code_message = '数据有误';}this.error_sms_code = true;} else {console.log(error.response.data);}})}}

```

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

全套笔记和代码自取移步gitee仓库: gitee仓库获取完整文档和代码

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day41WEB 攻防-通用漏洞XMLXXE无回显DTD 实体伪协议代码审计

本章知识点&#xff1a; 1 、 XML&XXE- 原理 & 发现 & 利用 & 修复等 2 、 XML&XXE- 黑盒模式下的发现与利用 3 、 XML&XXE- 白盒模式下的审计与利用 4 、 XML&XXE- 无回显 & 伪协议 & 产生层面 配套资源&#xff08;百度网盘&#x…

Stable Diffusion 绘画入门教程(webui)-ControlNet(IP2P)

上篇文章介绍了深度Depth&#xff0c;这篇文章介绍下IP2P&#xff08;InstructP2P&#xff09;, 通俗理解就是图生图&#xff0c;给原有图加一些效果,比如下图&#xff0c;左边为原图&#xff0c;右边为增加了效果的图&#xff1a; 文章目录 一、选大模型二、写提示词三、基础参…

Flink ML 的新特性解析与应用

摘要&#xff1a;本文整理自阿里巴巴算法专家赵伟波&#xff0c;在 Flink Forward Asia 2023 AI特征工程专场的分享。本篇内容主要分为以下四部分&#xff1a; Flink ML 概况在线学习的设计与应用在线推理的设计与应用特征工程算法与应用 一、Flink ML 概况 Flink ML 是 Apache…

(六)激光线扫描-三维重建

本篇文章是《激光线扫描-三维重建》系列的最后一篇。 1. 基础理论 1.1 光平面 在之前光平面标定的文章中,已经提到过了,是指 激光发射器投射出一条线,形成的一个扇形区域平面就是光平面。 三维空间中平面的公式是: A X + B Y + C Z + D = 0 A X+B Y+C Z+D=0

创建一个基于Node.js的实时聊天应用

在当今数字化社会&#xff0c;实时通讯已成为人们生活中不可或缺的一部分。无论是在社交媒体平台上与朋友交流&#xff0c;还是在工作场合中与同事协作&#xff0c;实时聊天应用都扮演着重要角色。与此同时&#xff0c;Node.js作为一种流行的后端技术&#xff0c;为开发者提供了…

【C++】C++入门篇,初识C++----第一个C++结构,C++关键字,命名空间,C++的输入输出,缺省参数【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为【C】C入门篇&#xff0c;初识C----第一个C结构&#xff0c;命名空间&#xff0c;C的输入输出&#xff0c;缺省参数【图文详解】&#xff0c;深刻理解命名空间&#xff0c;带大家入门C&#xff0c;感谢观看&#xff0c;支持的可以给个一…

华为配置WDS手拉手业务示例

配置WDS手拉手业务示例 组网图形 图1 配置WDS手拉手业务示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。但企业考虑到AP通过有线部署的成本较高&#xff0c;所以通过建立…

SpringBoot源码解读与原理分析(三十)AOP模块的生命周期(三)代理对象的底层执行逻辑

文章目录 前言9.6 代理对象的底层执行逻辑9.6.1 DemoService#test9.6.2 获取增强器链9.6.2.1 前置准备9.6.2.2 匹配增强器9.6.2.3 匹配后的处理9.6.2.4 其他增强器的处理 9.6.3 执行增强器9.6.3.1 执行proceed方法9.6.3.2 下标值9.6.3.3 执行第一个增强器9.6.3.4 再次执行proce…

strings.xml补充知识

复数名词 <plurals name"book"><item name"one">book</item><item name"others">books</item> </plurals>int bookCount 4; Resources res getResources(); String bookCount res.getQuantityString(R.…

2.23数据结构

单向循环链表 创建单向循环链表&#xff0c;创建节点 &#xff0c;头插&#xff0c;按位置插入&#xff0c;输出&#xff0c;尾删&#xff0c;按位置删除功能 //main.c #include "loop_list.h" int main() {loop_p Hcreate_head();insert_head(H,12);insert_head(…

如何查看电脑使用记录?保障个人隐私和安全

查看电脑使用记录是了解电脑活动的一种重要方式&#xff0c;可以帮助用户追踪应用程序的使用情况、登录和关机时间、文件的访问记录等。在本文中&#xff0c;我们将介绍如何查看电脑使用记录的三个方法&#xff0c;以分步骤详细说明如何查看电脑使用记录&#xff0c;帮助用户更…

杂题——1097: 蛇行矩阵

题目描述 蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。 输入格式 本题有多组数据&#xff0c;每组数据由一个正整数N组成。&#xff08;N不大于100&#xff09; 输出格式 对于每一组数据&#xff0c;输出一个N行的蛇形矩阵。两组输出之间不要额外的空行。矩阵三角…

如何用Docker+jenkins 运行 python 自动化?

1.在 Linux 服务器安装 docker 2.创建 jenkins 容器 3.根据自动化项目依赖包构建 python 镜像(构建自动化 python 环境) 4.运行新的 python 容器&#xff0c;执行 jenkins 从仓库中拉下来的自动化项目 5.执行完成之后删除容器 环境准备 Linux 服务器一台(我的是 CentOS7) …

Jmeter之内置函数__property和__P的区别

1. __property函数 作用 读取 Jmeter 属性 语法格式 ${__property(key,var,default)} 参数讲解 小栗子 ${__property(key)} 读取 key 属性如果找不到 key 属性&#xff0c;则返回 key&#xff08;属性名&#xff09; ${__property(key,,default)} 读取 key 属性如果找不到 k…

PHP实现分离金额和其他内容便于统计计算

得到的结果可以粘贴到excel计算 <?php if($_GET["x"] "cha"){ $tips isset($_POST[tips]) ? $_POST[tips] : ; $pattern /(\d\.\d|\d)/; $result preg_replace($pattern, "\t\${1}\t", $tips); echo "<h2><strong>数…

Python流程控制有知道的吗?

流程控制是编程的核心概念之一&#xff0c;Python也不例外。在Python中&#xff0c;程序的流程控制结构主要包括顺序结构、选择结构和循环结构。这些结构让程序员能够更好地组织代码&#xff0c;使其按照特定的逻辑执行。 1.顺序结构 顺序结构是Python中最简单的流程控制结构&…

ELK介绍以及搭建

基础环境 hostnamectl set-hostname els01 hostnamectl set-hostname els02 hostnamectl set-hostname els03 hostnamectl set-hostname kbased -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config systemctl stop firewalld & systemctl disable firewalld# 安…

Unity数据持久化之PlayerPrefs

这里写目录标题 PlayerPrefs概述基本方法PlayerPrefs存储位置实践小项目反射知识补充数据管理类的创建反射存储数据----常用成员反射存储数据----List成员反射存储数据----Dictionary成员反射存储数据----自定义类成员反射读取数据----常用成员反射读取数据----List成员反射读取…

Sora-OpenAI 的 Text-to-Video 模型:制作逼真的 60s 视频片段

OpenAI 推出的人工智能功能曾经只存在于科幻小说中。 2022年&#xff0c;Openai 发布了 ChatGPT&#xff0c;展示了先进的语言模型如何实现自然对话。 随后&#xff0c;DALL-E 问世&#xff0c;它利用文字提示生成令人惊叹的合成图像。 现在&#xff0c;他们又推出了 Text-t…

选择适合你的编程语言

引言 在当今瞬息万变的技术领域中&#xff0c;选择一门合适的编程语言对于个人职业发展和技术成长至关重要。每种语言都拥有独特的设计哲学、应用场景和市场需求&#xff0c;因此&#xff0c;在决定投入时间和精力去学习哪种编程语言时&#xff0c;我们需要综合分析多个因素&a…