【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.hqwc.cn/news/488563.html

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

相关文章

试用nebulagraph

按照手册的快速入门&#xff0c;本地部署操作&#xff0c;基本没什么问题。有一些注意事项NebulaGraph Database 手册 (nebula-graph.com.cn) 默认安装路径在/usr/local/nebula ip的问题 在步骤3的时候 $ ./nebula-console -addr <ip> -port <port> -u <use…

一文带你解决如何设置Redis临时密码和永久密码

&#x1f49f;&#x1f49f;前言 ​ 友友们大家好&#xff0c;我是你们的小王同学&#x1f617;&#x1f617; 今天给大家打来的是 一文带你解决如何设置Redis临时密码和永久密码 希望能给大家带来有用的知识 觉得小王写的不错的话麻烦动动小手 点赞&#x1f44d; 收藏⭐ 评论&…

桥接模式:解耦抽象与实现,实现灵活多变的扩展结构

文章目录 一、引言二、应用场景与技术背景三、模式定义与实现四、实例详解五、优缺点分析总结&#xff1a; 一、引言 ​ 桥接模式是一种结构型设计模式&#xff0c;它将抽象部分与它的实现部分分离&#xff0c;使它们可以独立变化。这种模式通过创建一个抽象层和实现层的结构&…

超平面介绍

超平面公式 (1) 超平面是指n维线性空间中维度为n-1的子空间。它可以把线性空间分割成不相交的两部分。比如二维空间中&#xff0c;一条直线是一维的&#xff0c;它把平面分成了两部分&#xff1b;三维空间中&#xff0c;一个平面是二维的&#xff0c;它把空间分成了两部分。(2…

高级RAG:使用RAGAs + LlamaIndex进行RAG评估,包括原理、图和代码

原文地址&#xff1a;Using RAGAs LlamaIndex for RAG evaluation 2024 年 2 月 5 日 如果您已经为实际的业务系统开发了检索增强生成&#xff08;Retrieval Augmented Generation, RAG&#xff09;应用程序&#xff0c;那么您可能会关心它的有效性。换句话说&#xff0c;您…

数据结构-列表LinkedList

一,链表的简单的认识. 数组,栈,队列是线性数据结构,但都算不上是动态数据结构,底层都是依托静态数组,但是链表是确实真正意义上的动态数组. 为什么要学习链表? 1,链表时最简单的动态数据结构 2,掌握链表有助于学习更复杂的数据结构,例如,二叉树,trie. 3,学习链表有助于更深入…

抖音短视频:表情包账号的魅力与运营之道以及制作与工具

在短视频的浪潮中&#xff0c;抖音以其独特的创意和趣味性成为了年轻人的最爱。其中&#xff0c;表情包账号更是凭借其生动、形象的表现方式&#xff0c;赢得了众多用户的青睐。本文将深入探讨抖音短视频表情包账号的魅力所在以及如何有效运营。 一、表情包账号的独特魅力 情…

virtualenv env_name 使用 virtualenv 创建 python 虚拟环境

为什么要用这个 win7 32 环境下 pycharm 只能用低版本的&#xff0c;比如 2016,2018 此时pycharm 图形界面创建的 虚拟环境版本很低&#xff0c;有些包不兼容&#xff0c;因此用 virtualenv 模块&#xff0c;可以创建 20 版本以上的虚拟环境 virtualenv env_name官方文档 http…

88. 合并两个有序数组——javascript实现

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;合并后数组…

c#高级——插件开发

案例&#xff1a;WinForm计算器插件开发 1.建立插件库&#xff0c;设置各种自己所需的插件组件 如下图所示&#xff1a;进行了计算器的加减法插件计算组件 Calculator_DLL为总插件父类 Calculator_DLL_ADD 为插件子类的控件对象 Calculator_DLL_Sub Calculator_DLL_Factory 为…

Python爬虫-存储到csv乱码-使用utf-8-sig编码

代码 import requests import csvdef get_data():url https://careers.tencent.com/tencentcareer/api/post/Query?timestamp1708743664770&countryId&cityId&bgIds&productId&categoryId&parentCategoryId&attrId&keywordpython&pageIn…

数学建模资料分享

1. 往年各赛题的优秀论文 可以用来参考一下论文是怎么写的。参考论文的结构&#xff0c;格式&#xff0c;思路等等。 链接&#xff1a;https://pan.baidu.com/s/1WG2t4-x9MjtaSgkq4ue5AQ?pwdnlzx 提取码&#xff1a;nlzx --来自百度网盘超级会员V4的分享 2.论文模板 链接&a…