Day 61:【99天精通Python】Django 进阶 - 表单与用户认证 - 打造会员系统
前言
欢迎来到第61天!
在 Web 开发中,用户系统(注册、登录、注销)几乎是标配。在 Flask 中,我们需要自己设计 User 表,自己写 session 逻辑,比较繁琐。
而 Django 作为一个"自带电池"的框架,内置了一套非常完善的用户认证系统 (Auth System)。你不需要自己设计 User 表,也不用写加密算法,Django 全都帮你做好了。
此外,Django 的Form (表单)系统也非常强大,它不仅能自动生成 HTML 代码,还能自动验证用户输入的数据是否合法。
本节内容:
- Django Forms:自动生成表单与验证
- 使用内置 User 模型
- 实现注册、登录、注销功能
@login_required装饰器:保护你的页面- 实战练习:博客系统的用户中心
一、Django Forms:让表单处理变简单
Django 的 Form 类和 Model 类长得很像。它负责:
- 渲染:自动生成 HTML
<input>标签。 - 验证:检查用户输入是否符合规则(如邮箱格式、密码长度)。
1.1 定义表单 (hello/forms.py)
新建forms.py:
fromdjangoimportformsclassLoginForm(forms.Form):# widget 决定了在页面上显示什么控件username=forms.CharField(label="用户名",max_length=20)password=forms.CharField(label="密码",widget=forms.PasswordInput)1.2 在视图中使用表单 (hello/views.py)
fromdjango.shortcutsimportrender,redirectfrom.formsimportLoginFormdeflogin_view(request):ifrequest.method=='POST':# 将用户提交的数据 (request.POST) 绑定到表单form=LoginForm(request.POST)ifform.is_valid():# 获取清洗后的数据data=form.cleaned_data user=data['username']pwd=data['password']# ... 后续登录逻辑 ...returnHttpResponse("校验通过!")else:# GET 请求:创建一个空表单form=LoginForm()returnrender(request,'hello/login.html',{'form':form})1.3 在模板中渲染 (hello/templates/hello/login.html)
Django 可以用{{ form.as_p }}一键生成所有输入框。
<formmethod="post"><!-- 必须加上 CSRF 令牌,否则报错 403 -->{% csrf_token %} {{ form.as_p }}<buttontype="submit">登录</button></form>二、用户认证系统 (Auth)
Django 默认提供了一个User模型,包含字段:username,password,email,is_superuser等。
2.1 常用方法
需要引入django.contrib.auth:
authenticate(username, password): 验证用户名密码是否正确。如果正确返回 user 对象,否则返回 None。login(request, user): 将用户登录状态写入 Session。logout(request): 清除 Session,注销用户。create_user(...): 创建新用户(会自动加密密码)。
三、实战:完整的登录与注销
我们修改login_view,接入真正的认证逻辑。
fromdjango.contrib.authimportauthenticate,login,logoutfromdjango.httpimportHttpResponsedeflogin_view(request):ifrequest.method=='POST':form=LoginForm(request.POST)ifform.is_valid():data=form.cleaned_data# 1. 验证身份user=authenticate(username=data['username'],password=data['password'])ifuserisnotNone:# 2. 登录login(request,user)# 跳转到首页 (需在 urls.py 定义 name='index')returnredirect('index')else:# 这里的 error 会在模板中显示(如果你手动处理的话)# 为了简单演示,直接返回响应returnHttpResponse("账号或密码错误")else:form=LoginForm()returnrender(request,'hello/login.html',{'form':form})deflogout_view(request):logout(request)returnredirect('index')配置路由 (hello/urls.py):
path('login/',views.login_view,name='login'),path('logout/',views.logout_view,name='logout'),四、注册功能:ModelForm
如果要写注册功能,我们需要用户填很多字段。既然User模型已经定义了这些字段,我们不需要再手写forms.Form,可以直接用ModelForm从模型生成表单。
4.1 定义注册表单
fromdjango.contrib.auth.modelsimportUserclassRegisterForm(forms.ModelForm):# 额外添加确认密码字段confirm_password=forms.CharField(label="确认密码",widget=forms.PasswordInput)password=forms.CharField(label="密码",widget=forms.PasswordInput)classMeta:model=User# 指定让用户填哪些字段fields=['username','email','password']# 自定义校验:检查两次密码是否一致defclean(self):cleaned_data=super().clean()pwd=cleaned_data.get("password")confirm=cleaned_data.get("confirm_password")ifpwd!=confirm:raiseforms.ValidationError("两次密码不一致")returncleaned_data4.2 注册视图
defregister_view(request):ifrequest.method=='POST':form=RegisterForm(request.POST)ifform.is_valid():# 注意:不能直接 form.save(),因为密码需要加密# commit=False 表示先生成对象但不存数据库user=form.save(commit=False)user.set_password(form.cleaned_data['password'])# 加密user.save()# 保存returnredirect('login')else:form=RegisterForm()returnrender(request,'hello/register.html',{'form':form})五、保护页面:@login_required
有些页面(如"写文章"、“个人中心”)只有登录后才能访问。
Django 提供了一个装饰器@login_required。
fromdjango.contrib.auth.decoratorsimportlogin_required# 如果未登录访问,会自动跳转到 settings.LOGIN_URL 配置的地址@login_required(login_url='/hello/login/')defprofile(request):# request.user 自动包含当前登录用户returnHttpResponse(f"欢迎进入个人中心,{request.user.username}")六、模板中的用户状态
在 HTML 模板中,我们可以直接通过{{ user }}获取当前用户状态。
<!-- base.html (或者 index.html) --><nav>{% if user.is_authenticated %}<span>你好,{{ user.username }}</span><ahref="{% url'logout'%}">注销</a>{% else %}<ahref="{% url'login'%}">登录</a><ahref="{% url'register'%}">注册</a>{% endif %}</nav>七、小结
关键要点:
- Form负责处理输入和验证,一定要用
is_valid()。 - Auth系统帮我们处理了 Session 和密码加密,千万不要自己存明文密码。
- ModelForm是快速开发的神器,能直接把 Model 变成表单。
八、课后作业
- 完善注册页:实现注册页面,并在注册成功后自动帮用户登录 (
login函数),然后跳转到首页。 - 修改密码:编写一个视图,允许已登录用户修改自己的密码(提示:使用
user.set_password()并保存,注意修改密码后 Session 会失效,需要update_session_auth_hash保持登录)。 - 博客发布:结合 Day 60 的
Article模型,制作一个"发布文章"的页面。- 使用
ModelForm。 - 需要
@login_required。 - 保存时,自动将
author字段设置为request.user(需先给 Article 增加 author 外键)。
- 使用
下节预告
Day 62:Python Web 部署 (Nginx + Gunicorn)- 代码在本地跑得好好的,怎么让它在公网服务器上跑起来?明天我们学习生产环境的部署流程!
系列导航:
- 上一篇:Day 60 - Django模型Models
- 下一篇:Day 62 - PythonWeb部署(待更新)