完整的 Django 初学者指南 - 第 2 部分

网页版项目

我不了解您,但就我个人而言,通过查看实际示例和代码片段,我学到了更多。对我来说,这是难以处理在在例子你读一个概念 Class AClass B,或者当我看到经典的 foo(bar)例子。我不想和你做那种事。

所以,在我们进入有趣的部分之前,先玩玩模型、视图和所有东西。让我们花点时间简要讨论一下我们将要开发的这个项目。

如果您已经有 Web 开发经验并且觉得它的细节太多,您可以浏览图片以了解我们将要构建的内容,然后跳转到本教程的模型 部分。

但是,如果您不熟悉 Web 开发,我强烈建议您继续阅读。它将为您提供有关 Web 应用程序建模和设计的一些很好的见解。Web 开发和一般的软件开发不仅仅是编码。

火箭科学

用例图

我们的项目是一个讨论板(一个论坛)。整个想法是维护几个board ,它们的行为类似于类别。然后,在特定板内,用户可以通过创建新主题 来开始新的讨论。在该主题中,其他用户可以参与讨论发布回复。

我们需要找到一种方法来区分普通用户和管理员用户,因为只有管理员才能创建新的板。下面概述了我们的主要用例和每种类型用户的角色:

用例图

类图

从用例图中,我们可以开始考虑我们项目的实体 。实体是我们将要创建的模型,它与我们的 Django 应用程序将处理的数据密切相关。

为了能够实现上一节中描述的用例,我们至少需要实现以下模型:BoardTopicPostUser

基本类图

花时间思考模型如何相互关联也很重要。实线告诉我们的是,在Topic 中 ,我们需要有一个字段来标识它属于哪个Board 。同样,帖子 将需要一个字段来表示它属于哪个主题 ,以便我们可以在讨论中仅列出在特定主题中创建的帖子 。最后,我们需要在Topic和Post中的字段来了解谁发起了讨论,以便我们可以识别谁在发布回复。

我们还可以与BoardUser 模型建立关联,因此我们可以确定谁创建了给定的Board 。但此信息与应用程序无关。还有其他方法可以跟踪此信息,稍后您将看到。

现在我们有了基本的类表示,我们必须考虑每个模型将携带什么样的信息。这种事情很容易变得复杂。所以尽量把注意力集中在重要的地方。开始开发所需的信息。稍后,我们可以使用migrations 改进模型,您将在下一个教程中详细介绍。

但就目前而言,这将是我们模型字段的基本表示:

类图

这个类图强调模型之间的关系。这些线条和箭头最终将在以后转换为字段。

对于Board 模型,我们将从两个字段开始:namedescription 。该名称 字段必须是唯一的,所以要避免重复板的名称。该描述 只是给什么样的主板是所有关于一个提示。

主题 模式将包括四个领域:主题最后更新 日期将被用来定义主题排序,主题起动机 来识别用户 谁开始的主题 ,和一个叫做场 来定义哪些主板 特定主题 属于.

帖子 车型将拥有一个信息 场,这将是用于存储后答复的文本,在创建 日期和时间字段主要用来订购帖子 一内主题 ,一个在更新的 日期和时间栏通知用户 何时以及是否编辑了给定的帖子 。与日期和时间字段一样,我们还必须引用User 模型:.created 和updated . 。

最后,用户 模型。在类图中,我只提到了字段usernamepasswordemail 和超级用户 标志,因为这几乎是我们现在要使用的全部内容。需要注意的是,我们不需要创建User 模型,因为 Django 已经在contrib包中内置了User 模型 。我们将使用它。

关于多重性在类图(数字 10..*等等),这里是你如何阅读:

类图板和主题关联一个主题 必须与一个 ( 1) 相关联(这意味着它不能为空),并且一个 可以与许多主题 相关联或没有 ( 0..*)相关联。这意味着Board 可能没有单个Topic 存在。

类图话题和帖子关联一个主题 应该至少有一个帖子 (起始帖子 ),它也可以有很多帖子1..*)。一个 帖子 必须与一个主题 相关联,并且只能与一个主题( 1)相关联。

类图主题和用户关联一个主题 必须有一个且只有一个关联的用户 :主题起始用户1)。一个用户 可能有很多或没有主题0..*)。

类图帖子和用户关联一个帖子 必须有一个并且只有一个用户 与:创建者1)相关联。一个用户 可能有很多或没有 帖子0..*)。PostUser 之间的第二个关联是直接关联 (参见行尾的箭头),这意味着我们只对关系的一侧感兴趣,即User 编辑给定Post 的内容 。它将被翻译成updated by 字段。多重性表示 0..1,这意味着 更新的 字段可能为空(Post 未编辑)并且最多只能与一个User 相关联。

绘制此类图的另一种方法是强调字段而不是模型之间的关系:

类图属性

图 4:强调类(模型)的属性(字段)的类图

上面的表示与上一个等效,也更接近我们将要使用 Django Models API 设计的内容。在这个表示中,我们可以更清楚地看到,在Post 模型中,关联 主题创建者更新者 成为模型字段。另一个需要注意的有趣的事情是,在 Topic 模型中,我们现在有一个名为posts()的操作 (一个类方法 。我们将通过实现反向关系来实现这一点,其中 Django 将自动在数据库中执行查询以返回属于特定主题的所有帖子 的列表。

好的,现在足够的 UML!为了绘制本节中介绍的图表,我使用了 StarUML工具。

线框

在花了一些时间设计应用程序模型之后,我喜欢创建一些线框图来定义需要完成的工作,并清楚地了解我们要去哪里。

线框漫画

然后基于线框图,我们可以更深入地了解应用程序中涉及的实体。

首先,我们需要显示主页中的所有板:

线框板

图 5:电路板项目线框主页列出了所有可用的电路板。

如果用户点击一个链接,比如在 Django 面板中,它应该列出所有主题:

线框主题

图 6:Boards 项目线框,列出了 Django board 中的所有主题。

这里我们有两条主要路径:用户点击“新话题”按钮创建新话题,或者用户点击话题查看或参与讨论。

“新话题”画面:

线框新主题

图 7:新主题屏幕

现在是主题屏幕,显示帖子和讨论:

线框帖子

图 8:主题帖子列表屏幕

如果用户单击回复按钮,他们将看到下面的屏幕,其中包含反向顺序的帖子摘要(最新的在前):

线框回复

图 9:回复主题屏幕

要绘制线框,您可以使用draw.io服务,它是免费的。


Models

模型基本上是应用程序数据库布局的表示。我们将在本节中做的是创建我们在上一节中建模的类的 Django 表示:BoardTopicPost 。该用户 模型中已经定义了一个内置的应用程序命名的权威性 ,这是我们列出 INSTALLED_APPS的配置命名空间下django.contrib.auth

我们将在board/models.py 文件中完成所有工作。下面是我们如何表示我们的类图( 见图 4)。在 Django 应用程序中:

from django.db import models
from django.contrib.auth.models import User


class Board(models.Model):
    name = models.CharField(max_length=30, unique=True)
    description = models.CharField(max_length=100)


class Topic(models.Model):
    subject = models.CharField(max_length=255)
    last_updated = models.DateTimeField(auto_now_add=True)
    board = models.ForeignKey(Board, related_name='topics')
    starter = models.ForeignKey(User, related_name='topics')


class Post(models.Model):
    message = models.TextField(max_length=4000)
    topic = models.ForeignKey(Topic, related_name='posts')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(null=True)
    created_by = models.ForeignKey(User, related_name='posts')
    updated_by = models.ForeignKey(User, null=True, related_name='+')

所有模型都是django.db.models.Model 类的子类。每个类都会被转换成数据库表 。每个字段由django.db.models.Field 子类(内置 Django 核心)的实例表示,并将被转换为数据库列

fields CharFieldDateTimeField等都是django.db.models.Field 的 子类,它们包含在 Django 核心中——随时可以使用。

在这里,我们仅使用 CharFieldTextFieldDateTimeFieldForeignKey字段来定义我们的模型。但是 Django 提供了广泛的选项来表示不同类型的数据,例如 IntegerFieldBooleanField、 DecimalField等等。我们将根据需要引用它们。

某些字段具有必需的参数,例如 CharField. 我们应该始终设置一个 max_length. 此信息将用于创建数据库列。Django 需要知道数据库列需要多大。max_lengthDjango Forms API 也将使用该 参数来验证用户输入。稍后再谈。

Board模型定义中,更具体地说是在 name字段中,我们还设置了参数 unique=True,顾名思义,它将在数据库级别强制执行字段的唯一性。

Post模型中,该 created_at字段有一个可选参数,auto_now_add设置为 True。这将指示 Django 在 Post创建对象时设置当前日期和时间。

在模型之间创建关系的一种方法是使用 ForeignKey字段。它将在模型之间创建链接并在数据库级别创建适当的关系。该 ForeignKey字段需要一个位置参数,其中包含对其将相关的模型的引用。

例如,在 Topic模型中,board字段是 ForeignKeyBoard模型。它告诉 Django 一个 Topic实例只与一个 Board实例相关。该 related_name参数将用于创建 反向关系 ,其中 Board实例将有权访问 Topic属于它的实例列表。

Django 会自动创建这种反向关系——这 related_name是可选的。但是如果我们不为其设置名称,Django 将使用名称生成它:(class_name)_set。例如,在 Board模型中,Topic实例将在 topic_set属性下可用。相反,我们只是将其重命名为 topics,使其感觉更自然。

Post模型中,该 updated_by字段设置 related_name='+'. 这告诉 Django 我们不需要这种反向关系,所以它会忽略它。

您可以在下面看到类图和使用 Django 生成模型的源代码之间的比较。绿线代表我们如何处理反向关系。

类图模型定义

此时,您可能会问自己:“主键/ID 怎么样”?如果我们不为模型指定主键,Django 会自动为我们生成它。所以我们现在很好。在下一节中,您将更好地了解它是如何工作的。

迁移模型

下一步是告诉 Django 创建数据库,以便我们可以开始使用它。

打开命令行工具,激活虚拟环境,进入manage.py文件所在文件夹,运行以下命令:

python manage.py makemigrations

作为输出,您将得到如下内容:

Migrations for 'boards':
  boards/migrations/0001_initial.py
    - Create model Board
    - Create model Post
    - Create model Topic
    - Add field topic to post
    - Add field updated_by to post

在这一点上,Django的创建了一个名为文件0001_initial.py 内部电路板/迁移 目录。它代表我们应用程序模型的当前状态。在下一步中,Django 将使用此文件来创建表和列。

迁移文件被翻译成 SQL 语句。如果您熟悉 SQL,可以运行以下命令来检查将在数据库中执行的 SQL 指令:

python manage.py sqlmigrate boards 0001

如果您不熟悉 SQL,请不要担心。在本教程系列中,我们不会直接使用 SQL。所有的工作都将使用 Django ORM 完成,它是一个与数据库通信的抽象层。

现在下一步是 我们生成的迁移应用到数据库:

python manage.py migrate

输出应该是这样的:

Operations to perform:
  Apply all migrations: admin, auth, boards, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying boards.0001_initial... OK
  Applying sessions.0001_initial... OK

因为这是我们第一次迁移数据库,该 migrate命令还应用了来自 Django contrib 应用程序的现有迁移文件,列在 INSTALLED_APPS. 这是预期的。

该行 Applying boards.0001_initial... OK是我们在上一步中生成的迁移。

就是这样!我们的数据库已准备好使用。

SQLite

注意:  重要的是要注意SQLite 是一个生产质量的数据库。许多公司在数千种产品中使用 SQLite,例如所有 Android 和 iOS 设备、所有主要 Web 浏览器、Windows 10、macOS 等。

它只是不适合所有情况。SQLite 无法与 MySQL、PostgreSQL 或 Oracle 等数据库进行比较。大容量网站、写入密集型应用程序、非常大的数据集、高并发性,这些情况最终会导致使用 SQLite 出现问题。

我们将在项目开发期间使用 SQLite,因为它很方便,我们不需要安装任何其他东西。当我们将项目部署到生产环境时,我们将切换到 PostgreSQL。对于简单的网站,这很好用。但是对于复杂的网站,建议开发和生产使用同一个数据库。

最后修改:2021 年 06 月 14 日
如果觉得我的文章对你有用,请随意赞赏