1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
|
---
title: 'Django Tutorial Part 2: 创建网站的地基'
slug: learn/Server-side/Django/skeleton_website
translation_of: Learn/Server-side/Django/skeleton_website
---
<div>{{LearnSidebar}}</div>
<div>{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}</div>
<p class="summary"><a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Django教程</a>的第二篇文章会展示怎样创建一个网站的"框架",在这个框架的基础上,你可以继续填充整站使用的settings, urls,模型(models),视图(views)和模板(templates)。</p>
<table class="learn-box standard-table">
<tbody>
<tr>
<th scope="row">前提:</th>
<td><a href="/en-US/docs/Learn/Server-side/Django/development_environment">创建Django的开发环境</a>。复习 <a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Django教程</a>。</td>
</tr>
<tr>
<th scope="row">目标:</th>
<td>能够使用Django提供的工具包搭建你自己的网站工程。</td>
</tr>
</tbody>
</table>
<h2 id="概述">概述</h2>
<p>这篇文章会展示怎样创建一个网站的"框架",在这个框架的基础上,你可以继续填充整站使用的settings, urls,模型(models),视图(views)和模板(templates)(我们会在接下来的文章里讨论)。</p>
<p>搭建“框架”的过程很直接:</p>
<ol>
<li>使用django-admin工具创建工程的文件夹,基本的文件模板和工程管理脚本(<strong>manage.py</strong>)。</li>
<li><span style="line-height: 1.5;">用</span><strong style="line-height: 1.5;">manage.py</strong><span style="line-height: 1.5;"> 创建一个或多个应用。</span>
<div class="note">
<p><span style="font-size: 14px;"><strong>注意:</strong>一个网站可能由多个部分组成,比如,主要页面,博客,wiki,下载区域等。Django鼓励将这些部分作为分开的应用开发。如果这样的话,在需要可以在不同的工程中复用这些应用。</span></p>
</div>
</li>
<li> 在工程里注册新的应用。</li>
<li>为每个应用分配url。</li>
</ol>
<p>为 <a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">locallibrary</a> 这个项目创建的网站文件夹和它的工程文件夹都命名为<em>locallibrary</em>。我们只创建一个名为<em>catalog</em>的应用。最高层的项目文件结构如下所示:</p>
<pre class="brush: bash"><em>locallibrary/ # 网站文件夹</em>
<strong>manage.py </strong># 用来运行Django工具的脚本(由django-admin创建)
<em>locallibrary/ # 网站/项目文件夹(由django-admin创建)</em>
<em>catalog/ # 应用文件夹 </em>(由manage.py创建)</pre>
<p>接下来的部分会详细讨论创建网站框架的过程,并会展示怎么测试这些变化。最后,我们会讨论在这个阶段里你可以设置的整站级的配置。</p>
<h2 id="创建项目">创建项目</h2>
<p>首先打开命令行工具,进入你想要创建Django应用的地方(最好是你容易找到的地方),为新网站创建一个文件夹(这里是:<em>locallibrary</em>)。用cd命令进入文件夹:</p>
<pre class="brush: bash">mkdir locallibrary
cd locallibrary</pre>
<p>用<code>django-admin startproject</code>命令创建新项目,并进入该文件夹。</p>
<pre class="brush: bash">django-admin startproject locallibrary
cd locallibrary</pre>
<p><code>django-admin</code>工具会创建如下所示的文件夹结构</p>
<pre class="brush: bash"><em>locallibrary/</em>
<strong>manage.py</strong>
<em>locallibrary/</em>
settings.py
urls.py
wsgi.py</pre>
<p>locallibrary项目的子文件夹是整个网站的进入点:</p>
<ul>
<li><strong>settings.py</strong> 包含所有的网站设置。这是可以注册所有创建的应用的地方,也是静态文件,数据库配置的地方,等等。</li>
<li><strong>urls.py </strong>定义了网站url到view的映射<strong>。</strong>虽然这里可以包含所有的url,但是更常见的做法是把应用相关的url包含在相关应用中,你可以在接下来的教程里看到。</li>
<li><strong style="line-height: 1.5;">wsgi.py</strong><span style="line-height: 1.5;"> 帮助Django应用和网络服务器间的通讯。你可以把这个当作模板。</span></li>
</ul>
<p><strong>manage.py</strong>脚本可以创建应用,和数据库通讯,启动开发用网络服务器。</p>
<h2 id="创建catalog应用">创建catalog应用</h2>
<p>接下来,在locallibrary项目里,使用下面的命令创建catalog应用(和您项目的<strong>manage.py</strong>在同一个文件夹下)</p>
<pre class="brush: bash">python3 manage.py startapp catalog</pre>
<div class="note">
<p><span style="font-size: 14px;"><strong>注意:</strong>Linux/Mac OS X应用可以使用上面的命令。在windows平台下应该改为:</span> <code>py -3 manage.py startapp catalog</code></p>
<p>如果你是windows系统,在这个部分用<code>py -3</code> 替代<code>python3</code>。</p>
</div>
<p>这个工具创建了一个新的文件夹,并为该应用创建了不同的文件(下面黑体所示)。绝大多数文件的命令和它们的目的有关(比如视图函数就是<strong>views.py,</strong>模型就是<strong>models.py,</strong>测试是<strong>tests.py,</strong>网站管理设置是<strong>admin.py,</strong>注册应用是<strong>apps.py)</strong>,并且还包含了为项目所用的最小模板。</p>
<p>执行命令后的文件夹结构如下所示:</p>
<pre class="brush: bash"><em>locallibrary/</em>
manage.py
<em>locallibrary/
</em><strong> <em>catalog/</em>
admin.py
apps.py
models.py
tests.py
views.py
__init__.py
<em>migrations/</em></strong></pre>
<p>除上面所说的文件外,我们还有:</p>
<ul>
<li>一个<em>migration</em>文件夹,用来存储“migrations”——当你修改你的数据模型时,这个文件会自动升级你的数据库。</li>
<li><strong>__init__.py</strong> — 一个空文件,Django/Python会将这个文件作为<a href="https://docs.python.org/3/tutorial/modules.html#packages">Python 包</a>并允许你在项目的其他部分使用它。</li>
</ul>
<div class="note">
<p><span style="font-size: 14px;"><strong>注意</strong></span>: 你注意到上面的文件里有些缺失嘛? 尽管由views和models的文件,可是url映射,网站模板,静态文件在哪里呢?我们会在接下来的部分展示如何创建它们(并不是每个网站都需要,不过这个例子需要)</p>
</div>
<h2 id="注册catalog应用">注册catalog应用</h2>
<p>既然应用已经创建好了,我们还必须在项目里注册它,以便工具在运行时它会包括在里面(比如在数据库里添加模型时)。在项目的settings里,把应用添加进<code>INSTALLED_APPS</code> ,就完成了注册。</p>
<p>打开项目设置文件 <strong>locallibrary/locallibrary/settings.py</strong> 找到 <code>INSTALLED_APPS</code> 列表里的定义。 如下所示,在列表的最后添加新的一行。</p>
<pre class="brush: bash">INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
<strong> 'catalog.apps.CatalogConfig', </strong>
]</pre>
<p>新的这行详细说明了应用配置文件在 (<code>CatalogConfig</code>) <strong>/locallibrary/catalog/apps.py</strong> 里,当你创建应用时就完成了这个过程。</p>
<div class="note">
<p><strong>注意</strong>: 注意到<code>INSTALLED_APPS已经有许多其他的应用了</code> (还有 <code>MIDDLEWARE</code>, 在settings的下面)。这些应用为 <a href="/en-US/docs/Learn/Server-side/Django/Admin_site">Django administration site</a> 提供了支持和许多功能(包括会话,认证系统等)。</p>
</div>
<h2 id="配置数据库">配置数据库</h2>
<p>现在可以为项目配置数据库了——为了避免性能上的差异,最好在生产和开发中使用同一种数据库。你可以在<a href="https://docs.djangoproject.com/en/1.10/ref/settings/#databases">数据库</a> 里找到不同的设置方法(Django文档)。 </p>
<p>在这个项目里,我们使用SQLite。因为在展示用的数据库中,我们不会有很多并发存取的行为。同时,也因为SQLite不需要额外的配置工作。你可以在<strong>settings.py</strong>里看到这个数据库怎样配置的。(更多信息如下所示)</p>
<pre class="brush: python">DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
</pre>
<p>因为我们使用SQLite,不需要其他的设置了。我们继续吧!</p>
<h2 id="其他项目设置">其他项目设置</h2>
<p>settings.py里还包括其他的一些设置,现在只需要改变<a href="https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-TIME_ZONE">时区</a> — 改为和 标准<a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">tz时区数据表</a> 里的字符串相同就可以了(数据表里的TZ 列有你想要的时区)。 把<code>TIME_ZONE</code>的值改为你的时区,比如</p>
<pre class="brush: python">TIME_ZONE = 'Asia/Shanghai'</pre>
<p>有两个设置你现在不会用到,不过你应该留意:</p>
<ul>
<li><code>SECRET_KEY</code>. 这个密匙值是Django网站安全策略的一部分。如果在开发环境中没有包好这个密匙,把代码投入生产环境时最好用不同的密匙代替。(可能从环境变量或文件中读取)。</li>
<li><code>DEBUG</code>. 这个会在debug日志里输出错误信息,而不是输入HTTP的返回码。在生产环境中,它应设置为false,因为输出的错误信息会帮助想要攻击网站的人。</li>
</ul>
<h2 id="链接URL映射器">链接URL映射器</h2>
<p>在项目文件夹里,创建网站时同时生成了URL映射器(<strong>urls.py</strong>)。尽管你可以用它来管理所有的URL映射,但是更常用的做法是把URL映射留到它们相关的应用中。</p>
<p>打开<strong>locallibrary/locallibrary/urls.py</strong> 并注意指导文字解释了一些使用URL映射器的方法。</p>
<pre><code>"""locallibrary URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]</code></pre>
<p> </p>
<p><span style="letter-spacing: -0.00333rem;">URL 映射通过</span><code style="font-style: normal; letter-spacing: -0.00333rem;">urlpatterns</code><span style="letter-spacing: -0.00333rem;"> 变量管理,它是</span><code style="font-style: normal; letter-spacing: -0.00333rem;">path()</code><span style="letter-spacing: -0.00333rem;"> 函数的一个Python列表结构。 每个</span><code style="font-style: normal; letter-spacing: -0.00333rem;">path()</code><span style="letter-spacing: -0.00333rem;">函数要么将URL式样(URL pattern)关联到特定视图(</span><em>specific view)</em><span style="letter-spacing: -0.00333rem;">,将在模式匹配时显示;要么关联到某个URL式样列表的测试代码。 (第二种情况下,URL式样是目标模型里的“base URL”). </span><code style="font-style: normal; letter-spacing: -0.00333rem;">urlpatterns</code><span style="letter-spacing: -0.00333rem;"> 列表最开始定义了一个函数,这个函数将所有带有模型 </span><em>admin/</em><span style="letter-spacing: -0.00333rem;"> 的URL映射到模块</span><code style="font-style: normal; letter-spacing: -0.00333rem;">admin.site.urls</code><span style="letter-spacing: -0.00333rem;">。这个函数包含了Administration 应用自己的URL映射定义。</span></p>
<div class="note">
<p>注意:path() 中的路由是一个字符串,用于定义要匹配的URL模式。该字符串可能包括一个命名变量(尖括号中)</p>
<p>例:<code>'catalog/<id>/'</code>。此模式将匹配如 <strong>/catalog/<em>any_chars</em>/</strong> 的URL ,并将 any_chars 作为具有参数名称 <code>id</code> 的字符串传递给视图。我们将在后面的主题中进一步讨论路径方法和路由模式</p>
</div>
<p>将下面的行添加到文件的底部,以便将新的项添加到 <code>urlpatterns</code> 列表中。这个新项目包括一个 <code>path()</code> ,它将带有 <code>catalog/</code> 的请求转发到模块 <code>catalog.urls</code> (使用相对路径 URL <strong>/catalog/urls.py</strong>)。</p>
<pre><code># Use include() to add paths from the catalog application
from django.conf.urls import include
from django.urls import path
urlpatterns += [
path('catalog/', include('catalog.urls')),
]</code></pre>
<p>现在让我们把网站的根URL(例:<code>127.0.0.1:8000</code>)重定向到该URL:<code>127.0.0.1:8000/catalog/</code>; 这是我们将在这个项目中使用的唯一应用程序,所以我们最好这样做。为了完成这个目标,我们将使用一个特殊的视图函数(<code>RedirectView</code>), 当在 <code>path()</code> 函数中指定的URL模式匹配时(在这个例子中是根URL),它将新的相对URL作为其第一个参数重定向到(<code>/catalog/</code>)。</p>
<p>将以下行再次添加到文件的底部:</p>
<pre><code>#Add URL maps to redirect the base URL to our application
from django.views.generic import RedirectView
urlpatterns += [
path('', RedirectView.as_view(url='/catalog/')),
]</code></pre>
<p>将路径函数的第一个参数留空以表示'/'。如果你将第一个参数写为'/',Django会在你启动服务器时给出以下警告:</p>
<p> </p>
<p> </p>
<p> </p>
<pre><code>System check identified some issues:
WARNINGS:
?: (urls.W002) Your URL pattern '/' has a route beginning with a '/'.
Remove this slash as it is unnecessary.
If this pattern is targeted in an include(), ensure the include() pattern has a trailing '/'.</code></pre>
<p> </p>
<p>Django 默认不提供CSS, JavaScript, 和图片等静态文件 。但是当你在开发环境中开发时,这些静态文件也很有用。作为对这个URL映射器的最后一项添加,你可以通过添加以下行在开发期间启用静态文件的服务。</p>
<p>把下面的代码加到文件最后:</p>
<p> </p>
<pre><code># Use static() to add url mapping to serve static files during development (only)
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)</code></pre>
<p> </p>
<div class="note">
<p><strong>注意</strong>: 有很多方法扩展<code>urlpatterns</code> 列表(在上面的代码里我们通过 <code>+=</code> 运算符来区分新旧代码)。我们同样可以用原先列表的定义:</p>
<pre>urlpatterns = [
path('admin/', admin.site.urls),
path('catalog/', include('catalog.urls')),
path('', RedirectView.as_view(url='/catalog/', permanent=True)),
] + <code>static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)</code></pre>
<p> </p>
<p><span style="font-size: 1.2rem; letter-spacing: -0.00333rem;">除此以外,我们也可以包含import代码行 (</span><code style="font-style: normal; letter-spacing: -0.00333rem;">from django.conf.urls import include</code><span style="font-size: 1.2rem; letter-spacing: -0.00333rem;">) ,这样更容易看出我们添加的代码,通常我们把import代码行放在Python文件的开头。</span></p>
</div>
<p>最后,在catalog 文件夹下创建一个名为 <strong>urls.py </strong>的文件,并添加以下文本以定义导入(空)的 <code>urlpatterns</code>。这是我们在编写应用时添加式样的地方。</p>
<pre><code>from django.urls import path
from catalog import views
urlpatterns = [
]</code></pre>
<h2 id="测试网站框架">测试网站框架</h2>
<p>现在我们有了一个完整的框架项目。这个网站现在还什么都不能做,但是我们仍然要运行以下,以确保我们的更改是有效的。</p>
<p>在运行前,我们应该向运行<em>数据库迁移</em>。这会更新我们的数据库并且包含所有安装的应用(同时去除一些警告)。</p>
<h3 id="运行数据库迁移">运行数据库迁移</h3>
<p>Django 使用对象关系映射器(ORM)将Django代码中的模型定义映射到底层数据库使用的数据结构。当我们更改模型定义时,Django会跟踪更改并创建数据库迁移脚本 (in <strong>/locallibrary/catalog/migrations/</strong>) 来自动迁移数据库中的底层数据结构来</p>
<p>当我们创建网站时,Django会自动添加一些模型供网站的管理部分使用(稍后我们会解释)。运行以下命令来定义数据库中这些模型的表(确保你位于包含<strong> manage.py 的目录中</strong>):</p>
<pre class="brush: bash">python3 manage.py makemigrations
python3 manage.py migrate
</pre>
<div class="warning">
<p><strong>重要信息</strong>: 每次模型改变,都需要运行以上命令,来影响需要存储的数据结构(包括添加和删除整个模型和单个字段)。</p>
</div>
<p>该 <strong><code>makemigrations</code></strong> 命令创建(但不适用)项目中安装的所有应用程序的迁移(你可以指定应用程序名称,也可以为单个项目运行迁移)。这让你有机会在应用这些迁移之前检查这些迁移代码—当你是Django专家时,你可以选择稍微调整它们。</p>
<p>这 <strong><code>migrate</code></strong> 命令 明确应用迁移你的数据库(Django跟踪哪些已添加到当前数据库)。</p>
<div class="note">
<p><strong>注意</strong>: 看 <a href="https://docs.djangoproject.com/en/1.10/topics/migrations/">Migrations</a> (Django docs) ,了解较少使用的迁移命令的其他信息。</p>
</div>
<h3 id="运行网站">运行网站</h3>
<p>在开发期间,你首先要使用开发网络服务器和浏览你本机的浏览器,来测试你的网站。</p>
<div class="note">
<p><strong>注意</strong>: 这个开发网络服务器并不够强大以及不足以用于生产使用,但是它能非常容易得使你在开发期间,获得你的Django网站和运行它,以此来进行快速测试。<br>
默认情况下,服务器会开通(http://127.0.0.1:8000/),但你也可以选择其他端口。有关更多信息,查阅( <a href="https://docs.djangoproject.com/en/1.10/ref/django-admin/#runserver">django-admin and manage.py: runserver</a> )(Django docs).</p>
</div>
<p>通过调用 <code>runserver</code> 命令运行Web服务器(与<strong>manage.py</strong>位于同一目录下):</p>
<pre class="brush: bash">python3 manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
September 22, 2016 - 16:11:26
Django version 1.10, using settings 'locallibrary.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
</pre>
<p>一旦服务器运行,你可以用你的浏览器导航到 <a href="http://127.0.0.1:8000/"><code>http://127.0.0.1:8000/</code> </a>查看。你应该会看到一个错误页面,如下所示。</p>
<p><img alt="Django debug page for a 404 not found error" src="https://mdn.mozillademos.org/files/14009/django_404_debug_page.png" style="display: block; height: 545px; margin: 0px auto; width: 871px;"></p>
<p>别担心,这个错误页面是预期结果。因为我们没有在 <code>catalogs.urls</code> 模块中定义任何页面/网址。<strong>(留意</strong>:当我们导航网站根目录URL时,我们被重定向到了<strong>/catalog 。)</strong></p>
<div class="note">
<p><strong>注意</strong>: 上面的页面展示了一个重要的Django功能—自动调试日志记录。每当找不到页面,或者代码引发任何错误,就会显示错误页面,其中会提供有用的信息。在这种情况下,你可以看到我们提供的 URL 与我们任何 URL 模式都不匹配(像列出的那样)。生产环境中,日志功能将被关闭(当我们将网站存放在网络上时),这种情况下,将提供的信息量更少,但用户友好的页面。</p>
</div>
<p>这个时候,我们知道Django正在工作。</p>
<div class="note">
<p><strong>注意</strong>: 每当进行重大更改时,都应重新运行迁移并重新测试站点。这并不需要很长时间。</p>
</div>
<h2 id="挑战自我">挑战自我</h2>
<p>该 <strong>catalog/ </strong>目录包含视图,模型和应用程序其他部分的文件。你可以打开这些文件并查看样板。</p>
<p>如上所述,管理站点的 URL 映射已经添加到项目的 <strong>urls.py</strong> 中。导航到浏览器中的管理区域,看看会发生什么(您可以从上面的映射中推断出正确的URL)。</p>
<ul>
</ul>
<h2 id="概要">概要</h2>
<p>你现在已经创建了一个完整的基本网站项目骨架,你可以继续填加网址,模型,视图和模版。</p>
<p>现在, <a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Local Library website</a> 的骨架已经完成并运行,是时候开始编写代码,让这个网站做它应该做的事情了。</p>
<h2 id="更多">更多</h2>
<ul>
<li><a href="https://docs.djangoproject.com/en/1.10/intro/tutorial01/">编写你的第一个Django应用 - part 1</a> (Django docs)</li>
<li><a href="https://docs.djangoproject.com/en/1.10/ref/applications/#configuring-applications">Applications</a> (Django Docs). 包括配置应用的信息。</li>
</ul>
<p>{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}</p>
|