【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 %}
相关推荐
懂点Tech2 小时前
ctfshow misc28:GIF 高度修改解题与脚本实现
开发语言·windows·python
comedate3 小时前
SMLib 的 Examples 导读:PyAPI / SM_API / SMLib 三组示例怎么读
python·cad·smlib·examples·sm_api
云和数据.ChenGuang3 小时前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
摇滚侠3 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 12
java·数据库·笔记
川石课堂软件测试3 小时前
学习软件测试需掌握的一些知识
数据库·python·sql·功能测试·网络协议·mysql·http
万化冥合4 小时前
PyBox屏幕键盘如何辅助演示键盘操作?
python·计算机外设
车软学堂4 小时前
从测试转开发,到底要补什么
网络·人工智能·python·功能测试·单片机·车载系统·自动化
天空依然蔚蓝4 小时前
分享一个自动检测网站在线状态的python程序
python·运维开发·1024程序员节
岁月宁静4 小时前
一个 AI 项目从本地到上线,要经过哪些步骤?全流程讲清楚
python·docker·agent
Cosolar5 小时前
不收费、不加水印、数据归你:我做了个开源的在线简历工具
后端·面试·前端框架