编写你的第一个Django应用程序,第1部分

让我们通过例子学习。

本教程中,我们将带领你创建一个基本的投票应用。

它包含两部分:

  • 一个公开站点,允许人们查看投票并对它们投票。
  • 一个管理后台站点,允许你添加、更改和删除投票。

我们假设你已经安装好Django 你可以通过在shell提示符(以$前缀表示)中运行以下命令来检查Django是否已安装及其版本:

$ python -m django --version

如果Django已经安装,你应该看到安装的版本号。 如果还没有安装,你会看到一个“No module named django”的错误。

本教程是针对Django 1.11和Python 3.4或更高版本编写的。 如果Django版本不符,可以通过当前页面右下角的版本转换器查看适用于你所使用的版本的Django教程,或者把Django升级到最新的版本。 如果你还在使用2.7版本的Python,你将需要按照注释中的内容稍微调整一下示例代码。

关于如何删除旧版本的Django并安装一个新的,请参见如何安装Django中的建议。

你可以在下列地址寻求帮助:

如果在学习本教程的过程中遇到问题,请向django-users发送邮件或者访问#django on irc.freenode.net与其他可能会帮助你的Django用户交流。

创建一个项目

如果这是你第一次使用Django,你需要完成一些初始化设置。 你需要自动生成一些代码,这些代码创建一个Django项目 — 一个Django实例的设置集合,包括数据库的配置、Django有关的选项和应用有关的选项。

从命令行cd到要存储代码的目录,然后运行以下命令:

$ django-admin startproject mysite

这将会在你的当前目录下生成一个 mysite 目录。 如果它不能工作,请查看运行django-admin遇到的问题

注意

你给项目命名时,项目名称不能和Python或Django的 内部组件名称同名。 尤其,你应该避免使用类似test(与Django自身冲突)或 django(与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文档中阅读关于python包的更多内容
  • mysite/settings.py:该Django 项目的设置/配置。 Django settings 将告诉你这些设置如何工作。
  • mysite/urls.py:此Django项目的URL声明;Django驱动的网站的“目录”。 你可以在URL dispatcher 中阅读到更多关于URL的内容。
  • mysite/wsgi.py:用于你的项目的与WSGI兼容的Web服务器入口。 更多细节请参见如何使用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.    (运行'python manage.py migrate'来应用它们。)

September 06, 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服务器。 我们在Django中内置了它,这样你就可以在不配置用于生产环境的服务器 —— 例如Apache —— 的情况下快速开发出产品,直到你准备好上线。

请注意:不要在任何生产环境使用这个服务器。 它仅仅是用于在开发中使用。 (我们的重点是编写Web框架,非Web服务器。)

既然服务器已经运行,请用你的浏览器访问 http://127.0.0.1:8000/ 在淡蓝色背景下,你将看到一个“Welcome to Django”的页面。 它运行成功了!

更改端口

默认情况下,runserver命令在内部IP的8000端口启动开发服务器。

如果你需改变服务器的端口,把要使用的端口作为一个命令行参数传递给它。 例如,这个命令在8080端口启动服务器:

$ python manage.py runserver 8080

如果你需改变服务器的IP地址,把IP地址和端口号放到一起。 例如,要监听所有可用的公共IP(如果你正在运行Vagrant或想要在网络上的其他计算机上炫耀你的工作),请使用:

$ python manage.py runserver 0:8000

00.0.0.0的快捷方式。 开发服务器的所有文档可以在runserver的参考手册中找到。

runserver的自动重载

开发服务器会根据需要自动重新载入Python代码。 你不必为了使更改的代码生效而重启服务器。 然而,一些行为比如添加文件,不会触发服务器的重启,所以在这种情况下你需要手动重启服务器。

创建投票应用

现在,你的开发环境 —— 一个“项目” —— 已经建立起来,你将开始在上面做一些东西。

你编写的每个Django应用都是遵循特定约定且包含一个Python包。 Django自带一个工具,它可以自动生成应用的基本目录结构,这样你就能专心于书写代码而不是创建目录。

应用和项目的区别

项目和应用之间有什么不同? 应用是一个Web应用程序,它完成具体的事项 —— 比如一个博客系统、一个存储公共档案的数据库或者一个简单的投票应用。 一个项目是特定网站的配置和应用程序的集合。 一个项目可以包含多个应用。 一个应用可以运用到多个项目中去。

你的应用可以放在Python path上的任何位置。 在本教程中,我们将在你的manage.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

我们的polls应用将基于这个目录结构。

编写你的第一个视图

我们来写第一个视图。 打开文件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的文件。 你的应用的目录应该如下所示:

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()函数允许引用其他URLconfs。 请注意,include()函数的正则表达式不具有$(字符串结束匹配符),而是尾部斜线。 每当Django遇到include()时,它将删除与此相匹配的URL部分,并将剩余的字符串发送到包含的URLconf进行进一步处理。

include()背后的想法是即插即用使网址变得容易。 由于投票应用是在自己的URLconf(polls/urls.py)中,它们可以放在“/polls/”下或“/fun_polls/”下或“/content/polls/”下,或任何其他路径根,并且应用程序仍然可以工作。

何时使用include()

当你要包含其他URL模式时,应始终使用include() admin.site.urls是唯一的例外。

与你看到的不一致?

如果你看到的是include(admin.site.urls)而不是admin.site.urls,你可能使用的是一个与本教程版本不匹配的Django版本。 你应该切换到旧版本或者新版本的Django。

你现在已将index视图连接到URLconf中。 让我们验证它的工作,运行以下命令:

$ python manage.py runserver

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

url()函数传递四个参数,两个必选参数:regexview,两个可选参数:kwargsname 在这里,值得重新审视这些参数。

url()参数:regex

术语“regex”是一种常用的缩写,意思是“正则表达式”,它是用于匹配字符串中的模式的语法,换言之,在这里是匹配url。 Django从第一个正则表达式开始,在列表中自上而下匹配,将请求的URL与每个正则表达式进行比较,直到找到匹配的一个。

请注意,这些正则表达式不搜索GET和POST参数或域名。 例如,在https://www.example.com/myapp/的请求中,URLconf将查找myapp/ https://www.example.com/myapp/?page=3的请求中,URLconf仍将查找myapp/

如果你需要正则表达式的帮助,请参阅维基百科的条目re模块的文档。 此外,由Jeffrey Friedl撰写的O'Reilly书“精通正则表达式”非常棒。 但实际上,你不需要成为正则表达式的专家,因为你只需要知道如何捕获简单的规则。 实际上,复杂的正则表达式的查找性能可能很差,所以你可能不应该依靠正则表达式的全部功能。

最后,一个性能提示:这些正则表达式是第一次加载URLconf模块时被编译。 它们超级快(只要查找不是太复杂,如上所述)。

url()参数:view

当Django发现正则表达式匹配时,Django将调用指定的视图函数,使用HttpRequest对象作为第一个参数,并将正则表达式中的任何“捕获”值作为其他参数。 如果正则表达式使用简单的捕获,则值作为位置参数传递;如果它使用命名捕获,则值作为关键字参数传递。 我们稍后会给出一个例子。

url()参数:kwargs

任意关键词参数可以在字典中传递到目标视图。 我们不会在该教程中使用Django的这个功能。

url()参数:name

命名你的URL可让你从Django其他地方明确地引用它,特别是在模板中。 这个强大的功能允许你在仅接触单个文件的情况下对项目的URL模式进行全局更改。

当你对基本请求和响应的流程感到满意时,请阅读本教程的第2部分开始与数据库一起工作。