配置静态文件
在项目根目录下创建静态文件static目录,用于放置静态的文件
在settings 文件中定义静态内容
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
把静态的文件如css,js,image放入static目录中:

把当前关于注册用到的模板放到模板文件中,

在应用users中 views视图定义处理注册的请求函数,返回注册的页面:
类视图:http://python.usyiyi.cn/translate/django_182/topics/class-based-views/intro.html
# 导入类视图,主要给urls
from django.views.generic import View
class RegisterView(View):
"""注册"""
def get(self, request):
"""对应get请求方式,提供注册页面"""
return render(request, "register.html", )
在根级urls中配置到应用users的跳转路径
import users.urls
url(r'^users/', include(users.urls, namespace="users")),
在uers.urls.py中配置请求路径
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^register$', views.RegisterView.as_view(), name="register"),
]
在浏览器地址栏中输入:
http://127.0.0.1:8000/users/register
返回的页面如下所示:

注册页中的html代码如下:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>天天生鲜-注册</title>
<link rel="stylesheet" type="text/css" href="../static/css/reset.css">
<link rel="stylesheet" type="text/css" href="../static/css/main.css">
<script type="text/javascript" src="../static/js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="../static/js/register.js"></script>
</head>
<body>
<div class="register_con">
<div class="l_con fl">
<a class="reg_logo"><img src="../static/images/logo02.png"></a>
<div class="reg_slogan">足不出户 · 新鲜每一天</div>
<div class="reg_banner"></div>
</div>
<div class="r_con fr">
<div class="reg_title clearfix">
<h1>用户注册</h1>
<a href="#">登录</a>
</div>
<div class="reg_form clearfix">
<form method="post">
{% csrf_token %}
<ul>
<li>
<label>用户名:</label>
<input type="text" name="user_name" id="user_name">
<span class="error_tip">提示信息</span>
</li>
<li>
<label>密码:</label>
<input type="password" name="pwd" id="pwd">
<span class="error_tip">提示信息</span>
</li>
<li>
<label>确认密码:</label>
<input type="password" name="cpwd" id="cpwd">
<span class="error_tip">提示信息</span>
</li>
<li>
<label>邮箱:</label>
<input type="text" name="email" id="email">
<span class="error_tip">提示信息</span>
{{ errmsg }}
</li>
<li class="agreement">
<input type="checkbox" name="allow" id="allow" checked="checked">
<label>同意”天天生鲜用户使用协议“</label>
<span class="error_tip2">提示信息</span>
</li>
<li class="reg_sub">
<input type="submit" value="注 册" name="">
</li>
</ul>
</form>
</div>
</div>
</div>
<div class="footer no-mp">
<div class="foot_link">
<a href="#">关于我们</a>
<span>|</span>
<a href="#">联系我们</a>
<span>|</span>
<a href="#">招聘人才</a>
<span>|</span>
<a href="#">友情链接</a>
</div>
<p>CopyRight © 2016 北京天天生鲜信息技术有限公司 All Rights Reserved</p>
<p>电话:010-****888 京ICP备*******8号</p>
</div>
</body>
</html>
用户提交表单的时候接受发送的post请求,由于表单中action表单的地址没写,所以还在原来的请求地址和视图函数中处理,只不过是post的请求而已,
在视图函数中,添加post请求处理的函数:


from django.core.urlresolvers import reverse
from django import db
from .models import *
import re
def post(self, request):
"""对应post请求方式,接收处理用户的注册数据"""
# 接收传入的参数
user_name = request.POST.get("user_name")
password = request.POST.get("pwd")
email = request.POST.get("email")
allow = request.POST.get("allow")
# 检验参数的正确性
if not all([user_name, password, email]):
# 重定向到注册页面
return redirect(reverse("users:register"))
if not re.match(r"^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$", email):
# 返回错误信息
return render(request, "register.html", {"errmsg": "邮箱格式不正确"})
if allow != "on":
return render(request, "register.html", {"errmsg": "请接收注册协议!"})
# 进行业务逻辑处理,将数据保存到数据库
# 注意用户的密码要加密,
try:
# django的AbstractUser基类提供的创建用户的方法
user = User.objects.create_user(user_name, email, password)
except db.IntegrityError:
# 如果用户名已存在,则抛出此异常信息
return render(request, "register.html", {"errmsg": "用户名已存在!"})
# 将用户的激活状态设置为假
user.is_active = False
user.save()
# 将结果返回给前端
return redirect(reverse("goods:index"))
在根基目录的urls中,构造商品应用的请求地址
import goods.urls
urlpatterns = [
url(r'^', include(goods.urls, namespace='goods')),
]
在商品的views中,构造商品主页的请求函数
from django.shortcuts import render
from django.views.generic import View
class IndexView(View):
def get(self,request):
return render(request,'index.html')
在应用goods中的urls中,构造商品主页的请求地址
from django.conf.urls import url
from goods import views
urlpatterns = [
url(r"^$", views.IndexView.as_view(), name="index"),
]
注册成功在数据库中的查询状态:

使用celery实现异步调用django的发送邮件的模块,让用户激活自己的账号.
主要思想是,先生成一个唯一的口令用来表示用户,通过django中的(itsdangerous模块),在使用celery服务器实现异步发送邮件.
1 根据用户的ID生成唯一的口令:
在用户模模型类中,创建生成唯一口令的方法:
用户生成注册口令文档 http://itsdangerous.readthedocs.io/en/latest/


from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
class User(AbstractUser, BaseModel):
"""用户"""
class Meta:
db_table = "df_users"
def generate_active_token(self):
"""生成激活令牌"""
# 构建序列化器(转换工具)对象
serializer = Serializer(settings.SECRET_KEY, 3600)
# 转换参数
token = serializer.dumps({"confirm": self.id}) # 返回bytes类型
return token.decode()
2 在项目根目录下创建celery_tasks的包用来存储用celery发送任务的模块,在包中创建tasks.py模块其内容为:


from celery import Celery
import os
#把jiango的配置模型放到系统的环境变量中,celery才可以调用django的模块
os.environ["DJANGO_SETTINGS_MODULE"] = "dailyfresh_13.settings"
# 放到celery服务器上时将注释打开
# import django
# django.setup()
from django.core.mail import send_mail
from django.conf import settings
# 创建celery应用对象
app = Celery("celery_tasks.tasks", broker="redis://10.211.55.5/2")
# 定义任务
@app.task
def send_active_email(user_name, to_email, token):
"""发送激活邮件"""
subject = "天天生鲜用户激活" # 邮件标题
body = "" # 邮件体
sender = settings.EMAIL_FROM # 发件人
receivers = [to_email] # 接收人
html_body = '<h1>尊敬的用户 %s, 感谢您注册天天生鲜!</h1>' \
'<br/><p>请点击此链接激活您的帐号<a href="http://127.0.0.1:8000/users/active/%s">' \
'http://127.0.0.1:8000/users/active/%s<a></p>' % (user_name, token, token) # html邮件体
send_mail(subject, body, sender, receivers, html_message=html_body)
3 调用celery任务入到broker队列中,以便刚才我们创建的celery workder服务器能够从队列中取出任务并执行。如何将任务函数加入到队列中,可使用delay()
在用户注册的post请求处理函数中,将发送邮件的任务函数加入到队列中,
把下面的两行代码加到 class RegisterView(View):的post请求函数中
from celery_tasks.tasks import send_active_email
# 为用户生成激活口令
token = user.generate_active_token()
# 使用celery异步发送邮件
send_active_email.delay(user_name, email, token)

4 打开项目的settings.py文件,配置Email:
# Email
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.126.com'
EMAIL_PORT = 25
#发送邮件的邮箱
EMAIL_HOST_USER = 'daily_fresh@126.com'
#在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'ITCAST123'
#收件人看到的发件人
EMAIL_FROM = '天天生鲜<daily_fresh@126.com>'
5 处理用户激活的请求:
定义用户激活的请求的处理函数:
# 口令过期
from itsdangerous import SignatureExpired
# 定义了激活的接口
class ActiveView(View):
"""激活"""
def get(self, request, token):
"""
:param request:
:param token: token是用户携带的口令,唯一标识用户
:return:
"""
# 解析口令token,获取用户身份
# 构建序列化器
s = Serializer(settings.SECRET_KEY)
try:
data = s.loads(token)
except SignatureExpired:
# 表示token过期
return HttpResponse("链接已过期!")
# 表示token未过期,
user_id = data.get("confirm")
# 查询用户的数据.处理bug
try:
user = User.objects.get(id=user_id)
except User.DoesNotExist:
# 用户不存在
return HttpResponse("用户不存在!")
# 设置用户的激活状态
user.is_active = True
user.save()
# 返回处理结果
return HttpResponse("ok")
# return redirect(reverse("users:login"))
6 配置用户激活请求的url:
url(r'^active/(?P<token>.+)', views.ActiveView.as_view(), name="active"),
5 .打开终端,执行命令:
celery -A celery_tasks.tasks worker --loglevel=info
用户dsa提交表单:

celery发送邮件成功:

用户dsa接受到邮件点击激活后,查询数据库中的is_active的状态为1,激活成功:

定义用户登陆请求的处理函数:
Django认证系统文档 http://python.usyiyi.cn/documents/django_182/topics/auth/default.html
from django.contrib.auth import authenticate, login
class LoginView(View):
"""登录"""
def get(self, request):
"""提供登录页面"""
return render(request, "login.html")
def post(self, request):
"""处理登录的数据"""
# 获取参数
user_name = request.POST.get("username")
password = request.POST.get("pwd")
# 参数校验
if not all([user_name, password]):
# 参数不完整
return render(request, "login.html")
# 登录业务逻辑处理
# try:
# password = sha256(password)
# User.objects.get(username=user_name, password=password)
# except User.DoesNotExist:
# return HttpResponse("用户名或密码错误")
# 使用django的认证系统进行用户密码的校验
user = authenticate(username=user_name, password=password)
if user is None:
# 用户的登录信息有误
return render(request, "login.html", {"errmsg": "用户名或密码错误!"})
# 判断用户的激活状态
if user.is_active is False:
return render(request, "login.html", {"errmsg": "用户尚未激活!"})
# 保存用户的登录状态
# 使用django的login函数保存用户的session数据
login(request, user)
# 登录成功,跳转到主页
return HttpResponse('登陆成功')
#return redirect(reverse("goods:index"))
在浏览器输入以下的网址:
http://127.0.0.1:8000/users/login

用户和激活的状态判断成功后,显示以下的页面:
配置用户登陆请求的url:
url(r'^login$', views.LoginView.as_view(), name="login"),
======================================================================================================
用户登陆成功,返回主页的请求处理函数,这个请求处理函数写在goods应用中的views函数中:

from django.shortcuts import render
from django.views.generic import View
# Create your views here.
class IndexView(View):
"""主页"""
def get(self, request):
return render(request, "index.html")
定义用户登陆主页的请求路径:
现在根据的请求路径urls中,定义再跳到goods应用中的urls
在根基定义跳转的路径:
url(r'^/', include(goods.urls, namespace="goods")),
在goods应用中的urls模块中写请求登陆主页的路径:
from django.conf.urls import url
from goods import views
urlpatterns = [
url(r"^$", views.IndexView.as_view(), name="index"),
]
在用户登陆处理函数login中把最后的登陆成功的路径跳转到主页
# return HttpResponse('登陆成功')
return redirect(reverse('goods:index'))

点击登陆,认证成功后,返回以下的页面:

============================================================
把session和缓存储在redis数据库中,在setings中配置代码以下:
pip install django-redis
django-redis文档:http://django-redis-chs.readthedocs.io/zh_CN/latest/#
django的session使用文档:http://python.usyiyi.cn/documents/django_182/topics/http/sessions.html
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://localhost/3",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
# Session
# http://django-redis-chs.readthedocs.io/zh_CN/latest/#session-backend
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
用户登陆成功后,在redis数据库中的查询的结果如下:
