第一个Django应用
准备
检查django版本
python -m django --version案例使用: Python 3.4 / Django 1.11.2
创建项目
django-admin startproject mysite这个步骤将在当前目录下创建mysite目录。注意不要采用python或django内建的组件的名字,例如django或test之类保留字。
在Django中,不需要像PHP那样把代码保存在web服务器的document根目录(例如/var/www),对于Django这不是一个好习惯,存在被别人查看web上代码的风险。要将代码存放在存放在document根目录之外,例如/home/mycode。
以下是startproject命令创建的mysite目录内容
mysite
├── manage.py* 命令行交互工具
└── mysite/
├── __init__.py 空文件,告知python这个目录是一个Python包
├── settings.py 设置文件
├── urls.py url声明,也就是django网站的内容列表
└── wsgi.py WSGI兼容的web服务创建项目
验证Django项目工作,进入mysite目录,然后执行
此时看到输出
注意:默认开发环境django运行监听在127.0.0.1:8000,所以外部不能直接访问。
可以通过django参数来指定端口以及监听的IP地址
例如,监听端口改成8080
监听所有网络接口的8000端口
注意:在CentOS 7上默认开启了firewall防火墙,要能够让外部访问,需要执行如下命令
此时在浏览器上访问 http://SERVER_IP:8000 可以看到Django页面,但是,如果是从外部访问,django有一个安全限制,会在页面提示所访问的http头部中包含的主机IP地址不在允许范围(默认只允许127.0.0.1回环地址访问):
参考 Invalid http_host header ,修改 setting.py 配置文件,设置
如果是放宽所有服务器可以设置
ALLOWED_HOSTS = ['*']
创建polls应用
以上是创建了mysite项目,接下来需要在项目中创建应用:每个应用就是按照一系列约定编写的python包。Django有一个工具可以自动生成app的基本目录结构,这样就可以聚焦在编写代码而不是创建目录。
projects vs. apps
app是一个web应用可以完成一定工作,例如weblog,数据库记录,投票系统等。project则是一组配置和apps用于构建website。一个project可以包含多个apps,而一个app可以属于多个projects。
创建app
此时在项目目录下创建按了polls子目录
修改第一个视图
polls/views.py
注意:必须
from django.http import HttpResponse之后才能使用return HttpResponse("...")
创建
polls/urls.py
然后在根上指出root URL在
polls.urls模块,所以在mysite/urls.py添加
注意:这里
mysite/urls.py是在项目目录下默认就建立的一个子目录,也就是默认就有一个app代表网站自身。其中已经有了一个urls.py文件,默认就包含了url(r'^admin/', admin.site.urls),
必须先
from django.conf.urls import include才能使用include('polls.urls'),这样就可以把部分url引用放到各自目录下。
url()功能可以传递4个参数,有两个参数regex和view是必须的,另外两个kwargs和name是可选的。
url()参数:regex
regex是"规则表达式"(regular expression)的缩写。注意,这些规则表达式不会搜索GET和POST参数,或者域名。例如,请求 https://www.example.com/myapp/ ,则URLconf将看到myapp/,并且请求 https://www.example.com/myapp/?page=3 ,此时URL依然只看到 myapp/。
规则表达式应该在首次URLconf模块加载时编译以确保性能。
url()参数:view
当Django找寻匹配的正则表达式,就会请求特定视图功能,使用一个HttpRequest对象作为第一个参数,并且任何在正则表达式"捕捉到"的值就作为参数。如果regex使用简单捕捉,值就作为位置参数。如果使用命名的捕捉,值就作为一个关键值参数传递。
url()参数:kwargs
抽象关键词参数将作为一个字典传递给目标视图。
url()参数:name
命名你所使用的URL就可以作为一个明确的引用在Django任何位置使用,特别是在模板中。这个强大的功能使得你可以创建全局变更到URL参数给项目,只需要访问一个单一文件。
数据库设置
编辑
mysite/settings.py,这是一个使用模块层变量表达Django设置的Python模块。默认使用SQLite,如果是生产环境,则可以使用更具扩展性的数据库,如PostgreSQL。
如果使用其他数据库,需要安装相应的database bindings并修改配置文件
修改mysite/settings.py,其中DATABASES配置中的ENGINE设置成相应的数据库类型,如'django.db.backends.postgresql', 'django.db.backends.mysql'
如果不使用SQLite,需要配置增加USER,PASSWORD和HOST参数。
settings.py中其他设置
settings.py中其他设置时区 -
TIME_ZONE激活的Django apps -
INSTALLED_APPS
这些应用默认包含了一个共用案例的便利转换。一些应用使用至少一个数据库表,所以需要在使用它们之前先创建数据库表。这个工作通过以下命令完成:
这个migrate命令会检查INSTALLED_APPS设置并根据misite/settings.py创建任何需要的数据库表以及和应用程序一起发布的数据库迁移。可以通过数据库管理来查看上述命令创建的表格。
创建模式
现在需要定义模式 - 也就是使用附加的元数据来定义数据库结构。
这个简单的投票程序,创建2个models:Question和Choice: Question是一个问题并且有一个发布时间;Choice则有两个字段:选择文本和一个投票记录。每个Choice和一个Question关联。
这些概念是通过简单的Python classes。编辑pools/models.py
每个model都是通过django.db.models.Model的子类来表述class。每个模块有一系列类变量,也就是在模式中表示数据库字段。
每个字段都通过一个Field类的实例来表述 - 例如,CharField是字符字段,而DateTimeField是日期字段。这样就可以告知Django每个数据字段的类型。
每个字段实例的名字(例如question_text或pub_date)是字段的名字,使用机器友好的格式。在Python代码中可以使用这些值,并且数据库将它们作为列名字。
一些字段有附加参数,例如CharField需要设置max_length。这个参数限制只作用于数据库schema。
注意,上述定义使用了ForeignKey告知Django每个Choice是和一个Question关联的。Django支持所有常用数据库关系:many-to-one, many-to-many, one-to-one。
激活模式
模式的少量代码可以赋予Django大量的西溪,这样Django可以:
为应用程序创建一个数据库schema(
CREATE TABLE声明)创建一个Python数据库访问API来访问
Question和Choice对象
目前需要首先告诉项目,polls应用已安装好。
Django apps 是
热插拔(pluggable),可以将一个app用于多个项目,然后可以分发apps,因为app在Django安装是并没有附加。
要将应用添加到项目,需要在INSTALLED_APPS设置中加上一个引用配置类。这里的polls/apps.py文件中有一个PollsConfig类,所以其点路径是polls.apps.PollsConfig。编辑mysite/settings.py文件添加点路径到INSTALLED_APPS设置中。
mysite/settings.py
此时Django就知道包含polls这个app,执行以下命令
就会看到如下输出信息:
这里使用makemigrations是告知Django作出了模式修改,并希望作为一个migration来将更改存储。
migration是Django存储修改到模式中(然后是数据库schema)- 也就是磁盘中的文件。要查看刚才创建polls的新模型可以查看polls/migrations/0001_initial.py。
运行migration来管理数据库schema的操作,通过sqlmigrate来获取migration名字和返回SQL:
此时可以看到以下输出
这里sqlmigrate命令并没有实际migrate数据库,而只是打印输出到屏幕,这样可以查看SQL Django会执行的操作,对于检查Django将要做的操作非常有用,特别是作为数据库管理员还可以修改SQL脚本。
如果感兴趣,还可以运行 python manage.py check 来检查项目的问题,而不会实际做修改。
现在可以运行migrate来创建数据库的模式表格:
简单来说,实现模式修改需要3个步骤:
修改模式(在
models.py中修改)运行
python manage.py makemigrations来创建这些修改的migrations运行
python manage.py migrate将这些修改作用到数据库
有关详细的manage.py工具使用信息参考django-admin documentation
使用API
可以通过交互的Python shell来使用Django API:
这里使用manage.py而不是直接python是因为可以设置DJANGO_SETTINGS_MODULE环境变量,这是通过mysite/settings.py文件中导入的路径
如果不是使用
manage.py则需要使用以下命令来设置:
一旦进入shell,可以使用database API
这里会发现<Question: Question object>是完全无用对象,通过修改Question模型(polls/models.py)来添加__str__()方法:
这里重要的是添加__str__()方法到模型中,不仅是处理交互,也是因为对象的代表在整个Django自动化生成的管理中使用。
注意,这个是常规的Python方法,现在加上自定义方法polls/models.py:
这里import datetime和from django.utils import timezone是引用Python标准datetime模块和Django的time-zone相关工具django.utils.timezone。
保存好上述修改,然后重新启动一个python manage.py shell:
Django Admin
创建admin用户
完成后,即可通过 http://127.0.0.1:8000/admin/ 访问管理登录界面
现在需要告诉admin有关Question对象才能具有admin界面,所以编辑
polls/admin.py文件:
此时注册了Question,Django就知道如何显示在管理索引页面。
点击"Question",就位于Question的"修改列表",该页面也就是数据库的显示所有question的页面,可以允许修改。
如果"Date published"显示的时间不是你实际创建时间,则表明前面设置
TIME_ZONE设置错误。
视图
在Django中,web页面和其他内容都是通过视图view来传递的,每个视图都是通过一个简单的Python功能(或方法,例如在基于类的视图中)来表述。Django将通过检查请求的URL来选择视图。
编写更多视图
在polls/views.py中增加更多的视图:
对应于新的视图,需要在url()调用中添加polls.urls,所以在polls/urls.py
从浏览器中查看诸如/polls/34/,则将运行detail()方法并吸纳是URL中指定的ID,而/polls/34/results/和/polls/34/vote/也是如此显示相应的results和vote页面。
当请求web网站/polls/34/,Django将加载mysite.urls方法,因为在mysite子目录下的settings.py中设置了ROOT_URLCONF = 'mysite.urls'。Django找到模拟改为urlpatterns变量(在urls.py文件中),然后依次转换正则表达式。
当找到^polls/匹配,它就会剥离出匹配的文本polls/并发送剩下的文本34/给polls.urls的URLconf进行进一步处理,见 mysite/urls.py 中代码:
然后就会匹配polls/urls.py文件中的r'^(?P<question_id>[0-9]+)/$',这样就会调用detial()视图,类似:
这里的question_id='34'是从(?P<question_id>[0-9]+)得到的。使用围绕一个样式(pattern)的圆括号(parentheses)可以"捕获"(captures)通过样式匹配的文本,然后发送文本作为视图功能的参数。?P<question_id>定义了用于标识匹配的样式来定义名字;而[0-9]+则是匹配一系列数字的正则表达式。
由于URLyangshi是正则表达式,所以它没有任何限制。通常不需要加上诸如.html的URL,除非你想要这样也行,如:
不过,不要这样做,这很笨拙。
编写视图实际完成工作
每个视图负责做两件事情之一:返回一个HttpResponse对象包含请求页面的内容,或者抛出一个异常,诸如Http404。其余随你所愿。
视图可以从数据库中读取记录;视图可以使用一个模板系统,例如Django的模板,或者使用第三方Python模板系统。视图可以生成一个PDF文件,输出XML,动态创建一个ZIP文件,甚至任何使用Python库可以完成的事情。
所有Django期望的是HttpResponse或一个异常。
由于使用方便,可以使用Django自己的数据库API。这里使用了一个新的index()视图,显示最新的5个poll问题,通过逗号分隔,按照发布时间。polls/views.py
这里主要的问题是:页面设计是硬编码到视图的。如果需要修改页面样式,需要修改Python代码。所以使用Django模板系统来分离Python中的设计来创建视图。
首先在polls目录下创建目录templates,因为Django会在这个目录下查找模板。
项目的TEMPLATES设置描述了Django如何加载和渲染末按。默认设置文件配置了一个DjangoTemplates后端,其APP_DIRS选项设置为True。按照惯例,DjangoTemplates在每个INSTALLED_APPS的templates子目录查找。
在pools/子目录下创建templates目录,然后再在这个目录下创建polls,并在其中存放一个index.html。也就是,模板文件是polls/templates/polls/index.html。因为app_directories模板加载器将会按照上述路径工作,所以引用这个模板只需要使用polls/index.html。
然后更新polls/views.py中的index视图引用上述模板:
上述代码加载称为polls/index.html的模板,然后传递它一个上下文,这个上下文就是映射模板变量名到Pyton对象的目录映射。
现在浏览器加载访问/polls/就会看到类表展示,并且有问题的详细页面信息的超链接。
render()快捷方式
一个非常常用的风格是从一个template模板加载,填写一个context上下文,然后返回一个HttpResponse对象作为渲染模板的结果。Django提供一个快捷方式,一下是完整的 index() 视图:
polls/views.py:
render()功能捕获请求对象作为第一个参数,模板名称作为第2个参数,即一个目录作为可选的第3个参数。返回一个使用给定context上下文渲染的模板作为HttpResponse对象。
404错误页面
polls/view.py
这里提供了一个 Http404异常,如果请求的ID不存在对应问题的话。
polls/templates/polls/detail.html:
一个常用的方式是使用 get() 和在对象不存在时返回 Http404
以下是 detail() 视图的重写:
polls/views.py
这里get_object_or_404()功能使用一个Django模块作为第一个参数并且一个关键词参数作为随意数字,传递给get()模式管理的功能。如果对象不存在则返回Http404
这里去掉了前面的ObjectDoesNotExist异常处理,代之以get_object_or_404()实现了Django的一种维护丢失关系的处理快速模式的设计目标。(理解为约定俗成规则?)
这里的get_list_or_404()功能只使用了get_object_or_404(),异常使用filter()代替了get(),则在list是空的时候返回Http404。
使用模板系统
返回到detail()视图,给出上下文变量的question,这里有一个polls/detail.html模板类似,
polls/templates/polls/detail.html:
这里模板系统使用dot-lookup语法来访问变量属性。在这个阿尼中 {{ question.question_text }},首先Django对对象question使用一个字典查询。失败,就尝试一个属性查询,对这个案例就是成功的。如果属性查询失败,它将尝试列表索引(list-index)查询。
模式调用发生在 `
循环:question.choice_set.all是作为question.choice_set.all()的Python代码解释的,它将返回一个Choice对象并符合
`标签的使用。
详细模板使用见 template guide
参考
Last updated
Was this helpful?