当前位置: 首页 > news >正文

【Django开发】0到1开发美多shop项目:用户登录模块开发。全md文档笔记(附代码 文档)

本系列文章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. 用户名登录接口定义

```python class LoginView(View): """用户名登录"""

def get(self, request):"""提供登录界面:param request: 请求对象:return: 登录界面"""passdef post(self, request):"""实现登录逻辑:param request: 请求对象:return: 登录结果"""pass

```

4. 用户名登录后端逻辑

```python 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. 知识要点

  1. 登录的核心思想:认证和状态保持

  2. 通过用户的认证,确定该登录用户是美多商场的注册用户。

  3. 通过状态保持缓存用户的唯一标识信息,用于后续是否登录的判断。

多账号登录

  • Django自带的用户认证后端默认是使用用户名实现用户认证的。
  • 用户认证后端位置:django.contrib.auth.backends.ModelBackend。

  • 如果想实现用户名和手机号都可以认证用户,就需要自定义用户认证后端。

  • 自定义用户认证后端步骤

  • 在users应用中新建utils.py文件

  • 新建类,继承自ModelBackend
  • 重写认证authenticate()方法
  • 分别使用用户名和手机号查询用户
  • 返回查询到的用户实例

1. 自定义用户认证后端

users.utils.py

```python 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.配置自定义用户认证后端

```python

指定自定义的用户认证后端

AUTHENTICATION_BACKENDS = ['users.utils.UsernameMobileAuthBackend'] ```

3. 测试自定义用户认证后端

4. 知识要点

  1. Django自带的用户认证系统只会使用用户名去认证一个用户。

  2. 所以我们为了实现多账号登录,就可以自定义认证后端,采用其他的唯一信息去认证一个用户。

首页用户名展示

1. 首页用户名展示方案

方案一

  • 模板中 request 变量直接渲染用户名
  • 缺点:不方便做首页静态化

html {% 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请求获取用户信息
  • 缺点:需要发送网络请求

```html

```

方案三

  • Vue读取cookie渲染用户信息

```html

```

结论:

  • 对比此三个方案,我们在本项目中选择 方案三

实现步骤:

  • 注册或登录后,用户名写入到cookie
  • Vue渲染主页用户名

2. 用户名写入到cookie

```python

响应注册结果

response = redirect(reverse('contents:index'))

注册时用户名写入到cookie,有效期15天

response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

return response ```

```python

响应登录结果

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

```html

```

2.index.js

js mounted(){ // 获取cookie中的用户名 this.username = getCookie('username'); },

退出登录

1. logout()方法介绍

  1. 退出登录:

  2. 回顾登录:将通过认证的用户的唯一标识信息,写入到当前session会话中

  3. 退出登录:正好和登录相反(清理session会话信息)

  4. logout()方法:

  5. Django用户认证系统提供了logout()方法

  6. 封装了清理session的操作,帮助我们快速实现登出一个用户

  7. logout()位置:

  8. django.contrib.auth.__init__.py文件中

python logout(request)

2. logout()方法使用

```python class LogoutView(View): """退出登录"""

def get(self, request):"""实现退出登录逻辑"""# 清理sessionlogout(request)# 退出登录,重定向到登录页response = redirect(reverse('contents:index'))# 退出登录时清除cookie中的usernameresponse.delete_cookie('username')return response

```

3. 知识要点

  1. 退出登录的核心思想就是清理登录时缓存的状态保持信息。
  2. 由于首页中用户名是从cookie中读取的。所以退出登录时,需要将cookie中用户名清除。

判断用户是否登录

1. 展示用户中心界面

```python class UserInfoView(View): """用户中心"""

def get(self, request):"""提供个人信息界面"""return render(request, 'user_center_info.html')

```

需求:

  • 当用户登录后,才能访问用户中心。
  • 如果用户未登录,就不允许访问用户中心,将用户引导到登录界面。

实现方案:

  • 需要判断用户是否登录。
  • 根据是否登录的结果,决定用户是否可以访问用户中心。

2. is_authenticate 判断用户是否登录

介绍:

  • Django用户认证系统提供了方法request.user.is_authenticated()来判断用户是否登录。
  • 如果通过登录验证则返回True。反之,返回False
  • 缺点:登录验证逻辑很多地方都需要,所以该代码需要重复编码好多次。

```python 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配置项指定的地址。

  • 如下配置:表示当用户未通过登录验证时,将用户重定向到登录页面。 python LOGIN_URL = '/login/'

1.装饰as_view()方法返回值

提示:

  • login_required装饰器可以直接装饰函数视图,但是本项目使用的是类视图。
  • as_view()方法的返回值就是将类视图转成的函数视图。

结论:

  • 要想使用login_required装饰器装饰类视图,可以间接的装饰as_view()方法的返回值,以达到预期效果。

python url(r'^info/$', login_required(views.UserInfoView.as_view()), name='info'),

```python class UserInfoView(View): """用户中心"""

def get(self, request):"""提供个人信息界面"""return render(request, 'user_center_info.html')

```

2.定义View子类封装login_required装饰器

  • 提示:LoginRequired(object)依赖于视图类View,复用性很差。

python url(r'^info/$', views.UserInfoView.as_view(), name='info'),

```python 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)不依赖于任何视图类,复用性更强。

python url(r'^info/$', views.UserInfoView.as_view(), name='info'),

```python 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)

```python class LoginRequiredMixin(object): """验证用户是否登录扩展类"""

@classmethod def as_view(cls, **initkwargs): # 自定义的as_view()方法中,调用父类的as_view()方法 view = super().as_view() return login_required(view) ```

```python class UserInfoView(LoginRequiredMixin, View): """用户中心"""

def get(self, request):"""提供个人信息界面"""return render(request, 'user_center_info.html')

```

4. 登录时next参数的使用

1.next参数的效果

python http://127.0.0.1:8000/login/?next=/info/

2.next参数的作用

  • 由Django用户认证系统提供,搭配login_required装饰器使用。
  • 记录了用户未登录时访问的地址信息,可以帮助我们实现在用户登录成功后直接进入未登录时访问的地址。

```python

响应登录结果

next = request.GET.get('next') if next: response = redirect(next) else: response = redirect(reverse('contents:index')) ```

5. 知识要点

  1. 判断用户是否登录依然使用状态保持信息实现。
  2. 项目中很多接口都是需要用户登录才能访问的,所以为了方便编码,我们将判断用户登录的操作封装到装饰器中。
  3. 登录时next参数的作用是为了方便用户从哪里进入到登录页面,登录成功后就回到哪里。

QQ登录

未完待续, 同学们请等待下一期

仓库里完整资料代码:

请移步这里获取文档和代码

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~

相关文章:

  • Python 高级语法:一切皆对象
  • 【Flink精讲】Flink任务调度机制
  • ElasticSearch语法
  • 【计算机网络】深度学习使用应用层的HTTP协议
  • 设计模式: 策略模式
  • 猫毛过敏却想养猫时?如何缓解猫毛过敏?宠物空气净化器推荐
  • Linux——缓冲区封装系统文件操作
  • 3.WEB渗透测试-前置基础知识-快速搭建渗透环境(上)
  • 手写commonJS里面的require函数
  • 基于相位的运动放大:如何检测和放大难以察觉的运动(01/2)
  • 【Java EE初阶二十一】http的简单理解(二)
  • 数据结构 计算结构体大小
  • Spring Boot 手写starter!!!
  • 第二章、FFmpeg增加RTP协议外部扩展信息解析
  • 蓝桥杯嵌入式第12届真题(完成) STM32G431
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • __proto__ 和 prototype的关系
  • 【node学习】协程
  • Angular 响应式表单之下拉框
  • gf框架之分页模块(五) - 自定义分页
  • js面向对象
  • Magento 1.x 中文订单打印乱码
  • Shell编程
  • tweak 支持第三方库
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 计算机常识 - 收藏集 - 掘金
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 解析带emoji和链接的聊天系统消息
  • 让你的分享飞起来——极光推出社会化分享组件
  • 以太坊客户端Geth命令参数详解
  • 优秀架构师必须掌握的架构思维
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • # 达梦数据库知识点
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (C#)获取字符编码的类
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .NET 解决重复提交问题
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • .Net程序帮助文档制作
  • .net打印*三角形
  • ?php echo ?,?php echo Hello world!;?
  • @Autowired标签与 @Resource标签 的区别
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [1181]linux两台服务器之间传输文件和文件夹
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用
  • [BJDCTF2020]The mystery of ip1
  • [bzoj 3534][Sdoi2014] 重建