编写你的第一个Django App,第一章
让我们用一个示例来开始学习吧。
通过这个手册,我们将带你参观如何创建一个基本的投票应用。
这个应用由两部分组成:
- 一个允许人们查看民意调查并投票的公共网站。
- 一个允许由你来添加、更改、删除投票的管理网站。
我们假设你已经安装了Django。你可以通过运行下面的shell提示符命令来查看Django安装的版本。(以$作为前缀)
$ python -m django --version
如果Django已经安装了,你就会看到你所安装的Django的版本。如果没有安装成功,则会提示一则错误信息“No module named django”(没有名为django的模块)。
这个教程适用于Django1.11和Python3.4及以上的版本。如果Django版本不匹配,你可以通过参考手册底部右下角的版本切换器选择你的Django版本,或者升级Django为最新版本。如果你仍在使用Python2.7,你需要稍微调整示例代码,如评论中所述。
查看 如何安装Django关于如何删除老版本的Django并安装新版本方面的建议。
到哪里获取帮助?
如果你在阅读此教程中遇到了问题,请给 django-users发送信息,或者访问 #django on irc.freenode.net和其他可能帮助你的Django开发者交流。
创建一个项目
如果这是你第一次使用Django,你必须处理一些初始设置。也就是说,你需要自动生成一些代码来建立一个Django项目——就是一个Django实例的设置集,它包含了数据库设置,Django细节设置,以及应用细节设置。
通过命令行,cd到你想要存储代码的路径(mysite),然后你就可以运行下面这条命令了:
$ django-admin startproject mysite
这就会在你的当前路径下创建一个mysite目录(就是个文件夹),如果它没有正常工作,查看 Problems running django-admin。
- 注意:你的项目的命名必须要避开python内置包的名字以及Django组件的名字。特别的,这意味着你要避免使用命名像django(将会和Django自己冲突)或者test(将会和Python内置包名冲突)
- 这些代码应该写在哪里?
如果你的后端是普通的PHP(没有使用较新的框架),你可能过去常常把代码放在web服务器的根目录下(比如 /var/www)。在Django中你不必这么做。把所有的python代码都放在你服务器的根目录下并不是一个明智的做法,因为也许会有一定的风险,就是其他人通过网页能查看的你的代码,这对安全而言没有好处。
让我们看一下 startproject创建了什么:
mysite/
-----manage.py
-----mysite/
---------init.py
---------settings.py
---------urls.py
---------wsgi.py
(这里的树结构画的不是很清楚,再用语言描述一下,在mysite文件夹中有manage.py文件和mysite文件夹,在mysite文件夹中有init.py、settings.py、urls.py、wsqi.py文件)
这些文件是:
- 外面的mysite文件夹是根目录,也是你的项目的容器。它的名字对Django而言并不重要,你可以将其重命名为任何你喜欢的名字。
- manage.py:一个很实用的命令行,它使得你和你的Django项目拥有更多的交互方式。你可以在django-admin and manage.py中了解manage.py的所有细节。
- 里面的mysite目录是关于你的项目的真实的python包。它的名字就是python包的名字,你需要使用它导入任何包中的内容(例如:mysite.urls)
- mysite/init.py:这是一个空文件,告诉python这是一个应该被认为是python的包。如果你是一个python的初学者,可以在在官方文档中阅读more about packages。
- mysite/settings.py:用来配置Django项目。 Django settings将告诉你所有如何设置工作的细节。
- mysite/urls.py:为Django项目生命URL。这是一个启动Django项目的RUL目录。你可以了解更多在 URL dispatcher中。
- mysite/wsgi.py:为你的项目提供一个网关接口兼容的web服务器的入口,查看 How to deploy with WSGI 的更多细节。
开发服务器
让我们来验证Django项目的工作。把目录更改到外面的mysite路径,如果你还没有更改目录就运行了下面的命令:
$ python manage.py runserver
你将会在命令行中看到下面的输出:
Performing system checks...
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.
September 06, 2017 - 15:50:53Django version 1.11, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
- 注意:忽略关于未应用的数据库迁移的警告,我们将马上处理数据库。
你已经启动了Django开发服务器,完全用python编写的轻量级服务器。我们已经将它和Django包含在一起了,所以你可以快速的开发,而不需要处理服务器的配置。——就像Apache服务器一样,直到你准备好生产为止。
现在是值得注意的时候:不要在任何类似于生产环境的地方使用该服务器。它只能在开发时使用。(我们在做web框架的业务,而不是web服务器)
现在服务器正在运行,用你的浏览器访问http://127.0.0.1:8000/,你会看见一个呈现出“Welcome to Django”的页面,令人愉快的淡蓝色背景,它已经工作了。
- 改变端口
在默认设置中,runserver命令开启开发服务器本地IP的8000端口。
如果你想改变服务器的端口,把它作为一个命令参数。示例:在8080端口上开启服务器
$ python manage.py runserver 8080
如果你想改变服务器的IP,把它和端口号一起作为命令参数。示例:监听所有可用的公共IP(如果你想运行Vagrant 或者你想炫耀可以通过网络在其他电脑上工作是很有用的)
$ python manage.py runserver 0:8000
0是0.0.0.0的简写方式,开发服务器的全部文档可以在runserver指南中被找到。
- 自动重新加载runserver
开发服务器根据需要对python代码进行自动重新加载,你不必为了使修改的代码生效而重启服务器。然而,一些类似于添加文件的操作无法触发重新启动机制,所以在这些情况下你必须重启服务器。
创建投票应用
目前为止,一个名为“project”的环境已经搭建好了,你可以开始工作了。
你用Django写的每个应用都会包含一个python包,这是约定俗成的。Django有一个实用的功能就是,自动生成应用的基本目录结构,让你专注于编写代码,而不是创建目录结构。
- 项目和应用程序
项目和应用程序有什么区别呢?一个应用程序就是可以做一些事情的web应用——例如,网络日志系统,一个公共记录的数据库或者一个简单的投票应用程序。一个项目是配置的集合和一个或者多个特别的网站应用程序。
你的应用程序可以在python路径中的任何地方,在本教程中,我们将在你的manage.py文件旁边创建我们的投票应用程序,目的是这样就可以导入顶级模块(导入的是mysite)了,而非mysite的子模块。
为了创建应用,请确保你目前所在路径和manage.py一致,然后输入如下命令:
$ python manage.py startapp polls
这将会创建一个名为“polls”的目录,它的目录结构如下所示:
polls/
------init.py
------admin.py
------apps.py
------migrations/
--------init.py
------models.py
------tests.py
------views.py
(在polls目录中,有init.py、admin.py、apps.py、models.py、tests.py、view.py和一个migrations文件夹,migrations目录中有init.py文件)
这个目录结构将会容纳polls应用程序。
编写你的第一个View
让我们开始写第一个View吧。打开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中最简单的View了。为了调用view,我们需要把它映射到URL上——如此我们就需要一个URLconf。
为了在polls目录中创建一个URLconf,创建一个名为“urls.py”的文件,然后你的应用程序目录现在是这样:
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'),
]
下一步就是指向polls.urls模块的根URLconf,在mysite/urls.py中导入django.conf.urls.include,并在urlpatterns列表中插入一个include()方法,所以你urls.py应该如下所示:
#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()方法允许引用其他URLconfs。值得注意的是,include()方法的正则表达式没有‘$’符号,但是有一个‘/’尾斜杠。无论何时,当Django邂逅include()方法时,它可以将URL的任何部分与该点匹配,并将剩余的字符串发送到包含的URLconf,以便进行进一步的处理。
include()方法的想法是使URLs“即插即用”,使用起来更简单。因为polls在他们自己的URLconf中(polls/urls.py),他们可以被置于“/polls/”目录下,或者“/fun_polls/”下,再或者“/content/polls”,或者其他根路径,应用程序仍然正常工作。
- 当使用include()方法时
当你的项目包含了其他URL patterns时,你应该经常使用include()方法。admin.site.urls是唯一的例外。 - 和你看到的不一样?
如果你看到的是include(admin.site.urls),而不是admin.site.urls,那么你使用的Django版本可能和本教程不匹配。你可以切换到旧版本的教程,也可以升级Django版本。
现在你已经将一个index view连接到了URLconf,让我们来验证它正在工作,运行如下命令:
$ python manage.py runserver
在浏览器中访问 http://localhost:8000/polls/ ,然后你应该可以看到文字“Hello, World.You’re at the polls index.”,这是你在index view中定义的内容。
url()方法传递了4个参数,其中2个是必须的参数:regex和view,其余两个是可选参数:kwargs和name。这个时候,应该回顾一下这些参数的作用。
url()函数 参数:regex
这个叫做“regex”的参数一般来说,意思是“regular expression”(正则表达式)的缩写,它是一种匹配字符串模式的一种语法,或匹配ulr模式。Django从第一个正则表达式开始,然后在列表中从上至下依次对比请求URL和正则表达式,知道它找到一个匹配的为止。(如果找不到,那么会返回404Error)
- 注意,这些正则表达式没有搜索GET和POST参数、域名。举个例子,一个请求发送到https://www.example.com/myapp/,URLconf时将会查找 myapp/。一个请求发送到https://www.example.com/myapp/?page=3,URLconf依然会查找myapp/。
如果你需要正则表达式方面的帮助,请看 Wikipedia’s entry,在文档 re
模块也能查到相关信息。Jeffrey Friedl的《Mastering Regular Expressions》(精通正则表达式)这本书很棒。然而,在实践中,你不必成为一个正则表达式专家,因为你只需要知道如何捕捉相同模式即可(就是让字符串匹配正则表达式)。事实上,复杂的正则表达式搜索性能很差,所以你不应该依赖regexes的全部力量。
最后,一份性能报告:这些正则表达式在URLconf模块加载后第一时间被编译,这样就非常快(只要查找不像上面那样复杂)(作者应该是指regex和请求URL的匹配结果会在URLconf模块加载后就知道了)。
url()函数 参数:view
当Django发现了一个匹配的正则表达式后,Django会调用指定的view()方法,用一个 HttpRequest
对象作为第一个参数,任何被正则表达式匹配的值都将作为其他参数。如果regex使用简单的匹配模式,那么值将作为位置参数传递;如果它使用命名匹配,那么值将作为关键字参数。我们会给大家举个例子。
ulr()函数 参数:kwargs
任意的关键字参数都以字典的方式传递到目标view,我们将在教程中使用这一特性。
url()函数 参数:name
命名你的URL可以让你清楚的从Django的其他地方引用它,特别是在模板(tamplate)中。这个强大的功能特性允许你更改全局URL patterns时,只涉及到一个文件。
当你对基本的请求和响应流感到满意时(作者可能是指,对基本的请求和响应方式有基本的了解时),阅读教程的第二章开始使用数据库。