【Web应用开发笔记】Django笔记8:用户账户相关功能

前言

之前我们的"博客页面"项目已经有了如下功能:

  • 查看所有博客、博客具体页面
  • 新增博客
  • 编辑博客
  • 删除博客

这意味着我们的核心操作已经完成。但是还没有给用户提供账号相关功能

  • 注册
  • 登入
  • 登出

用户账户的这些功能如果自己实现显然会有很多可预见的问题,比如各种字符串校验、重名检查、安全校验 等等。

好在 Django 内置了相关的功能,我们可以直接使用。

1. 登入、登出

1.1 URL 配置

  • learn_django/urls.py
    • urlpatterns 列表中新增如下内容
python 复制代码
path("accounts/", include("django.contrib.auth.urls")),
  • 视图
    • 有了这个内置功能之后,我们不需要创建相关的视图了,因为 django.contrib.auth.urls 已经内置了完整的视图和模板。
    • 例如:
URL 路径 功能 内置视图
/accounts/login/ 登录页面 LoginView
/accounts/logout/ 登出功能 LogoutView
/accounts/password_change/ 修改密码 PasswordChangeView
/accounts/password_reset/ 重置密码 PasswordResetView
... ... ...
  • 模板来源:
    Django 内置了默认模板(位于 django/contrib/auth/templates/)
    如果你创建了 templates/registration/login.html,Django 会优先使用你的模板覆盖默认模板

1.2 settings.py

python 复制代码
# login
LOGIN_REDIRECT_URL = "home"
LOGOUT_REDIRECT_URL = "home"
配置项 作用 使用场景
LOGIN_REDIRECT_URL 登录成功后跳转的页面 用户提交登录表单验证通过后
LOGOUT_REDIRECT_URL 登出成功后跳转的页面 用户点击登出后

1.3 页面修改

1.3.1 登录页

  • templates/registration/login.html
html 复制代码
<!-- templates/registration/login.html -->
{% extends "base.html" %}

{% block content %}
<h2>Log In</h2>
<form method="post">{% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Log In</button>
</form>
{% endblock content %}

1.3.2 base.html

想象一下,假如我们希望在所有页面的最上面都可以看到如下信息:

  • 当前有没有登录
  • 是谁登录了
  • 没有登录的需要一个登录链接
  • 登录了的需要一个登出链接

满足以上要点的方法就是:

  • 所有页面:在 base.html 中
  • 条件选择:{% if user.is_authenticated %} ... {% else %} ... {% endif %}
  • 登入:{% url 'login' %}
  • 登出:{% url 'logout' %}

最终得到的页面如下:

  • templates/base.html
    • 关注这段:{% if user.is_authenticated %} 引导的逻辑
html 复制代码
<!-- templates/base.html -->
{% load static %}

<html>
    <head>
        <title>Django blog</title>
        <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400"
            rel="stylesheet">
        <link href="{% static 'css/base.css' %}" rel="stylesheet">
    </head>
    <body>
        <div>
            <header>
                <!-- start new HTML... -->
                <div class="nav-left">
                    <h1><a href="{% url 'home' %}">Django blog</a></h1>
                </div>
                <div class="nav-right">
                    <a href="{% url 'post_new' %}">+ New Blog Post</a>
                </div>
                <!-- end new HTML... -->
            </header>

            {% if user.is_authenticated %}
                <p>Hi {{ user.username }}!</p>
                <p><a href="{% url 'logout' %}">Log out</a></p>
            {% else %}
                <p>You are not logged in.</p>
                <a href="{% url 'login' %}">Log In</a>
            {% endif %}

            {% block content %}
            {% endblock content %}
        </div>
    </body>
</html>

2. 注册

现在我们需要给用户提供注册功能

推荐的做法是用一个专门的 APP 来干这件事

2.1 创建 APP

  • 自动创建文件
bash 复制代码
python manage.py startapp accounts
  • 注册到 settings.py
    • 在 INSTALLED_APPS 列表添加如下字符串:
python 复制代码
"accounts",

2.2 URL 配置

  • learn_django/urls.py
    • urlpatterns 列表中新增如下内容
python 复制代码
path("accounts/", include("accounts.urls")),

这意味着我们需要在 accounts/ 文件夹下新建 url.py 并配置路径

  • accounts/urls.py
python 复制代码
# accounts/urls.py
from django.urls import path
from .views import SignUpView

urlpatterns = [
    path("signup/", SignUpView.as_view(), name="signup"),
]

现在,现在这个 SignUpView 视图还没创建,我们下一步在 view.py 中创建这个类。

2.3 视图

  • accounts/views.py
python 复制代码
# accounts/views.py
from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from django.views.generic import CreateView

class SignUpView(CreateView):
    form_class = UserCreationForm
    template_name = "registration/signup.html"
    success_url = reverse_lazy("login")

还记得 success_url 和 reverse_lazy 是干什么的吗?

现在就差 templates/registration/signup.html 了。

2.4 模版

  • templates/registration/signup.html
html 复制代码
<!-- templates/registration/signup.html -->
{% extends "base.html" %}

{% block content %}
<h2>Sign Up</h2>
<form method="post">{% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Sign Up</button>
</form>
{% endblock content %}

还是一如既往的简洁。这一切都归功于 CBV 机制。

有兴趣可以去了解上代码中的这两个类:

  • CreateView
  • UserCreationForm

看看它们做了什么

2.5 效果

3. bug fix

3.1 个人使用 & 分析

我开始浏览我的项目,这让我发现了一些不合逻辑的地方。

其原因如下:

  • 因为我新增了用户注册、登录、登出 的功能
  • 这个功能与之前的页面:新建、编辑、删除 有逻辑上的联系
  • 这个联系就在于 用户 & 作者 两者的联系
    • 当前用户是作者这个集合中的一个元素
    • 用户的操作权限应该仅限于该用户所创建的博客
    • 未登录的时候只能赋予"浏览"权限

最终我总结了一下,我的页面应该具备以下逻辑:

  • 在我没登录的时候,不应该提供:
    • "新建、编辑、删除" 功能
  • 在我登录之后
    • "新建页面"不需要提供 author 选项,直接采用登录的用户即可
    • 我只能编辑、删除当前用户创建过的页面

3.2 代码修改

  • blog/views.py
    • 在"创建博客"的视图中,去掉 author 的选项,直接设置为当前用户
python 复制代码
class BlogCreateView(CreateView):
    model = Post
    template_name = "post_new.html"
    fields = ["title", "body"]
    
    def form_valid(self, form):
        form.instance.author = self.request.user  # 设置当前用户为作者
        return super().form_valid(form)
  • templates/base.html
    • 用 {% if user.is_authenticated %} 包裹了"新建博客"的链接
html 复制代码
                {% if user.is_authenticated %}
                <div class="nav-right">
                    <a href="{% url 'post_new' %}">+ New Blog Post</a>
                </div>
                {% endif %}
  • templates/post_detail.html
    • 使用 {% if user.is_authenticated and user == post.author %} 包裹了"编辑、删除"功能
python 复制代码
<!-- 只有作者才能看到编辑和删除链接 -->
{% if user.is_authenticated and user == post.author %}
    <a href="{% url 'post_edit' post.pk %}">+ Edit Blog Post</a>
    <p><a href="{% url 'post_delete' post.pk %}">+ Delete Blog Post</a></p>
{% endif %}
相关推荐
词元Max2 分钟前
2.5 Python 类型注解与运行时类型检查
开发语言·python
沪漂阿龙3 分钟前
深度解析Pandas数据组合:从concat到merge,打通你的数据处理任督二脉
python·数据分析·pandas
无籽西瓜a9 分钟前
【西瓜带你学设计模式 | 第五期 - 建造者模式】建造者模式 —— 产品构建实现、优缺点与适用场景及模式区别
java·后端·设计模式·软件工程·建造者模式
童园管理札记10 分钟前
2026实测|GPT-4.5+Agent智能体:3小时搭建企业级客服系统,附完整源码与部署教程(一)
经验分享·python·深度学习·重构·学习方法
墨^O^16 分钟前
进程与线程的核心区别及 Linux 启动全过程解析
linux·c++·笔记·学习
寒秋花开曾相惜16 分钟前
(学习笔记)3.9 异质的数据结构(3.9.1 结构)
c语言·网络·数据结构·数据库·笔记·学习
大飞记Python17 分钟前
【2026更新】Python基础学习指南(AI版)——安装
自动化测试·python·ai编程
猹叉叉(学习版)26 分钟前
【系统分析师_知识点整理】 10.软件需求工程
笔记·需求分析·软考·系统分析师
LuminousCPP28 分钟前
C语言自定义类型全解析
c语言·笔记·枚举·结构体·联合体
AI街潜水的八角28 分钟前
YOLO26手语识别项目实战1-三十五种手语实时检测系统数据集说明(含下载链接)
python·深度学习