本教程从以下位置开始 Tutorial 1 停下来了。我们将设置数据库,创建您的第一个模型,并快速介绍Django自动生成的管理站点。
从哪里获得帮助:
如果您在阅读本教程时遇到困难,请访问 Getting Help 部分的常见问题解答。
现在,张开嘴 mysite/settings.py
.这是一个普通的Python模块,具有代表Django设置的模块级变量。
默认情况下, DATABASES
配置使用SQLite。如果您是数据库新手,或者只是有兴趣尝试Django,那么这是最简单的选择。SQLite包含在Python中,因此您不需要安装任何其他东西来支持您的数据库。然而,当开始您的第一个真正的项目时,您可能想要使用更可扩展的数据库,例如PostgreSQL,以避免以后出现数据库切换的麻烦。
如果您希望使用其他数据库,请参阅 details to customize and get your database running 。
当您编辑时 mysite/settings.py
,设置 TIME_ZONE
到您的时区。
另外,请注意 INSTALLED_APPS
设置在文件顶部。它保存在此Django实例中激活的所有Django应用程序的名称。应用程序可以在多个项目中使用,并且您可以打包和分发它们,供其他人在其项目中使用。
默认情况下, INSTALLED_APPS
包含以下应用程序,所有这些应用程序均随Django提供:
django.contrib.admin
--管理网站。您很快就会使用它。
django.contrib.auth
--认证系统。
django.contrib.contenttypes
--内容类型的框架。
django.contrib.sessions
--会议框架。
django.contrib.messages
--消息传递框架。
django.contrib.staticfiles
--管理静态文件的框架。
为了方便常见情况,默认包含这些应用程序。
不过,其中一些应用程序至少使用一个数据库表,因此我们需要在数据库中创建这些表,然后才能使用它们。为此,请运行以下命令:
$ python manage.py migrate
...\> py manage.py migrate
这个 migrate
命令查看 INSTALLED_APPS
设置,并根据中的数据库设置创建任何必要的数据库表 mysite/settings.py
文件和应用程序附带的数据库迁移(我们将在后面讨论这些内容)。对于它应用的每个迁移,您都会看到一条消息。如果您感兴趣,可以运行数据库的命令行客户端,然后输入 \dt
(PostgreSQL)、 SHOW TABLES;
(MariaDB、MySQL)、 .tables
(SQLite),或 SELECT TABLE_NAME FROM USER_TABLES;
(Oracle)以显示Django创建的表。
对于极简主义者来说
正如我们上面所说,默认应用程序包含在常见情况下,但并非每个人都需要它们。如果您不需要其中的任何或全部,请随时评论或删除相应的行 INSTALLED_APPS
在运行之前 migrate
。这个 migrate
命令将仅运行中的应用程序的迁移 INSTALLED_APPS
。
现在我们将定义您的模型--本质上是您的数据库布局,以及额外的元数据。
哲理
模型是关于您的数据的唯一、明确的信息源。它包含要存储的数据的基本字段和行为。Django遵循着 DRY Principle 。目标是在一个地方定义您的数据模型,并自动从中派生内容。
这包括迁移--例如,与Ruby On Rails不同的是,迁移完全源自您的模型文件,本质上是Django可以滚动以更新您的数据库模式以匹配当前模型的历史记录。
在我们的民意调查应用程序中,我们将创建两个模型: Question
和 Choice
。一个 Question
有一个问题和一个发布日期。一 Choice
有两个字段:选择文本和投票计数。每个 Choice
与一个 Question
。
这些概念由Python类表示。编辑 polls/models.py
文件,因此它看起来像这样:
polls/models.py
¶from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
在这里,每个模型都由一个类表示,该类将其进行子分类 django.db.models.Model
.每个模型都有多个类变量,每个类变量代表模型中的一个数据库字段。
每个字段都由 Field
类--例如, CharField
对于字符字段和 DateTimeField
用于日期时间。这告诉Django每个字段包含什么类型的数据。
的姓名 Field
实例(例如 question_text
或 pub_date
)是字段的名称,采用机器友好的格式。您将在Python代码中使用此值,并且您的数据库将使用它作为列名。
您可以使用可选的第一位置参数 Field
以指定人类可读的名称。它被用于Django的一些内省部分,并且兼作文档。如果未提供此字段,Django将使用机器可读的名称。在本示例中,我们仅定义了人类可读的名称 Question.pub_date
.对于该模型中的所有其他字段,该字段的机器可读名称足以作为其人类可读名称。
一些人 Field
类需要参数。 CharField
例如,需要您给它一个 max_length
.正如我们很快就会看到的那样,它不仅在数据库模式中使用,而且在验证中使用。
A Field
还可以有各种可选参数;在这种情况下,我们设置了 default
的价值 votes
设置为0。
最后,请注意,使用定义了关系 ForeignKey
.这告诉姜戈每个人 Choice
与单一有关 Question
. Django支持所有常见的数据库关系:多对一、多对多和一对一。
这一小部分模型代码为Django提供了很多信息。有了它,Django能够:
创建数据库模式 (CREATE TABLE
声明)对此应用程序。
创建Python数据库访问API用于访问 Question
和 Choice
物体。
但首先我们需要告诉我们的项目 polls
应用程序已安装。
哲理
Django应用程序是“可插入的”:您可以在多个项目中使用一个应用程序,并且可以分发应用程序,因为它们不必绑定到给定的Django安装。
要将该应用程序包含在我们的项目中,我们需要在 INSTALLED_APPS
设置.的 PollsConfig
班级在 polls/apps.py
文件,因此其虚线路径是 'polls.apps.PollsConfig'
.编辑 mysite/settings.py
文件并将虚线路径添加到 INSTALLED_APPS
设置.它看起来像这样:
mysite/settings.py
¶INSTALLED_APPS = [
"polls.apps.PollsConfig",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
现在姜戈知道要包括 polls
app。让我们运行另一个命令:
$ python manage.py makemigrations polls
...\> py manage.py makemigrations polls
您应该看到类似于以下内容的内容:
Migrations for 'polls':
polls/migrations/0001_initial.py
+ Create model Question
+ Create model Choice
通过运行 makemigrations
,您正在告诉Django您已经对模型进行了一些更改(在本例中,您已经进行了新的更改),并且您希望将这些更改存储为 migration 。
迁移是Django存储对模型(以及数据库模式)的更改的方式--它们是磁盘上的文件。如果您愿意,您可以阅读新模型的迁移;这是文件 polls/migrations/0001_initial.py
.别担心,您不需要每次Django制作它们时都阅读它们,但它们的设计是可人工编辑的,以防您想手动调整Django改变事物的方式。
有一个命令可以为您运行迁移并自动管理您的数据库模式-称为 migrate
,我们稍后将讨论它-但首先,让我们看看迁移将运行什么SQL。的 sqlmigrate
命令获取迁移名称并返回其SQL:
$ python manage.py sqlmigrate polls 0001
...\> py 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;
请注意以下几点:
确切的输出将根据您使用的数据库而异。上面的例子是为PostgreSQL生成的。
通过组合应用程序名称自动生成表名称 (polls
)以及模特的别名-- question
和 choice
. (You可以覆盖此行为。)
主密钥(ID)会自动添加。(You也可以覆盖这一点。)
按照惯例,姜戈补充 "_id"
到外部关键字字段名称。(Yes,您也可以覆盖此功能。)
外国钥匙关系由一位明确表示 FOREIGN KEY
约束。别担心 DEFERRABLE
部分;它告诉PostgreSQL在事务结束之前不要强制执行外部密钥。
它是为您正在使用的数据库量身定做的,因此特定于数据库的字段类型,如 auto_increment
(MySQL), bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
(PostgreSQL),或 integer primary key autoincrement
(SQLite)是自动为您处理的。对于字段名称的引号也是如此--例如,使用双引号或单引号。
这个 sqlmigrate
命令实际上不会在您的数据库上运行迁移-相反,它会将其打印到屏幕上,以便您可以查看SQL Django认为需要的内容。它对于检查Django要做什么或者您是否有需要SQL脚本进行更改的数据库管理员很有用。
如果您感兴趣,也可以跑步 python manage.py check
;这将检查您的项目中的任何问题,而无需进行迁移或触摸数据库。
现在,快跑 migrate
再次在数据库中创建这些模型表:
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
...\> py manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
这个 migrate
命令获取所有尚未应用的迁移(Django使用数据库中名为 django_migrations
)并在您的数据库中运行它们-本质上是将您对模型所做的更改与数据库中的模式同步。
迁移非常强大,可以让您在开发项目时随着时间的推移更改模型,而无需删除数据库或表并创建新数据库或表-它专门用于实时升级您的数据库,而不会丢失数据。我们将在本教程的后面部分更深入地介绍它们,但目前,请记住进行模型更改的三步指南:
更改您的模型(在 models.py
)。
跑 python manage.py makemigrations
为这些变化创建迁移
跑 python manage.py migrate
将这些更改应用到数据库。
之所以有单独的命令来进行和应用迁移,是因为您将将迁移提交到您的版本控制系统,并将其与您的应用程序一起交付;它们不仅使您的开发变得更容易,而且还可供其他开发人员使用。在生产中使用。
请阅读 django-admin documentation 有关什么的完整信息 manage.py
实用程序可以做。
现在,让我们进入交互式Python shell并尝试一下Django为您提供的免费API。要调用Python shell,请使用以下命令:
$ python manage.py shell
...\> py manage.py shell
我们使用这个而不是简单地输入“python”,因为 manage.py
设置 DJANGO_SETTINGS_MODULE
环境变量,它为Django提供了Python导入路径 mysite/settings.py
文件.默认情况下 shell
命令自动从您的导入模型 INSTALLED_APPS
.
一旦您进入Shell,就可以探索 database API :
# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>
# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# Save the object into the database. You have to call save() explicitly.
>>> q.save()
# Now it has an ID.
>>> q.id
1
# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=datetime.UTC)
# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
等一下 <Question: Question object (1)>
并不是这个对象的有用表示。让我们通过编辑 Question
模型(在 polls/models.py
文件)并添加 __str__()
控制电源的 Question
和 Choice
:
polls/models.py
¶from django.db import models
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
重要的是要补充 __str__()
方法到您的模型,不仅是为了您在处理交互式提示时的方便,而且还因为对象的表示在整个Django自动生成的管理中使用。
让我们还向这个模型添加一个自定义方法:
polls/models.py
¶import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
请注意添加 import datetime
和 from django.utils import timezone
,参考Python的标准 datetime
模块和Django的时区相关实用程序 django.utils.timezone
,分别。如果您不熟悉Python中的时区处理,您可以在 time zone support docs 。
保存这些更改并通过运行以下命令启动新的Python交互Shell python manage.py shell
再说一遍:
# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith="What")
<QuerySet [<Question: What's up?>]>
# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>
# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set (defined as "choice_set") to hold the "other side" of a ForeignKey
# relation (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)
# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>
# Create three choices.
>>> q.choice_set.create(choice_text="Not much", votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text="The sky", votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text="Just hacking again", votes=0)
# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>
# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith="Just hacking")
>>> c.delete()
有关模型关系的更多信息,请参阅 Accessing related objects .有关如何使用双强调线通过API执行字段查找的详细信息,请参阅 Field lookups .有关数据库API的完整详细信息,请参阅我们的 Database API reference 。
哲理
为您的员工或客户生成管理站点以添加、更改和删除内容是一项乏味的工作,不需要太多的创造力。因此,Django完全自动化了模型的管理界面的创建。
Django是在新闻编辑室环境中撰写的,“内容出版商”和“公共”网站之间有着非常明显的区分。网站管理员使用该系统添加新闻报道、事件、体育比分等,并且该内容显示在公共网站上。Django解决了为网站管理员创建统一界面来编辑内容的问题。
该管理员无意供网站访问者使用。这是为网站经理准备的。
首先,我们需要创建一个可以登录管理站点的用户。运行以下命令:
$ python manage.py createsuperuser
...\> py manage.py createsuperuser
输入您所需的用户名并按输入键。
Username: admin
然后系统会提示您输入所需的电子邮件地址:
Email address: admin@example.com
最后一步是输入您的密码。您将被要求输入密码两次,第二次作为第一次的确认。
Password: **********
Password (again): *********
Superuser created successfully.
Django管理站点默认处于激活状态。让我们启动开发服务器并探索它。
如果服务器未运行,请按如下方式启动:
$ python manage.py runserver
...\> py manage.py runserver
现在,打开Web浏览器并转到您本地域上的“/ADMIN/”--例如,http://127.0.0.1:8000/admin/.您应该会看到管理员的登录屏幕:
自.以来 translation 如果您设置,则默认打开 LANGUAGE_CODE
,登录屏幕将以给定语言显示(如果Django有适当的翻译)。
现在,尝试使用您在上一步中创建的超级用户帐户登录。您应该看到Django管理索引页面:
您应该看到几种类型的可编辑内容:组和用户。它们由 django.contrib.auth
,Django发布的身份验证框架。
但我们的民意调查应用程序在哪里?它不会显示在管理索引页面上。
还有一件事要做:我们需要告诉管理员 Question
对象有一个管理界面。为此,请打开 polls/admin.py
文件,并将其编辑为如下所示:
polls/admin.py
¶from django.contrib import admin
from .models import Question
admin.site.register(Question)
现在我们已经注册了 Question
,Django知道它应该显示在管理索引页面上:
单击“问题”。现在,您位于“更改列表”页面以获取问题。此页面显示数据库中的所有问题,并允许您选择一个来更改它。有“What ' s up?“我们之前提出的问题:
单击“怎么了?”编辑它的问题:
这里需要注意的事项:
该表格是从 Question
模特。
不同的模型字段类型 (DateTimeField
, CharField
)对应于适当的HTML输入小部件。每种类型的字段都知道如何在Django管理中显示自己。
每个 DateTimeField
获得免费的JavaScript快捷方式。日期有一个“今天”快捷方式和日历弹出窗口,时间有一个“现在”快捷方式和一个方便的弹出窗口,列出了常用输入的时间。
页面底部为您提供了几个选项:
保存--卸载更改并返回到此类型对象的更改列表页面。
保存并继续编辑--收件箱更改并重新加载此对象的管理页面。
保存并添加另一个--收件箱更改并加载此类型对象的新空白表单。
删除--显示删除确认页面。
如果“发布日期”的值与您在中创建问题的时间不匹配 Tutorial 1 ,这可能意味着您忘记为 TIME_ZONE
设置.更改它,重新加载页面并检查是否出现正确的值。
单击“今天”和“现在”快捷方式更改“发布日期”。然后单击“保存并继续编辑”。”然后点击右上角的“历史”。您会看到一个页面,列出了Django管理员对此对象所做的所有更改,以及做出更改的人的时间戳和用户名:
当您熟悉模型API并熟悉管理网站后,请阅读 part 3 of this tutorial 了解如何向我们的民意调查应用程序添加更多视图。
5月 28, 2025