
本系列文章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.请求参数:表单
参数名类型是否必传说明usernamestring是用户名passwordstring是密码rememberedstring是是否记住用户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 %}
-
- 欢迎您:<em>{{ user.username }}</em>
- |
- <a target="_blank" href="https://www.cnblogs.com/#">退出</a>
-
- {% else %}
-
- <a target="_blank" href="https://www.cnblogs.com/login.html">登录</a>
- |
- <a target="_blank" href="https://www.cnblogs.com/register.html">注册</a>
-
- {% endif %}
复制代码 方案二
- 发送ajax请求获取用户信息
- 缺点:需要发送网络请求
方案三
- 欢迎您:<em>[[ username ]]</em>
- |
- <a target="_blank" href="https://www.cnblogs.com/#">退出</a>
- <a target="_blank" href="https://www.cnblogs.com/login.html">登录</a>
- |
- <a target="_blank" href="https://www.cnblogs.com/register.html">注册</a>
复制代码 结论:
实现步骤:
- 注册或登录后,用户名写入到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- 欢迎您:<em>[[ username ]]</em>
- |
- <a target="_blank" href="https://www.cnblogs.com/#">退出</a>
- <a target="_blank" href="https://www.cnblogs.com/login.html">登录</a>
- |
- <a target="_blank" href="https://www.cnblogs.com/register.html">注册</a>
复制代码 2.index.js- mounted(){
- // 获取cookie中的用户名
- this.username = getCookie('username');
- },
复制代码 退出登录
1. logout()方法介绍
- 退出登录:
- 回顾登录:将通过认证的用户的唯一标识信息,写入到当前session会话中
- 退出登录:正好和登录相反(清理session会话信息)
- logout()方法:
- Django用户认证系统提供了logout()方法
- 封装了清理session的操作,帮助我们快速实现登出一个用户
- logout()位置:
- django.contrib.auth.__init__.py文件中
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配置项指定的地址。
- 如下配置:表示当用户未通过登录验证时,将用户重定向到登录页面。
- [/code]
- [/list]LOGIN_URL = '/login/'
- [code]>
- **1.装饰`as_view()`方法返回值**
- 提示:
- * `login_required装饰器`可以直接装饰函数视图,但是本项目使用的是类视图。
- * `as_view()`方法的返回值就是将类视图转成的函数视图。
- 结论:
- * 要想使用`login_required装饰器`装饰类视图,可以间接的装饰`as_view()`方法的返回值,以达到预期效果。
- ```python
- 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登录
未完待续, 同学们请等待下一期
仓库里完整资料代码:
请移步这里获取文档和代码
感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
|