如何創建 Django 模型

介紹

在先前的教程中,“如何創建Django應用程序並將其連接到數據庫”,我們介紹了如何創建一個MySQL數據庫,如何創建和啟動一個Django應用程序,以及如何將其連接到一個MySQL數據庫。

在本教程中,我們將創建Django 模型,這些模型定義了我們將要存儲的Blog應用程序數據的字段和行為。這些模型將從您的Django應用程序映射數據到數據庫。這是Django用來通過它們的對象關係映射(ORM)API生成數據庫表的方式,被稱為“模型”。

先決條件

本教程是“Django開發系列”的一部分,是該系列的延續。

如果您沒有跟隨這個系列,我們做出以下假設:

由於本教程主要處理Django模型,即使你的設置有些不同,你可能也能夠跟隨進行。

第1步 — 創建Django應用程序

為了與Django的模塊化哲學保持一致,我們將在我們的項目中創建一個Django應用程序,其中包含創建博客網站所需的所有文件。

每當我們開始在Python和Django中進行工作時,我們應該激活我們的Python虛擬環境並移動到我們應用程序的根目錄。如果你跟隨系列,可以通過輸入以下命令實現這一點。

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

然後,讓我們運行這個命令:

  1. 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 — 添加帖子模型

首先,我們需要打開並編輯models.py文件,以便其中包含生成Post模型的代碼。一個Post模型包含以下數據庫字段:

  • title — 博客帖子的標題。
  • slug — 存儲並生成網頁的有效URL。
  • content — 博客帖子的文本內容。
  • created_on — 帖子創建的日期。
  • author — 撰寫該帖子的人。

現在,進入包含models.py文件的目錄。

  1. cd ~/my_blog_app/blog/blogsite

使用cat命令在終端中顯示文件的內容。

  1. cat models.py

文件應該包含以下代碼,其中導入了模型,並包含一條注釋描述應將其放入此models.py文件中的內容。

models.py
from django.db import models

# 在這裡創建您的模型。

在您喜歡的文本編輯器中,將以下代碼添加到models.py文件中。我們將使用nano作為我們的文本編輯器,但您可以使用您喜歡的任何編輯器。

  1. nano models.py

在這個文件中,已經添加了用於導入模型API的代碼,我們可以刪除後面的註釋。然後,我們將導入slugify以從字符串生成slug,導入Django的User進行身份驗證,以及從django.urls導入reverse以在創建URL時提供更大的靈活性。

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

然後,添加在我們將要調用的模型類上的類方法Post,具有以下數據庫字段:titleslugcontentcreated_onauthor。將這些添加到您的導入語句下方。

models.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的功能以及保存帖子的功能。這是至關重要的,因為這會創建一個與我們的唯一帖子相匹配的唯一鏈接。

models.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類通常包含其他與數據庫字段定義無關的重要模型邏輯。

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

        def __unicode__(self):
            return self.title

最後,我們將在此文件中添加Comment模型。這涉及添加另一個名為Comment的類,其簽名中包含models.Models,並定義以下數據庫字段:

  • name — 發表評論的人的名字。
  • email — 發布評論的人的電子郵件地址。
  • text — 評論本身的文本。
  • post — 發布評論的帖子。
  • created_on — 評論創建時間。
models.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文件與以下匹配:

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,可以通過輸入CTRLX,然後Y,然後ENTER來執行此操作。

有了設置好的models.py文件,我們可以繼續更新我們的settings.py文件。

步驟3 — 更新設置

現在,我們已經向應用程序添加了模型,我們必須通知我們的項目該應用程序的存在,該應用程序是我們剛剛添加的blogsite。 我們通過將其添加到settings.py中的INSTALLED_APPS部分來完成此操作。

導航到包含您的settings.py的目錄。

  1. cd ~/my_blog_app/blog/blog

從這裡,例如使用nano打開您的settings.py文件。

  1. nano settings.py

打開文件後,按照下面的說明將您的blogsite應用程序添加到文件的INSTALLED_APPS部分。

settings.py
# 應用程序定義
INSTALLED_APPS = [
    'blogsite',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

在添加了blogsite應用程序後,您可以保存並退出文件。

此時,我們準備好繼續應用這些更改。

步驟 4 —— 進行遷移

在添加了模型PostComment之後,下一步是應用這些更改,以便我們的MySQL數據庫架構能識別它們並創建必要的表格。

首先,我們必須使用makemigrations命令將我們的模型更改打包到個別的遷移文件中。這些文件類似於像Git這樣的版本控制系統中的commits

現在,如果您導航到~/my_blog_app/blog/blogsite/migrations並運行ls,您會注意到那裡只有一個__init__.py文件。一旦我們添加了遷移,這將會改變。

使用cd切換到博客目錄,像這樣:

  1. cd ~/my_blog_app/blog

然後在manage.py上運行makemigrations命令。

  1. 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.py。 當您運行makemigrations時,0001_initial.py文件會自動生成。 每次運行makemigrations時都會生成一個類似的文件。

從該目錄運行less 0001_initial.py,如果您想查看文件包含的內容。

現在導航到~/my_blog_app/blog:

  1. cd ~/my_blog_app/blog

由於我們已經創建了一個遷移文件,所以我們必須使用migrate命令將這些文件描述的更改應用到數據庫中。 但首先,讓我們使用showmigrations命令檢查當前存在哪些遷移。

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

您會注意到所有遷移都已檢查,除了我們剛剛使用模型PostComment創建的0001_initial的遷移。

現在,讓我們檢查一下一旦我們進行遷移,將執行哪些SQL語句,使用以下命令。 它將遷移和遷移標題作為參數:

  1. python manage.py sqlmigrate blogsite 0001_initial

下面揭示了在幕後製作的實際SQL查詢。

Output
-- -- 創建模型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); -- -- 創建模型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

我們將收到以下輸出:

Output
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一起使用的每個數據庫,請確保權衡每個的優缺點。

步驟5 — 驗證數據庫模式

完成遷移後,我們應該驗證我們通過Django模型創建的MySQL表的成功生成。

要執行這個操作,在終端機中運行以下命令以登錄到MySQL。我們將使用在上一篇教程中創建的djangouser

  1. mysql blog_data -u djangouser

現在,選擇我們的數據庫blog_data。如果你不知道正在使用的數據庫,你可以在SQL中顯示所有數據庫使用SHOW DATABASES;

  1. USE blog_data;

然後輸入以下命令來查看表格。

  1. 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。這些是我們剛剛建立的模型。讓我們驗證它們包含我們定義的字段。

  1. 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)
  1. 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環境時,你可以運行deactivate命令:

  1. deactivate

退出你的編程環境將把你返回到終端命令提示符。

結論

在這個教學中,我們已成功在部落格網頁應用程式中添加了基本功能的模型。您已經學會了如何編碼 modelsmigrations 的運作方式以及將 Django models 轉換為實際的 MySQL 資料庫表格的過程。

Source:
https://www.digitalocean.com/community/tutorials/how-to-create-django-models