PythonWebFramework_Django_DevelopWeb

上一篇 / 下一篇  2006-07-19 12:18:07 / 天气: 晴朗 / 心情: 高兴 / 个人分类:Python

Python Web 框架,第 1 部分:使用 Django 和 Python 开发 Web 站点

Python Django Web 框架,从安装到完成 Web 站点的设计

s#L$[6rL6G0
本系列文章一共有两篇,本文是其中的第一篇。在这一篇文章中,我们将展示 Django 的用法,Django 是 Python 编程语言驱动的一个开源模型-视图-控制器(MVC)风格的 Web 应用程序框架。使用 Django,我们在几分钟之内就可以创建高品质、易维护、数据库驱动的应用程序。
Linux宝库Q[P%H ]&^9@

Django 项目是一个定制框架,它源自一个在线新闻 Web 站点,于 2005 年以开源的形式被释放出来。Django 框架的核心组件有:

L+@3nK,Dh0
  • 用于创建模型的对象关系映射
  • 为最终用户设计的完美管理界面
  • 一流的 URL 设计
  • 设计者友好的模板语言
  • 缓存系统

qNc5s?-l3p+N0本文是有关 Python Web 框架的由两篇文章组成的系列文章的第一篇。第二篇文章将向您介绍 TurboGears 框架。Linux宝库*w5{W#A)l S"wo q

Linux宝库?y"_i:H}

要使用并理解本文中提供的代码,则需要安装 Python,并了解在初学者的水平上如何使用 Python。要查看是否安装了 Python 以及 Python 的版本号,可以输入python -V。Django 至少需要 2.3.5 版本的 Python,可以从 Python Web 站点上下载它(关于链接请参阅本文后面参考资料部分)。我们至少还应该顺便熟悉一下 MVC 架构。

cy;C:^*Z*D0Linux宝库]%L"S/UR1aFM Y/B}&Q

安装 DjangoLinux宝库y*Z,ji#['fW L

Linux宝库K7b2a f s.A `,W

本文使用了 Django 的开发版本,以便能够利用 Django 框架的最新改进。建议您在 0.95 版正式发布之前使用这个版本。关于最新发行版本,请参阅 Django 的 Web 站点(再次请您参阅参考资料来获得链接)。Linux宝库*U9tG BLJP&FW

,e},a\+A4J0按照以下步骤下载并安装 Django:

@"x] A!^ @f]W2v0Linux宝库9C'h(C3I%y+O;|

Linux宝库-KVGeoBR}
清单 1. 下载并安装 Django
rMR;~.r6~r{n0

~/downloads# svn co http://code.djangoproject.com/svn/django/trunk/ django_src
~/downloads# cd django_src
~/downloads# python setup.py install

G|Hg"A g#Y#\0
l{.]Z s0
Linux宝库L\s\K

,oNUI;O$^0
Linux宝库MH&m8J%PB

x:@y@&U0
y'^U~*?9t0

#J.r RI@7vu0

5~;rybA Y~^h0Django 管理工具Linux宝库,Zc$a poQ2@Q!c

Linux宝库GeT I7x2W c0Uj

在安装 Django 之后,您现在应该已经有了可用的管理工具 django-admin.py。清单 2 给出了这个管理工具中可以使用的一些命令:

\3Mo P'YK@4lFA0

&qe!k fbH']0
vp"[#~?V,~X0清单 2. 使用 Django 管理工具Linux宝库B'JJc%uW]

~/dev$ django-admin.py
usage: django-admin.py action [options]
actions:
  adminindex [modelmodule ...]
    Prints the admin-index template snippet for the given model
    module name(s).

  ... snip ...

  startapp [appname]
    Creates a Django app directory structure for the given app name
    in the current directory.

  startproject [projectname]
    Creates a Django project directory structure for the given
    project name in the current directory.

  validate
    Validates all installed models.

options:
  -h, --help		show this help message and exit
  --settings=SETTINGS	Python path to settings module, e.g.
			"myproject.settings.main". If this isn't
			provided, the DJANGO_SETTINGS_MODULE
			environment variable will be used.
  --pythonpath=PYTHONPATH
			Lets you manually add a directory the Python
			path, e.g. "/home/djangoprojects/myproject".

P~['Y)w!]pLr6KD0Linux宝库-^fR p/l.[p

^$d8T ^$jt0

@PH!o3{'G+n(Jt0

y9v F3t R5F6i Dwr#U0

D.X$H.OoT c0s vV0Linux宝库 _xOY3l

No7L0~3\ q0Linux宝库0Z+uB3?9D

Django 项目和应用程序Linux宝库wW0im,}&n/FEmL/h C

9] m(a1UJ0要启动 Django 项,请使用 django-adminstartproject命令,如下所示:

0B6L7f v?Lc ar0Linux宝库%`Tq!H&_)gM


tKXV&l2X5W*Cu0清单 3. 启动项目Linux宝库_7] neEB

~/dev$ django-admin.py startproject djproject
Linux宝库4Ux]0FAv

OoG:m-a0Linux宝库;x%EbI;WG6V$XC m

上面这个命令会创建一个 djproject 目录,其中包含了运行 Django 项目所需要的基本配置文件:

t`4fUv:Buk%E0Linux宝库xq`(R&K$^5[$O


U3p`kB8k0清单 4. djproject 目录的内容
H4S7MMEI0

__init__.py
manage.py
settings.py
urls.py

#JpvIb{4MQH0Linux宝库e.r`a$d"\0M

Linux宝库B1J^%`e5G#s

对于这个项目来说,我们要构建一个职位公告板应用程序 “jobs”。要创建应用程序,可以使用manage.py脚本,这是一个特定于项目的 django-admin.py 脚本,其中 settings.py 文件可以自动提供:Linux宝库 C,[+pbZ

Linux宝库Fb&`R @


:]E2Q4D|!A0L7`0清单 5. 使用 manage.py startapp
$g!K#QOm0

~/dev$ cd djproject
~/dev/djproject$ python manage.py startapp jobs
Linux宝库dZ |lz.a6L0O},I

i!x9njH_&b0Linux宝库9JQSq-[ ?6v

这将创建一个应用程序骨架,其中模型有一个 Python 模块,视图有另外一个 Python 模块。jobs 目录中包含以下文件:Linux宝库3S&[r$fB ]P^(u8m

4]A]1QW+z0Linux宝库3@h2j9L RO._
清单 6. jobs 应用程序目录中的内容
Z\fb ?9y;m0N0?$a0

__init__.py
models.py
views.py
Linux宝库(T g(e~,n
Linux宝库&no(Pt,Aw6x,|

Linux宝库:^K:F*y L`T

提供应用程序在项目中的位置纯粹是为新 Django 开发人员建立的一种惯例,并不是必需的。一旦开始在几个项目中混合使用应用程序,就可以将应用程序放到自己的命名空间中,并使用设置和主 URL 文件将它们绑定在一起。现在,请按照下面给出的步骤执行操作。

/HC k&nz0

'c LI^ U'L*n0为了使 Django 认识到新应用程序的存在,还需要向 settings.py 文件中的 INSTALLED_APPS 添加一个条目。对于这个职位公告板应用程序来说,我们必须添加字符串djproject.jobsLinux宝库? d:R!TOh;l)W j

Linux宝库;Ep5n'K\w


JejG}{E/\D5Wo0j6p0清单 7. 向 settings.py 中添加一个条目Linux宝库a,X q9j's}0Ka

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'djproject.jobs',
)

:xj"T3E;qY/l'C0Linux宝库4Cs,sw R7RM%k+u

6fMM,T6zq x7E0
Linux宝库&j5J]2f0a

zL8L[V R0

w D/_j7dg0Linux宝库&O:o.Z!El@#Y

z"y ]u8h2kk gi8c0Linux宝库!m6h ?*xl^ m:s_

创建一个模型Linux宝库IH Acp1Lr3s U)r0gK

9RZ#LStd BK0Django 提供了自己的对象关系型数据映射组件(object-relational mapper,ORM)库,它可以通过 Python 对象接口支持动态数据库访问。这个 Python 接口非常有用,功能十分强大,但如果需要,也可以灵活地不使用这个接口,而是直接使用 SQL。Linux宝库8l)CTFb'l6A n

Linux宝库 IWg&n(n&U*O*Q

ORM 目前提供了对 PostgreSQL、MySQL、SQLite 和 Microsoft® SQL 数据库的支持。Linux宝库j S_D9Cg|K$U:n

Linux宝库E Xr/s OK(lV

这个例子使用 SQLite 作为后台数据库。SQLite 是一个轻量级数据库,它不需要进行任何配置,自身能够以一个简单文件的形式存在于磁盘上。要使用 SQLite,可以简单地使用 setuptools 来安装 pysqlite(有关 setuptools 的更多资料,尤其是有关easy_install工具(需要单独安装)的资料,请参阅参考资料):Linux宝库q!Q~%c }2B

'i#VGey7_"I0easy_install pysqliteLinux宝库 i8J7zDx8B8N

'G o[5J#Z3X%GB0在使用这个模型之前,需要在设置文件中对数据库进行配置。SQLite 只需要指定数据库引擎和数据库名即可。Linux宝库G}5s$Z4r ty

J+Wu;zE.}*^ S3r0Linux宝库 v2PW3imV`/P
清单 8. 在 settings.py 中配置数据库Linux宝库#zynjB$vFOM;]D O

DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = '/path/to/dev/djproject/database.db'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''

,e6i(QQz&y0Linux宝库mmmM4guf7q5q

Linux宝库#^Yv+|(XTD/G

这个职位公告板应用程序有两种类型的对象:Location 和 Job。Location 包含 city、state(可选)和 country 字段。Job 包含 location、title、description 和 publish date 字段。Linux宝库m y S"p*TN@

Mae)t:LzgJ7P0
(onZ[)BU0清单 9. jobs/models.py 模块
~l.V)O4i O{1w5?0

from django.db import models

class Location(models.Model):
    city = models.CharField(maxlength=50)
    state = models.CharField(maxlength=50, null=True, blank=True)
    country = models.CharField(maxlength=50)

    def __str__(self):
        if self.state:
            return "%s, %s, %s" % (self.city, self.state, self.country)
        else:
            return "%s, %s" % (self.city, self.country)

class Job(models.Model):
    pub_date = models.DateField()
    job_title = models.CharField(maxlength=50)
    job_description = models.TextField()
    location = models.ForeignKey(Location)

    def __str__(self):
        return "%s (%s)" % (self.job_title, self.location)

"sK}7Bz:}'z"K0Linux宝库S v] c+k Nt

q/j*~&M?Q0__str__方法是 Python 中的一个特殊类,它返回对象的字符串表示。Django 在 Admin 工具中显示对象时广泛地使用了这个方法。

0h0~,_+z1wfX9},e0

0\IF)`Z5s0要设置这个模型的模式,请返回 manage.py 的sql命令。此时模式尚未确定。Linux宝库9W%XO(I?:|k

O(WIQ }^[0Linux宝库 }skUl"~
清单 10. 使用 manage.py sql 命令查看数据库模式
%DTc/enPKG U0

~/dev/djproject$ python manage.py sql jobs

BEGIN;
CREATE TABLE "jobs_job" (
    "id" integer NOT NULL PRIMARY KEY,
    "pub_date" date NOT NULL,
    "job_title" varchar(50) NOT NULL,
    "job_description" text NOT NULL,
    "location_id" integer NOT NULL
);
CREATE TABLE "jobs_location" (
    "id" integer NOT NULL PRIMARY KEY,
    "city" varchar(50) NOT NULL,
    "state" varchar(50) NULL,
    "country" varchar(50) NOT NULL
);
COMMIT;

/J^5L(wx(r Q0Linux宝库F UX4?.B$yk

0h;z'@-O#Fm(l0为了初始化并安装这个模型,请运行数据库命令syncdbLinux宝库n9Wa2|o%p?0q

Linux宝库H bd T8z;z N4WoN

~/dev/djproject$ python manage.py syncdb

A.e-h!KJ0Linux宝库,l)X@ee`n

注意,syncdb命令要求我们创建一个超级用户帐号。这是因为 django.contrib.auth 应用程序(提供基本的用户身份验证功能)默认情况下是在 INSTALLED_APPS 设置中提供的。超级用户名和密码用来登录将在下一节介绍的管理工具。记住,这是 Django 的超级用户,而不是系统的超级用户。Linux宝库 GQ {2am1h

Linux宝库Q/hA.S7kG~ O9L


z|'Y.N0?U ?0

Linux宝库0^1K!J$W#eo&v-H5\;aT
Linux宝库P5d}*\#`ZS0b

s7puM l9b'e0

5fj*ox'ZI0Linux宝库4UxY.A_7bXub

Z@lrj0

Z&_8D2~/Q5w9i0查询集

"MU%Mi[+sI+x#r`0Linux宝库%XcKR,V[

Django 模型通过默认的 Manager 类objects来访问数据库。例如,要打印所有 Job 的列表,则应该使用objects管理器的all方法:Linux宝库S9H*e;f#o]g

4yl.^8s1uNP T5}0
&]J%`v(rO0清单 11. 打印所有的职位
{5O\H1OV0

>>> from jobs.models import Job
>>> for job in Job.objects.all():
...     print job
Linux宝库qnOx8@9ne/Jm

r2T+hD,uZk0

c XQBM'[C!h JW d0Manager 类还有两个过滤方法:一个是filter,另外一个是exclude。过滤方法可以接受满足某个条件的所有方法,但是排除不满足这个条件的其他方法。下面的查询应该可以给出相同的结果(“gte” 表示 “大于或等于”,而 “lt” 表示 “小于”)。

BX U!}{Dq,v(W5h0Linux宝库-].hDGu&Agl

Linux宝库;?t3x0zg*t6`
清单 12. 排除和过滤职位Linux宝库!U"t6u^NX1w

>>> from jobs.models import Job
>>> from datetime import datetime
>>> q1 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1))
>>> q2 = Job.objects.exclude(pub_date__lt=datetime(2006, 1, 1))
Linux宝库"P(e cS^Q0M|
Linux宝库{ @9Xt\7v~!}+T

Linux宝库 i#L.Jx kq,l

filterexclude方法返回一些 QuerySet 对象,这些对象可以链接在一起,甚至可以执行连接操作。下面的q4查询会查找从 2006 年 1 月 1 日开始在俄亥俄州的 Cleveland 张贴的职位:Linux宝库*g!LI6F-v:G7g#K |%K

k)qp&o{e ]M5J0
`5a2B6a(q0清单 13. 对职位进行更多的排除和过滤Linux宝库G3J5V!iD

>>> from jobs.models import Job
>>> from datetime import datetime
>>> q3 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1))
>>> q4 = q3.filter(location__city__exact="Cleveland",
...                location__state__exact="Ohio")

g7uIW8u}Q+I"n n0Linux宝库I _@&dB$T$DO.W|H

Linux宝库P^2tsq^

QuerySets 是惰性的,这一点非常不错。这意味着只在对数据库进行求值之后才会对它们执行查询,这会比立即执行查询的速度更快。Linux宝库(v i q Li7`6_

yIXI+zYX I0这种惰性利用了 Python 的分片(slicing)功能。下面的代码并没有先请求所有的记录,然后对所需要的记录进行分片,而是在实际的查询中使用了 5 作为 OFFSET、10 作为 LIMIT,这可以极大地提高性能。

a+ZP'xzw0Linux宝库2{i'WJYe0V

Linux宝库GC Fy2o!~
清单 14. Python 分片Linux宝库Bc8T;m P$T}nXX

>>> from jobs.models import Job
>>> for job in Job.objects.all()[5:15]
...     print job
Linux宝库F2uk1F#h

@QwZ9[,W"F+[z B(b0Linux宝库?)r2G"f4Se2}#A6@yv W

注意:使用count方法可以确定一个 QuerySet 中有多少记录。Python 的len方法会进行全面的计算,然后统计那些以记录形式返回的行数,而count方法执行的则是真正的 SQL COUNT 操作,其速度更快。我们这样做,数据库管理员会感激我们的。Linux宝库3ll1i eW

Linux宝库2mn"G:}Q-tA;d

Linux宝库JQ!u];c
清单 15. 统计记录数
$K{$JD rP(F ajb0

>>> from jobs.models import Job
>>> print "Count = ", Job.objects.count()       # GOOD!
>>> print "Count = ", len(Job.objects.all())    # BAD!
Linux宝库D m i NZ8C

4r3h+HO,ANQ0

G2QV-LfK$H0有关的更多信息,请参阅参考资料部分给出的 Django “Database API reference” 的链接。Linux宝库c3V9e(eh

Linux宝库4[6e4oKP A#c~

Linux宝库*`P Q&BT0X

Linux宝库@U%D%X5@%MeAE
Linux宝库`f#paN
Linux宝库u!h2_v(A^

!Ac6q@oZ.t0Linux宝库\%b1dC/uM
Linux宝库H| ki.n-u0PzV/z:k(b

Linux宝库M3r6p c r-w9e

管理员工具Linux宝库0BSF l0@;hb0A/?

Linux宝库t4T8P'Z+~S

Django 的最大卖点之一是其一流的管理界面。这个工具是按照最终用户的思路设计的。它为我们的项目提供了很多数据输入工具。Linux宝库0[G3~ c8S;}

Linux宝库+Q?%CN|skx

管理工具是 Django 提供的一个应用程序。与jobs应用程序一样,在使用之前也必须进行安装。第一个步骤是将应用程序的模块(django.contrib.admin)添加到 INSTALLED_APPS 设置中:Linux宝库n'jWhv W$i

Linux宝库E(e:CA2bHPEy5M


]w,h|;R o0清单 16. 修改 settings.pyLinux宝库)Jj*N1DN A{ym

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'djproject.jobs',
    'django.contrib.admin',
)
Linux宝库tm-tTYJ
Linux宝库,L:X;g,TG!?b4z1M5S8f

Linux宝库1bW DMF

要让该管理工具可以通过 /admin URL 使用,只需要简单地取消项目的 urls.py 文件中提供的对应行的内容即可。下一节将详细介绍 URL 的配置。

N2GY]1Rw i]'T0

(eF$Jr']fw:z3H0
J3BZA U&V v0清单 17. 使管理工具可以通过 urls.py 使用
1l%t/Vg4eEx0

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^admin/', include('django.contrib.admin.urls.admin')),
)

9vX.k0E7x:^0

1o\ u*wT.vS;N;[x)q0

bu e0f Jn0这个管理应用程序有自己的数据库模型,但也需要进行安装。我们可以再次使用syncdb命令来完成这个过程:

k4P/B NK0

]tP oVK[0python manage.py syncdb

Uh x6E/qu0Linux宝库l3s2d,Z1p])Q4I.z

要查看这个管理工具,可以使用 Django 提供的测试服务器。Linux宝库']G$[{ P*ftY5B*E

?1m7WG"T4T0
;g!?%t|B C^7|4U0清单 18. 使用测试服务器来查看管理工具
2E/UAh9p"gg3n0

~/dev/djproject$ python manage.py runserver
Validating models...
0 errors found.

Django version 0.95 (post-magic-removal), using settings 'djproject.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).

ZAV;I0@.n'I0

/?JLp h"I7~,P"t1ir5g0

,^Z T,UL:m%A*`2b8C0现在可以使用 http://localhost:8000/admin 启动管理工具,并使用前面创建的超级用户帐号进行登录。我们注意到现在还没有可用的模块。Linux宝库vWl'UNM

|4j)k/xBl(],C0要让一个类可以通过管理工具进行访问,我们需要为其创建一个 Admin 子类。然后可以通过为这个子类添加类属性来定制如何对每个类进行管理。清单 19 展示了如何将 Location 类添加到这个管理工具中。

:qg B&A PA0

L,fp8YWA9@X2l0Linux宝库,g`qa(H x t0O
清单 19. 使用管理工具添加 Location 类Linux宝库Je.b'Al9A.[v[

class Location(meta.Model):
    ...
    class Admin:
        list_display = ("city", "state", "country")

3r{koS0Linux宝库7Z^Ay1q-G

6g4HIE2j H3[PM U0现在就可以通过管理界面来创建、更新和删除 Location 记录了。Linux宝库(BC%E'_!z _K

+~1^!_.q`6h;eT p0Linux宝库|+BU*k{*Q,B
图 1. 使用管理工具编辑位置Linux宝库/][ N^bb
使用管理工具编辑位置
b8@*S ~8G%SN1u0

Q(J5dt!DW2Q3{0Linux宝库2oFw(Y inZ-_8|d

可以按照list_display类的属性指定的城市、州和国家来列出记录并对它们进行排序。Linux宝库3s9D/`vY~n

Linux宝库:LO];pW5m8h/h

Linux宝库Bw*o.jr.X3Xg
图 2. 使用管理工具显示位置
x,{.qxIc8?0使用管理工具显示位置Linux宝库0s/M2B~%r:FT3J
Linux宝库&E(X9p8N5qv

Linux宝库-WTUG!`n"T

管理工具有无数用来管理每种模块类的选项。清单 20 给出了几个适用于 Job 类的例子:Linux宝库2jPgG e+].\'}u.o)n

Linux宝库8t[*\W/e@

Linux宝库u,XE{W:F1F6} n5T
清单 20. 管理模块类的选项
4e JVBmS0

class Job(meta.Model):
    ...
    class Admin:
	list_display = ("job_title", "location", "pub_date")
	ordering = ["-pub_date"]
	search_fields = ("job_title", "job_description")
	list_filter = ("location",)
Linux宝库0UvHmh#k/{ l'M}
Linux宝库 I,O3?[6OrV#S

Linux宝库\|^2K\Vn2P4\:Dp

根据以上设置,职位的标题、位置和发布日期都会在显示职位记录时用到。职位可以按照发布时间进行排序,最开始是最近发布的职位(减号表示降序)。用户可以按照标题和说明来查找职位,管理员可以根据位置对记录进行过滤。Linux宝库#h w1ekZ0J

0a*g%L5F'SR0Linux宝库+A.\"W RS.fb'?K
图 3. 使用管理工具显示职位
M3_vn B(g3h0使用管理工具显示职位
ZS7| a zh6nj)@w c0
beh f4o'oxT0

Linux宝库Qi9uH4X5B5P5I4V~

_k!B6f-h0
Linux宝库'U [7[O}/L)j7?

j4jX+DG Y0Linux宝库K8TI8bm6l'RP

U%E+v.F&D/i.fm @0

LCAS!T^L0设计 URL 方案Linux宝库?q%K:Sp%ec"sjn#xE

Linux宝库V;kG4i3kBH2T&jh

Django URL 分发系统使用了正则表达式配置模块,它可以将 URL 字符串模式映射为 Python 方法views。这个系统允许 URL 与底层代码完全脱节,从而实现最大的控制和灵活性。Linux宝库J"hg4P-N[AiO IA

!e9A4|5r3^"C0urls.py 模块被创建和定义成 URL 配置的默认起点(通过 settings.py 模块中的 ROOT_URLCONF 值)。URL 配置文件的惟一要求是必须包含一个定义模式urlpatterns的对象。Linux宝库Jf%AC,\_)K

Linux宝库D zqh6@u2F)Y

这个职位公告板应用程序会在启动时打开一个索引和一个详细视图,它们可以通过以下的 URL 映射进行访问:

7f#G4d k"^!J0
  • /jobs索引视图:显示最近的 10 个职位
  • /jobs/1详细视图:显示 ID 为 1 的职位信息

0v(Bm&k w6GlO|0@0这两个视图(索引视图和详细视图)都是在这个 jobs 应用程序的 views.py 模块中实现的。在项目的 urls.py 文件中实现这种配置看起来如下所示:Linux宝库D7G(ZVD

Linux宝库i!l)Ji/}pE Qd


+P@"xP.[vu~1{_0清单 21. 在 djproject/urls.py 中实现视图的配置Linux宝库V ir&`;WrA

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^admin/', include('django.contrib.admin.urls.admin')),

    (r'^jobs/$', 'djproject.jobs.views.index'),
    (r'^jobs/(?P<job_id>\d+)/$', 'djproject.jobs.views.detail'),
)
Linux宝库 cQ}0G[ M {B4q5mc
Linux宝库l$gwMa&oS

Linux宝库7~e#yyA#H;F

注意<job_id>部分,这在后面非常重要。Linux宝库C:f(}$]TL

Linux宝库[T~LD?

最佳实践是提取出应用程序特有的 URL 模式,并将它们放入应用程序自身中。这样可以取消应用程序与项目的耦合限制,从而更好地实现重用。jobs 使用的应用程序级的 URL 配置文件如下所示:Linux宝库`#}9Gm"T4oqZn

Linux宝库P:T5K*s@(l%~!Y

Linux宝库9n!A v5BB T$}.~
清单 22. 应用程序级的 URL 配置文件 urls.pyLinux宝库@+ET9pf'f

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^$', 'djproject.jobs.views.index'),
    (r'^(?P<job_id>\d+)/$', 'djproject.jobs.views.detail'),
)

2FLzt(v{RI+Q {0Linux宝库1DDl&Aa+_/I

d#P-d9LL0由于 view 方法现在都是来自同一个模块,因此第一个参数可以使用这个模块的根名称来指定 djproject.jobs.views,Django 会使用它来查找index方法和detail方法:

;L&Gm6Kf~Iv0Linux宝库7el6X$a1}y&R.O

Linux宝库/z6_[:| wf
清单 23. jobs/urls.py:查找 index 和 detail 方法
~H4B7[YUze0

from django.conf.urls.defaults import *

urlpatterns = patterns('djproject.jobs.views',
    (r'^$', 'index'),
    (r'^(?P<object_id>\d+)/$', 'detail'),
)
Linux宝库LpW*I1^ U?#f

0j!H-S9JF5X*w a0Linux宝库%M5LDC\#bE_

尝试上面的 jobs URL 会返回到这个项目中,因为它们是使用include函数将其作为一个整体来实现的。应用程序级的 URL 被绑定到下面的/jobs部分:

_XY:v.K.h[G0Linux宝库E4sg(B{;| dn!J


z @"IJA9dhV&a8M0清单 24. djproject/urls.py:将 URL 送回该项目
.VMQ4~(L-_ SX-S0

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^admin/', include('django.contrib.admin.urls.admin')),
    (r'^jobs/', include('djproject.jobs.urls')),
)
Linux宝库X'~n;U X6} H

/hfaO Yw*^0

o"?E-WdO0如果现在尝试使用测试服务器来访问索引页(http://localhost:8000/jobs),会得到一个错误,因为正在调用的视图(djproject.jobs.views.index)不存在。Linux宝库^(U,gB x-]$x

Linux宝库)b3Er| b,fJ?

Linux宝库4M6F0F.s+{b#mk'v


\'_Z;sZ)w P0

8qdv"O+aog0

.B1@E%b/T5l}H X0
Linux宝库(R,[ v7Yj&R6e+\.Q

.Q.A6[Z9w/V/d0Linux宝库I/Q.l-v5]

9S&Ji"d2I6s }$V)?0实现视图

Cl'Q&il(v;u&n0Linux宝库Z UG7Vo_M

视图是一个简单的 Python 方法,它接受一个请求对象,负责实现:

c'H/JQ't"z0
  • 任何业务逻辑(直接或间接)
  • 上下文字典,它包含模板数据
  • 使用一个上下文来表示模板
  • 响应对象,它将所表示的结果返回到这个框架中

/Bt.|6R Q?)v0在 Django 中,当一个 URL 被请求时,所调用的 Python 方法称为一个视图(view),这个视图所加载并呈现的页面称为模板(template)。由于这个原因,Django 小组将 Django 称为一个 MVT(model-view-template)框架。另一方面,TurboGears 把自己的方法称作控制器(controller),将所呈现的模板称为视图(view),因此缩写也是 MVC。其区别在于广义的语义,因为它们所实现的内容是相同的。Linux宝库Y g a6S(bL4M

Linux宝库.P!eV?:M d`u7k W

最简单的视图可能会返回一个使用字符串初始化过的 HttpResponse 对象。创建下面的方法,并生成一个/jobsHTTP 请求,以确保 urls.py 和 views.py 文件都已经正确设置。Linux宝库enb/HfawG

sb:X y9kVN~0
@&gd{ f0清单 25. jobs/views.py (v1)
+J^$b ` N^"b-\0

from django.utils.httpwrappers import HttpResponse

def index(request):
    return HttpResponse("Job Index View")

0j2_L`UA6E4]0Linux宝库*A[6[Lc3v

Linux宝库@ O0gdwH#N0fcJ$O

下面的代码将获取最近的 10 个职位,并通过一个模板呈现出来,然后返回响应。没有下一节中的模板文件,这段代码就无法正常工作。Linux宝库'c8mcuP{m

.{8egt#w*l4k0
#SP!W5W`(i T0清单 26. jobs/views.py (v2)Linux宝库(u D.x^a!elj

from django.template import Context, loader
from django.http import HttpResponse
from jobs.models import Job

from django.template import Context, loader
from django.http import HttpResponse
from jobs.models import Job

def index(request):
    object_list = Job.objects.order_by('-pub_date')[:10]
    t = loader.get_template('jobs/job_list.html')
    c = Context({
        'object_list': object_list,
    })
    return HttpResponse(t.render(c))
Linux宝库0c5Plx,FXO

*`5VaG%zy|*}.R#j P0Linux宝库&`&U'w\ ASe#Z

在上面的代码中,模板是由jobs/job_list.html字符串进行命名的。该模板是使用名为object_list的职位列表的上下文呈现的。所呈现的模板字符串随后被传递到 HTTPResponse 构造器中,后者通过这个框架被发送回请求客户机那里。Linux宝库9B6w#O1h:N)A5C v

;t C7Q6|qorE/D0加载模板、创建内容以及返回新响应对象的步骤在下面都被render_to_response方法取代了。新增内容是详细视图方法使用了一个get_object_or_404方法,通过该方法使用所提供的参数获取一个 Job 对象。如果没有找到这个对象,就会触发 404 异常。这两个方法减少了很多 Web 应用程序中的样板代码。Linux宝库 Jx;Q @x R PV.Q&c

Linux宝库+`-{Jd E%_|6b8vVj


\6ExX `|;c0清单 27. jobs/views.py (v3)
!_6\cyPW)E0

from django.shortcuts import get_object_or_404, render_to_response
from jobs.models import Job

def index(request):
    object_list = Job.objects.order_by('-pub_date')[:10]
    return render_to_response('jobs/job_list.html',
                              {'object_list': object_list})

def detail(request, object_id):
    job = get_object_or_404(Job, pk=object_id)
    return render_to_response('jobs/job_detail.html',
                              {'object': job})
Linux宝库3V\di"i1bP3l

Z7t E f-m)U:X~0

2^w'G*r*L`D1U0注意,detail使用object_id作为一个参数。这是前面提到过的 jobs urls.py 文件中/jobs/URL 路径后面的数字。它以后会作为主键(pk)传递给get_object_or_404方法。Linux宝库'H J:I[)p3L0GGY

Linux宝库c%~1HAqu/g;h v)j

上面的视图仍然会失败,因为它们所加载和呈现的模板(jobs/job_list.html and jobs/job_detail.html)不存在。Linux宝库j*fG o8AC

Linux宝库R+TrM z


CNL6@9kIyS0

Linux宝库A'Y bc Q"l:| tAQ'~c
Linux宝库X&N#f,[Q~^
Linux宝库h&z$iQ _M
Linux宝库K }_-k&zUz^
Linux宝库-k!c*?5iJet
Linux宝库*wo(}R3N8n

7|mgc7dGU0创建模板

B[/k)Z9KH!{h1uh0Linux宝库KU/x%~aE

Django 提供了一种模板语言,该语言被设计为能够快速呈现且易于使用。Django 模板是利用{{ variables }}{% tags %}中嵌入的文本创建的。变量会使用它们表示的值进行计算和替换。标记用来实现基本的控制逻辑。模板可以用来生成任何基于文本的格式,包括 HTML、XML、CSV 和纯文本。Linux宝库b/Y;LWN8gO

@!i'Vyl \aw]Q*|0第一个步骤是定义将模板加载到什么地方。为了简便起见,我们需要在 djproject 下面创建一个 templates 目录,并将这个路径添加到 settings.py 的 TEMPLATE_DIRS 条目中:Linux宝库)| ^I I8?Cn d

0[| Z.iux!\0
| l/L-];g KQ?0清单 28. 在 settings.py 中创建一个 templates 目录Linux宝库}#~c/^*YM5a9TZ b

TEMPLATE_DIRS = (
    '/path/to/devdir/djproject/templates/',
)

y^Zp&h@4V%~&E0

K0_r5_k,Sh ~0

Z/r`H-Wl$p0Django 模板支持称为模板继承(template inheritance)的概念,它允许站点设计人员创建一个统一的外表,而不用替换每个模板的内容。我们可以通过使用块标记定义骨干文档或基础文档来使用继承。这些块标记都是使用一些包含内容的页面模板来填充的。这个例子给出了一个包含称为titleextraheadcontent的块的 HTML 骨干:

9R~pP_#_)ea0Linux宝库V*yOuF


+R,a+M9p$LkW%O0清单 29. 骨干文档 templates/base.htmlLinux宝库i~4jjc

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Company Site: {% block title %}Page{% endblock %}</title>
    {% block extrahead %}{% endblock %}
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>
Linux宝库$PVA1E!`QTE3C

~{,PjuI[h6b0

;_0q*zG{0为了取消应用程序与项目之间的耦合,我们使用了一个中间基本文件作为 Job 应用程序所有页面文件的基础。对于这个例子来说,为了简便起见,我们将应用程序的 CSS 放到这个基本文件中。在实际的应用程序中,需要有一个正确配置的 Web 服务器,将这个 CSS 提取出来,并将其放到 Web 服务器所服务的静态文件中。Linux宝库'U}4^k0Fo7g0T

Linux宝库+?j-\ |dK

Linux宝库8A3~"\#q'gD1c
清单 30. 中间基础文件 templates/jobs/base.htmlLinux宝库SP_Rk&O{

{% extends "base.html" %}

{% block extrahead %}
    <style>
        body {
            font-style: arial;
        }
        h1 {
            text-align: center;
        }
        .job .title {
            font-size: 120%;
            font-weight: bold;
        }
        .job .posted {
            font-style: italic;
        }
    </style>
{% endblock %}
Linux宝库2e};PvTD3e
Linux宝库_XH |mL3o

Linux宝库mr1OxOEC y_U

默认情况下,Django 测试服务器并不会为静态文件提供服务,因为这是 Web 服务器的工作。但是在开发过程中,如果您希望 Django 可以提供图像、样式表等,那么请参阅参考资料中有关如何激活这个特性的链接。

k?^.pn6|qG5Fo0

)zM LlP,o1MJ0现在我们要创建视图所加载并呈现的两个页面模板。jobs/job_list.html模板简单地循环遍历object_list,它通过索引视图遍历其内容,并显示一个到每条记录的详细页面的链接。Linux宝库6O?6iw6p

Linux宝库+XB/~Q+y


]-eS:yLJ ]yS0清单 31. templates/jobs/job_list.html 模板
&Y{]%P!Ip'U0

{% extends "jobs/base.html" %}

{% block title %}Job List{% endblock %}

{% block content %}
    <h1>Job List</h1>
    <ul>
    {% for job in object_list %}
        <li><a href="{{ job.id }}">{{ job.job_title }}</a></li>
    {% endfor %}
    </ul>
{% endblock %}
Linux宝库a@ q9H!G0]v)A0h
Linux宝库3x(jO} Q4a)r2d7K%nY

Linux宝库v0M#J;y.T~|^$\

jobs/job_detail.html页面会显示一条称为job的记录:Linux宝库2i#F{ar"E#F@0W?

Linux宝库*\)W xv!l _

Linux宝库0J5sv0E6J O1f
清单 32. templates/jobs/job_detail.html 页面Linux宝库 e.g fLF7O

{% extends "jobs/base" %}

{% block title %}Job Detail{% endblock %}

{% block content %}
    <h1>Job Detail</h1>

    <div class="job">
        <div class="title">
            {{ job.job_title }}
            -
            {{ job.location }}
        </div>
        <div class="posted">
            Posted: {{ job.pub_date|date:"d-M-Y" }}
        </div>
        <div class="description">
            {{ job.job_description }}
        </div>
    </div>
{% endblock %}
Linux宝库]%K1P:Uv {U%cyt-rt
Linux宝库 _*^!@j+c;m

2c0c0mM2Ph*~;ol0Django 模板语言已经被设计为只能实现有限的功能。这种限制可以为非程序员保持模板的简单性,同时还可以让程序员不会将业务逻辑放到不属于自己的地方,即表示层。请参阅参考资料中模板语言文档的链接。

6Y#uA5e2g-aK0

Ys]p9~lRtf0
.k1\:e3@`zy"D0


/K4q&wPl;ez6{*U@0
Linux宝库'U,e){,g T-C
Linux宝库x f _6x%?4E;X
Linux宝库8f&M;_7r.} P;D_j

%C2GpD1K!t0Linux宝库\J3l;P)L

(T&e,A:K?"^9O*OX0通用视图Linux宝库*H'rd&QA)e9k

Linux宝库&Ea"Z p0M N/OB4aB

Django 提供了 4 种通用视图(generic view),它们可以让开发人员创建遵循典型模式的应用程序:Linux宝库1C/|BH5s0X/k2G

  • 页面列表/详细页面(与上面的例子类似)
  • 基于数据的记录分类(对于新闻或 blog 站点非常有用)
  • 对象的创建、更新和删除(CRUD)
  • 简单直接的模板表示或简单地对 HTTP 重新进行定向
Linux宝库-sV N)lY]*~i|

我们没有创建样板视图方法,而是将所有的业务逻辑都放入了 urls.py 文件中,它们都由 Django 提供的通用视图进行处理。Linux宝库'UZF,U7c1Oo.@KgJ1N

Linux宝库V z h.`^h]u1Zm*v

Linux宝库d{kk}Xy
清单 33. jobs/urls.py 中的通用视图
4l%~ Nq4L`0

from django.conf.urls.defaults import *
from jobs.models import Job

info_dict = {
    'queryset': Job.objects.all(),
}

urlpatterns = patterns('django.views.generic.list_detail',
    (r'^$', 'object_list', info_dict),
    (r'^(?P<object_id>\d+)/$', 'object_detail', info_dict),
)
Linux宝库vAQ7z:X_ I6o{
Linux宝库$VN+h V S2_

Linux宝库-y t I&AK

这个 urls.py 文件中的 3 个主要变化如下:Linux宝库| lK&vl_4\8J gb

  • info_dict映射对象会为要访问的 Job 提供一个查询集。
  • 它使用了django.views.generic.list_detail,而不是djproject.jobs.views
  • 真正的视图调用是object_listobject_detail
Linux宝库LJ%}8ZsS8J

这个项目需要遵循一些要求才能让通用视图自动工作:

4t4|U'xj$W0_0
  • 通用详细视图期望获得一个object_id参数。
  • 模板遵循下面的命名模式:app_label/model_name_list.html (jobs/job_list.html)app_label/model_name_detail.html (jobs/job_detail.html)
  • 列表模板处理一个名为object_list的列表。
  • 详细模板处理一个名为object的对象。

C;U3G)t(gK^!l-w0更多选项可以通过info_dict来传递,其中包括指定每个页面中对象个数的paginate_by值。Linux宝库 c!}!a/z%L$g7\

Ip;y;Z!G0Linux宝库U:x_/s S5g'|!~

Linux宝库7l hIA!T g*N k
Linux宝库OqLD/}g;n
Linux宝库7Qg*]Bg cT8|*}+_

b*j N-}kN Ci(sq0Linux宝库+zR*t-^i-g@Q

?2_:hzM0

d^N }9v4P0结束语

E7p"n*xj*k0

~&E-hWXK ?/_)z2kodW0本系列的下一篇文章将介绍 TurboGears,这是另外一个 Python Web 框架;并且会将该框架与 Django 进行比较。Linux宝库/K,F9@u3lgX@.R%{,D c


TAG: 电脑网络 Python

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-09-06  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 17185
  • 日志数: 30
  • 建立时间: 2006-07-08
  • 更新时间: 2006-08-30

RSS订阅

Open Toolbar