用 Django 和 Python 构建个人日记
目录
一个日记是个人安全的空间。在 Django 的帮助下,您可以在自己的计算机上创建日记,而无需将数据存储在其他人的云端。通过跟随下面的项目,您将看到在 Django 中构建一个正常运行的Web 应用程序的速度有多快,而无需任何外部依赖。
在本教程中,您将学习如何:
- 设置Django 项目
- 使用标准SQLite数据库
- 使用 Django管理站点
- 创建模型和基于类的视图
- 嵌套和样式模板
- 通过身份验证保护您的日记
本教程将指导您逐步完成最终日记。如果您刚刚开始使用 Django 并希望完成您的第一个真正的项目,那么本教程适合您!
演示视频
在您日记的主页上,您会看到一个条目列表。您可以滚动浏览它们并通过单击按钮创建新的。本教程中提供了样式,因此您可以专注于代码的 Django 部分。这是一个快速演示视频,展示了它的实际效果:
在本教程结束时,您将能够完美地浏览您的日记,以按需创建、阅读、更新和删除条目。
项目概况
本教程分为多个步骤。这样,您就可以休息并按照自己的节奏继续。在每一步中,您都将处理日记项目的特定领域:
- 设置你的 Django 日记项目
- 在后端创建条目
- 在前端显示条目
- 添加样式
- 在前端管理条目
- 改善您的用户体验
- 实施认证
通过跟随,您将探索 Web 应用程序的基础知识以及如何添加 Django 项目的常见功能。完成本教程后,您将创建自己的个人日记应用程序,并将有一个Django 项目蓝图来构建。
先决条件
您不需要任何先前的 Django 知识即可完成此项目。如果您想了解有关本教程中遇到的主题的更多信息,您将在此过程中找到指向资源的链接。
但是,您应该习惯于使用命令行并且具备Python 和类的基本知识。尽管了解虚拟环境和会有所帮助,但您将在学习本教程时学习如何设置所有内容。pip
第 1 步:设置你的 Django 日记
通过创建项目目录并设置虚拟环境来启动项目。此设置将使您的代码与您机器上的任何其他项目隔离。您可以随意命名项目文件夹和虚拟环境。在本教程中,项目文件夹命名为my-diary
,虚拟环境命名为.venv
:
$ mkdir my-diary
$ cd my-diary
$ python3 -m venv .venv
$ source .venv/bin/activate
您的提示现在以括号中的虚拟环境名称开头。这是虚拟环境被激活的指示符。对于本教程的其余部分,必须激活您的虚拟环境。以下所有步骤都将在此目录或其子目录中进行。
注意:要在Windows上激活您的虚拟环境,您可能需要运行以下命令:
c:\> python -m venv .venv
c:\> .venv\Scripts\activate.bat
对于其他平台和 shell,您可能需要使用不同的命令。
对您的日记唯一的其他要求是 Django 本身。安装本教程的特定版本pip
:
(.venv) $ python -m pip install Django==3.2.1
此命令安装 Django 和 Django 需要的一些依赖项。这就是您所需要的一切。
初始化 Django
满足所有要求后,是时候启动 Django 项目本身了。使用 Django 的命令行实用程序创建基本项目结构:
(.venv) $ django-admin startproject diary .
不要忘记.
在上述命令的末尾添加点 ( )。点阻止 Django 为您的日记项目创建另一个目录。
Django 刚刚创建了一个manage.py
文件和一个以diary
五个文件命名的文件夹。您不必确切了解他们的工作。如果你好奇,你可以看一看这些文件。它们在开头都包含一个解释,描述它们为什么存在。在本教程中,您只需要编辑其中两个:
文件 | 在教程中编辑? |
---|---|
manage.py |
❌ |
diary/__init__.py |
❌ |
diary/asgi.py |
❌ |
diary/settings.py |
✅ |
diary/urls.py |
✅ |
diary/wsgi.py |
❌ |
从现在开始,该manage.py
文件将接管命令行中的管理任务。您将在本教程中遇到其中一些。
创建数据库
现在你的 Django 日记项目的基础已经准备好了,你需要一个地方来存储你日记的未来内容。为此,您必须创建一个数据库。
如果没有提供其他数据库配置,Django默认支持多个数据库并使用SQLite数据库。您只需要一个SQLite数据库,因为您是连接到它的唯一用户,并且您的 Django 日记项目只会在本地运行。
最好的部分是您可以使用单个命令创建 SQLite 数据库。通过运行migrations,您可以将数据库架构的更改应用到数据库中:
(.venv) $ python manage.py migrate
当您查看项目目录时,您应该会看到一个db.sqlite3
文件。拍拍自己的肩膀:您刚刚创建了一个数据库!
要将项目的当前状态与本教程的可下载文件进行比较,请单击以下链接:
与本节相关的文件在source_code_step_1/
目录中。
成为超级用户
作为您个人日记的所有者,您已经获得了superuser
. 使用以下命令声明它:
(.venv) $ python manage.py createsuperuser
Username (leave blank to use 'root'): admin
Email address: admin@example.com
Password: RealPyth0n
Password (again): RealPyth0n
Superuser created successfully.
系统会提示您选择用户名、提供电子邮件地址并设置密码。这是你日记的关键,所以一定要记住它。
运行开发 Web 服务器
您将经常使用的另一个命令是runserver
. 此命令运行轻量级开发 Web 服务器:
(.venv) $ python manage.py runserver
您可以指定IP 地址和端口runserver
。默认情况下,服务器在端口8000
上运行127.0.0.1
并且只能在您的计算机上访问。在服务器运行的情况下,您可以在浏览器中使用http://127.0.0.1:8000
或访问您的 Django 项目http://localhost:8000
:
这是您日记的主页。到目前为止,只能看到火箭。这意味着安装成功。
重要提示:每次在浏览器中访问日记项目时,如果尚未运行,则必须先启动本地开发 Web 服务器。
通过访问http://localhost:8000/admin
并使用您的凭据登录来完成本教程的第一步:
这是您自己的Django 管理站点!它是 Django最强大的功能之一。只需进行一些调整,您就可以立即管理内容和用户。目前,在 Django 管理站点中没有什么可看的。是时候改变它了!
第 2 步:将您的日记条目添加到后端
一个 Django 项目包含一个或多个应用程序。应用程序的范围应该是有限的。一开始,区分项目和应用程序可能会令人困惑。但是在大型 Django 项目中,这种关注点分离可以保持代码库干净。这种结构的另一个优点是您可以将应用程序重用于其他项目。
连接条目应用程序
在您的终端中,Django 开发 Web 服务器可能仍在运行。通过在终端中按Ctrl+C来停止它。
在本教程中,您只需要一个额外的应用程序。该应用程序的主要目的是处理您的日记条目,所以让我们调用该应用程序entries
。运行命令以创建entries
应用程序:
(.venv) $ python manage.py startapp entries
此命令entries
在您的项目中创建一个包含一些预定义文件的文件夹。在本教程后面,您只需要编辑其中的三个:
文件 | 在教程中编辑? |
---|---|
entries/__init__.py |
❌ |
entries/admin.py |
✅ |
entries/apps.py |
❌ |
entries/models.py |
✅ |
entries/tests.py |
❌ |
entries/views.py |
✅ |
如您所见,其中一些与diary/
目录中的文件具有相同的名称。通过单击下面的链接,您可以将您的文件夹结构与目录中的结构进行比较source_code_step_2/
:
到目前为止,Django 不知道您刚刚创建的应用程序。要将entries
应用程序连接到 Django 日记项目,请在 中的列表开头添加配置类的路径:INSTALLED_APPS
diary/settings.py
# diary/settings.py
INSTALLED_APPS = [
"entries.apps.EntriesConfig",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
该entries
应用程序插入到diary
项目,现在,Django的发现它的配置。这些配置之一是描述您的日记条目在数据库中的外观的模型。
创建条目模型
您已经创建了数据库。现在是时候定义存储日记条目的数据库表了。在 Django 中,您可以使用模型类来做到这一点。就像 Python 中的常规类一样,模型名称应该是单数和大写。当您的应用程序被调用时entries
,您的模型将被调用Entry
。
Entry
模型的字段是日记条目将具有的元素。在前面,这些字段将显示为表单。在后面,它们将是您的Entry
数据库表的列。本教程中的日记条目包含三个字段:
title
是标题。content
是正文正文。date_created
是创建日期和时间。
在 中entries/models.py
,首先从导入 。然后在同一个文件中创建类,如下所示:timezone
django.utils
Entry
1# entries/models.py
2
3from django.db import models
4from django.utils import timezone
5
6class Entry(models.Model):
7 title = models.CharField(max_length=200)
8 content = models.TextField()
9 date_created = models.DateTimeField(default=timezone.now)
10
11 def __str__(self):
12 return self.title
13
14 class Meta:
15 verbose_name_plural = "Entries"
通过导入timezone
模块,您可以将其timezone.now
用作第9 行中的default
参数date_created
。这样,如果您在创建条目时未为其定义特定值,则默认情况下将使用当前日期和时间。稍后在为日记条目创建表单时,您将使用此行为。
除了title
, content
, 和 之外date_created
,Django 会自动添加id
一个唯一的主键。该字符串表示与主键条目的1
将是Entry object (1)
默认。添加 时.__str__()
,您可以自定义显示的内容。对于日记条目,标题是更好的字符串表示形式。
您必须调整的另一个变量是verbose_name_plural
. 否则,Django 会拼出你的Entry
asEntrys
和 not的复数形式Entries
。
注册入门模型
要Entry
在 Django 管理站点中查看模型,您需要在以下位置注册它entries/admin.py
:
# entries/admin.py
from django.contrib import admin
from .models import Entry
admin.site.register(Entry)
当您忘记在管理站点中注册模型时,Django 不会抛出错误。毕竟,并非每个模型都需要在用户界面中进行管理。但是对于日记中最小的可行产品,您将利用内置的 Django 管理站点。
迁移入口模型
添加新类并在管理站点上注册后,您需要为 Django制作迁移文件并运行它们。使用makemigrations
,您可以创建迁移文件,其中包含 Django 构建数据库的说明。使用migrate
,您可以实现它们:
(.venv) $ python manage.py makemigrations
(.venv) $ python manage.py migrate
迁移完成后,运行开发 Web 服务器,移动到浏览器,然后访问 Django 管理站点http://localhost:8000/admin
:
目前,没有列出任何条目。通过单击添加条目为您的日记至少创建一个条目来完成此步骤。不知道写什么?也许想想你的 Django 日记项目有一个功能齐全的后端是多么棒!
第 3 步:在前端显示您的日记条目
您现在可以在 Django 管理站点中添加新条目。但是当你在浏览器中访问你的日记首页时,它仍然显示了抖动的火箭。在这一步中,您将学习如何在前端显示您的日记条目。
如果您想查看此步骤结束时的代码外观,请单击以下链接:
与此步骤相关的文件在source_code_step_3/
目录中。
创建列表和详细信息视图
Django 中有两种视图:基于函数的视图和基于类的视图。两者都接受网络请求并返回网络响应。一般来说,基于函数的视图给你更多的控制,但也有更多的工作。基于类的视图给你更少的控制,但也更少的工作。
减少工作听起来不错。但这并不是您在日记中使用基于类的视图的唯一原因。您的 Django 日记将使用 Web 应用程序的典型视图,例如显示数据库项目列表或其详细信息。这就是为什么基于类的视图是日记视图的不错选择。
Django 提供了许多开箱即用的通用视图。在这种情况下,您将创建a和 a 的子类并将它们连接到您的模型中:DetailView
ListView
Entry
entries/views.py
1# entries/views.py
2
3from django.views.generic import (
4 ListView,
5 DetailView,
6)
7
8from .models import Entry
9
10class EntryListView(ListView):
11 model = Entry
12 queryset = Entry.objects.all().order_by("-date_created")
13
14class EntryDetailView(DetailView):
15 model = Entry
正如所承诺的,此时没有太多代码需要您编写。第Entry.objects.all()
12 行的查询将返回按主键排序的所有条目。增强它.order_by("-date_created")
会以升序返回您的条目,最新的条目位于列表顶部。
当你写这样的视图时,Django 会在后台做一些假设,比如视图要渲染的模板的名称和位置。
创建您的模板
使用模板,您可以动态生成 HTML。Django 期望您刚刚创建的基于类的视图的模板位于具有特定名称的特定位置。为您的模板创建子文件夹:
(.venv) $ mkdir -p entries/templates/entries
当然,模板的路径看起来有点奇怪。但是通过这种方式,您可以确保 Django 会找到完全正确的模板,即使其他应用程序共享相同的模型名称。在 中entries/templates/entries/
,您将存储Entry
模型的所有模板文件。首先创建entry_list.html
并添加以下内容:
1<!-- entries/templates/entries/entry_list.html -->
2
3{% for entry in entry_list %}
4 <article>
5 <h2 class="{{ entry.date_created|date:'l' }}">
6 {{ entry.date_created|date:'Y-m-d H:i' }}
7 </h2>
8 <h3>
9 <a href="{% url 'entry-detail' entry.id %}">
10 {{ entry.title }}
11 </a>
12 </h3>
13 </article>
14{% endfor %}
在 Django 模板中,您甚至可以动态引用 CSS 类。当您查看<h2>
第 5 行时,您可以看到class="{{ entry.date_created|date:'l' }}"
已添加到其中。这显示了具有特殊格式的时间戳。这样,<h2>
元素将工作日作为一个类,您可以稍后在 CSS 中为每个工作日指定一个独特的颜色。
在entry_list
循环内部,您可以访问Entry
模型的字段。为了不让列表中的信息过多,您只会在访问条目的详细信息页面时显示内容。entries/templates/entries/
使用entry_detail.html
作为文件名创建此详细信息页面并添加以下内容:
<!-- entries/templates/entries/entry_detail.html -->
<article>
<h2>{{ entry.date_created|date:'Y-m-d H:i' }}</h2>
<h3>{{ entry.title }}</h3>
<p>{{ entry.content }}</p>
</article>
一个detail
模板期望的是一个条目对象。这就是为什么您可以直接在此处访问它而无需循环。
将路线添加到您的视图
要查看正在运行的模板,您需要将视图连接到URL。Django 使用一个urls.py
文件来分派来自浏览器中用户的传入请求。diary
项目文件夹中已经存在这样的文件。对于条目应用程序,您必须首先创建它entries/urls.py
并将路径添加到EntryListView
和EntryDetailView
:
1# entries/urls.py
2
3from django.urls import path
4
5from . import views
6
7urlpatterns = [
8 path(
9 "",
10 views.EntryListView.as_view(),
11 name="entry-list"
12 ),
13 path(
14 "entry/<int:pk>",
15 views.EntryDetailView.as_view(),
16 name="entry-detail"
17 ),
18]
第8 行和第 13 行的path()
函数必须至少有两个参数:
- 一个路由字符串模式,其中包含一个 URL 模式
- 对视图的引用,它是基于类的视图的
as_view()
函数
此外,您可以将参数作为kwargs传递并提供name。使用名称,您可以在 Django 项目中轻松引用视图。因此,即使您决定更改 URL 模式,也不必更新模板。
现在,对于网址entries
的应用程序已经到位,你需要将它们连接到urlpatterns
列表中diary
。当您打开 时diary/urls.py
,您将看到urlpatterns
您的 Django 日记项目使用的。到目前为止,只有到 的路由"admin/"
,它是默认添加的,因此您可以访问 Django 管理站点。要在访问时显示日记条目http://localhost:8000
,首先需要将根 URL 分派到entries
应用程序:
# diary/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("entries.urls")),
]
创建新模板后,手动重新启动 Django 开发 Web 服务器。然后访问http://localhost:8000
并欣赏您的观点:
您可以通过点击相应的链接列表或访问看到一个条目的详细信息http://localhost:8000/entries/1
,其中1
是ID
一个现有的条目。
现在一切就绪,可以在前端查看您的条目。不过,您的日记看起来仍然有些单调。让我们在下一步中改变它!
第 4 步:让你的 Django 日记看起来不错
在此步骤中,您将为日记添加一些样式。如果你想看一下这一步完成的代码,那就点击下面的链接,查看source_code_step_4/
目录:
虽然你的写作很有创意,但日记的设计目前有点基础。你可以开始通过创建一个调味的东西了基础模板,在entries/templates/entries/base.html
与此内容:
<!-- entries/templates/entries/base.html -->
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Diary</title>
<link rel="stylesheet" href="{% static 'css/diary.css' %}">
</head>
<body>
<h1><a href="/">Dear diary …</a></h1>
{% block content %}{% endblock %}
</body>
</html>
使用模板继承,您不必在模板中重复标记。相反,您扩展您的子模板。然后 Django 在视图中提供它们时会自动将它们合并在一起。
添加样式表
通过{% load static %}
在模板文件的开头插入,您可以使用模板标签和 CSS 文件的相对路径来引用静态{% static %}
文件。建立diary.css
在entries/static/css/
扩大框下方查看CSS代码,你会添加到文件中。
diary.css 的内容显示隐藏
如前所述,<h2>
条目列表中的每个元素都将其工作日作为一个类。通过样式.Saturday
和.Sunday
不同,您可以轻松地在列表中发现周末。
扩展子模板
现在是时候将子模板与base.html
父模板连接起来了。更新entries/templates/entries/entries_list.html
它看起来像这样:
1<!-- entries/templates/entries/entries_list.html -->
2
3{% extends "entries/base.html" %}
4
5{% block content %}
6 {% for entry in object_list %}
7 <article>
8 <h2 class="{{ entry.date_created|date:'l' }}">
9 {{ entry.date_created|date:'Y-m-d H:i' }}
10 </h2>
11 <h3>
12 <a href="{% url 'entry-detail' entry.id %}">
13 {{ entry.title }}
14 </a>
15 </h3>
16 </article>
17 {% endfor %}
18{% endblock %}
该{% block %}
模板标签定义了一个子模板可以覆盖文档的一部分。要启用此功能,您必须声明您的子模板扩展了父模板并定义了一个具有相同名称的块元素。使用第{% extends %}
3 行的模板标记,您将其定义entries/base.html
为父级。{% block %}
并{% endblock %}
在第 5 行和第 18 行包装将放置在content
父级块中的标记。
做同样的事情entries/templates/entries/entries_detail.html
:
<!-- entries/templates/entries/entries_detail.html -->
{% extends "entries/base.html" %}
{% block content %}
<article>
<h2>{{ entry.date_created|date:'Y-m-d H:i' }}</h2>
<h3>{{ entry.title }}</h3>
<p>{{ entry.content }}</p>
</article>
{% endblock %}
这两个模板都从其父模板继承了 HTML 结构和样式。它们共享相同的标题和<h1>
标题,以及由diary.css
. 要查看此操作,请启动您的 Django 开发服务器并转到http://localhost:8000
:
您现在可以有风格地阅读您的条目。但是,当您想要创建、更新或删除条目时,您必须转到 Django 管理站点。当您想快速记下一些想法时,点击次数太多了。在下一步中,您将通过将此功能添加到前端来改进您的工作流程。
第 5 步:在前端管理您的日记条目
当您构建和使用 Web 应用程序时,您会一直执行四个基本操作。这些操作非常常见,以至于它们经常被CRUD首字母缩写词所指代:
- Create
- Read
- Update
- Delete
在 Django 管理站点中,您已经可以执行所有这些操作。在前端,您目前只能阅读您的条目。为了类似于 Django 管理站点的功能,您将重复您已经为EntryDetail
and所做的工作EntryList
,添加一个视图、一个模板和一个 URL。
添加视图
在entries/views.py
已经导入ListView
和DetailView
至今。更新您的导入语句,使其看起来像这样:
# entries/views.py
from django.urls import reverse_lazy
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView,
)
在底部添加您的三个子类entries/views.py
:
1# entries/views.py
2
3class EntryCreateView(CreateView):
4 model = Entry
5 fields = ["title", "content"]
6 success_url = reverse_lazy("entry-list")
7
8class EntryUpdateView(UpdateView):
9 model = Entry
10 fields = ["title", "content"]
11
12 def get_success_url(self):
13 return reverse_lazy(
14 "entry-detail",
15 kwargs={"pk": self.entry.id}
16 )
17
18class EntryDeleteView(DeleteView):
19 model = Entry
20 success_url = reverse_lazy("entry-list")
这一次,将类连接到您的Entry
模型是不够的。对于EntryCreateView
and EntryUpdateView
,您还需要定义表单中应该显示哪些模型字段,如第 5 行和第 10EntryDeleteView
行所示。您的第 18 行仅执行删除条目项的操作,因此您不需要定义其中的任何字段。
此外,您需要定义在提交视图表单后应该将用户重定向到何处。默认情况下,.get_success_url()
只返回 的值success_url
。在 中EntryUpdateView
,您需要覆盖此方法。
通过在第 15 行中提供entry.id
作为关键字参数,您在编辑后停留在条目详细信息页面上。您不使用 URL,而是使用reverse_lazy按名称引用它们,就像您在模板中所做的那样。
创建模板
像以前一样,Django 查找具有特定名称的模板:
- 对于
EntryDeleteView
,它是entry_confirm_delete.html
。 - 对于
EntryCreateView
,它是entry_form.html
。 - 因为
EntryUpdateView
它会entry_update_form.html
。
当 Django 找不到 时entry_update_form.html
,它会尝试entry_form.html
作为后备。您可以通过创建一个处理两个视图的模板entries/templates/entries/
并添加一个基本提交表单来利用这一点:
1<!-- entries/templates/entries/entry_form.html -->
2
3{% extends "entries/base.html" %}
4{% block content %}
5 <form method="post">
6 {% csrf_token %}
7 {{ form.as_p }}
8 <input type="submit" value="Save">
9 </form>
10 {% if entry %}
11 <a href="{% url 'entry-detail' entry.id %}">
12 <button>Cancel</button>
13 </a>
14 {% else %}
15 <a href="{% url 'entry-list' %}">
16 <button>Cancel</button>
17 </a>
18 {% endif %}
19{% endblock %}
当此模板由 加载时CreateView
,表单将为空,取消它会再次将您带到条目列表。当由 加载时CreateUpdateView
,它将预先填充条目的当前标题和内容。取消会将您带到条目详细信息页面。
有多种方法可以在模板中呈现表单。随着{{ form.as_p }}
在第7行,Django会显示您在包裹在段落视图中定义的字段。每当您在 Django 表单中发布内容时,您还必须在其中包含第6 行中的{% csrf_token %}
模板标记。这是一种防止跨站点请求伪造的安全措施。
与其他模板一样,您{% extends "entries/base.html" %}
在第 3 行添加以扩展基本模板。然后定义要包含在第block content
4 行和第 18 行之间的标记中的内容。对entry_confirm_delete.html
in使用相同的模式entries/templates/entries/
:
<!-- entries/templates/entries/entry_confirm_delete.html -->
{% extends "entries/base.html" %}
{% block content %}
<form method="post">{% csrf_token %}
<p>
Are you sure you want to delete
<em>"{{ entry.title }}"</em>
created on {{ entry.date_created|date:'Y-m-d' }}?
</p>
<input type="submit" value="Confirm">
</form>
<a href="{% url 'entry-detail' entry.id %}">
<button>Cancel</button>
</a>
{% endblock %}
当您要删除条目时,将显示此模板。在表单中提及"{{ entry.title }}"
和 会{{ entry.created_date|date:'Y-m-d' }}
提醒您按下确认键将删除哪个条目。
创建 URL
创建视图及其模板后,创建它们的路由以在前端访问它们。向urlpatterns
in添加三个额外的路径entries/urls.py
:
# entries/urls.py
urlpatterns = [
path(
"",
views.EntryListView.as_view(),
name="entry-list"
),
path(
"entry/<int:pk>",
views.EntryDetailView.as_view(),
name="entry-detail"
),
path(
"create",
views.EntryCreateView.as_view(),
name="entry-create"
),
path(
"entry/<int:pk>/update",
views.EntryUpdateView.as_view(),
name="entry-update",
),
path(
"entry/<int:pk>/delete",
views.EntryDeleteView.as_view(),
name="entry-delete",
),
]
对于entry-create
,您只需要一个基本create
路径。像entry-detail
前面创建,entry-update
并且entry-delete
需要一个主键,以确定哪个入口应更新或删除。
现在,您可以直接在前端创建、更新和删除日记条目。启动开发web服务器,访问http://localhost:8000/create
测试。如果您想将您的代码与本教程中的代码进行比较,请单击以下链接:
您可以在source_code_step_5/
目录中找到与此步骤相关的文件。
第 6 步:改善您的用户体验
使用您的日记,您可能会偶然发现一些让导航有点烦人的怪癖。在这一步中,您将一一解决它们。您会看到界面中的微小变化会对您的日记用户体验产生重大影响。
处理您的成功
得到一些反馈总是很好的,尤其是当它是积极的时。使用消息框架,您可以快速定义在提交表单后显示的一次性闪现消息。要使用此功能,进口messages
和SuccessMessageMixin
到entries/views.py
:
# entries/views.py
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
EntryListView
并且EntryDetailView
是阅读视图并且不处理表单。他们可能会在模板中显示一条消息,但不会发送一条消息。这意味着您不需要SuccessMessageMixin
为它们创建子类。EntryCreateView
,EntryUpdateView
并且EntryDeleteView
,在另一方面,也通知添加到邮件存储,所以你需要调整它们的功能:
1# entries/views.py
2
3class EntryCreateView(SuccessMessageMixin, CreateView):
4 model = Entry
5 fields = ["title", "content"]
6 success_url = reverse_lazy("entry-list")
7 success_message = "Your new entry was created!"
8
9class EntryUpdateView(SuccessMessageMixin, UpdateView):
10 model = Entry
11 fields = ["title", "content"]
12 success_message = "Your entry was updated!"
13
14 def get_success_url(self):
15 return reverse_lazy(
16 "entry-detail",
17 kwargs={"pk": self.object.pk}
18 )
在第 3 行和第 9行继承SuccessMessageMixin
in之后,您在第 7 行和第 12 行为它们定义 a 。特别是当您执行删除条目等破坏性操作时,提供一切正常的反馈至关重要。要在 中显示消息,您必须添加自定义方法并手动将自定义添加到消息框架:EntryCreateView
EntryUpdateView
success_message
DeleteView
.delete()
success_message
1# entries/views.py
2
3class EntryDeleteView(DeleteView):
4 model = Entry
5 success_url = reverse_lazy("entry-list")
6 success_message = "Your entry was deleted!"
7
8 def delete(self, request, *args, **kwargs):
9 messages.success(self.request, self.success_message)
10 return super().delete(request, *args, **kwargs)
您在第 8 行需要这个额外的方法,因为DeleteView
该类不是FormView
. 这就是为什么你可以跳过添加SuccessMessageMixin
在EntryDeleteView
第3行。
点击下方链接,查看完整内容entries/views.py
。您可以在source_code_step_6/
目录中找到它:
现在视图发送消息,您需要增强模板以显示它们。
获取消息
消息存储在消息存储器中。通过循环遍历它,您可以显示当前在消息存储中的所有消息。在 Django 模板中,您可以通过使用消息模板标签来实现这一点。您构建日记和构建模板的方式,您只需要将其添加到entries/base.html
:
1<!-- entries/base.html -->
2
3<h1><a href="/">Dear diary …</a></h1>
4
5{% if messages %}
6 <ul class="messages">
7 {% for message in messages %}
8 <li class="message">
9 {{ message }}
10 </li>
11 {% endfor %}
12 </ul>
13{% endif %}
14
15{% block content %}{% endblock %}
通过将消息列表包装{% if messages %}
在第 4 行和第 12 行,您可以确保只有在存储中有任何消息时才会有条件地显示它。
改善您的导航
要创建、编辑或删除条目,您需要记住相应的 URL,然后在地址栏中键入它们。多么乏味!幸运的是,您可以通过向视图添加链接来解决此问题。从模板中的entry-create
视图链接开始entries/templates/entries/entry-list.html
:
1<!-- entries/templates/entries/entry-list.html -->
2
3{% block content %}
4<article>
5 <h2 class="mark">{% now "Y-m-d H:i" %}</em></h2>
6 <a href="{% url 'entry-create' %}"><button>Add new entry</button></a>
7</article>
8
9{% for entry in object_list %}
此标记将类似于其他日记条目列表项。立即向entries/templates/entries/entry_detail.html
模板添加新段落以</article>
快速编辑或删除条目:
<!-- entries/templates/entries/entry_detail.html -->
</article>
<p>
<a href="{% url 'entry-update' entry.id %}">✍️ Edit</a>
<a href="{% url 'entry-delete' entry.id %}">⛔ Delete</a>
</p>
{% endblock %}
此代码在分别链接到entry-update
和的条目详细信息下方添加了两个链接entry-delete
。
设计您的消息
最后,通过添加.messages
和.message
结尾来设置 flash 消息的样式entries/static/css/diary.css
:
/* entries/static/css/diary.css */
/* Messages */
.messages {
padding: 0;
list-style: none;
}
.message {
width: 100%;
background: lightblue;
padding: 1rem;
text-align: center;
margin: 1rem 0;
}
通过在终端中按Ctrl+C停止开发 Web 服务器并重新启动它。然后访问http://localhost:8000
以查看您的操作更改。如果消息看起来没有样式,您可能需要清除浏览器的缓存,以便重新加载样式表更改:
您现在拥有一个完全用 Django 构建的完全可用的日记 Web 应用程序。尽管您的日记仅存储在本地,但最好确保只有您可以访问它。让我们在开始记录之前添加该限制。
第 7 步:锁定你的 Django 日记
多么小的金锁是用于物理日记,登录表单是用于您的数字日志。此锁的关键是您已用于登录 Django 管理站点的名称和密码组合。
重用您的 Django 管理员登录
Django 提供的身份验证系统非常基础。对于其他有普通用户的项目,可以考虑定制。但是对于你的 Django 日记,重复使用 Django 管理站点的登录就足够了。稍后您会发现这一切正常。首先,让我们注意注销。
添加注销链接
您通过访问一个特殊的 URL 来注销。Django 已经提供了一个带有名称的 URL,用于admin:logout
将您从 Django 管理站点注销。当您登录并从项目中的任何位置访问此 URL 时,Django 会自动将您注销。要快速访问此 URL,请在 底部添加指向它的链接entries/templates/entries/base.html
:
<!-- entries/templates/entries/base.html -->
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Diary</title>
<link rel="stylesheet" href="{% static 'css/diary.css' %}">
</head>
<body>
<h1><a href="/">Dear diary …</a></h1>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li class="message">
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
{% block content %}{% endblock %}
<hr>
<a href="{% url 'admin:logout' %}">Logout</a>
</body>
</html>
启动您的开发 Web 服务器,转到您的主页http://localhost:8000
,然后单击注销链接。现在,当您访问 时http://localhost:8000/admin
,您会看到登录表单。这意味着您已注销。但是,当您http://localhost:8000
再次访问时,您的日记条目仍然可以访问。是时候改变它了!
限制访问您的视图
在 Django 中,您可以定义允许谁查看哪些视图。默认情况下,它们对访问您网站的所有人开放。要确保视图需要经过身份验证的用户才能访问,请LoginRequiredMixin
在顶部导入entries/views.py
:
# entries/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView,
)
from .models import Entry
一旦视图类使用LoginRequiredMixin
,它首先需要成功登录。此外,您必须定义 alogin_url
以便 Django 在您未登录时知道将您重定向到何处。 您可以创建一个继承并定义in的基类,而不是单独对所有类执行此操作:LoginRequiredMixin
login_url
entries/views.py
# entries/views.py
class LockedView(LoginRequiredMixin):
login_url = "admin:login"
现在,您可以LockedView
在所有其他视图中进行继承,这些视图应该只能由经过身份验证的用户访问。编辑entries/views.py
使您的类看起来像这样:
# entries/views.py
class EntryListView(LockedView, ListView):
model = Entry
queryset = Entry.objects.all().order_by("-created_date")
class EntryDetailView(LockedView, DetailView):
model = Entry
class EntryCreateView(LockedView, SuccessMessageMixin, CreateView):
model = Entry
fields = ["title", "content"]
success_url = reverse_lazy("entry-list")
success_message = "Your new entry was created!"
class EntryUpdateView(LockedView, SuccessMessageMixin, UpdateView):
model = Entry
fields = ["title", "content"]
success_message = "Your entry was updated!"
def get_success_url(self):
return reverse_lazy("entry-detail", kwargs={"pk": self.object.pk})
class EntryDeleteView(LockedView, SuccessMessageMixin, DeleteView):
model = Entry
success_url = reverse_lazy("entry-list")
success_message = "Your entry was deleted!"
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs)
现在,当您访问 时http://localhost:8000
,您将被重定向到 Django 登录表单。登录后,您将被重定向到条目列表,并看到仅对您可见的所有内容:
就是这样!您已经成功地在 Django 中建立了自己的个人日记。如果您想将您的代码与项目的最终代码进行比较,请单击以下链接:
该项目的完整代码在source_code_step_final/
目录中。
下一步
您构建的日记功能齐全,随时可用。但它也是一个很好的基础。也许您已经对如何进一步改进日记有了一些想法。或者,您可以尝试以下想法之一:
- 为您最近的条目添加一个页面。
- 给每个工作日一个颜色。
- 在 HTML
<title>
标记中显示创建日期。 - 为条目创建一天选择的表情符号。
- 对条目列表进行分页。
在本教程中,您了解了 Django 提供的一些基本概念和模式。希望它激发了一些深入研究这个 Python Web 框架的兴趣。如果您想继续您的旅程并了解更多信息,您可以查看以下教程:
- 使用 Django 的第一步:设置 Django 项目
- Django 入门第 1 部分:构建投资组合应用程序
- 在 Django Admin 中管理用户需要知道什么
- 使用 Python 自定义 Django Admin
- 使用 Django、Vue 和 GraphQL 构建博客
您可以将通过完成日记项目获得的知识应用于其他 Django 教程,并将您的 Web 应用程序技能提升到一个新的水平!
结论
在本教程中,您使用 Django 从头开始创建了一个个人日记。您学习了如何构建一个可以日常使用的全功能 Web 应用程序。它利用了 Django 的许多优势,包括管理站点、基于类的视图、消息框架和模板系统。
这个 Django 项目也是您未来 Django 项目的完美基础。您在此日记项目中完成的步骤与其他项目基本相同,例如博客或待办事项应用程序。
在本教程中,您学习了如何:
- 设置Django 项目
- 使用标准SQLite数据库
- 使用 Django管理站点
- 创建模型和基于类的视图
- 嵌套和样式模板
- 通过身份验证保护您的日记
- 点赞
- 收藏
- 关注作者
评论(0)