共计 7471 个字符,预计需要花费 19 分钟才能阅读完成。
本系列文章 md 笔记(已分享)次要探讨 django 商城我的项目相干常识。我的项目利用 Django 框架开发一套前后端不拆散的商城我的项目(4.0 版本)含代码和文档。性能包含前后端不拆散,不便 SEO。采纳 Django + Jinja2 模板引擎 + Vue.js 实现前后端逻辑,Nginx 服务器(反向代理)Nginx 服务器(动态首页、商品详情页、uwsgi 服务器(美多商场业务场景),后端服务:MySQL、Redis、Celery、RabbitMQ、Docker、FastDFS、Elasticsearch、Crontab,内部接口:容联云、QQ 互联、支付宝。
仓库里残缺材料代码:
请移步这里获取文档和代码
感兴趣的小伙伴能够自取哦,欢送大家点赞转发~
共 11 章,132 子模块
账号登录
用户名登录
1. 用户名登录逻辑剖析
2. 用户名登录接口设计
1. 申请形式
选项 | 计划 |
---|---|
申请办法 | POST |
申请地址 | /login/ |
2. 申请参数:表单
参数名 | 类型 | 是否必传 | 阐明 |
---|---|---|---|
username | string | 是 | 用户名 |
password | string | 是 | 明码 |
remembered | string | 是 | 是否记住用户 |
3. 响应后果:HTML
字段 | 阐明 |
---|---|
登录失败 | 响应谬误提醒 |
登录胜利 | 重定向到首页 |
3. 用户名登录接口定义
class LoginView(View):
"""用户名登录"""
def get(self, request):
"""
提供登录界面
:param request: 申请对象
:return: 登录界面
"""
pass
def post(self, request):
"""
实现登录逻辑
:param request: 申请对象
:return: 登录后果
"""
pass
4. 用户名登录后端逻辑
class LoginView(View):
"""用户名登录"""
def get(self, request):
"""
提供登录界面
:param request: 申请对象
:return: 登录界面
"""return render(request,'login.html')
def post(self, request):
"""
实现登录逻辑
:param request: 申请对象
:return: 登录后果
"""
# 承受参数
username = request.POST.get('username')
password = request.POST.get('password')
remembered = request.POST.get('remembered')
# 校验参数
# 判断参数是否齐全
if not all([username, password]):
return http.HttpResponseForbidden('短少必传参数')
# 判断用户名是否是 5 -20 个字符
if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
return http.HttpResponseForbidden('请输出正确的用户名或手机号')
# 判断明码是否是 8 -20 个数字
if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
return http.HttpResponseForbidden('明码起码 8 位,最长 20 位')
# 认证登录用户
user = authenticate(username=username, password=password)
if user is None:
return render(request, 'login.html', {'account_errmsg': '用户名或明码谬误'})
# 实现状态放弃
login(request, user)
# 设置状态放弃的周期
if remembered != 'on':
# 没有记住用户:浏览器会话完结就过期
request.session.set_expiry(0)
else:
# 记住用户:None 示意两周后过期
request.session.set_expiry(None)
# 响应登录后果
return redirect(reverse('contents:index'))
5. 常识要点
-
登录的核心思想:认证和状态放弃
- 通过用户的认证,确定该登录用户是美多商场的注册用户。
- 通过状态放弃缓存用户的惟一标识信息,用于后续是否登录的判断。
多账号登录
- Django 自带的用户认证后端默认是应用用户名实现用户认证的。
- 用户认证后端地位:django.contrib.auth.backends.ModelBackend。
- 如果想实现用户名和手机号都能够认证用户,就须要自定义用户认证后端。
-
自定义用户认证后端步骤
- 在 users 利用中新建 utils.py 文件
- 新建类,继承自 ModelBackend
- 重写认证 authenticate()办法
- 别离应用用户名和手机号查问用户
- 返回查问到的用户实例
1. 自定义用户认证后端
users.utils.py
from django.contrib.auth.backends import ModelBackend
import re
from .models import User
def get_user_by_account(account):
"""
依据 account 查问用户
:param account: 用户名或者手机号
:return: user
"""
try:
if re.match('^1[3-9]\d{9}$', account):
# 手机号登录
user = User.objects.get(mobile=account)
else:
# 用户名登录
user = User.objects.get(username=account)
except User.DoesNotExist:
return None
else:
return user
class UsernameMobileAuthBackend(ModelBackend):
"""自定义用户认证后端"""
def authenticate(self, request, username=None, password=None, **kwargs):
"""
重写认证办法,实现多账号登录
:param request: 申请对象
:param username: 用户名
:param password: 明码
:param kwargs: 其余参数
:return: user
"""
# 依据传入的 username 获取 user 对象。username 能够是手机号也能够是账号
user = get_user_by_account(username)
# 校验 user 是否存在并校验明码是否正确
if user and user.check_password(password):
return user
2. 配置自定义用户认证后端
1.Django 自带认证后端源码
2. 配置自定义用户认证后端
# 指定自定义的用户认证后端
AUTHENTICATION_BACKENDS = ['users.utils.UsernameMobileAuthBackend']
3. 测试自定义用户认证后端
4. 常识要点
-
Django 自带的用户认证零碎只会应用用户名去认证一个用户。
- 所以咱们为了实现多账号登录,就能够自定义认证后端,采纳其余的惟一信息去认证一个用户。
首页用户名展现
1. 首页用户名展现计划
计划一
- 模板中 request 变量间接渲染用户名
- 毛病:不不便做首页动态化
{% if user.is_authenticated %}
<div class="login_btn fl">
欢迎您:<em>{{user.username}}</em>
<span>|</span>
<a href="#"> 退出 </a>
</div>
{% else %}
<div class="login_btn fl">
<a href="login.html"> 登录 </a>
<span>|</span>
<a href="register.html"> 注册 </a>
</div>
{% endif %}
计划二
- 发送 ajax 申请获取用户信息
- 毛病:须要发送网络申请
<div class="login_btn fl">
{# ajax 渲染 #}
</div>
计划三
- Vue 读取 cookie 渲染用户信息
<div v-if="username" class="login_btn fl">
欢迎您:<em>[[username]]</em>
<span>|</span>
<a href="#"> 退出 </a>
</div>
<div v-else class="login_btn fl">
<a href="login.html"> 登录 </a>
<span>|</span>
<a href="register.html"> 注册 </a>
</div>
论断:
- 比照此三个计划,咱们在本我的项目中抉择 计划三
实现步骤:
- 注册或登录后,用户名写入到 cookie
- Vue 渲染主页用户名
2. 用户名写入到 cookie
# 响应注册后果
response = redirect(reverse('contents:index'))
# 注册时用户名写入到 cookie,有效期 15 天
response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
return response
# 响应登录后果
response = redirect(reverse('contents:index'))
# 登录时用户名写入到 cookie,有效期 15 天
response.set_cookie('username', user.username, max_age=3600 * 24 * 15)
return response
3. Vue 渲染首页用户名
1.index.html
<div v-if="username" class="login_btn fl">
欢迎您:<em>[[username]]</em>
<span>|</span>
<a href="#"> 退出 </a>
</div>
<div v-else class="login_btn fl">
<a href="login.html"> 登录 </a>
<span>|</span>
<a href="register.html"> 注册 </a>
</div>
2.index.js
mounted(){
// 获取 cookie 中的用户名
this.username = getCookie('username');
},
退出登录
1. logout()办法介绍
-
退出登录:
- 回顾登录:将通过认证的用户的惟一标识信息,写入到以后 session 会话中
- 退出登录:正好和登录相同(清理 session 会话信息)
-
logout()办法:
- Django 用户认证零碎提供了
logout()
办法 - 封装了清理 session 的操作,帮忙咱们疾速实现登出一个用户
- Django 用户认证零碎提供了
-
logout()地位:
django.contrib.auth.__init__.py
文件中
logout(request)
2. logout()办法应用
class LogoutView(View):
"""退出登录"""
def get(self, request):
"""实现退出登录逻辑"""
# 清理 session
logout(request)
# 退出登录,重定向到登录页
response = redirect(reverse('contents:index'))
# 退出登录时革除 cookie 中的 username
response.delete_cookie('username')
return response
3. 常识要点
- 退出登录的核心思想就是清理登录时缓存的状态放弃信息。
- 因为首页中用户名是从 cookie 中读取的。所以退出登录时,须要将 cookie 中用户名革除。
判断用户是否登录
1. 展现用户核心界面
class UserInfoView(View):
"""用户核心"""
def get(self, request):
"""提供个人信息界面"""
return render(request, 'user_center_info.html')
需要:
- 当用户登录后,能力拜访用户核心。
- 如果用户未登录,就不容许拜访用户核心,将用户疏导到登录界面。
实现计划:
- 须要判断用户是否登录。
- 依据是否登录的后果,决定用户是否能够拜访用户核心。
2. is_authenticate
判断用户是否登录
介绍:
- Django 用户认证零碎提供了办法
request.user.is_authenticated()
来判断用户是否登录。 - 如果通过登录验证则返回True。反之,返回False。
- 毛病:登录验证逻辑很多中央都须要,所以该代码须要反复编码好屡次。
class UserInfoView(View):
"""用户核心"""
def get(self, request):
"""提供个人信息界面"""
if request.user.is_authenticated():
return render(request, 'user_center_info.html')
else:
return redirect(reverse('users:login'))
3. login_required 装璜器
判断用户是否登录
-
Django 用户认证零碎提供了装璜器
login_required
来判断用户是否登录。- 外部封装了
is_authenticate
- 地位:
django.contrib.auth.decorators
- 外部封装了
- 如果通过登录验证则进入到视图外部,执行视图逻辑。
-
如果未通过登录验证则被重定向到
LOGIN_URL
配置项指定的地址。-
如下配置:示意当用户未通过登录验证时,将用户重定向到登录页面。
LOGIN_URL = '/login/'
-
1. 装璜
as_view()
办法返回值
提醒:
login_required 装璜器
能够间接装璜函数视图,然而本我的项目应用的是类视图。as_view()
办法的返回值就是将类视图转成的函数视图。
论断:
- 要想应用
login_required 装璜器
装璜类视图,能够间接的装璜as_view()
办法的返回值,以达到预期成果。
url(r'^info/$', login_required(views.UserInfoView.as_view()), name='info'),
class UserInfoView(View):
"""用户核心"""
def get(self, request):
"""提供个人信息界面"""
return render(request, 'user_center_info.html')
2. 定义 View 子类封装
login_required 装璜器
- 提醒:
LoginRequired(object)
依赖于视图类View
,复用性很差。
url(r'^info/$', views.UserInfoView.as_view(), name='info'),
class LoginRequired(View):
"""验证用户是否登陆"""
@classmethod
def as_view(cls, **initkwargs):
# 自定义 as_view()办法中,调用父类的 as_view()办法
view = super().as_view()
return login_required(view)
class UserInfoView(LoginRequired):
"""用户核心"""
def get(self, request):
"""提供个人信息界面"""
return render(request, 'user_center_info.html')
3. 定义 obejct 子类封装
login_required 装璜器
- 提醒:
LoginRequired(object)
不依赖于任何视图类,复用性更强。
url(r'^info/$', views.UserInfoView.as_view(), name='info'),
class LoginRequired(object):
"""验证用户是否登陆"""
@classmethod
def as_view(cls, **initkwargs):
# 自定义 as_view()办法中,调用父类的 as_view()办法
view = super().as_view()
return login_required(view)
class UserInfoView(LoginRequired, View):
"""用户核心"""
def get(self, request):
"""提供个人信息界面"""
return render(request, 'user_center_info.html')
4. 定义验证用户是否登录扩大类
- 提醒:定义扩大类不便我的项目中导入和应用(
meiduo_mall.utils.views.py
)
class LoginRequiredMixin(object):
"""验证用户是否登录扩大类"""
@classmethod
def as_view(cls, **initkwargs):
# 自定义的 as_view()办法中,调用父类的 as_view()办法
view = super().as_view()
return login_required(view)
class UserInfoView(LoginRequiredMixin, View):
"""用户核心"""
def get(self, request):
"""提供个人信息界面"""
return render(request, 'user_center_info.html')
4. 登录时 next 参数的应用
1.next 参数的成果
http://127.0.0.1:8000/login/?next=/info/
2.next 参数的作用
- 由 Django 用户认证零碎提供,搭配
login_required 装璜器
应用。 - 记录了用户未登录时拜访的地址信息,能够帮忙咱们实现在用户登录胜利后间接进入未登录时拜访的地址。
# 响应登录后果
next = request.GET.get('next')
if next:
response = redirect(next)
else:
response = redirect(reverse('contents:index'))
5. 常识要点
- 判断用户是否登录仍然应用状态放弃信息实现。
- 我的项目中很多接口都是须要用户登录能力拜访的,所以为了不便编码,咱们将判断用户登录的操作封装到装璜器中。
- 登录时 next 参数的作用是为了不便用户从哪里进入到登录页面,登录胜利后就回到哪里。
QQ 登录
未完待续,同学们请期待下一期
仓库里残缺材料代码:
请移步这里获取文档和代码
感兴趣的小伙伴能够自取哦,欢送大家点赞转发~
正文完