2023年Django模型创建完全指南:从入门到实例详解

引言在之前的教程《如何创建一个Django应用并连接到数据库》中,我们介绍了如何创建一个MySQL数据库,如何创建和启动一个Django应用,并如何将其连接到一个MySQL数据库。

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

先决条件这个教程是Django开发系列的一部分,也是这个系列的延续。

如果您还没有跟随本系列的进展,那我们做出以下假设:

  • You have Django version 4 or higher installed.
  • You have connected your Django app to a database. We are using MySQL, and you can achieve this connection by following part two of the Django series, “How To Create a Django App and Connect it to a Database.”
  • You are working with a Unix-based operating system, preferably an Ubuntu 22.04 cloud server as this is the system we have tested on. If you would like to set up Django on a similar environment, please refer to our tutorial, “How To Install Django and Set Up a Development Environment on Ubuntu 22.04.”

由于本教程主要涉及Django模型,即使您的设置有些不同,您也可能能够跟随进行。

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

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

  1. cd ~/my_blog_app
  2. . env/bin/activate
  3. cd blog

 

从那里开始,让我们运行这个命令。

  1. 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

我们在本教程中要重点关注的文件是位于blogsite目录下的models.py文件。

第二步 – 添加文章模型 bù -首先,我们需要打开并编辑models.py文件,以便其中包含用于生成帖子模型的代码。帖子模型包含以下数据库字段:

  • title — The title of the blog post.
  • slug — Where valid URLs are stored and generated for web pages.
  • content — The textual content of the blog post.
  • created_on — The date on which the post was created.
  • author — The person who has written the post.

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

  1. cd ~/my_blog_app/blog/blogsite

 

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

  1. cat models.py

 

文件应该包含以下代码,其中包含导入模块的语句,并有一条注释描述该models.py文件中需要放置的内容。

模型.py

from django.db import models

# Create your models here.

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

  1. nano models.py

 

在这个文件中,已经添加了导入模型 API 的代码,我们可以继续删除后面的注释。然后,我们将导入 slugify 用于从字符串生成 slug,导入 Django 的 User 进行身份验证,并从 django.urls 导入 reverse,以便在创建 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,包括以下数据库字段:标题、Slug、内容、创建时间和作者。在导入语句下方添加这些字段。

模型.py

这是文章《如何创建Django模型》的第2部分(共7部分)。

...
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 模型。这涉及到在签名中添加另一个名为 Comment 的类,并定义以下数据库字段:models.Models。

  • name — The name of the person posting the comment.
  • email — The email address of the person posting the comment.
  • text — The text of the comment itself.
  • post — The post with which the comment was made.
  • created_on — The time the comment was created.
模型.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

这是文章《如何创建Django模型》的第4部分(共7部分)。

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,然后按下回车键来完成。

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

步骤3 — 更新设置

现在我们已经在应用程序中添加了模型,必须告知项目我们刚刚创建的博客应用程序的存在。我们通过将它添加到settings.py文件中的INSTALLED_APPS部分来实现这一点。

导航到包含settings.py文件的目录。

  1. cd ~/my_blog_app/blog/blog

从这里开始,打开settings.py文件,例如使用nano编辑器。

  1. nano settings.py

文件打开后,按照下面所示,在文件的INSTALLED_APPS部分中添加博客站点应用程序。

配置文件.py

# 应用程序定义
INSTALLED_APPS = [
    'blogsite',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

添加博客应用程序后,保存并退出文件。

此时,我们已经准备好开始应用这些更改。

第四步 – 进行迁移操作

在模型中添加了Post和Comment之后,下一步是应用这些更改,使MySQL数据库架构能够识别它们并创建所需的表格。

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

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

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

  1. cd ~/my_blog_app/blog

然后在manage.py文件上运行makemigrations命令。

  1. python manage.py makemigrations

应该在终端窗口中看到以下输出。

输出

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。运行makemigrations时,0001_initial.py文件会自动生成。每次运行makemigrations时,都会生成类似的文件。

如果您想查看该文件的内容,请在所在目录中使用cat命令查看0001_initial.py文件。

现在导航到~/my_blog_app/blog目录。

  1. cd ~/my_blog_app/blog

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

  1. python manage.py showmigrations
输出

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语句,使用以下命令。该命令需要接受应用程序名称和迁移名称作为参数。

  1. python manage.py sqlmigrate blogsite 0001_initial

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

输出


-- -- 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数据库中。


  1. python manage.py migrate

我们将会得到以下的输出:

输出

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

你现在已成功应用了迁移。

需要牢记的是,根据Django文档所述,在使用MySQL作为后端时,Django迁移存在三个注意事项。

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

在考虑与Django一起使用的每个数据库时,一定要权衡每个数据库的优缺点。

第五步——验证数据库架构

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

要实现这一点,在终端中运行以下命令来登录到MySQL。我们将使用之前教程中创建的djangouser。


  1. mysql blog_data -u djangouser

现在,选择我们的数据库blog_data。如果你不知道正在使用的数据库,你可以在SQL中使用SHOW DATABASES;命令显示所有数据库。


  1. USE blog_data;

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


  1. SHOW TABLES;

这个SQL查询应该显示以下内容:

输出

+----------------------------+
| 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。这些是我们刚刚自己创建的模型。让我们验证一下它们是否包含我们定义的字段。


  1. DESCRIBE blogsite_comment;
输出

这是文章《如何创建Django模型》的第7部分(共7部分)。

+------------+--------------+------+-----+---------+----------------+
| 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 行记录 (0.00 秒)
  1. DESCRIBE blogsite_post;

 

输出
+------------+--------------+------+-----+---------+----------------+
| 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 行记录 (0.00 秒)

我们已经验证了数据库表格是通过我们的Django模型迁移成功生成的。

当你想要关闭MySQL时,可以使用CTRL + D的组合键。当你准备离开Python环境时,可以运行deactivate命令。

  1. deactivate

 

禁用你的编程环境将使你返回到终端命令提示符。

结论

在这个教程中,我们在博客网站应用程序中成功添加了基本功能的模型。您已经学会如何编写模型,迁移工作的原理以及将Django模型转换为实际的MySQL数据库表的过程。

bannerAds