三、Django基础之Part2

一、创建一个项目

如果这是你第一次使用Django,那么你必须进行一些初始设置。也就是通过自动生成代码来建立一个Django项目Project-一个Django项目的设置集,包含了数据库配置,Django详细选项设置和应用特性配置。

在命令行中,使用cd命令进入你想存储代码所在的目录,然后运行一下命令:

> django-admin.py startproject mysite

这将在当前目录创建一个mysite目录。如果失败了,请查看Problems running django-admin.py.

你需要避免使用python保留字或Django组件名作为项目的名称。尤其是你应该避免使用的命名如:django (与 Django 本身会冲突) 或者 test (与 Python 内置的包名会冲突).

这段代码应该放在哪里?

如果你有一般 PHP 的编程背景(未使用流行的框架),可能会将你的代码放在 Web 服务器的文档根目录下(例如:/var/www)。而在 Django 中,你不必这么做。将任何 Python 代码放在你的 Web 服务器文档根目录不会是一个好主意,因为这可能会增加人们通过 Web 方式查看到你的代码的风险。这不利于安全。

当你的代码放在你的文档根目录,以外的某些目录,列如/home/mycode.

让我们来看看startproject 都创建了些什么:

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py

文件解释:

  • 外层mysite/目录只是你项目的一个容器。对于Django来说该目录并不重要;你可以重命名为你喜欢的。
  • manage.py:一个实用的命令行工具,可让你以各种方式与该Django项目进行交互。你可以在django-admin.py and manage.py中查看关于manage.py所有的细节。
  • 内层mysite/目录事你项目中的实际Python包。该目录就是Python包名,通过它你可以导入它里面的任何东西。(e.g.import.mysite.settings).
  • mysite/init.py: 一个空文件,告诉Python该目录是一个Python包。
  • mysite/settings.py: 该Django项目设置/配置;
  • mysite/urls.py: 该Django项目的URL声明;一份由Django驱动网站目录
  • mysite/wsgi.py: 一个WSGI兼容的Web服务器的入口,以便运行你的项目;

二、开发用服务器

让我们来验证是否工作,从外层mysite目录切换进去,利用python manage.py runserver运行;

➜  mysite python3.6 manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).

July 01, 2018 - 02:45:18
Django version 1.11.11, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

你已经启动了Django开发服务器,一个纯粹的由Python编写的轻量级Web服务器。我们在Django内包含了这个服务器,这样你就可以迅速开发了,在产品投入使用之前不必去配置一台生产环境下的服务器-列如Apache,Nginx。
注意:不要在任何类似生产环境中使用此服务器。它仅适用于开发环境。(我们提供的是Web框架的业务,而不是Web服务器。)

现在服务器正在运行中,请在你的web浏览器中访问http://127.0.0.1:8000/。你会看到一个令人愉悦的,柔和的淡蓝色 “Welcome to Django” 页面。它工作正常!

更改端口号

默认情况下,runserver 命令启动的开发服务器只监听本地 IP 的 8000 端口。

如果你想改变服务器的端口,把它作为一个命令行参数传递即可。例如以下命令启动的服务器将监听 8080 端口:

> python manage.py runserver 8080

# 如果你想改变服务器 IP ,把它和端口号一起传递即可。因此,要监听所有公共 IP 地址(如果你想在其他电脑上炫耀你的工作),请使用:

python manage.py runserver 0.0.0.0:8000

三、数据库设置

现在,编辑mysite/settings.py。这是一个普通的Python模块,包含了代表Django设置模块级变量。更改 DATABASES 中 ‘default’ 下的以下键的值,以匹配您的数据库连接设置。

  • ENGINCE: 从django.db.backends.postgresql_psycopg2’, ‘django.db.backends.mysql’, ‘django.db.backends.sqlite3’, ‘django.db.backends.oracle’中选一个, 至于其他请查看 also available.
  • NAME: 你的数据库名。如果你使用SQLite,该数据库将是你计算机上的一个文件;在这种情况下,NAME将是一个完整的绝对路径,而且还包含该文件的名称。如果该文件不存在,它会在第一次同步数据库时自动创建;
    ps: 当指定路径时,总是使用正斜杠,即使是在Windows下(例如:C:/homes/user/mysite/sqlite3.db)

  • USER: 数据库用户名(SQLite下不需要)
  • PASSWORD: 数据库密码(SQLite下不需要)
  • HOST: 你的数据库主机地址。如果和你的数据库服务器是同一台物理机器,请将此处保留为空(或者设置为127.0.0.1)(SQLite下不需要);

如果你是新建数据库,我们建议只使用SQLite,将ENGINE改为django.db.backends.sqlite3并且将NAME设置为想存放数据库的地方。SQLite是内置在Python中的,因此你不需要安装任何东西来支持你的数据库。

如果你使用 SQLite ,你不需要事先创建任何东西 - 在需要的时候,将会自动创建数据库文件。
当你编辑 settings.py 时,将 TIME_ZONE 修改为你所在的时区。默认值是美国中央时区(芝加哥)。

同时,注意文件底部的INSTALLED_PASS设置。它保存了当前Django实例已激活的所有Django应用。每个应用可以被多个项目使用,而且你可以打包和分发给其他人在他们的项目中使用。

默认情况下,INSTALLED_APPS 包含以下应用,这些都是由Django提供的:

  • django.contrib.auth - 身份验证系统
  • django.contrib.contenttypes - 内容类型框架
  • django.contrib.sessions - session 框架
  • django.contrib.sites - 网站管理框架
  • django.contrib.messages - 消息框架
  • django.contrib.staticfiles - 静态文件管理框架

这些应用在一般情况下是默认包含的。

所有这些应用中每个应用至少使用一个数据库表,所以在使用它们之前我们需要创建数据库中的表。要做到这一点,请运行如下命令:

python manage.py syncdb

syncdb 命令参照 INSTALLED_APPS 设置,并在你的 settings.py 文件所配置的数据库中创建必要的数据库表。每创建一个数据库表你都会看到一条消息,接着你会看到一个提示询问你是否想要在身份验证系统内创建个超级用户。按提示输入后结束。

就像我们上面所说的,一般情况下以上应用都默认包含在内,但不是每个人都需要它们。如果不需要某些或全部应用,在运行 syncdb 命令前可从 INSTALLED_APPS 内随意注释或删除相应的行。syncdb 命令只会为 INSTALLED_APPS 内的应用创建表。

四、创建模型

现在你的项目开发环境建立好了,你可以开工了,小伙伴,是不是很激动

你通过Django编写的每个应用都是Python包组成的,这些包存放你的Python path中并且遵循一定的命名规范。Django提供了个实用工具可以自动生成一个应用的基本目录架构,因此那你可以专注于编写代码而不是去创建目录。

项目(Projects)vs 应用(apps)
项目与应用之间有什么不同之处?应用是一个提供功能的Web 应用-例如:一个博客系统,一个公共记录的数据库或者一个简单的投票系统。项目是针对一个特定的Web网站相关的配置和其应用的组合。一个项目可以包含多个应用。一个应用可以在多个项目中使用。

你的应用可以存放在Python path中的任何位置。我们将通过你的manage.py文件创建我们的投票应用,以便它的可以作为顶层模块导入,而不是作为mysite的字模块。

要创建你的应用,请确认与manage.py 文件在同一的目录下并输入以下的命令:

➜  python3.6 manage.py startapp polls

这将创建一个polls目录,其展开的样子如下所示:

polls/
    __init__.py
    models.py
    tests.py
    views.py

ps: 此目录结构就是投票应用

在Django 中编写一个有数据库支持的Web应用的第一步就是定义你的模型 - 从本质上讲就是数据库设计及其附加的元数据。

说明:
模型是有关你数据的唯一且明确的数据源。它包含了你所要存储的数据的基本字段和行为。Django蹲循DRY原则。目标是为了只在一个地方定义你的数据模型就可从中自动获取数据。

在这简单的投票应用中,我们将创建两个模型:Poll和Choice。Poll有问题和发布日期两个字段。Choice有两个字段:选项(choice)的文本内容和投票数。每一个Choice都与一个Poll关联。

这些概念都由简单的Python类来实现。编辑polls/models.py 文件后如下所示:

from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

代码很简单。每个模型都由继承自django.db.models.Model 子类的类来描述。每个模型都有一些变量,每一个类变量都代表了一个数据库段。

每个字段由一个Field的实例来表现 - 比如CharField表示字段类型的字段和DateTimeField表示日期时间型的字段。这会告诉Django每个字段都保存了什么类型的数据。

每一个Field实例的名字就是字段的名字(如:question或pub_date),其格式属于亲和机器式。在你的Python代码中会使用这个值,而你的数据库会将这个值作为表的列名。

你可以在初始化Field实例时使用第一个位置的可选参数来制定人类可读的名字。这在Django的内省部分中被使用到了,而且兼作文档的一部分来增强代码的可读性。若字段未提供该参数,Django将使用符合机器习惯的名字。接下来,我们仅定义了一个符合人类习惯的字段名 Poll.pub_date 。对于模型中的其他字段,机器名称就已经足够替代人类名称了。

一些 Field 实例是需要参数的。 例如 CharField 需要你指定 ~django.db.models.CharField.max_length。这不仅适用于数据库结构,以后我们还会看到也用于数据验证中。

一个 Field 实例可以有不同的可选参数; 在本例中,我们将 votes 的 default 的值设为 0 。

最后,注意我们使用了 ForeignKey 定义了一个关联。它告诉 Django 每一个Choice 关联一个 Poll 。 Django 支持常见数据库的所有关联:多对一( many-to-ones ),多对多( many-to-manys ) 和 一对一 ( one-to-ones )。

五、激活模型

要在项目中包含应用,我们需要在 INSTALLED_APPS 设置里添加这个应用的设置类。这个设置类 PollsConfig 在 polls/apps.py 文件里,它的点分路径是 ‘polls.apps.PollsConfig’。编辑 mysite/settings.py,然后在 INSTALLED_APPS 设置里添加这个点分路径,使其包含字符串 polls。看起来应该像这样:

# 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',
]

现在Django已经知道包含了polls应用。让我们运行如下命令:

mysite python3.6  manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Choice
    - Create model Poll
    - Add field poll to choice

通过运行 makemigrations 命令,你告诉了 Django 你对模型文件做了些修改(在上面例子,你创建了新的模型),修改的部分被储存为了一次 迁移。

迁移是Django对于模型(也就是你的数据库结构)的修改的存储方式 - 它们其实也只是一些磁盘上的文件。如果你想的话,你可以阅读一下你的模型的迁移数据,它被存储在polls/migrations/0001_initial.py
里。别担心,你不需要每次都阅读迁移文件,但是文件被设计成人类可编辑的形式,这是为了能手动对它们进行微调。

Django有个自动执行数据库迁移并同步管理你的数据库结构的命令是 migrate,我们马上就会接触它 - 但是首先,让我们看看迁移命令会执行哪些SQL语句。 sqlmigrate命令接收一个迁移的名称,然后返回对应的SQL:

python3.6 manage.py sqlmigrate polls 0001


BEGIN;
--
-- 创建 Choice 模型
--
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL
);
--
-- 创建 Question 模型
--
CREATE TABLE "polls_question" (
    "id" serial NOT NULL PRIMARY KEY,
    "question_text" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
--
-- 对 choice 表添加 question 字段
--
ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
ALTER TABLE "polls_choice"
  ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"
    FOREIGN KEY ("question_id")
    REFERENCES "polls_question" ("id")
    DEFERRABLE INITIALLY DEFERRED;
COMMIT;

说明:

  • 输出的内容和你使用的数据库有关,上面的输出示例使用的是PostgreSQL。
  • 数据库的表名是由应用名(polls)和模型名的小写形式(question和choice)连接而来。(如果需要,你可以自定义此行为)
  • 主键(ID)会被自动添加,(当然你也可以自定义)
  • 惯例下,Django会在外键字段名后追加字符串id。(同样,这也可以自定义)
  • 外键关系由FOREIGN KEY生成,别担心 DEFERRABLE 部分,它只是告诉 PostgreSQL,请在事务全都执行完之后再创建外键关系。
  • 外键关系由POREIGN KEY生成。别担心DEFERRABLE部分,它只是告诉PostgreSQL,你在事物全部执行完之后再创建外键关系。
  • 生成SQL语句是为你所用的数据库定制的,所以哪些和数据库有关的字段类型,比如auto_increment(MyDWL)、serial(PostgreSQL)和 integer primary key autoincrement(SQLite),都会为你自动处理的。那些和引号相关的事情 - 例如,是使用单引号还是双引号 - 也一样会被自动处理。
  • sqlmigrate命令并没有真正在你的数据库中执行迁移 - 它只是把命令输出到屏幕上,让你看看Django认为需要执行哪些SQL语句。

现在,再次运行 migrate 命令,在数据库里创建模型的数据表:

➜  mysite python3.6 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying polls.0001_initial... OK
  Applying sessions.0001_initial... OK

migrate 命令选中所有还没有执行过的迁移(Django通过在数据库中创建一个特殊的表django_migrations来跟踪执行过哪些迁移)并应用在数据库上 - 也就是将你对模型的更改同步到数据库结构上。

迁移是非常强大的功能,它能让你在开发过程中持续的改变数据库结构而不需要重新阐述的创建表 - 它专注于使数据库平滑升级而不会丢数据。

你需要记住,改变模型需要三步:

  • 编辑models.py文件,改变模型
  • 运行 python manage.py makemigrations 为模型的改变生成迁移文件。
  • 运行 python manage.py migrate 来应用数据库迁移。

数据库迁移被分解成生成和应用两个命令是为了让你能够在代码控制系统上提交迁移数据并使其能在多个应用里使用;这不仅仅会让开发更加简单,也给别的开发者和生产环境中的使用带来方便。

六、初试 API

现在让我们进入交互式 Python 命令行,尝试一下 Django 为你创建的各种 API。通过以下命令打开 Python 命令行:

mysite python3.6 manage.py shell
Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)

我们使用这个命令而不是简单的使用 “Python” 是因为 manage.py 会设置 DJANGO_SETTINGS_MODULE 环境变量,这个变量会让 Django 根据 mysite/settings.py 文件来设置 Python 包的导入路径。

我就是不想用manage.py
如果你不想使用 manage.py ,没问题,你只要手动将 DJANGO_SETTINGS_MODULE 环境变量设置为 mysite.settings 就行。打开一个普通的 Python 命令行,然后输入以下命令来配置 Django:

>>> import django
>>> django.setup()

如果抛出 AttributeError 错误,说明你使用的 Django 版本可能和本教程不一致。你可以切换到旧版本的教程或者把 Django 升级至最新版本。

你必须在 manage.py 所在目录中运行 python 命令,或者确保这个目录在 Python path 里,因为只有这样 import mysite 才能被正确的执行。

当你成功进入命令行后,来试试 数据库 API 吧:

>>> from polls.models import Question, Choice   # 导入刚刚创建的模型类
# 现在系统里还没有 Question 对象
>>> Question.objects.all()
<QuerySet []>
# 创建新 Question
# 在 settings 文件里,时区支持被设为开启状态,所以
# pub_date 字段要求一个带有时区信息(tzinfo)
# 的 datetime 数据。请使用 timezone.now() 代替
# datetime.datetime.now(),这样就能获取正确的时间。
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# 想将对象保存到数据库中,必须显式的调用 save()。
>>> q.save()
# 现在它被分配了一个 ID。注意有可能你的结果是“1L”而不是“1”,
# 这取决于你在使用哪种数据库。这不是什么大问题;只是表明
# 你所用的数据库后端倾向于将整数转换为 Python 的
# long integer 对象。
>>> q.id
1
# 通过属性来获取模型字段的值
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# 通过改变属性值来改变模型字段,然后调用 save()。
>>> q.question_text = "What's up"
>>> q.save()
# objects.all() 显示数据库中所有 question。
>>> Question.objects.all()
<QuerySet [<Question: Question object>]>

用  表示这个对象没什么帮助信息,它无法告诉我们这个对象的详细信息。让我们通过编辑 Question 模型的代码(polls/models.py 文件),给 Question 和 Choice 增加 str() 方法来改善这个问题:

# polls/models.py
from django.db import models
from django.utils.encoding import python_2_unicode_compatible、
@python_2_unicode_compatible  # 如果你想支持 Python 2
class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text
@python_2_unicode_compatible  # 如果你想支持 Python 2
class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

给模型增加 str() 方法是很重要的,这不仅仅能给你在交互式的命令行里使用带来方便,而且 Django 自动生成的 admin 里也是使用这个方法来表示对象的。

注意这些只是 Python 的普通方法。我们可以向模型里添加自定义方法,示范:

# 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 中的时区处理,可以看看 时区支持文档。

保存文件然后通过 python manage.py shell 命令再次打开 Python 交互式命令行:

>>> from polls.models import Question, Choice
# 确认添加的 __str__() 是否正常工作。
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
# Django 提供了丰富的数据库查找 API,
# 通过关键字参数就能轻松使用。
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>
# 获取今年发布的问题
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# 查找一个不存在的 ID 将会引发异常
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.
# 通过主键来查找数据是非常常见的需求,所以 Django
# 为这种需求专门制定了一个参数。
# 以下代码等同于 Question.objects.get(id=1)。
>>> Question.objects.get(pk=1)
<Question: What's up?>
# 确认我们自定义的方法正常工作。
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# 给这个问题添加几个选项。create 函数会创建一个新的
# Choice 对象,执行 INSERT 语句,将 Choice 添加到
# Question 的选项列表中,最后返回刚刚创建的
# Choice 对象。Django 创建了一个集合 API 来使你可以从
# 外键关系的另一方管理关联的数据。
# (例如,可以获取问题的选项列表)
>>> q = Question.objects.get(pk=1)
# 显示所有和当前问题关联的选项列表,现在是空的。
>>> q.choice_set.all()
<QuerySet []>
# 创建三个选项。
>>> 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 对象能通过 API 获取关联到的 Question 对象。
>>> c.question
<Question: What's up?>
# 反过来,Question 对象也可以获取 Choice 对象
>>> q.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> q.choice_set.count()
3
# 查找 API 的关键字参数可以自动调用关系函数。
# 只需使用双下划线来分隔关系函数。
# 只要你想,这个调用链可以无限长。
# 例如查找所有「所在问题的发布日期是今年」的选项
# (重用我们之前创建的 'current_year' 变量)
>>> Choice.objects.filter(question__pub_date__year=current_year)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
# 试试删除一个选项,使用 delete() 函数。
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

七、Django 的管理站点

介绍

设计哲学:
为你的团队和客户创建一个用于添加、修改和删除网站内容的管理页面是一项乏味的工作,而且不需要太多的创造力。因为这些原因,Django 提供完全自动地为模型创建管理接口的功能。

Django 产生于一个公众页面和内容发布者页面完全分离的新闻类站点的开发过程中。站点管理人员使用管理系统来添加新闻、事件和体育时讯等,这些添加的内容被显示在公众页面上。Django 通过为站点管理人员创建统一的内容编辑界面解决了这个问题。

管理界面不是为了网站的访问者,而是为管理者准备的。

创建管理员账户

首先,我们得创建一个能登录管理页面的用户。请运行下面的命令:

➜  mysite python3.6 manage.py createsuperuser
Username (leave blank to use 'xcn'): admin   # 输入你想用的用户名
Email address: [email protected]   # 输入邮箱
Password:    # 输入密码
Password (again):    # 再次确认密码
Superuser created successfully.

启动用于开发的服务器

Django 的管理界面默认就是启用的。让我们启动开发服务器,看看它到底是什么样的。

python3.6 manage.py runserver

进入管理页面

创建的超级用户来登录。然后你将会看到 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 知道它应该被显示在索引页里:

点击 “Question”。现在看到是 Question 对象的修改列表。这个界面会显示所有数据库里的 Question 对象,你可以选择一个来修改。这里现在有我们在上一部分中创建的 “What’s up?” 问题。

点击 “What’s up?” 来编辑这个 Question 对象:

注意:

  • 这个表单是从 Question 模型中自动生成的。
  • 不同的字段类型 日期时间字段(DateTimeField)、字符字段(CharField) 会生成对应的 HTML 输入控件。每个类型的字段都知道它们该如何在管理页面里显示自己。
  • 每个 日期时间字段(DateTimeField) 都有 JavaScript 写的快捷按钮。日期有转到今天(Today)的快捷按钮和一个弹出式日历界面。时间有设为现在(Now)的快捷按钮和一个列出常用时间的方便的弹出式列表。

页面的底部提供了几个选项:

  • 保存(Save) - 保存改变,然后返回对象列表。
  • 保存并继续编辑(Save and continue editing) - 保存改变,然后重新载入当前对象的修改界面。
  • 保存并新增(Save and add another) - 保存改变,然后添加一个新的空对象并载入修改界面。
  • 删除(Delete) - 显示一个确认删除页面。

如果显示的“发布日期(Date Published)”和你在教程第一部分里创建它们的时间不一致,这意味着你可能没有正确的设置 TIME_ZONE。改变设置,然后重新载入页面看看是否显示了正确的值。

通过点击“今天”(Today)和“现在(Now)”按钮改变“发布日期(Date Published)”。然后点击“保存并继续编辑(Save and add another)”按钮。然后点击右上角的“历史(History)”按钮。你会看到一个列出了所有通过 Django 管理页面对当前对象进行的改变的页面,其中列出了时间戳和进行修改操作的用户名:

八、编写你的第一个视图

创建并打开 polls/views.py,然后写进python代码:

# polls/views.py
from django.http import HttpResponse
def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

这也许是Django中最简单的视图了。为了调用这个视图,我们需要在它和一个URL之间做映射,这就需要URLconf。

为了在polls目录下创建一个URLconf,需要先创建urls.py文件,你的应用目录现在应该是这样的:

python polls/ __init__.py admin.py apps.py migrations/ __init__.py models.py tests.py urls.py views.py

polls/urls.py文件里包含以下代码;

# polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^$', views.index, name='index'),
]

下一步就是将根目录下的URLconf指向polls.urls模块。在mysite/urls.pyt中导入django.conf.urls.include,并且在urlpatterns列表中插入include(),如下:

# mysite/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
    url(r'^polls/', include('polls.urls')),
    url(r'^admin/', admin.site.urls),
]

include()函数允许引用其他的URLconf。要注意到include()函数并没有$(字符串匹配结束),取而代之的是尾部的一个斜杠。每当Django遇到include(),它就会排除正则匹配的部分,并将剩下的字符串发送到引用的URLconf中进一步的处理。

include()背后的想法是想使得URL的即插即用变得简单。polls是在它们自己的URLconf中(polls/urls.py),它们是可以被放在/polls/,"fun_polls","/content/polls",或者其他任何路径,而应用仍然是可以运行的。

神马时候使用inclode()

当你要包含其他URL匹配模式时,你应该一直使用inculde()。admin.site.urls在这里是一个例外。

现在你已经将index视图和URLconf连接在一起了。让我们验证下是不是生效了,运行一下命令:

$ python manage.py runserver

在你的浏览器中打开 http://localhost:8000/polls/。你应该能看到文字 “Hello, world. You’re at the polls index.” —— 这是你在 index 视图中定义的。

url函数有四个参数,两个必须参数:regex正则和view视图;两个选项参数:kwargs字典和name名字。

  • regex参数:术语“regex”是正则表达式 “regular expression” 的缩写,是匹配字符串的一段语法,像这里例子的是url匹配模式。Django从列表的第一个正则表达式开始,按顺序匹配请求的URL,直到找到与之匹配的。

  • view参数:当Django发现一个正则表达式匹配时,Django就会调用指定视图函数,HttpRequest对象作为第一个参数,正则表达式捕捉的值作为其他参数。如果正则使用简单捕获,值会作为为位置参数传递;如果使用命名捕获,值会作为关键字传递。

  • kwargs参数:任意的关键字参数都可以作为字典传递到目标视图。
  • name参数:命名你的URL可以让你在Django的别处明白引用的是什么,特别是在模版里。这个强大的特性允许你在项目对一个文件操作就能对URL模式做全局改变。

猜你喜欢

转载自www.cnblogs.com/baishuchao/p/9262232.html