如何创建 Django 模型

介绍

在之前的教程“如何创建 Django 应用程序并将其连接到数据库”中,我们介绍了如何创建 MySQL 数据库、如何创建和启动 Django 应用程序以及如何将其连接到 MySQL 数据库。

在本教程中,我们将创建 Django模型来定义我们将存储的博客应用程序数据的字段和行为。这些模型将数据从 Django 应用程序映射到数据库。这是 Django 用来通过其对象关系映射 (ORM) API(称为“模型”)生成数据库表的工具。

先决条件

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

如果您还没有关注本系列,我们将做出以下假设:

由于本教程主要涉及 Django 模型,因此即使您的设置有所不同,您也可以继续学习。

第 1 步 – 创建 Django 应用程序

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

每当我们开始在 Python 和 Django 中工作时,我们应该激活我们的 Python 虚拟环境并进入我们应用程序的根目录。如果你跟着这个系列,你可以通过输入以下内容来实现这一点。

  • cd ~/my_blog_app
  • . env/bin/activate
  • cd blog

从那里,让我们运行这个命令:

  • python manage.py startapp blogsite

这将创建我们的应用程序以及一个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文件将是blogsite目录中的文件。

第 2 步 – 添加 Posts 模型

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

  • title — 博客文章的标题。
  • slug — 为网页存储和生成有效 URL 的位置。
  • content — 博客文章的文本内容。
  • created_on — 创建帖子的日期。
  • author — 写帖子的人。

现在,进入models.py包含文件的目录

  • cd ~/my_blog_app/blog/blogsite

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

  • cat models.py

该文件应包含以下代码,用于导入模型,以及描述要放入该models.py文件的内容的注释

模型.py
from django.db import models

# Create your models here.

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

  • nano models.py

在这个文件中,已经添加了导入模型 API 的代码,我们可以继续删除后面的注释。然后我们将导入slugify用于从字符串生成 slug,DjangoUser用于身份验证,以及reversefromdjango.urls为我们创建 URL 提供更大的灵活性。

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

然后,在我们将调用的模型类上添加类方法Post,具有以下数据库字段titleslugcontentcreated_onauthor在您的导入语句下方添加这些内容。

模型.py
...
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 的功能和保存帖子的功能。这很重要,因为这会创建一个唯一的链接来匹配我们的独特帖子。

模型.py
...
    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)

现在,我们需要告诉模型帖子应该如何排序,并显示在网页上。这个逻辑将被添加到嵌套的内部Meta类中。Meta类通常包含一个不相关的数据库字段定义其他重要的模式逻辑。

模型.py
...
    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title

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

  • name — 发表评论的人的姓名。
  • email — 发表评论的人的电子邮件地址。
  • text — 评论本身的文本。
  • post — 发表评论的帖子。
  • created_on — 创建评论的时间。
模型.py
...
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文件符合以下条件:

模型.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,则可以通过键入CTRLand X,然后Y,然后 来实现ENTER

随着models.py文件设置,我们可以继续更新我们的settings.py文件。

第 3 步 – 更新设置

现在我们已经向我们的应用程序添加了模型,我们必须通知我们的项目blogsite我们刚刚添加应用程序的存在我们通过将它添加到 中的INSTALLED_APPS部分来做到这一点settings.py

导航到您settings.py居住的目录

  • cd ~/my_blog_app/blog/blog

从这里,打开您的settings.py文件,例如使用 nano。

  • nano settings.py

打开文件后,将您的blogsite应用程序添加INSTALLED_APPS文件部分,如下所示。

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

随着blogsite添加的应用,可以保存并退出该文件。

此时,我们已准备好继续应用这些更改。

第 4 步 – 进行迁移

随着我们的模型Post,并Comment补充说,下一步就是让我们的应用这些更改MySQL数据库架构识别它们,并创建所需的表。

首先,我们必须使用命令将我们的模型更改打包到单独的迁移文件中makemigrations这些文件类似于commitsGit 等版本控制系统中的文件

现在,如果您导航到~/my_blog_app/blog/blogsite/migrations并运行ls,您会注意到只有一个__init__.py文件。一旦我们添加了迁移,这种情况就会改变。

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

  • cd ~/my_blog_app/blog

然后在makemigrations运行命令manage.py

  • 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文件吗?如果我们现在cd回到那个目录,我们会注意到添加了两个项目:__pycache__0001_initial.py0001_initial.py文件是在您运行时自动生成的makemigrations每次运行时都会生成一个类似的文件makemigrations

less 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

您会注意到,除了0001_initial我们刚刚使用模型PostComment.

现在让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 文档中所述,使用 MySQL 作为后端的 Django 迁移有 3 个警告。

  • 缺乏对围绕模式更改操作的事务的支持。换句话说,如果迁移未能成功应用,您将必须手动取消您所做的更改以尝试另一次迁移。在失败的迁移中进行任何更改之前,不可能回滚到更早的点。
  • 对于大多数模式更改操作,MySQL 将完全重写表。在最坏的情况下,时间复杂度将与表中要添加或删除列的行数成正比。根据 Django 文档,这可能慢到每百万行一分钟。
  • 在 MySQL 中,列、表和索引的名称长度有很小的限制。所有列和索引覆盖的组合大小也有限制。虽然其他一些后端可以支持在 Django 中创建的更高限制,但在 MySQL 后端就位的情况下将无法创建相同的索引。

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

第 5 步 – 验证数据库架构

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

为此,请在终端中运行以下命令以登录 MySQL。我们将使用djangouser我们在上一教程中创建的

  • 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_commentblogsite_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+关闭 MySQL,D当您准备好离开 Python 环境时,您可以运行以下deactivate命令:

  • deactivate

停用您的编程环境将使您回到终端命令提示符。

结论

在本教程中,我们成功地为博客 Web 应用程序中的基本功能添加了模型。您已经学习了如何编码models、如何migrations工作以及将 Django 转换models为实际MySQL数据库表的过程。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁