编写你的第一个Django应用, 第一部分
让我们通过案例来学习。
通过这个教程,我们将创建一个基本的投票应用。
它将分为两部分
- 一个用户访问站点,用来投票和查看投票结果
- 一个管理网站,让你能够添加,修改和删除投票信息
我们假设你已经安装好了Django。你通过以下命令来知道你是否安装了Django, 安装的是哪一个版本。
$ python -m django --version
如果Django已经安装,你可以看到你安装的版本信息。如果没有, 你将看到出错信息(No module named django)。
这个教程是基于Django 1.11和Python 3.4或更新来写的。如果你的Django版本不匹配, 你可以使用这个页面右下角的版本切换器转换到你对应版本的教程,或者将你的版本更新到新版。如果你还在使用Python 2.7,你可能需要根据注解稍微调整一下示例代码。
参见《如何安装Django》来获取删除旧版安装新版Django的建议。
从哪里获取帮助:
如果你在参照教程学习的过程中遇到问题,请发送消息到django-users邮件列表或者在irc.freenode.net上访问#django来与其他Django使用者交谈以获取帮助。
创建一个项目
如果这是你首次使用Django, 你会需要关注一下一些初始设置。也就是你可能需要自动生成一些代码来建立一个Django项目 - 一堆Django实例的设置, 包括数据库的配置, Django本身的选项配置和应用程序特定的配置。
进入命令行, cd
到你打算放置代码的目录, 然后运行以下命令:
$ django-admin startproject mysite
这将创建一个mysite的目录到你的当前目录。如果这个不工作,请参见《运行django-admin的问题》。
笔记
你应该尽量避免使用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和manage.py》那里阅读所有关于manage.py
的细节。- 子目录
mysite/
是一个你项目的Python包。它的名字就是当你需要引用里面内容时候的Python包名(比如mysite.urls
)。 mysite/__init__.py
: 一个空文件用来告诉Python这个目录是一个Python的包。如果你是一个Python的初学者,你可以阅读Python官方文档里面关于包的部分。mysite/settings.py
:这是这个Django项目的配置文件。《Django配置》会告诉你这个配置文件是怎么工作。mysite/urls.py
:Django项目的URL申明;其实就是你Django网站的一个目录。你可以阅读《URL的分发》来了解更多关于Django URL处理的内容。mysite/wsgi.py
:用于WSGI兼容网站的入口程序。参见《如何使用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.
July 27, 2017 - 15:50:53
Django 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编写的轻量级的Web服务器。我们把这个服务器包含在Python里面是为了你能够快速开发,当你还没有准备在正式的服务器(比如Apache)上发布, 你就可以在这个简单server上进行开发。
这边要提醒的是:不要使用这个服务器在生产环境中运行。这个只是适合于开发中使用。(我们只是在开发一个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代码。你不需要在修改完代码后手工重启服务器来使之生效。然后有些行为比如增加代码就不会触发重启,所以你在这些情况下需要手工重启服务器。
创建投票应用
现在你的环境里面已经开启了一个项目, 所以你可以开始在上面工作了。
每个在Django里面的应用程序都包含了一堆符合一定规范的Python包。Django包含了一个附件来自动给你的应用创建目录结构, 这样你可以把注意力放在编写代码上而不是创建目录上。
项目和应用
项目和应用有什么区别?一个应用指的是完成一些事情的Web应用 - 比如网站日志系统,公开记录数据库系统或者是一个简单投票系统。一个项目则是一堆配置和一堆应用的集合,放在一个特定的网站上。一个项目可以包含多个应用。一个应用也可以被包含在多个项目里面。
你的应用将存在于你的Python路径下。在这个教程里面, 我们将在你的mange.py
文件所在目录创建一个投票应用, 这样他就可以作为顶级模块来被应用,而不是作为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
这个目录结构就会是你的投票应用要使用的目录。
编写你的第一个视图(View)
让我们开始编写第一个视图。打开文件polls/views.py
然后写入一下的Python代码:
polls/views.py
from djano.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
这是一个在Django中能写的尽可能简单的视图。为了调用这个视图,我们需要一个映射到它的URL - 因此我们需要一个URLconf对象。
为了创建URLconf对象到polls
目录,我们需要创建一个文件,名字叫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'),
]
下一步我们需要将根URLconf指向polls.urls
模块。在mysite/urls.py
里面,添加引用django.conf.urls.include
和插入include()
调用在urlpatterns
列表里面,你的代码应该像这样:
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()
, 他会把URL匹配的部分截断, 然后把剩下的部分发送到被include
进来的URLconf去处理。
这个include()
的做法使得URL可以被随意的绑定到一个前缀上去。由于投票应用有自己的URLconf (polls/urls.py
), 他可以被放置到"/polls/"
后面,或着放置到"/fun_polls/"
后面,或者"/content/polls/"
后面,或者其他任意前缀后面,这个应用都可以工作。
什么时候使用
include()
你应该在任何使用其他URL的时候都使用include()
函数,唯一的例外是admin.site.urls
-
和你看到的不一样
如果你看到include(admin.site.urls)
而不是admin.site.urls
, 那么你可以正在使用和这个教程版本不一致的Django版本。你应该切回旧的教程或者升级你的Djang。
你已经绑定了index
视图到URLconf对象。让我们来验证一下它是否工作,运行下面的命令:
$ python manage.py runserver
然后用你的浏览器访问http://localhost:8000/polls/, 你应该能够看到你在index
视图里面输出的文本”Hello, world. You’re at the polls index.”。
有4个参数需要被传递到url()
函数,两个是必须的: regex
和view
, 还有两个是可选的:kwargs
和name
。在这里,我们值得来看一下这些参数都是干什么的。
url()
参数: regex
属于"regex"
通常是正则表达式的缩写"regular expression"
,是一个专门用来匹配字符串的格式,在这里被用来匹配URL。Django会从第一个正则表示式开始顺着这个列表往下,对请求的URL进行匹配,直到找到一个匹配的。
请注意,这里的正则表达式不会用来匹配GET和POST的参数以及域名。比如请求https://www.example.com/myapp/, URLconf对象会用查找匹配myapp/
。而在请求https://www.example.com/myapp/?page=3, URLconf对象任然是去找匹配myapp/
的视图。
如果你需要正则表达式的帮助,你可以参考Wikipedia里面的内容或者参见Python文档里面关于re
模块的内容。如果你能参考O’Reilly出版的Jeffrey Fiedl写的《精通正则表达式》(Mastering Regular Expressions)那是最好的了。平时使用的话,你不需要是个正则表达式的专家,你只需要弄懂一些基本模式匹配的写法。事实上,复杂的正则表达式,通常也就意味着很慢的匹配性能,所以你也不能过分依赖与正则表达式的全部能力。
最后,针对性能提一句:这些正则表达式会在URLconf模块首次载入的时候就会被编译。所以他们还是相当快的(只要这个表达式不要过分的复杂)。
url()
参数: view
当Django找到一个匹配的正则表达式, Django将会调用指定的视图view函数,并且使用HttpRequest
对象作为第一个参数传给view函数,使用正则表达式匹配的子元素则作为剩下的参数传给view函数。如果正则表达式使用简单抓取,这些值就会当成位置参数传给view函数,如果使用命名抓取,就会使用关键字参数。我们接下来会给出一个示例。
url()
参数:kwargs
任意的关键字参数都会作为一个字典类型传给目标视图。我们在这个教程里面不会使用这个功能。
url()
参数: name
将你的URL链接命名就可以没有歧义的在Django里面引用这个链接,特别是当你在使用templates模板的时候。这个功能可以使你在全局修改URL的时候只需要碰一个文件。
如果你觉得可以理解基本的请求和响应流程的时候,你就可以接下去阅读第二部分,将涉及到数据库的部分。