创建好用户模型类后,我们开始来实现第一个业务逻辑——用户注册
分析要实现的业务逻辑,明确在这个业务中需要涉及到几个相关子业务,将每个子业务当做一个接口来设计。
分析接口的功能任务,明确接口的访问方式与返回数据:
特别强调:在前后端分离的应用模式中,我们作为后端开发人员设计后端接口时,可以不用考虑返回给前端数据后,前端如何处理,这是前端开发人员的工作,我们只需明确我们要保存的或者要返回的是什么数据即可。
明确上述每一点后,即可开始编写接口
短信验证功能可以归属为第三方功能,所以创建一个新应用verifications,在此应用中实现短信验证码
请求方式: GET /sms_codes/(?P
请求参数: 路径参数
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
mobile | str | 是 | 手机号 |
返回数据:json
返回值 | 类型 | 是否必传 | 说明 |
---|---|---|---|
message | str | 否 | OK,发送成功 |
class SMSCodeView(APIView):
"""发送短信验证码"""
def get(self, request, mobile):
"""
发送短信验证码
url(r"^sms_codes/(?P1[3-9]\d{9})/$", views.SMSCodeView.as_view()),
:param request:
:param mobile: 路径传参的手机号
:return:
"""
# 1.创建redis链接对象
redis_conn = get_redis_connection("verify_codes")
# 2.判断60秒内不允许重复发送短信
send_flag = redis_conn.get("send_flag_%s" % mobile)
if send_flag:
return Response({"message":"发送短信过于频繁"}, status=status.HTTP_400_BAD_REQUEST)
# 生成短信验证码
sms_code = "%06d" % random.randint(0, 999999)
# 发送短信: 调用第三方SDK
CCP().send_template_sms(mobile,[sms_code, 300//60], 1)
print("短信验证码:%s" % sms_code)
# 使用redis管道pipeline缓存sms_code
pl = redis_conn.pipeline()
pl.setex("sms_code_%s" % mobile, 300//60, sms_code)
pl.setex("send_flag_%s" % mobile, 300//60, 1)
# 执行
pl.execute()
# 返回响应
return Response({"message":"OK"})
但是,实现到这里,似乎一切都没有错,但是前端的请求却不能被后端接收,原因就是我们使用前后端分离的模式, 所以需要做跨域访问。
现在为前端和后端扥别设置两个不同的域名:
位置 | 域名 |
---|---|
前端 | www.meiduo.site |
后端 | api.meiduo.site |
编辑*/etc/hosts*文件,可以设置本地域名
sudo nano /etc/hosts
在文件中增加两条信息:
127.0.0.1 api.meiduo.site
127.0.0.1 www.meiduo.site
windows系统中若设置本地域名,hosts文件在如下目录:
C:\Windows\System32\drivers\etc
我们在前端front_end_pc/js目录中,创建host.js文件用以为前端保存后端域名
var host = 'http://api.meiduo.site:8000';
在所有需要访问后端接口的前端页面中都引入host.js,使用host变量即可指代后端域名。
修改settings配置中的ALLOWED_HOSTS
一旦不再使用127.0.0.1访问Django后端,需要在配置文件中修改ALLOWED_HOSTS,增加可以访问后端的域名
ALLOWED_HOSTS = ['api.meiduo.site', '127.0.0.1', 'localhost', 'www.meiduo.site']
我们为前端和后端分别设置了两个不同的域名
位置 | 域名 |
---|---|
前端 | www.meiduo.site |
后端 | api.meiduo.site |
现在,前端与后端分处不同的域名,我们需要为后端添加跨域访问的支持。
我们使用CORS来解决后端对跨域访问的支持。
使用django-cors-headers扩展
参考文档https://github.com/ottoyiu/django-cors-headers/
pip install django-cors-headers
INSTALLED_APPS = (
...
'corsheaders',
...
)
MIDDLEWARE = [
# 跨域放在最上边
'corsheaders.middleware.CorsMiddleware',
...
]
# CORS
CORS_ORIGIN_WHITELIST = (
'127.0.0.1:8080',
'localhost:8080',
'www.meiduo.site:8080',
'api.meiduo.site:8000'
)
CORS_ALLOW_CREDENTIALS = True # 允许携带cookie
pip install celery
在meiduo/meiduo_mall下(manage同级)创建celery_tasks用于保存celery异步任务。
在celery_tasks目录下创建config.py文件,用于保存celery的配置信息。
broker_url = "redis://127.0.0.1/14"
在celery_tasks目录下创建main.py文件,用于作为celery的启动文件
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文件,用于保存发送短信的异步任务
# -*-coding:utf-8-*-
from celery_tasks.main import app
from meiduo_mall.libs.yuntongxun.sms import CCP
# 发送短信的方法
from meiduo_mall.utils.exceptions import logger
@ app.task(name="send_sms_code")
def send_sms_code(mobile, sms_code):
"""
发送短信验证码的任务
:param mobile1:
:param sms_code:
:return:
"""
try:
ccp = CCP()
result = ccp.send_template_sms(mobile, [sms_code, 5], 1)
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异步任务发送短信
from celery_tasks.sms.tasks import send_sms_code
class SMSCodeView(APIView):
"""发送短信验证码"""
def get(self, request, mobile):
"""
发送短信验证码
url(r"^sms_codes/(?P1[3-9]\d{9})/$", views.SMSCodeView.as_view()),
:param request:
:param mobile: 路径传参的手机号
:return:
"""
...
# 使用selery发送短信
send_sms_code.delay(mobile, sms_code,300//60)
print("短信验证码:%s" % sms_code)
...
启动celery异步任务:
celery -A celery_tasks.main worker -l info