网站的建设需要虚拟机吗,免费的公司起名网,湖南优化推广,高速建设材料在哪个网站购买本系列文章md笔记#xff08;已分享#xff09;主要讨论django商城项目开发相关知识。本项目利用Django框架开发一套前后端不分离的商城项目#xff08;4.0版本#xff09;含代码和文档。功能包括前后端不分离#xff0c;方便SEO。采用Django Jinja2模板引擎 Vue.js实现…
本系列文章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(namesend_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/(?Pusername\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(usernameusername).count() data {username: username,count: count}return Response(data)前端实现
在js/register.js中修改
js // 检查用户名 check_username: function (){ var len this.username.length; if(len5||len20) { 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/(?Pmobile1[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(mobilemobile).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_onlyTrue) sms_code serializers.CharField(label短信验证码, write_onlyTrue) allow serializers.CharField(label同意协议, write_onlyTrue)
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仓库获取完整文档和代码
感兴趣的小伙伴可以自取哦欢迎大家点赞转发~