用于那些不理解django教程的人们的鼓舞诗篇②-1 模型与数据库
暫時先不管,我們運行服務器(runserver)並確認上一次的情況。因為我們創建了一個名為”polls”的應用程式,所以在網址(url)後面加上”/polls”,如果看到”創建第一個視圖(view)”這個文字,就表示OK!
※因為上次我們修改了兩個urls.py文件,所以讓我們按照教程的方式恢復它們。
确认成功显示后,请检查您运行了runserver命令的终端。最初应该出现这样的句子。
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
「有18个未应用的迁移!如果这些迁移没有正确进行,可能会出现『不是我想的那样!』的情况!」有人这样说。
嗯,我想你可能对迁移不太了解,我就从这方面开始解释吧。
迁移:对数据库的变更进行“预约”
顺应时代潮流迅速应对的确是好事,但是有时候稍稍放慢脚步再执行更好。不仅限于Django,许多应用程序都使用了“数据库”这个东西来管理网站用户和展示信息等等,虽然我用了一个笼统的词语“整理”,但其中包括着一系列的操作。
・储存新用户信息
・修正或更改现有用户的地址等信息
・删除已售出商品的页面
有很多不同的东西,如数据库语言和查询语言,像MySQL、PostgreSQL等有很多可供选择的。
在Python中,幸运的是原本就包含了一个名为sqlite3的数据库语言。但是,当网站规模变得越来越大时,可能会出现需要更换其他数据库语言的情况,这时就会变得相当棘手。起初,使用SQLite3对于练习和学习目的来说是足够的,但需要根据需要修改settings.py,就像教程中的前辈所说的那样。
话有点跑题,但是这种数据库的变动,因为它是应用程序核心部分的变动,所以如果在pycharm中敲代码并立即进行变动的话,可能会导致数据误删除,引发各种事件。迁移,则是为了防止这种情况发生,把想要进行的变动以”迁移文件”的形式记录下来的系统。
当查看错误信息的后半部分时
the migrations for app(s): admin, auth, contenttypes, sessions.
管理员、认证、内容类型和会话这四个应用的迁移还未完成,这里所说的应用与之前创建的投票应用(polls)属于同样的处理方式。在初始状态下,预先准备好的应用会在settings.py中的INSTALLED_APPS列表中列出。之后可以在这里逐步添加应用程序。
# 略
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig',
]
我们来看一下这里的”polls”目录。应该会自动创建一个名为”migrations”的目录。这里是用来存放预订迁移变更的目录。
先在默认状态下进行所需的迁移,然后再尝试在polls应用程序中进行迁移。
像runserver一样,我们将命令交给manage.py前辈来处理,同样适用于django。
python manage.py migrate
迁移的动词形式是迁移(migrate)。它的意思是”移动”,但可以理解为从迁移目录移动到django的核心部分,就像是从migration文件夹搬移内容到django本身一样(这只是个模糊的比喻?)。
好好好!你可能会看到一个“okokok!”的提示,但如果有什么问题,错误会在这里显示。为了保险起见,请确保在运行服务器时错误已消失。
迁移命令所做的是根据settings.py中的INSTALLED_APP参考,为每个应用创建指定的数据库表。
让我们尝试制作模型吧。
让我们去创建一个模型。
根据官方的教程,
模型是针对现有数据的独一无二的决定性来源。模型包括对所需存储的数据至关重要的字段和该数据的行为。Django 遵循DRY原则。Django模型的目标是在一个地方定义数据模型并从中自动提取数据。
这包括迁移-与Ruby On Rails不同,迁移是完全从模型文件生成的。迁移本质上只是一种历史记录。Django可以在更新数据库模式的同时继续迁移历史记录,并使其与当前模型匹配。
有些人可能会对他们不连贯的陈述感到困惑,而且他们的动机目前还不清楚。看到这些情况,很多人可能会坚决放弃使用Django,不再继续下去。
在这里简要地谈一下Django的本质。
本来应该在上次讨论这个话题,一般的技术书籍或者网站都是从介绍”Django是什么”开始的。但现在既然遇到了困境,重新审视一下”Django到底是什么”也是相当重要的。
Django是MTV框架
有很多种Web框架,除了Django之外。作为描述Django的词汇,通常会用到”MTV框架”这个词来表示。每个框架都有自己的特点和优势。
-
- M:model(モデル) → データベースを担当するところ
-
- T:template(テンプレート) → HTMLなどの表示を担当するところ
- V:view(ビュー) → バックエンド(見えない部分)を担当するところ
“MTV框架”是由这三个组件组成的应用程序,它来自于…
让我们更加深入地探讨一下这个所谓的“模型”。
在数据库中搜索、删除、添加、获取数据等操作都是通过使用模型来完成的。负责这些操作的是项目中各个应用的models.py文件。模型有一些特征或规则。
-
- 1つのモデルが1つのテーブルと対応する
-
- モデル名は大文字で始める
- idは自動的についかされる
尽管到了这个地步,我觉得还是有点犹豫。那么,让我们在这里尝试编写一个 polls/models.py 吧。按照教程的指导,我们将创建两个模型,question 和 choice。
from django.db import models
# モデルを作成
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeFiels("発行日")
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes= models.IntegerField(default=0)
在这里,让我们揭示模型的真面目!模型是指这个models.py文件中的类,即django.models.Model的子类。这些类根据之前的规则将形成各自的表。每个模型都有属性(类变量),它们对应表中的各个字段。
我们使用CharField和DateTimeField来指定每个字段中包含的数据类型。例如,Question模型中可以包含以下数据类型:
-
- question_textというCharField型(文字列)のフィールド
- pub_dateというDateTime型のフィールド
在中国文化中只需要一种选择性地解释:“包括”。在每个字段的第一个参数中,您可以指定字段名。对于pub_date,这就是“发布日期”。
通过外键关联,建立了Question表和Choice表之间的关系。
CharField和ForeignKey等词汇是SQL的基础术语,如果完全不了解的话,可以先学习SQL的基础知识再回来,或者先查找所需内容,继续前进。
如果已经不行了,毫不犹豫地去SQL里查找就好。
激活模型
当你创建了模型后,你肯定迫不及待地想要迁移!但是,由于django前辈不知道有一个叫做polls的应用程序,所以即使告诉他关于polls应用程序的models.py,他也不知所云。因此,我们需要注册这个应用程序。
让我们将polls添加到已安装的应用程序列表中。哦,这听起来有点熟悉。
对了,是settings.py中的INSTALLED_APPS列表。让我们进行编辑。
# 略
INSTALLED_APPS = [
# ここにpollsアプリを追加
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
创建迁移文件:makemigrations
执行迁移的步骤如下。
-
- モデルの作成(済)
-
- マイグレーションファイルの作成
- マイグレーション
负责创建第二个迁移文件的是makemigrations命令。先试一下吧。还是要请manage.py大哥帮忙。我的常见错误是,
x makemigration
o makemigrations(复数形式)
所以要小心点。
python manage.py makemigrations polls
如果一切顺利,将会显示如下内容。
polls\migrations\0001_initial.py
- Create model Question
- Create model Choice
当运行makemigrations命令时,会在应用的migration文件夹中创建一个名为migration的文件,我们去看看是什么样的文件。应该会有一个名为0001_initial.py的文件。
# Generated by Django 4.2.2 on 2023-06-29 14:16
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Question',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('question_text', models.CharField(max_length=200)),
('pub_date', models.DateTimeField(verbose_name='発行日')),
],
),
migrations.CreateModel(
name='Choice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('choice_text', models.CharField(max_length=200)),
('votes', models.IntegerField(default=0)),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.question')),
],
),
]
我认为你一眼就能看出来,我会制作一个问题和选择的模型!
那么,让我们执行makemigrations生成的迁移文件吧。在那之前,友善的官方教程前辈向我们介绍了一个命令,可以查看实际执行的查询语句,我们来试试看吧(此时尚未执行迁移)。
python manage.py sqlmigrate polls 0001
由於公式文件前輩對其進行了簡潔易讀的整理,所以讓我們來查看一下終端輸出。
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL,
"question_id" bigint NOT NULL
);
ALTER TABLE "polls_choice"
ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id"
FOREIGN KEY ("question_id")
REFERENCES "polls_question" ("id")
DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;
让我们实际执行迁移吧。
python manage.py migrate
如果成功显示“OK”,则迁移成功。现在可以创建问题和选择表。
尽管第二个教程还没有完成,但我们先到这里吧。
紧接着是②-2。