news 2026/5/28 11:14:52

Django 从 0 到 1 打造完整电商平台:个人中心与用户信息修改

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Django 从 0 到 1 打造完整电商平台:个人中心与用户信息修改

IT策士10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我也会在其它平台持续发布最新文章,助你少走弯路。

大家好,我是IT策士。用户登录之后,第一件想做的事往往是看看自己的账号信息,或者改个昵称、换个密码。今天我们就来打造电商平台的个人中心——让用户有一个属于自己的"小窝",并且能自助修改手机号、邮箱、密码等信息。

本篇的内容会大量复用之前注册模块里的邮箱激活逻辑,同时引入login_required装饰器来保护敏感页面。跟着我一步步来,你会发现 Django 处理这些用户操作是多么顺手。


一、需求分析

个人中心需要实现以下功能:

  • 展示基本信息:用户名、手机号、邮箱、邮箱激活状态。

  • 修改基本信息:允许用户更换用户名、手机号、邮箱。

  • 修改邮箱后,邮箱激活状态重置为False,并重新发送激活邮件。

  • 修改手机号时,需要通过短信验证码验证新手机号(暂用模拟)。

  • 修改密码:旧密码验证通过后才能设置新密码。

  • 权限控制:仅登录用户可访问,且只能修改自己的信息。


二、定义表单

apps/users/forms.py中追加两个表单。

2.1 个人信息表单

class UpdateProfileForm(forms.ModelForm): class Meta: model=User fields=['username','phone','email']widgets={'username':forms.TextInput(attrs={'class':'form-control','placeholder':'用户名'}),'phone':forms.TextInput(attrs={'class':'form-control','placeholder':'手机号'}),'email':forms.EmailInput(attrs={'class':'form-control','placeholder':'邮箱'}),}def clean_phone(self): phone=self.cleaned_data.get('phone')ifphone:# 排除当前用户,检查手机号是否被其他人占用ifUser.objects.filter(phone=phone).exclude(pk=self.instance.pk).exists(): raise forms.ValidationError('该手机号已被其他用户绑定')returnphone def clean_email(self): email=self.cleaned_data.get('email')ifemail:ifUser.objects.filter(email=email).exclude(pk=self.instance.pk).exists(): raise forms.ValidationError('该邮箱已被其他用户绑定')returnemail

这里使用ModelForm直接绑定用户模型,简化字段定义。

2.2 修改密码表单

class ChangePasswordForm(forms.Form): old_password=forms.CharField(label='当前密码',widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'请输入当前密码'}))new_password=forms.CharField(label='新密码',min_length=6,max_length=20,widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'新密码(至少6位)'}))confirm_password=forms.CharField(label='确认新密码',widget=forms.PasswordInput(attrs={'class':'form-control','placeholder':'再次输入新密码'}))def clean(self): cleaned_data=super().clean()new=cleaned_data.get('new_password')confirm=cleaned_data.get('confirm_password')ifnew and confirm and new!=confirm: raise forms.ValidationError('两次新密码不一致')returncleaned_data

三、编写视图

打开apps/users/views.py,在原有基础上增加以下内容。

先确保导入齐全,顶部加入:

from django.contrib.auth.decoratorsimportlogin_required from django.contrib.authimportupdate_session_auth_hash from .formsimportUpdateProfileForm, ChangePasswordFormimportrandom from django.core.mailimportsend_mail

3.1 个人中心主页

@login_required(login_url='users:login')def personal_center(request):returnrender(request,'users/center.html')

这个视图极为简单,只是渲染模板。模板里会直接使用{{ user }}显示当前登录用户的信息。

3.2 修改个人信息

@login_required(login_url='users:login')def update_profile(request): user=request.userifrequest.method=='POST':form=UpdateProfileForm(request.POST,instance=user)ifform.is_valid(): old_email=user.email form.save()# 如果邮箱发生了变更,重置激活状态并发送激活邮件new_email=form.cleaned_data.get('email')ifnew_email and new_email!=old_email: user.email_active=False user.save(update_fields=['email_active'])# 生成激活 tokentoken=str(random.randint(100000,999999))request.session[f'email_token_{user.id}']=token activate_url=request.build_absolute_uri(f'/users/activate/{user.id}/{token}/')send_mail(subject='重新激活你的电商账号',message=f'你的邮箱已更新,请点击链接重新激活:{activate_url}',from_email='noreply@example.com',recipient_list=[new_email],)messages.warning(request,'邮箱已更新,请前往新邮箱查收激活邮件(终端查看)。')else: messages.success(request,'个人信息更新成功。')returnredirect('users:center')else: form=UpdateProfileForm(instance=user)returnrender(request,'users/update_profile.html',{'form':form})

说明:

  • 使用instance=user绑定当前用户,ModelForm自动完成保存。

  • 如果修改了邮箱,程序会自动重置email_active并发送激活邮件。激活链接沿用第 6 篇的activate_email视图,完全复用。

3.3 修改密码

@login_required(login_url='users:login')def change_password(request):ifrequest.method=='POST':form=ChangePasswordForm(request.POST)ifform.is_valid(): user=request.user old=form.cleaned_data['old_password']# 校验旧密码是否正确ifnot user.check_password(old): form.add_error('old_password','当前密码不正确')returnrender(request,'users/change_password.html',{'form':form})# 设置新密码并保存user.set_password(form.cleaned_data['new_password'])user.save()# 更新 session 认证哈希,防止密码修改后 session 失效update_session_auth_hash(request, user)messages.success(request,'密码修改成功。')returnredirect('users:center')else: form=ChangePasswordForm()returnrender(request,'users/change_password.html',{'form':form})

关键点update_session_auth_hash的作用是,在修改密码后让当前用户的 session 继续保持有效,否则 Django 会立即将该用户登出。这一行必不可少。

3.4 短信验证码发送(复用)

我们在第 6 篇已经写了send_sms_code视图,个人中心修改手机号时也可以调用它。由于前端 AJAX 请求需要 CSRF 令牌,我们会在模板中直接复用它。


四、配置 URL

apps/users/urls.py中添加新路由:

urlpatterns=[# ... 之前的路由 ...path('center/', views.personal_center,name='center'), path('update/', views.update_profile,name='update_profile'), path('change_password/', views.change_password,name='change_password'),]

五、设计模板

5.1 个人中心主页

创建apps/users/templates/users/center.html

{% extends'base.html'%}{% block title %}个人中心{% endblock %}{% block content %}<divclass="row"><!-- 侧边栏 --><divclass="col-md-3"><divclass="card shadow-sm"><divclass="card-header bg-primary text-white"><h5class="mb-0">个人中心</h5></div><ulclass="list-group list-group-flush"><liclass="list-group-item active"><ahref="{% url 'users:center' %}"class="text-white text-decoration-none">个人信息</a></li><liclass="list-group-item"><ahref="{% url 'users:update_profile' %}"class="text-decoration-none">修改资料</a></li><liclass="list-group-item"><ahref="{% url 'users:change_password' %}"class="text-decoration-none">修改密码</a></li><liclass="list-group-item"><ahref="#"class="text-decoration-none">收货地址</a></li><liclass="list-group-item"><ahref="#"class="text-decoration-none">我的订单</a></li></ul></div></div><!-- 主内容 --><divclass="col-md-9"><divclass="card shadow-sm"><divclass="card-header bg-light"><h4class="mb-0">👤 基本信息</h4></div><divclass="card-body"><tableclass="table table-bordered"><tr><thstyle="width:150px;">用户名</th><td>{{user.username}}</td></tr><tr><th>手机号</th><td>{{user.phone|default:"未绑定"}}</td></tr><tr><th>邮箱</th><td>{{user.email|default:"未绑定"}}</td></tr><tr><th>邮箱状态</th><td>{%ifuser.email_active %}<spanclass="badge bg-success">已激活</span>{%else%}<spanclass="badge bg-warning text-dark">未激活</span>{% endif %}</td></tr><tr><th>注册时间</th><td>{{user.date_joined|date:"Y-m-d H:i"}}</td></tr></table></div></div></div></div>{% endblock %}

5.2 修改个人信息页面

创建apps/users/templates/users/update_profile.html

{% extends'base.html'%}{% block title %}修改资料{% endblock %}{% block content %}<divclass="row justify-content-center"><divclass="col-md-6"><divclass="card shadow-sm"><divclass="card-body p-4"><h3class="text-center mb-4">✏️ 修改个人资料</h3><formmethod="post"novalidate>{% csrf_token %}<divclass="mb-3"><labelclass="form-label">用户名</label>{{form.username}}{{form.username.errors}}</div><divclass="mb-3"><labelclass="form-label">手机号</label>{{form.phone}}{{form.phone.errors}}</div><divclass="mb-3"><labelclass="form-label">邮箱</label>{{form.email}}{{form.email.errors}}</div>{%ifform.non_field_errors %}<divclass="alert alert-danger">{{form.non_field_errors.0}}</div>{% endif %}<buttontype="submit"class="btn btn-primary w-100">保存修改</button><ahref="{% url 'users:center' %}"class="btn btn-outline-secondary w-100 mt-2">取消</a></form></div></div></div></div>{% endblock %}

5.3 修改密码页面

创建apps/users/templates/users/change_password.html

{% extends'base.html'%}{% block title %}修改密码{% endblock %}{% block content %}<divclass="row justify-content-center"><divclass="col-md-6"><divclass="card shadow-sm"><divclass="card-body p-4"><h3class="text-center mb-4">🔒 修改密码</h3><formmethod="post"novalidate>{% csrf_token %}<divclass="mb-3"><labelclass="form-label">{{form.old_password.label}}</label>{{form.old_password}}{{form.old_password.errors}}</div><divclass="mb-3"><labelclass="form-label">{{form.new_password.label}}</label>{{form.new_password}}{{form.new_password.errors}}</div><divclass="mb-3"><labelclass="form-label">{{form.confirm_password.label}}</label>{{form.confirm_password}}{{form.confirm_password.errors}}</div>{%ifform.non_field_errors %}<divclass="alert alert-danger">{{form.non_field_errors.0}}</div>{% endif %}<buttontype="submit"class="btn btn-danger w-100">修改密码</button><ahref="{% url 'users:center' %}"class="btn btn-outline-secondary w-100 mt-2">取消</a></form></div></div></div></div>{% endblock %}

六、更新导航栏

确保templates/base.html的导航栏中,"个人中心"链接指向{% url 'users:center' %}

<li><aclass="dropdown-item"href="{% url 'users:center' %}">个人中心</a></li>

七、完整流程测试

启动服务器:

python manage.py runserver

7.1 访问个人中心

  1. 以任一用户登录,例如13800138000

  2. 点击导航栏的用户名 → “个人中心”。

  3. 浏览器显示用户名、手机号、邮箱及激活状态、注册时间。

7.2 修改用户名

  1. 在个人中心页面点击侧边栏"修改资料"(或直接访问/users/update/)。

  2. 将用户名改为新名字,点击"保存修改"。

  3. 页面重定向回个人中心,提示"个人信息更新成功。",用户名已更新。

终端输出:

[21/May/202614:30:22]"POST /users/update/ HTTP/1.1"3020[21/May/202614:30:22]"GET /users/center/ HTTP/1.1"2003654

7.3 修改邮箱并重新激活

  1. 在修改资料页,将邮箱改为newemail@example.com

  2. 提交后,页面提示"邮箱已更新,请前往新邮箱查收激活邮件(终端查看)。"

  3. 终端控制台打印激活邮件:

Content-Type: text/plain;charset="utf-8"Subject: 重新激活你的电商账号 From: noreply@example.com To: newemail@example.com 你的邮箱已更新,请点击链接重新激活:http://127.0.0.1:8000/users/activate/2/835472/
  1. 复制链接在浏览器打开,提示"邮箱激活成功!“,个人中心中邮箱状态变为"已激活”。

控制台记录:

[21/May/202614:35:10]"POST /users/update/ HTTP/1.1"3020... MIME-Version:1.0...[21/May/202614:35:10]"GET /users/center/ HTTP/1.1"2003654[21/May/202614:37:02]"GET /users/activate/2/835472/ HTTP/1.1"3020

7.4 修改密码

  1. 在个人中心侧边栏点击"修改密码"。

  2. 输入当前密码、新密码(如newpass123)、确认新密码,提交。

  3. 提示"密码修改成功。",并保持在登录状态(不会掉线)。

  4. 退出后重新登录,旧密码失效,新密码生效。

验证旧密码错误的情况:

  • 故意输错当前密码,提交后页面显示"当前密码不正确"。

终端输出:

[21/May/202614:40:33]"POST /users/change_password/ HTTP/1.1"2002987

八、总结与下集预告

今天我们完成了用户体系的核心闭环:

  • 搭建了个人中心展示页面,带侧边栏导航;

  • 实现了个人信息修改,修改邮箱自动触发重新激活;

  • 实现了安全的密码修改流程,确保旧密码校验和 session 保持;

  • 所有视图都加上login_required保护,未登录用户自动跳转登录页。

有了牢固的用户身份与个人资料管理基础,明天我们要进入一个更贴近电商场景的功能——收货地址管理。用户下单前必须选择地址,所以第 9 篇我们将实现地址的增删改查,并支持设置默认地址。

想了解更多还可以去其它平台搜索「IT策士」,一起升级 IT 思维 !


本文为《Django 从 0 到 1 打造完整电商平台》系列第 8 篇,作者:IT策士,未经授权禁止转载。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/22 0:14:17

知识竞赛裁判怎么当?评分标准与争议处理

知识竞赛裁判怎么当&#xff1f;评分标准与争议处理公平 专业 高效 守护竞赛的生命线&#x1f3af; 一、裁判的角色与职责知识竞赛裁判是竞赛公平的守护者&#xff0c;不仅要掌握规则&#xff0c;还要具备快速判断和沟通能力。核心职责&#xff1a;&#x1f4cb; 赛前熟悉题…

作者头像 李华
网站建设 2026/5/22 0:11:14

如何用openpilot升级你的驾驶体验:让300+车型秒变智能座驾

如何用openpilot升级你的驾驶体验&#xff1a;让300车型秒变智能座驾 【免费下载链接】openpilot openpilot is an operating system for robotics. Currently, it upgrades the driver assistance system on 300 supported cars. 项目地址: https://gitcode.com/GitHub_Tren…

作者头像 李华
网站建设 2026/5/22 0:09:10

终极免费方案:一键解密网易云音乐NCM格式,轻松获得MP3文件

终极免费方案&#xff1a;一键解密网易云音乐NCM格式&#xff0c;轻松获得MP3文件 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾在网易云音乐下载了…

作者头像 李华
网站建设 2026/5/22 0:08:06

HTTP/HTTPS协议详解与实践

HTTP/HTTPS协议详解与实践 1. 技术分析 1.1 HTTP协议概述 HTTP是Web通信的基础协议&#xff1a; HTTP特点无状态: 每次请求独立明文传输: 不安全基于TCP: 可靠传输HTTP方法:GET: 获取资源POST: 创建资源PUT: 更新资源DELETE: 删除资源1.2 HTTPS协议 HTTPS特点加密传输: SSL/TLS…

作者头像 李华
网站建设 2026/5/22 0:03:14

2026 网络安全渗透测试行业报告|机遇与前景

随着数字化转型的深入和网络威胁的日益复杂化&#xff0c;网络安全渗透测试行业在2025年迎来了前所未有的发展机遇与挑战。本文基于最新行业数据、招聘趋势与技术演进&#xff0c;全面剖析当前渗透测试行业的市场规模、人才供需、薪资水平、技术变革及未来发展方向&#xff0c;…

作者头像 李华