Python项目实战 4.1:账号登录

article/2025/9/12 7:49:13

目录

 一、用户名登录

二、多账号登录 

三、首页用户名展示

四、退出登录

五、判断用户是否登录


 一、用户名登录

1. 用户名登录逻辑分析

2. 用户名登录接口设计

1. 请求方式

选项方案
请求方法POST
请求地址/login/

2. 请求参数:表单

参数名类型是否必传说明
usernamestring用户名
passwordstring密码
rememberedstring是否记住用户

3. 响应结果:HTML

字段说明
登录失败响应错误提示
登录成功重定向到首页

3. 用户名登录后端逻辑(apps.users.views.py)


class LoginView(View):"""用户登录"""def get(self, request):"""提供用户登录页面"""return render(request, 'login.html')def post(self, request):"""实现用户登录逻辑"""# 接收参数username = request.POST.get('username')password = request.POST.get('password')remembered = request.POST.get('remembered')# 校验参数if not all([username, password]):return http.HttpResponseForbidden('缺少必传参数')if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):return http.HttpResponseForbidden('请输入正确的用户名或手机号')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)# 使用remembered确定状态保持周期(实现记住登录)if remembered != 'on':# 没有记住登录:状态保持在浏览器会话结束后就销毁request.session.set_expiry(0) # 单位是秒else:# 记住登录:状态保持周期为两周:默认是两周request.session.set_expiry(None)# 响应结果# 先取出nextnext = request.GET.get('next')if next:# 重定向到nextresponse = redirect(next)else:# 重定向到首页response = redirect(reverse('contents:index'))# 为了实现在首页的右上角展示用户名信息,我们需要将用户名缓存到cookie中# response.set_cookie('key', 'val', 'expiry')response.set_cookie('username', user.username, max_age=3600 * 24 * 15)# 用户登录成功,合并cookie购物车到redis购物车response = merge_carts_cookies_redis(request=request, user=user, response=response)# 响应结果return response

二、多账号登录 

  • Django自带的用户认证后端默认是使用用户名实现用户认证的。

  • 用户认证后端位置:django.contrib.auth.backends.ModelBackend。

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

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

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

 users.utils.py

from django.contrib.auth.backends import ModelBackend
import re
from .models import Userdef 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 Noneelse:return userclass 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

Django自带认证后端源码:

在配置文件中配置自定义用户认证后端:

# 指定自定义的用户认证后端
AUTHENTICATION_BACKENDS = ['users.utils.UsernameMobileAuthBackend']

三、首页用户名展示

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:

登录方法 class LoginView(View) 中添加:

# 响应登录结果
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()方法介绍

  1. 退出登录:

    • 回顾登录:将通过认证的用户的唯一标识信息,写入到当前session会话中
    • 退出登录:正好和登录相反(清理session会话信息)
  2. logout()方法:

    • Django用户认证系统提供了logout()方法
    • 封装了清理session的操作,帮助我们快速实现登出一个用户
  3. logout()位置:

    • django.contrib.auth.__init__.py文件中
logout(request)

2. logout()方法使用

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

五、判断用户是否登录

1. 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'))

2. login_required装饰器 判断用户是否登录

定义扩展类方便项目中导入和使用(utils.views.py)

from django.contrib.auth.mixins import LoginRequiredMixin
from django import httpfrom wangye_mall.utils.response_code import RETCODEclass LoginRequiredJSONMixin(LoginRequiredMixin):"""自定义判断用户是否登录的扩展类:返回JSON"""# 为什么只需要重写handle_no_permission?# 因为判断用户是否登录的操作,父类已经完成,子类只需要关心,如果用户未登录,对应怎样的操作def handle_no_permission(self):"""直接响应JSON数据"""return http.JsonResponse({'code': RETCODE.SESSIONERR, 'errmsg': '用户未登录'})

users.views.py

class UserInfoView(LoginRequiredMixin, View):"""用户中心"""def get(self, request):"""提供用户中心页面"""# 如果LoginRequiredMixin判断出用户已登录,那么request.user就是登陆用户对象context = {'username': request.user.username,'mobile': request.user.mobile,'email': request.user.email,'email_active': request.user.email_active}return render(request, 'user_center_info.html', context)

 ps:子应用urls.py记得添加

    # 用户登录url(r'^login/$', views.LoginView.as_view(), name='login'),# 用户退出登录url(r'^logout/$', views.LogoutView.as_view(), name='logout'),# 用户中心url(r'^info/$', views.UserInfoView.as_view(), name='info'),


http://chatgpt.dhexx.cn/article/MGGQThT5.shtml

相关文章

Python爬虫实战

文章目录 1. 引言2. 页面分析2.1 页面元素分析2.2 分页分析2.3 页面详情页面2.4 下载链接 3. 代码3.1 数据库结构3.2 步骤3.2.1 根据url获取页面结构3.2.2 解析页面数据3.2.3 数据存入数据库 4. 测试结果5. 完整代码 1. 引言 注&#xff1a;勿用于非法用途。 之前学习过Pytho…

insert into

7.insert into 如果我们想向表格中插入数据&#xff0c;就需要用到insert into语句了 7.1 insert into语法 INSERT INTO 表名 VALUES (值1, 值2,....) &#xff08;注&#xff1a;插入一行数据&#xff09; INSERT INTO 表名 (列名, 列名…

LaTeX: Missing } or { inserted. ^^I\For

报错 分析 可以发现&#xff0c;报错提示缺少{&#xff0c;但第306行并没有问题&#xff0c;并不缺少大括号。 这种情况下&#xff0c;很有可能是前面某个公式处出现了大括号缺失&#xff0c;建议从头到尾查找一遍。 修改 往前排查后发现某一处缺少大括号&#xff0c;如下所…

sqlserver触发器的使用以及inserted和deleted详解

背景&#xff1a;最近在项目中有需求是当人员表中有变动时&#xff08;比如&#xff1a;增加人员、修改人员信息、删除人员信息&#xff09;需要把这张表中的变动的信息同步到它对应的日志表中。那么如果用代码写逻辑的话在执行效率上会比较慢&#xff0c;正好sqlserver提供了触…

insert和insertSelective区别

使用逆向工程生成的代码做一个添加时通常都会给出两个答案&#xff0c;如题目想要增加一条数据会让你选择insert或者insertSelective 两者的区别在于如果选择insert 那么所有的字段都会添加一遍即使没有值 <insert id"insert" parameterType"com.ego.pojo.Tb…

Inserted和Deleted在insert、update、delete的简单使用

Inserted和Deleted在insert、update、delete的简单使用 Inserted表和Deleted表,仅仅在触发器运行时存在。当insert、update、delete操作时&#xff0c;可使用借助两个表来输出&#xff08;使用OUTPUT关键字&#xff09;操作前后的数据的变化。 Insert Update Delete Insert…

定义自定义指令;inserted()、update()

自定义指令的意义&#xff1a;对普通DOM元素进行底层操作&#xff1b; 作用 &#xff1a;可以获取到底层的dom&#xff0c;拿到想要的节点&#xff0c;从而进行操作&#xff1b; 实际应用&#xff1a;可以通过指令知道什么时候dom创建完成&#xff0c;从而进行依赖dom的库的初…

29.VUE自定义指令directive和inserted

VUE自定义指令directive和inserted 1.什么事自定义指令1.2使用自定义指令的方式 2.设置自定义组件2.1 设置全局指令2.2 设置私有指令2.3 钩子函数3. 案例 1.什么事自定义指令 指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 (v-for 例…

echarts中x轴 y轴配置(字体颜色,线的颜色,分割线,y周单位颜色)。vue中直接使用echarts以及vue中使用vue-echarts如何配置横向渐变与纵向渐变(后者适用于前者)

vue中直接使用echarts //var myChart this.$echarts.init(document.getElementById("echart-twoline")); //vue var myChart echarts.init(document.getElementById("echart-twoline"));//jquery var option {backgroundColor: "#323a5e",…

Echarts折线图X轴Y轴图例位置调整

当X轴数据过多时Echarts会默认显示一半 如下图只显示奇数月份 Echarts加入axisLabel然后将interval设置为0就会将横轴全部显示 看一下效果 但是信息太多,看起来黏在了一起,我们可以让它-30度角倾斜显示 同样在axisLabel将rotate设置为-30,再看一下效果 这下都显示出来的,但…

修改echarts的x轴y轴的刻度和刻度线文本颜色和xy轴的轴线颜色和标题title的字体颜色

1&#xff0c;x轴y轴都是一样的&#xff1a; 1.1修改刻度文本颜色&#xff1a; 找到xAxis和yAxis&#xff1a; 添加如下代码&#xff1a;&#xff08;和data和type同级并列&#xff09; axisLabel: {show: true,textStyle: {color: #fff} } 如图&#xff1a; 1.2修改xy轴的轴…

转:echarts图表x,y轴的设置

转自&#xff1a; https://www.cnblogs.com/cjh-strive/p/11065005.html 每到用echarts这门技术去画图的时候&#xff0c;我们大多人都是直接从echarts的官网的案例找相应的案例直接把代码复制到开发软件上基本随便一改就能使用&#xff0c;但是这种情况基本都是在练习的时候和…

r语言plot函数x轴y轴名字_R语言中绘图的注释函数小结

我们知道一个漂亮而清晰的图像的形成指定缺不了图像中细节的注释。那么今天我们就来总结下在R语言中那些注释函数。 首先,我们看下文本注释函数:text(),mtext(), legend()。这些函数都是R语言内置的基础函数,我们看下具体的实例: 1. text() 注释绘图中的任意点。 其中主要…

echarts的x轴y轴的颜色改变

在操作echarts时&#xff0c;需求要求echarts的xy轴的颜色要与图形的颜色一致。 图1&#xff1a; 图2&#xff1a; 解决方案&#xff1a; 代码展示&#xff1a; var myChart1; $(function() { document.getElementById("begin1").flatpickr(); document.getEl…

r语言plot函数x轴y轴名字_Matplotlib入门-1-plt.plot( )绘制折线图

在Python学堂1-8中,我们通过一个实例(温湿度变化曲线对比分析图)对Matplotlib模块中的常用折线图进行了初步的认知学习。本章及后续几章内容是对前面内容的总结以及细化。系统性的带领大家共同学习Matplotlib中的众多知识点。 废话不多说,直接开始 Matplotlib模块的导入 im…

echarts如何优雅的去掉x轴y轴

option_column: {color: [#9D509F],grid: {left: 0,right: 0,bottom: 0,top: 0,// grid 区域是否包含坐标轴的刻度标签containLabel: false},xAxis: [{type: category,boundaryGap: false,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun],show: true}],yAxis: [{show: false,axisLi…

echarts柱形图X轴Y轴相关配置

可配置XY轴刻度线&#xff0c;字体大小&#xff0c;柱形图大小颜色等 const options {tooltip: {trigger: axis,axisPointer: {// 坐标轴指示器&#xff0c;坐标轴触发有效type: shadow // 默认为直线&#xff0c;可选为&#xff1a;line | shadow},textStyle: {// 鼠标hover…

echarts中的x轴y轴颜色,文字颜色改变

echarts中的x轴y轴颜色&#xff0c;文字颜色改变 原先的图改变颜色之后的图重点代码全代码 在更换背景之后&#xff0c;原图中的xy轴的颜色不明显或是想改变XY轴的颜色以及轴上的文字颜色。 原先的图 改变颜色之后的图 重点代码 axisLine:{lineStyle:{//改变xy轴线条的颜色col…

echarts markline X轴 Y轴 添加标识线

一、X轴添加标识线 效果&#xff1a; 代码&#xff1a; markLine: {symbol: [none, none],itemStyle: {normal: {lineStyle: {type: dashed,color: red,},label: {show: true,position: end,distance: 20,textStyle: {color : red,fontSize: 14,},formatter: function() {ret…