47 KiB
用 Django 和 Python 创建个人日记
一个日记是个人的安全空间。在 Django 的帮助下,你可以在自己的电脑上创建日记,而无需将数据存储在别人的云中。通过跟随下面的项目,你将会看到在 Django 中没有任何外部依赖的情况下,你可以多快地构建一个有效的 web 应用。
在本教程中,您将学习如何:
- 建立一个 Django 项目
- 使用标准的 SQLite 数据库
- 利用 Django 管理站点
- 创建模型和基于类的视图
- 嵌套和样式模板
- 通过认证保护您的日记
本教程将引导你一步一步地完成你的最终日记。如果你刚刚开始使用 Django,并且想要完成你的第一个真正的项目,那么这个教程就是为你准备的!
要获得 Django 项目及其步骤的完整源代码,请单击下面的链接:
获取源代码: 点击此处获取源代码,您将在本教程中使用用 Django 和 Python 构建一个个人日记 web 应用程序。
演示视频
在你日记的主页上,你会有一个条目列表。你可以滚动浏览它们,并点击一个按钮来创建新的。本教程提供了样式,因此您可以专注于代码的 Django 部分。这里有一个快速演示视频,展示了它的实际效果:
https://player.vimeo.com/video/561429980?background=1
本教程结束时,你将能够完美地浏览你的日记,按需创建、阅读、更新和删除条目。
项目概述
本教程分为多个步骤。这样,你可以休息一下,然后按照自己的节奏继续。在每一步中,你将处理日记项目的一个特定领域:
- 建立你的 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
对于其他平台和 shells,您可能需要使用不同的命令。
你的日记的另一个要求是 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 |
981 号房 |
diary/urls.py |
981 号房 |
diary/wsgi.py |
-好的 |
从现在开始,manage.py文件将在命令行中接管的管理任务。在本教程中,您将会遇到其中的一些人。
创建数据库
现在你的 Django 日记项目的基础已经准备好了,你需要一个地方来存储你日记的未来内容。为此,必须创建一个数据库。
Django 附带了对多数据库的支持,如果没有提供其他数据库配置,默认情况下,它使用一个 T2 SQLite 数据库。一个 SQLite 数据库是您所需要的,因为您是唯一连接到它的用户,并且您的 Django 日记项目将只在本地运行。
最棒的是,您可以用一个命令创建一个 SQLite 数据库。通过运行迁移,您将数据库模式的更改应用到数据库中:
(.venv) $ python manage.py migrate
当您查看项目目录时,应该会看到一个db.sqlite3文件。拍拍自己的肩膀:你刚刚创建了一个数据库!
要将项目的当前状态与本教程的可下载文件进行比较,请单击下面的链接:
获取源代码: 点击此处获取源代码,您将在本教程中使用用 Django 和 Python 构建一个个人日记 web 应用程序。
与本节相关的文件在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.
系统会提示您选择用户名,提供电子邮件地址,并设置密码。这是你日记的关键,所以一定要记住。
运行开发网络服务器
您将经常使用的另一个命令是runserver。这个命令运行一个轻量级的开发 web 服务器:
(.venv) $ python manage.py runserver
您可以指定 IP 地址和 runserver 端口。默认情况下,服务器运行在127.0.0.1的端口8000上,并且只能在你的电脑上访问。随着服务器的运行,您可以使用http://127.0.0.1:8000或http://localhost:8000在浏览器中访问您的 Django 项目:
这是你日记的主页。到目前为止,只有一个火箭可以看到。这意味着安装成功。
**重要提示:**每次在浏览器中访问您的日记项目时,如果您的本地开发 web 服务器尚未运行,您必须首先启动它。
通过访问http://localhost:8000/admin并使用您的凭证登录,完成本教程的第一步:
这是你自己的 Django 管理网站!这是姜戈最强大的特色之一。只需进行一些调整,它就能让您立即管理内容和用户。目前,在 Django 管理站点上没有太多东西可看。是时候改变了!
第二步:将你的日记添加到后端
Django 项目包含一个或多个应用程序。一个 app 的范围应该是有限的。一开始,区分一个项目和应用可能会令人困惑。但是在大的 Django 项目中,这种关注点的分离保持了代码库的干净。这种结构的另一个好处是你可以重用其他项目的应用。
连接参赛作品 App
在您的终端中,Django 开发 web 服务器可能仍在运行。在终端按下 Ctrl + C 停止。
**提示:**打开第二个终端窗口,在一个窗口控制服务器,在另一个窗口运行命令:
导航到项目并激活虚拟环境后,您可以在第二个终端窗口中运行该项目的后续命令。
在本教程中,您只需要一个额外的应用程序。那个应用的主要目的是处理你的日记条目,所以让我们称这个应用为entries。运行命令创建entries应用程序:
(.venv) $ python manage.py startapp entries
该命令在您的项目中创建一个包含一些预定义文件的entries文件夹。在本教程的后面部分,您只需要编辑其中的三个:
| 文件 | 教程时编辑的? |
|---|---|
entries/__init__.py |
-好的 |
entries/admin.py |
981 号房 |
entries/apps.py |
-好的 |
entries/models.py |
981 号房 |
entries/tests.py |
-好的 |
entries/views.py |
981 号房 |
如您所见,其中一些与diary/目录中的文件同名。通过点击下面的链接,您可以将您的文件夹结构与source_code_step_2/目录中的文件夹结构进行比较:
获取源代码: 点击此处获取源代码,您将在本教程中使用用 Django 和 Python 构建一个个人日记 web 应用程序。
到目前为止,Django 还不知道你刚刚创建的应用程序。要将entries应用程序连接到 Django diary 项目,请在diary/settings.py的INSTALLED_APPS列表的开头添加配置类的路径:
# 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中,首先从django.utils进口和timezone。然后在同一个文件中创建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 行中date_created的default参数。这样,如果在创建条目时没有为当前日期和时间定义特定的值,则默认情况下将使用当前日期和时间。稍后在为日记条目创建表单时,您将利用这一行为。
除了title、content、date_created之外,Django 还会自动添加id作为唯一主键。默认情况下,主键为1的条目的字符串表示为Entry object (1)。当您添加.__str__()时,您可以自定义显示的内容。对于日记条目,标题是更好的字符串表示。
你要调整的另一个变量是verbose_name_plural。否则,Django 会把你的Entry的复数拼写成Entrys,而不是Entries。
注册进入模型
要在 Django 管理站点中查看Entry模型,您需要在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 日记项目有一个全功能后端是多么的棒!
第三步:在前端显示你的日记条目
现在,您可以在 Django 管理站点中添加新条目了。但是当你在浏览器中访问你的日记的主页时,它仍然显示着抖动的火箭。在这一步,你将学习如何在前端显示你的日记条目。
如果您想看看代码在这一步结束时的样子,请单击下面的链接:
获取源代码: 点击此处获取源代码,您将在本教程中使用用 Django 和 Python 构建一个个人日记 web 应用程序。
与此步骤相关的文件在source_code_step_3/目录中。
创建列表和详细视图
Django 中有两种视图:基于函数的视图和基于类的视图。两者都接受 web 请求并返回 web 响应。一般来说,基于函数的视图给你更多的控制,但也有更多的工作。基于类的视图给你更少的控制,但也更少的工作。
工作少听起来不错。但这并不是你在日记中使用基于类的视图的唯一原因。您的 Django 日记将使用 web 应用程序的典型视图,比如显示数据库项目列表或它们的详细信息。这就是为什么基于类的视图是你的日记视图的好选择。
Django 提供了许多开箱即用的通用视图。在这种情况下,您将创建 DetailView 和 ListView 的子类,并将它们连接到entries/views.py中的Entry模型:
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
正如所承诺的,现在没有太多的代码需要您编写。第 12 行的查询Entry.objects.all()将返回按主键排序的所有条目。用.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 类。当你看一看第 5 行的<h2>时,你可以看到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 应用程序,您必须首先在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 传递,并提供一个名称。有了名称,您就可以在 Django 项目中轻松地引用视图。所以即使你决定改变 URL 模式,你也不需要更新你的模板。
既然entries应用程序的 URL 已经准备好了,您需要将它们连接到diary的urlpatterns列表。当你打开diary/urls.py,你会看到你的 Django 日记项目使用的urlpatterns。到目前为止,只有到"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。
现在一切就绪,可以在前端看到您的条目。不过,你的日记看起来还是有点不规范。让我们在下一步中改变它!
第四步:让你的 Django 日记看起来更漂亮
在这一步,你将为你的日记增加一些风格。如果你想看看这一步完成的代码,点击下面的链接,查看source_code_step_4/目录:
获取源代码: 点击此处获取源代码,您将在本教程中使用用 Django 和 Python 构建一个个人日记 web 应用程序。
虽然你的写作很有创意,但日记的设计目前有点基础。您可以通过在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 %},你可以引用带有{% static %}模板标签和 CSS 文件相对路径的静态文件。在entries/static/css/中创建diary.css并展开下面的框来查看你将添加到文件中的 CSS 代码。
将下面的 CSS 代码复制并粘贴到diary.css中:
/* entries/static/css/diary.css */ * { box-sizing: border-box; } body { font-family: sans-serif; font-size: 18px; } a { color: inherit; } a:hover { opacity: 0.7; } h1 { font-size: 2.8em; } h1 a { text-decoration: none; } h2, h3 { font-size: 1.4em; margin: 0; display: inline-block; padding: 0.5rem 1rem; vertical-align: top; } h2 { background-color: aquamarine; } .mark { background-color: gainsboro; } .mark a { text-decoration: none; } article { margin-bottom: 0.5rem; } p { font-size: 1.2em; padding-left: 1rem; line-height: 1.3em; max-width: 36rem; color: dimgray; } em { font-style: normal; font-weight: bold; } /* Form */ label { display: block; } button, textarea, input { font-size: inherit; min-height: 2.5em; padding: 0 1rem; } input[type="text"], textarea { width: 100%; } textarea { padding: 0.5rem 1rem; font-family: sans-serif; } button, input[type="submit"] { margin: 0 1rem 2px 1rem; cursor: pointer; font-weight: bold; min-width: 8rem; } /* Day coloring */ .Saturday, .Sunday { background-color: lightsalmon; }
请随意增强和优化上面的代码,根据您的喜好调整任何元素。如果你不知道 CSS,如果你对 web 开发感兴趣,学习基础知识是值得的。
如前所述,条目列表中的每个<h2>元素都有自己的工作日作为一个类。通过对.Saturday和.Sunday进行不同的设计,你可以很容易地在列表中找到周末。
扩展子模板
现在是时候将子模板和base.html父模板连接起来了。更新entries/templates/entries/entry_list.html使其看起来像这样:
1<!-- entries/templates/entries/entry_list.html -->
2
3{% extends "entries/base.html" %} 4
5{% block content %} 6 {% for entry in entry_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 %}模板标签定义了子模板可以覆盖的文档的一部分。要实现这一点,您必须声明您的子模板扩展了父模板,并定义了一个同名的块元素。通过第 3 行的{% extends %}模板标签,您将entries/base.html定义为父模板。第 5 行和第 18 行的{% block %}和{% endblock %}将放置在父块的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 管理站点。当你想快速记下一些想法时,点击次数太多了。在下一步中,您将通过向前端添加此功能来改进您的工作流。
第五步:在前端管理你的日记条目
当您构建和使用 web 应用程序时,有四个基本操作您一直在执行。这些操作如此常见,以至于它们经常被简称为 CRUD :
- 创造
- ead
- 更新日期
- 删除
在 Django 管理站点中,您已经可以执行所有这些操作。在前端,你只能看到你的条目。为了模拟 Django 管理站点的功能,您将重复已经为EntryDetail和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和EntryUpdateView,您还需要定义应该在表单中显示哪些模型字段,正如您在第 5 行和第 10 行中看到的。您在第 18 行的EntryDeleteView只执行删除一个条目的动作,所以您不需要在其中定义任何字段。
此外,您需要定义用户在提交视图表单后应该被重定向到哪里。默认情况下, .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
13 </a>
14 {% else %}
15 <a href="{% url 'entry-list' %}">
16
17 </a>
18 {% endif %}
19{% endblock %}
当这个模板被CreateView加载时,表单将是空的,取消它将再次把你带到条目列表。当被CreateUpdateView加载时,它会被预填充当前条目的标题和内容。取消会将您带到条目详细信息页面。
在一个模板中有多种方式呈现一个表单。使用第 7 行的{{ form.as_p }}, Django 将显示您在视图中定义的字段,这些字段用段落包装。无论何时在 Django 表单中发布内容,都必须在第 6 行包含 {% csrf_token %}模板标签。这是防止跨站请求伪造的安全措施。
与其他模板一样,在第 3 行添加{% extends "entries/base.html" %}来扩展基本模板。然后定义在第 4 行和第 18 行之间的block content标记中包含什么。在entries/templates/entries/中,你对entry_confirm_delete.html使用相同的模式:
<!-- 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 %}">
</a>
{% endblock %}
当您要删除条目时,此模板将会出现。在表格中提到"{{ entry.title }}"和{{ entry.created_date|date:'Y-m-d' }}会提醒你通过按确认来删除哪个条目。
创建网址
创建视图及其模板后,创建它们的路线,以便在前端访问它们。在entries/urls.py中添加三条到urlpatterns的附加路径:
# 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进行测试。如果您想将您的代码与本教程中的代码进行比较,请单击下面的链接:
获取源代码: 点击此处获取源代码,您将在本教程中使用用 Django 和 Python 构建一个个人日记 web 应用程序。
你可以在source_code_step_5/目录中找到与此步骤相关的文件。
第六步:改善用户体验
利用你的日记,你可能会无意中发现一些怪癖,这些怪癖让你在周围浏览时有点讨厌。在这一步中,您将逐一解决它们。你会发现界面上的小变化会对你的日记用户体验产生大的影响。
掌控你的成功
得到一些反馈总是好的,尤其是积极的反馈。使用消息框架,您可以快速定义提交表单后显示的一次性快速消息。要使用该功能,将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 行的EntryCreateView中的SuccessMessageMixin和第 9 行的EntryUpdateView之后,你在第 7 行和第 12 行为它们定义了一个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的祖先。这就是为什么你可以跳过在第 3 行的EntryDeleteView中添加SuccessMessageMixin的原因。
点击下面的链接可以看到entries/views.py的全部内容。您可以在source_code_step_6/目录中找到它:
获取源代码: 点击此处获取源代码,您将在本教程中使用用 Django 和 Python 构建一个个人日记 web 应用程序。
既然视图发送消息,您需要增强模板来显示它们。
得到消息
消息存储在消息存储器中。通过循环,您可以显示当前在消息存储器中的所有消息。在 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 %}
通过将第 4 行和第 12 行的{% if messages %}中的消息列表打包,您可以确保只有在存储器中有任何消息的情况下才会显示。
改善您的导航
要创建、编辑或删除条目,您需要记住相应的 URL,然后在地址栏中键入它们。多么乏味!幸运的是,您可以通过向视图添加链接来解决这个问题。从链接到entries/templates/entries/entry_list.html模板中的entry-create视图开始:
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' %}"></a> 7</article> 8 9{% for entry in entry_list %}
这个标记将类似于其他日记条目列表项。在</article>之后向entries/templates/entries/entry_detail.html模板添加新段落,以快速编辑或删除条目:
<!-- 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。
为您的信息设计风格
最后,通过在entries/static/css/diary.css的末尾添加.messages和.message来设计简讯的样式:
/* 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 中构建的日记网络应用。虽然你的日记只存储在本地,但确保只有你能访问它是个好主意。在你开始写日志之前,让我们添加这个限制。
第七步:给你的 Django 日记上锁
一把小小的金锁对于一本实体日记来说是多么的重要,一张登录表对于你的电子日记本来说是多么的重要。这把锁的钥匙是您已经用来登录 Django 管理站点的用户名和密码组合。
重复使用您的 Django 管理员登录名
Django 提供的认证系统相当基础。对于其他有固定用户的项目,可以考虑定制它。但是对于你的 Django 日记,重用 Django 管理站点的登录就足够了。过一会儿你会发现它工作得很好。首先,让我们来解决注销问题。
添加注销链接
您可以通过访问一个特殊的 URL 退出。Django 已经提供了一个名为admin:logout的 URL 来让您退出 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 中,你可以定义谁可以查看哪些视图。默认情况下,它们对所有访问您网站的人开放。为了确保视图需要经过身份验证的用户才能访问,在entries/views.py的顶部导入LoginRequiredMixin:
# 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 ,就要求先成功登录。此外,您必须定义一个login_url,以便 Django 知道当您没有登录时将您重定向到哪里。您可以创建一个继承了LoginRequiredMixin的基类,并在entries/views.py中定义login_url,而不是单独为所有的类做这件事:
# 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 和 Python 构建一个个人日记 web 应用程序。
该项目的完整代码在source_code_step_final/目录中。
接下来的步骤
你建立的日记本功能齐全,随时可用。但是,这也是一个很好的基础。也许你已经有了一些关于如何进一步改善你的日记的想法。或者你可以试试下面的方法:
- 为您最近的条目添加页面。
- 给每个工作日一种颜色。
- 在 HTML
<title>标签中显示创建日期。 - 为条目创建当日选择表情符号。
- 对条目列表进行分页。
在本教程中,向您介绍了 Django 提供的一些基本概念和模式。希望它能激发人们对深入研究这个 Python web 框架的兴趣。如果你想继续你的旅程并了解更多,你可以看看这些教程:
- 你与 Django 的第一步:建立一个 Django 项目
- Django 第 1 部分入门:构建投资组合应用
- 在 Django Admin 中管理用户需要知道的事情
- 用 Python 定制 Django 管理
- 使用 Django、Vue 和 GraphQL 创建博客
您可以将通过完成日记项目获得的知识应用到其他 Django 教程中,并将您的 web 应用技能提升到一个新的水平!
结论
在本教程中,您使用 Django 从头开始创建了一个个人日记。您了解了如何构建一个可以日常使用的全功能 web 应用程序。它利用了 Django 的许多优势,包括管理站点、基于类的视图、消息框架和模板系统。
这个 Django 项目也是您未来 Django 项目的完美基础。你在这个日记项目中完成的步骤对于其他项目来说基本上是一样的,比如一个博客或者一个待办事项应用。
在本教程中,您学习了如何:
- 建立一个 Django 项目
- 使用标准的 SQLite 数据库
- 利用 Django 管理站点
- 创建模型和基于类的视图
- 嵌套和样式模板
- 通过认证保护您的日记
你可以点击下面的链接下载 Django 日记的完整源代码:
获取源代码: 点击此处获取源代码,您将在本教程中使用用 Django 和 Python 构建一个个人日记 web 应用程序。**********







