如何创建 Django 模型

0 股票
0
0
0
0

介绍

在本教程中,我们将创建 Django 模型,用于定义博客应用程序数据的字段和行为。这些模型会将 Django 应用程序数据映射到数据库。Django 正是利用对象关系映射 (ORM) API(称为«模型»)来生成数据库表。.

先决条件

本教程是 Django 开发系列教程的一部分,也是该系列教程的续篇。.

如果您之前没有关注过本系列文章,我们在此做出以下假设:

  • 您已安装 Django 版本 4 或更高版本。.
  • 您已将 Django 应用程序连接到数据库。.
  • 您正在使用基于 Unix 的操作系统,最好是 Ubuntu 22.04 云服务器,因为这是我们测试过的系统。.

由于本教程主要针对 Django 模型,即使您的设置不同,您也可能能够跟着操作。.

步骤 1 – 创建 Django 应用程序

为了遵循 Django 的模块化理念,我们将在项目中创建一个 Django 应用程序,其中包含创建博客网站所需的所有文件。.

每当我们开始使用 Python 和 Django 时,都需要激活 Python 虚拟环境并将其移动到应用程序的根目录。如果您按照本系列教程操作,可以通过输入以下命令来完成此操作。.

cd ~/my_blog_app
. env/bin/activate
cd blogr code... */

接下来,我们运行以下命令:

python manage.py startapp blogsite

该程序会创建我们的博客网站以及目录。.

在本教程系列进行到此阶段时,您的项目将具有以下目录结构:

my_blog_app/
└── blog
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── settings.cpython-38.pyc
│ │ ├── urls.cpython-38.pyc
│ │ └── wsgi.cpython-38.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blogsite
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py

本教程将重点介绍 models.py 文件,该文件位于网站的博客目录中。.

步骤二 – 添加文章模板

首先,我们需要打开并编辑 models.py 文件,使其包含生成 Post 模型所需的代码。Post 模型包含以下数据库字段:

  • 标题——博客文章的标题。.
  • Slug – 用于存储和生成网页有效 URL 的地方。.
  • 内容——博客文章的文本内容。.
  • create_on – 帖子创建的日期。.
  • 作者——撰写该帖子的人。.

现在进入 models.py 文件所在的目录。.

cd ~/my_blog_app/blog/blogsite

使用 cat 命令在终端中显示文件内容。.

cat models.py

该文件应包含以下导入模型的代码,以及解释 models.py 文件内容的注释。.

from django.db import models
# Create your models here.

使用您喜欢的文本编辑器,将以下代码添加到 models.py 文件中。我们将使用 nano 作为文本编辑器,但您可以使用任何您喜欢的编辑器。.

nano models.py

此文件中已添加了导入 API 模型的代码,我们可以删除下面的注释。接下来,我们导入 slugify 以从字符串生成 slug,导入用于身份验证的 Django 用户,以及反向的 django.urls,以便更灵活地创建 URL。.

from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse

接下来,在名为 Post 的模型类中添加一个类方法,该方法包含以下数据库字段:title、slug、content、created_on 和 author。将这些代码添加到导入语句下方。.

...
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()

接下来,我们添加一个生成 URL 的函数和一个文章保存函数。这非常重要,因为它会生成一个与我们文章相匹配的唯一链接。.

...
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])

def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)

现在我们需要告诉模型帖子应该如何排序并在网页上显示。这方面的逻辑将添加到嵌套的元类中。元类通常包含其他重要的模型逻辑,这些逻辑与数据库字段定义无关。.

...
class Meta:
ordering = ['created_on']

def __unicode__(self):
return self.title

最后,我们将 Comment 模型添加到此文件中。这需要添加一个名为 Comment 的新类,并在其签名中包含 models.Models,并定义以下数据库字段:

  • 姓名 – 提交评论者的姓名。.
  • 电子邮件 – 提交评论者的电子邮件地址。.
  • 正文——评论本身的文本内容。.
  • 帖子 – 发表评论的帖子。.
  • create_on – 评论创建时间。.
...
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)

至此,models.py 文件已编写完成。请确保您的 models.py 文件内容与以下内容一致:

from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse


class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()

def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])

def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)

class Meta:
ordering = ['created_on']

def __unicode__(self):
return self.title


class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)

请务必保存并关闭文件。如果您使用的是 nano 编辑器,可以通过按 CTRL 和 X,然后按 Y,最后按 ENTER 来完成此操作。.

models.py 文件运行后,我们可以更新 settings.py 文件。.

步骤 3 – 更新设置

现在我们已经向应用程序中添加了模型,我们需要通知项目组我们刚刚添加的博客网站应用程序的存在。我们通过将其添加到 settings.py 文件的 INSTALLED_APPS 部分来实现这一点。.

进入 settings.py 文件所在的目录。.

cd ~/my_blog_app/blog/blog

接下来,例如,使用 nano 打开你的 settings.py 文件。.

nano settings.py

打开该文件,将您网站的博客应用程序添加到文件的 INSTALLED_APPS 部分,如下所示。.

# Application definition
INSTALLED_APPS = [
'blogsite',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

添加网站博客应用程序后,即可保存文件并退出。.

目前,我们已准备好推进这些变革的实施。.

步骤 4 – 执行迁移

添加帖子和评论模型后,下一步是应用这些更改,以便我们的 MySQL 数据库架构能够识别它们并创建必要的表。.

首先,我们需要使用 makemigrations 命令将模型变更打包成单独的迁移文件。这些文件类似于 Git 等版本控制系统中的提交。.

现在,如果您进入 ~/my_blog_app/blog/blogsite/migrations 目录并运行 ls 命令,您会发现只有一个 __init__.py 文件。添加迁移后,这种情况会发生变化。.

使用 cd 命令切换到博客目录,如下所示:

cd ~/my_blog_app/blog

然后运行 manager.py 中的 makemigrations 命令。.

python manage.py makemigrations

然后,您应该在终端窗口中看到以下输出:

Output
Migrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Post
- Create model Comment

还记得我们之前访问 /~/my_blog_app/blog/blogsite/migrations 目录时,里面只有 __init__.py 文件吗?现在如果我们回到这个目录,会发现多了两个文件:__pycache__ 和 0001_initial.py。0001_initial.py 文件是在运行 makemigrations 命令时自动创建的。每次运行 makemigrations 命令都会创建一个类似的文件。.

如果要读取文件内容,只需从文件所在的目录运行 0001_initial.py 即可。.

现在前往 ~/my_blog_app/blog:

cd ~/my_blog_app/blog

既然我们已经创建了迁移文件,就需要使用 migrate 命令将这些文件中描述的更改应用到数据库。但首先,让我们使用 showmigrations 命令检查当前存在哪些迁移。.

python manage.py showmigrations
Output
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
blogsite
[ ] 0001_initial
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
sessions
[X] 0001_initial

你会注意到所有迁移都已检查,除了我们使用 Post 和 Comment 模型创建的 0001_initial 迁移之外。.

现在,让我们使用以下命令检查迁移完成后执行了哪些 SQL 语句。该命令接受迁移及其标题作为参数:

python manage.py sqlmigrate blogsite 0001_initial

下面显示的是后台实际执行的 SQL 查询。.

Output
--
-- Create model Post
--
CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL);
--
-- Create model Comment
--
CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL);
ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);

现在让我们运行迁移,将它们应用到我们的 MySQL 数据库。.

python manage.py migrate

我们将得到以下输出:

Output
Operations to perform:
Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
Applying blogsite.0001_initial... OK

您已成功应用迁移。.

需要注意的是,正如 Django 文档中所述,将 Django 迁移到 MySQL 作为后端时有三个注意事项。.

  • 不支持围绕模式变更操作的事务。换句话说,如果迁移失败,您必须手动选择已做的更改才能执行另一次迁移。无法回滚到对失败的迁移进行任何更改之前的某个时间点。.
  • 对于大多数模式变更操作,MySQL 会完全重写表。最坏情况下,时间复杂度与要添加或删除列的表中的行数成正比。根据 Django 文档,这可能需要每百万行花费一分钟的时间。.
  • 在 MySQL 中,列名、表名和索引名的长度都有限制。此外,所有列和索引卷的总大小也有限制。虽然某些后端可以支持 Django 中创建的更高限制,但使用 MySQL 后端无法创建相同的索引。.

对于任何考虑与 Django 一起使用的数据库,请务必权衡每种数据库的优缺点。.

步骤 5 – 验证数据库模式

迁移完成后,我们需要验证通过 Django 模型创建的 MySQL 表是否成功生成。.

为此,请在终端中运行以下命令登录 MySQL。.

mysql blog_data -u djangouser

现在,选择我们的 blog_data 数据库。如果您不知道当前使用的是哪个数据库,可以使用 SHOW DATABASES 命令显示所有数据库。在 SQL 中

USE blog_data;

然后输入以下命令查看表格。.

SHOW TABLES;

这条 SQL 查询语句应该会显示以下内容:

Output
+----------------------------+
| Tables_in_blog_data |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| blogsite_comment |
| blogsite_post |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
12 rows in set (0.01 sec)

这些表包括 blogsite_comment 和 blogsite_post。这些是我们自己创建的模型。让我们验证一下它们是否包含我们定义的字段。.

DESCRIBE blogsite_comment;
Output
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(42) | NO | | NULL | |
| email | varchar(75) | NO | | NULL | |
| website | varchar(200) | YES | | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| post_id | int | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
DESCRIBE blogsite_post;
Output
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| slug | varchar(255) | NO | UNI | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| author | longtext | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

我们已验证数据库表已通过 Django 模型迁移成功生成。.

您可以使用 CTRL + D 关闭 MySQL,当您准备退出 Python 环境时,可以运行 disable 命令:

deactivate

禁用开发环境后,您将返回到终端命令行。.

结果

在本教程中,我们成功地为博客 Web 应用程序添加了基本功能所需的模型。您学习了如何编写模型代码、迁移的工作原理,以及如何将 Django 模型转换为实际的 MySQL 数据库表。.

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

您可能也喜欢