用户注册
form 表单提交
-
注册时,因为用户的数据是要提交到后台的,所以用的是 form表单提交数据
- 如果表单的 action 没有设置,提交表单时,会向浏览器当前的地址提交数据(用户登陆时就需要这样)
- 加上是为了让其可以使用 django 的 CSRF 防护
后台处理流程
一般后台的处理流程都是这个样
类视图
-
将视图 view 以类的形式定义,
django.views.generic.View ( 与django.views.generic.base.View 是同一个)
,定义的类继承于 Viewclass RegisterView(View): '''注册''' def get(self, request): '''显示注册页面''' return render(request, 'register.html') def post(self, request): '''进行注册处理''' pass
-
urls.py
中配置路由使用类视图的as_view()
方法url(r'^register$', RegisterView.as_view(), name='register'), # 注册
-
由
dispatch()
方法具体将请求 request 分发至对应请求方式的处理方法中(get、post 等)
Django认证系统
方法名 | 备注 |
---|---|
create_user | 创建用户 |
authenticate | 登录验证 |
login | 记录登录状态 |
logout | 退出用户登录 |
is_authenticated | 判断用户是否登录 |
login_required装饰器 | 进行登录判断 |
user = User.objects.create_user(username, email, password)
user.is_active = 0 # 用户激活标志,django会默认为1,需手动改0,让用户自行激活
user.save()
-
返回应答时,使用反向解析
return redirect(reverse('goods:index'))
django发送邮件(celery)
- 是用celery 异步任务队列发送邮件
- 三者可在同台电脑,也可在不同电脑
- 处理者也需要任务的代码
- 安装:
pip install celery
-
使用:在项目中创建一个包存放任务代码(celery_tasks/tasks.py)
from celery import Celery from django.conf import settings from django.core.mail import send_mail from django.template import loader # 在任务处理者一端加这几句 import os import django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dailyfresh.settings") django.setup() from goods.models import GoodsType,IndexGoodsBanner,IndexPromotionBanner,IndexTypeGoodsBanner # 需放在django初始化的下面 # 创建一个对象 app = Celery('celert_tasks.tasks',broker='redis://127.0.0.1:6379/8') # 定义任务函数 @app.task def send_register_active_email(to_email,username,token): '''发送激活邮件''' subject = '天天生鲜欢迎信息' message = '' sender = settings.EMAIL_FROM recipient = [to_email] html_message = '<h1>%s,欢喜成为天天生鲜会员</h1>点击以下链接完成激活用户<br/><a href="http://127.0.0.1:8000/user/active/%s">http://127.0.0.1/user/active/%s</a>' % ( username, token, token) send_mail(subject, message, sender, recipient, html_message=html_message)
-
发出任务:在视图中导入
send_register_active_email
,再send_register_active_email.delay()
就可以发出任务了 -
任务处理者:需要copy一份任务代码到任务处理者的电脑上,启动代码
celery -A celery_tasks.tasks worker -l info
启动worker时需要用到django 的一些初始化配置,所以在任务处理着的代码中需要添加django的初始化
用户激活
-
发送激活邮件,包含激活链接:
/user/active/xxx
-
激活链接需包含用户的身份信息,并且要把身份信息加密
-
加密模块:itsdangerous,所需的是该模块中的TimedJSONWebSignatureSerializer 类
-
使用:
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer # 加密用户的身份信息,生成激活token serializer = Serializer(settings.SECRET_KEY, 3600) # 先实例化一个对象 info = {'confirm': user.id} token = serializer.dumps(info) # bytes token = token.decode()
-
解密用户身份信息
# 进行解密,获取要激活的用户信息 serializer = Serializer(settings.SECRET_KEY, 3600) try: info = serializer.loads(token) # 获取待激活用户的id user_id = info['confirm'] # 根据id获取用户信息 user = User.objects.get(id=user_id) user.is_active = 1 user.save() # 跳转到登录页面 return redirect(reverse('user:login')) except SignatureExpired as e: # 激活链接已过期 return HttpResponse('激活链接已过期')
用户登录
配置redis作为Django缓存和session后端
-
使用redis存储session
- 安装:
pip install django-redis
- 安装:
-
配置
# Django的缓存的配置 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/9", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } # 配置session存储 SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default"
-
记住用户的登录状态:
login(request, user)
父模板页面
-
可以把页面公用的部分放入父模板,然后在其中预留子页面需要的空间,子页面可以继承父模板,这样可以减少代码量
-
base.html(父)
-
login.html(子)
登录判断装饰器login_required
-
login_required()
完成下面的事情:- 如果用户没有登入,则重定向到
settings.LOGIN_URL
,并将当前访问的绝对路径传递到查询字符串中。例如:/accounts/login/?next=/polls/3/
- 如果用户已经登入,则正常执行视图。视图的代码可以安全地假设用户已经登入
- 默认情况下,在成功认证后用户应该被重定向的路径存储在查询字符串的一个叫做
"next"
的参数中。如果对该参数你倾向使用一个不同的名字,login_required()
带有一个可选的redirect_field_name
参数
- 如果用户没有登入,则重定向到
-
因为我们写的View 不是def,而是View类,所以无法直接使用装饰器,但我们可以在urls 中,用login_required() 返回要访问的视图
url(r'^$', login_required(UserInfoView.as_view()), name='user'), # 用户中心-信息页
-
自定义登录后跳转的页面
- 在settings.py 中添加:
LOGIN_URL = '/user/login'
- 在settings.py 中添加:
-
获取登录后要跳转的url
使用LoginRequireMixin
-
若觉得在urls 使用
login_required()
麻烦,我们可以在项目中新建一个包 utils(工具包) 专门存放该项目的一些工具 -
封装
as_view()
的 Mixin :将共同的行为运用于多个类的一种方法是编写一个封装as_view()
方法的Mixin-
在utils目录下建立一个
mixin.py
from django.contrib.auth.decorators import login_required class LoginRequiredMixin(object): @classmethod def as_view(cls,**initkwargs): # 调用父类的as_view view = super(LoginRequiredMixin, cls).as_view(**initkwargs) return login_required(view)
-
使用时,定义视图时先继承于
LoginRequiredMixin
class MyView(LoginRequiredMixin, View): ...
-
登录后的欢迎信息
-
Django会给request对象添加一个属性
request.user
-
如果用户未登录—–>user是AnonymousUser类的一个实例对象
-
如果用户登录—–>user是User类的一个实例对象,这时
request.user.is_authenticated()
会返回True -
在调用模板文件时,除了我们自己给模板文件传递变量外,django框架会把
request.user
也传过去 -
在模板文件中
退出登录
- django 内置认证系统有一个
logout()
方法 - 直接调用
logout(request)
传入request 即可
用户中心
模型类和模型管理器类
-
模型管理器的作用:
-
①改变原有查询的结果:
all()
-
②封装方法:用户操作模型类对应的数据表
-
在models.py中定义一个类
class AddressManager(models.Manager): '''地址模型管理器类''' # 1.改变原有查询的结果集:all() # 2.封装方法:用户操作模型类对应的数据表(增删改查) def get_default_address(self, user): '''获取用户默认收货地址''' # self.model:获取self对象所在的模型类 try: address = self.get(user=user, is_default=True) # models.Manager except self.model.DoesNotExist: # 不存在默认收货地址 address = None return address
-
然后在模型类中自定义一个模型管理器对象
# 自定义一个模型管理器对象 objects = AddressManager()
-
使用
# 获取用户的个人信息 user = request.user address = Address.objects.get_default_address(user)
-
-
历史浏览记录
-
存储在redis数据库中———>内存型数据库
-
如果所有用户的历史记录用一条数据来保存
- hash:
history:user_用户id:'1,2,3'
- hash:
-
若每个用户的历史浏览记录用一条数据保存
- list:
history_用户id:[2,3,1]
- 添加历史记录时,用户最新浏览的商品的id从列表左侧插入
- list:
-
django获取redis链接
-
之前:从redis中导入StrictRedis,然后再创建一个StrictRedis 对象
-
现在:用django_redis获取链接
from django_redis import get_redis_connection con = get_redis_connection('default')
default:settings.py中redis的配置
-