You are on page 1of 268

2010-5-5

The Django Book

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book


Table of contents
2.0, English -> Chinese
Django book 2.0
-

Django 100.00%
100.00%
URL 100.00%
100.00%
100.00%
Admin 100.00%
100.00%
URL 100.00%
99.74%
100.00%
100.00%
Django 100.00%
HTML 100.00%
86.16%
100.00%
django.contrib 99.72%
95.08%
100.00%
100.00%
100.00%
VCCDjango
http://djangobook.py3k.cn/2.0/

1/2

2010-5-5

The Django Book

Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.


This work is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

http://djangobook.py3k.cn/2.0/

2/2

2010-5-5

Django

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book


4
3

| | |

Django
DjangoWebWeb Django
Web

Web
Django Web Django
Web
Django framework

Django Django
Web

?
1

Django Web
Python

web
PythonWebCGI1998
PythonHTML.cgi

Python CGI10

#!/usr/bin/env python
import MySQLdb
print "ContentType: text/html\n"
print "<html><head><title>Books</title></head>"
print "<body>"
print "<h1>Books</h1>"
print "<ul>"
connection = MySQLdb.connect(user='me', passwd='letmein', db='my_db')
cursor = connection.cursor()
cursor.execute("SELECT name FROM books ORDER BY pub_date DESC LIMIT 10")
for row in cursor.fetchall():
print "<li>%s</li>" % row[0]
print "</ul>"
print "</body></html>"

djangobook.py3k.cn/2.0/chapter01/

1/6

2010-5-5

Django

connection.close()

CGIContent-Type HTML
HTML
HTML

16Python
16
latestbooks.cgi
1


CGI

Content-Type

WebPython

Web
Web Web
Django

MVC
Web
Django 4Python(models.py ,
views.py , urls.py ) html (latest_books.html )
# models.py (the database tables)
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=50)
pub_date = models.DateField()

# views.py (the business logic)


from django.shortcuts import render_to_response
from models import Book
def latest_books(request):
book_list = Book.objects.order_by('pub_date')[:10]
return render_to_response('latest_books.html', {'book_list': book_list})

djangobook.py3k.cn/2.0/chapter01/

2/6

2010-5-5

Django

# urls.py (the URL configuration)


from django.conf.urls.defaults import *
import views
urlpatterns = patterns('',
(r'^latest/$', views.latest_books),
)

# latest_books.html (the template)


<html><head><title>Books</title></head>
<body>
<h1>Books</h1>
<ul>
{% for book in book_list %}
<li>{{ book.name }}</li>
{% endfor %}
</ul>
</body></html>


models.py Python

(model)

Python SQL
views.py latest_books()
1

urls.py URL /latest/ URL latest_books()

example.comhttp://example.com/latest/
latest_books()
latest_books.html html

{% for book in book_list %}


--(MVC) MVC

5MVC
Django Web
URL
HTML Python

Django
Django
DjangoDjango

djangobook.py3k.cn/2.0/chapter01/

3/6

2010-5-5
3

Django

CGI
1.
2.
3.
4. 2 1
5. 2-4
6.

Django
Django Kansas Lawrence
2003 Lawrence Journal-World Adrian Holovaty
Simon Willison Python
World Online ,
LJWorld.comLawrence.com KUsports.com
Adrian Simon

2005 World Online World
Online Jacob Kaplan-Moss
Django
World OnlineAdrian and JacobDjango

Django Django
6
Amazon.com, craigslist.orgwashingtonpost.com
Django Django
* * * * , Django
1

Django Django
Web Django
Django


Django
Django
1-12 Django
Django 1-78-11Django12

djangobook.py3k.cn/2.0/chapter01/

4/6

2010-5-5

Django

13-20Django
Django
http://www.djangoproject.com/

if while for
/
Web
Web

Python
Django Python Django
Python Django Python Django
1

Python ,Django
Django
API

Python
Python Python
Python http://docs.python.org/tut/ Mark Pilgrims

Dive Into Python http://www.diveintopython.org/

Django
Django 1.1
Django Django 1.11.21.31.9
1
Django2.02.0
1.03 Python python 2.0
python 2.6python3.0
1.1

Django,Django ,
:django,app ,db ,
DjangoDjango
http://www.djangoproject.com/r/django-users
Django,Django IRC channel Freenode
IRC network#django

djangobook.py3k.cn/2.0/chapter01/

5/6

2010-5-5

Django

Django

| | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter01/

6/6

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book


4
2

| | | | |

:
WebDjango

DjangoPythonPython
Django /
12Django

Python
DjangoPythonPython

Python
Django2.32.62.32.6Python DjangoGIS
Python 2.42.6
Python,2.x 2.6
Django2.32.6PythonPython
Django
Python 2.3Python
Django Python 3.0
Python3.0Django Python3.0
PythonDjango
PythonPython 2.xPython 3.xPython
2.x

Linux Mac OS X Python ( OS X )


python Python python OS X/

/ , python .
Python 2.4.1 (#2, Mar 31 2005, 00:05:10)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1666)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

, Python. http://www.python.org/download/

Django
Django

djangobook.py3k.cn/2.0/chapter02/

1/8

2010-5-5

Django
Django

1.0.31.1
http://www.djangoproject.com/download/

LinuxDjango

Django
Django1.0.2final.tar.gzDjango
setup.py installPython
Unix
1. tar xzvf Django*.tar.gz
2. cd Django*
3. sudo python setup.py install

Windows7-Zip(http://www.djangoproject.com/r/7zip/).tar.gz
DOS ShellDjango

python setup.py install

DjangoPython`` site-package`` Python


/usr/lib/python2.4/sitepackages

Trunk
djangotrunk,djangosubversion
django
Subversion CVS Django Django
Subversion Django local checkout
Django Django
1

trunk djangotrunk
trunk
Django
Subversion http://subversion.tigris.org/
http://svnbook.red-bean.com/
Mac OS X 10.5SubversionDjango
svn version

djangobook.py3k.cn/2.0/chapter02/

2/8

2010-5-5

svn co http://code.djangoproject.com/svn/django/trunk djtrunk


pythonsite-packages /usr/lib/python2.4/site-packages

python c 'import sys, pprint; pprint.pprint(sys.path)'

site-packages
site-packages
1

django.pthdjtrunk
/home/me/code/djtrunk
1. djtrunk/django/bin PATH djangoadmin.py

django-admin.py

.pth http://www.djangoproject.com/r/python/site-module/

Subversion python setup.py install

Django bug
djtrunk svn update Subversion
http://code.djangoproject.com

trunktrunk Django
django
django django ``
djtrunk`` svn info Revision: (:) Django
Bug Django
[]Djano

Django
Django
ShellDjangopythonPython
django
>>> import django
>>> django.VERSION
(1, 1, 0, final', 1)

Python Python python

djangobook.py3k.cn/2.0/chapter02/

3/8

2010-5-5

Python (>>> )

(...
1

>>> print """This is a


... string that spans
... three lines."""
This is a
string that spans
three lines.
>>> def my_function(value):
...

print value

>>> my_function('hello')
hello

Python Shell

djangowebdjangopython
web
project

Django
PostgreSQL (http://www.postgresql.org/)
SQLite 3 (http://www.sqlite.org/)
MySQL (http://www.mysql.com/)
Oracle (http://www.oracle.com/)
Django DjangoGIS
PostgreSQL
PostgreSQL



Python Python

SQLite python2.5
SQLite
Python2.5

djangobook.py3k.cn/2.0/chapter02/

4/8

2010-5-5

Windows python2.5

Django PostgreSQL
PostgreSQL http://www.djangoproject.com/r/python-pgsql/ psycopg
psycopg2 1
2
Windows PostgreSQL http://www.djangoproject.com/r/pythonpgsql/windows/ psycopg
Linuxpython-psycopg2psycopg2pythonpython-postgresql

Django SQLite 3
Python 2.5 Python
SQLite
2

Python2.4 SQLite 32
http://www.djangoproject.com/r/sqlite/pysqlitehttp://www.djangoproject.com/r/python-sqlite/
pysqlite2.0.3
Windows SQLite pysqlite

Linuxpython-sqlite3sqlite-python
pysqlite

Django MySQL
djangoMySQL4.0 3.X SQL
http://www.djangoproject.com/r/python-mysql/ MySQLdb
1

Linuxpython-mysql,python-mysqldb,mysplpython

DjangoOracle
djangoOracle9i
Oraclecx_Oracle,http://cx-oracle.sourceforge.net/ 4.3.1
5.0bug

Django
Django

Django

djangobook.py3k.cn/2.0/chapter02/

5/8

2010-5-5
()

pythondjangoproject
django
Django Django
Django /home/username/djcode/

PHP Web ( /var/www


) Django Pythonweb server(root)
.

1

djangoadmin.py startproject mysite


mysite

setup.py Django djangoadmin.py

trunk djtrunk/django/bin djangoadmin.py


djangoadmin.py Unix, /usr/local/bin
, ,
sudo ln s /path/to/django/bin/djangoadmin.py /usr/local/bin/djangoadmin.py . Windows,
PATH .

djangolinuxdjangoadmin.pydjangoadmin
djangoadmin.py startproject ,
cd /usr/local/bindjangoadmin.pychmod +x djangoadmin.py
startproject 4
mysite/
__init__.py
manage.py
settings.py
urls.py

__init__.py Python ()

manage.py Django

python manage.py help

djangobook.py3k.cn/2.0/chapter02/

6/8

2010-5-5


settings.py Django

urls.py DjangoURL django

Django

django
djangoweb
Web Apache

(cd mysite )
python manage.py runserver

Validating models...
0 errors found.
Django version 1.0, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROLC.

8000,
http://127.0.0.1:8000/ Django

django web

20 Django
Development Server
runserver 8000

python manage.py runserver 8080


2

IP
`` 0.0.0.0`` IP
python manage.py runserver 0.0.0.0:8000

IP
http://192.168.1.103:8000/ . (IP ) Unix
ifconfig Windows ipconfig

?
1

djangobook.py3k.cn/2.0/chapter02/

7/8

2010-5-5

Django

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter02/

8/8

2010-5-5

URL

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

URL
Django Django
Django

Django Hello World

Hello world.
Hello worldhello.htmlHello
World
"Hello world" URL( http://www.example.com/hello.html ,
http://www.example.com/files/hello.html)
Django view function URL
URLconf Hello World

djangoadmin.py startprojectmysiteviews.py
Python Djangoview.py
view.py

Hello world views.py


from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world")

django.http import HttpResponse H HttpRequest


HttpResponse
hello
request Web
django.http.HttpRequestrequest

Django
hello
hello_wonderful_beautiful_world Your First URLconf

djangobook.py3k.cn/2.0/chapter03/

1/13

2010-5-5

URL

Django
HttpResponseHello world
PythonHttpRequest
HttpResponsePythonDjango

URLconf
python manage.py runserverDjango
Hello world mysitehello
URL HTML
HTMLURLURLconf
1

URLconf Django URL URL


Django URL URL
/foo/foo_view()Pythonview.py
djangoadmin.py startproject URLconf urls.py
urls.py
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^mysite/', include('mysite.foo.urls')),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
# (r'^admin/', include(admin.site.urls)),
)

URLconfDjango.
URLconf
from django.conf.urls.defaults import *
urlpatterns = patterns('',
)

django.conf.urls.defaultsDjango URLconf
patterns
patterns() urlpatterns patterns

djangobook.py3k.cn/2.0/chapter03/

2/13

2010-5-5

URL

urlpatterns Django ROOT_URLCONF URL


URL URLconf Django
Django URLconf
Django
URLconfURLviewURLviewPython tuple.
viewhello.
from django.conf.urls.defaults import *
from mysite.views import hello
urlpatterns = patterns('',
('^hello/$', hello),
)

( Python import mysite/views.py mysite.views )


hello mysite/views.pyPython

urlpatterns (^hello/$, hello), URLpatternPython

Django URL /hello/ hello


Python

Python import Python


Python
['','/usr/lib/python2.4/sitepackages','/home/username/djcode/']
from foo import bar Python foo.py ( Python

) Python /usr/lib/python2.4/sitepackages/foo.py
PythonPython
>>> import sys
>>> print sys.path

Python Python Django


1

URLpattern /hello/

DjangoURLURL(/) /hello/URL
(/)URL

djangobook.py3k.cn/2.0/chapter03/

3/13

2010-5-5

URL

(^)($)

$^hello//hello/
URL/hello/foo /hello/bar/hello/(^)
hello/$hello/URL/foo/bar/hello/hello/
^$hello/URL/foo/hello/bar
/hello/
URL^$
/hello/ URL
(/)URL (/)URL
URL settingAPPEND_SLASHD
URL/DjangoURL
APPEND_SLASHTrue. URLURL
APPEND_SLASHFalse,/URL.
hello Python (
) first-class objects

3

Django URLconf, python manage.py runserver (



http://127.0.0.1:8000/ http://127.0.0.1:8000/hello/
Python Server
`` http://127.0.0.1:8000/`` `` http://127.0.0.1:8000/hello/``
DjangoHello world
Djangoweb

( regexes ) Django URLconfs


URL
5

. (dot)

\d

[AZ]

A Z

[az]

a z

[AZaz]

a z

(, \d+ )

[^/]+

\d?

0 (, \d* 0 )

{1,3}

\d{1,3}

http://www.djangoproject.com/r/python/re-module/.

djangobook.py3k.cn/2.0/chapter03/

4/13

2010-5-5

URL

404
1

URLconfURL URL /hello/ URL


Django http://127.0.0.1:8000/goodbye/
http://127.0.0.1:8000/hello/subdirectory/ http://127.0.0.1:8000/ ()

Page not found 32 URLURLconfDjango

3-1 Django404 Error


404 DjangoURLconf
404

Page not found debug mode

http://127.0.0.1:8000/404Django
URL URLconf
URL.
URL.
URL`` ^$`` , :
from mysite.views import hello, my_homepage_view
urlpatterns = patterns('',
('^$', my_homepage_view),
# ...

djangobook.py3k.cn/2.0/chapter03/

5/13

2010-5-5

URL

Django
Django.
http://127.0.0.1:8000/hello/Hello worldDjango

settingpython manage.py runservermanage.py


setting.pyDjango TEMPLATE_DIRS
, DATABASE_NAME , . ROOT_URLCONFURLconfDjango
Python

django-admin.py startprojectsettings.pyurls.pysettings.py
ROOT_URLCONFurls.py. settings.py
ROOT_URLCONF = 'mysite.urls'

mysite/urls.py
1

URL /hello/ Django ROOT_URLCONF URLconf URLconf


URLpatterns URLpatternsview
HttpRequest HttpRequest

HttpRequest
HttpResponse Django
PythonHTTPbodyWeb Response

1. /hello/.
2. DjangoROOT_URLCONFURLconf.
3. DjangoURLconfURL/hello/
4.
5. HttpResponse
6. DjangoHttpResponseHTTP response Web page

Django-powered URLconfs
URLs URLs


Hello worldDjango
. /hello/HTML
1


.
Helloworld

djangobook.py3k.cn/2.0/chapter03/

6/13

2010-5-5

URL

HttpResponse python
pythondatetime
>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2008, 12, 13, 14, 9, 39, 2731)
>>> print now
20081213 14:09:39.002731

Django Python
PythonDjango DjangoDjango
Django
Djangodatetime.datetime.now()
HttpResponse
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
1

helloview.pyhello
view.py
from django.http import HttpResponse
import datetime
def hello(request):
return HttpResponse("Hello world")
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)

views.py
import datetime
datetime.datetime now
Python format-string HTML
%snow%s%s
datetime.datetime%s
2008-12-13 14:09:39.002731HTMLIt is now 2008-12-13 14:09:39.002731
HTML
helloHttpResponse

djangobook.py3k.cn/2.0/chapter03/

7/13

2010-5-5

URL

urls.pyURLDjangoURL /time/

from django.conf.urls.defaults import *


from mysite.views import hello, current_datetime
urlpatterns = patterns('',
('^hello/$', hello),
('^time/$', current_datetime),
)

current_datetime URL
URL/time/
URLconfpython manage.py runserver
http://127.0.0.1:8000/time/
Django
1

Django
America/Chicago Django/
settings.py

URL
DjangoURL

DjangoURL DjangoURL
URL

current_datetime URL /time/ /currenttime/


URL
URL
URL URL
current_datetimeURL
urlpatterns = patterns('',
('^hello/$', hello),
('^time/$', current_datetime),
('^anothertimepage/$', current_datetime),
)

URLconf

URL
1

`` current_datetime`` URL /time/


webURL URL
/books/243//books/81196/

/time/plus/1/
1 /time/plus/2/ 2 /time/plus/3/ 3

djangobook.py3k.cn/2.0/chapter03/

8/13

2010-5-5

URL

URL
urlpatterns = patterns('',
('^time/$', current_datetime),
('^time/plus/1/$', one_hour_ahead),
('^time/plus/2/$', two_hours_ahead),
('^time/plus/3/$', three_hours_ahead),
('^time/plus/4/$', four_hours_ahead),

2
)


234 5
URL
URL
webPHPJava
/time/plus?hours=3hours
Django ( Django
URL URL /time/plus/3/
URLWeb
DjangoURLURL
wildcard URLpatterns
URLd+1
urlpatterns = patterns('',
# ...
(r'^time/plus/\d+/$', hours_ahead),
# ...
)

# URL
URL /time/plus/2/ , /time/plus/25/ , /time/plus/100000000000/ URL
99
\d{1,2} :
(r'^time/plus/\d{1,2}/$', hours_ahead),

Web
99
3

r Python
Pythonn
rPythonn
nPythonPython
URL

djangobook.py3k.cn/2.0/chapter03/

9/13

2010-5-5

URL

URL
URL
\d{1,2}
(r'^time/plus/(\d{1,2})/$', hours_ahead),


URLconf
from django.conf.urls.defaults import *
from mysite.views import hello, current_datetime, hours_ahead
urlpatterns = patterns('',
(r'^hello/$', hello),
(r'^time/$', current_datetime),
(r'^time/plus/(\d{1,2})/$', hours_ahead),
)

hours_ahead

URLpattern
URLpattern


URL
URL

()
hours_ahead current_datetime

view
from django.http import Http404, HttpResponse
import datetime
def hours_ahead(request, offset):
try:
offset = int(offset)
except ValueError:
raise Http404()
dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
return HttpResponse(html)

, hours_ahead , : request offset . ()


request HttpRequest , current_datetime . :

HttpRequest ()

djangobook.py3k.cn/2.0/chapter03/

10/13

2010-5-5

URL
offset URL URL/time/plus/3/offset3

URL/time/plus/21/offset21string
integer21
Unicode objectsPython

offset Python
( request

offset int() .
int()PythonValueError
int(foo)ValueErrordjango.http.Http404
404
URL(d{1,2})
offset URLpattern
ValueError

/ current_datetime
datetime.datetime.now()/
datetime.timedeltadatetime.datetime dt
offsetint()datetime.timedeltahours

Python
%s (offset, dt)
HTMLHttpResponse
URLDjango
http://127.0.0.1:8000/time/plus/3/ http://127.0.0.1:8000/time/plus/5/

http://127.0.0.1:8000/time/plus/24/ http://127.0.0.1:8000/time/plus/100/
URL Django Page not found error ,
404 URL http://127.0.0.1:8000/time/plus/ ( ) 404

Django
Web views.py
Python hours_ahead offset = int(offset)
def hours_ahead(request, offset):
# try:
#
offset = int(offset)
# except ValueError:
#

raise Http404()

dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)

djangobook.py3k.cn/2.0/chapter03/

11/13

2010-5-5

URL
return HttpResponse(html)

/time/plus/3/ TypeError
"unsupported type for timedelta hours component: unicode" .
datetime.timedelta hours offset
datetime.timedelta TypeError
Django

( "unsupported type"

Python Python
Django

()
Local vars

TracebackSwitch to copy-and-paste view



Django IRC
Share this traceback on a public Web site
http://www.dpaste.com/URL
Request information Web GET POSTcookie
CGI Hrequest
RequestSettings Django
ROOT_URLCONFDjango D
Django Django
offset = int(offset)
print Django
print assert False
hours_ahead
def hours_ahead(request, offset):
try:
offset = int(offset)
except ValueError:
raise Http404()
dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
assert False
html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
return HttpResponse(html)

djangobook.py3k.cn/2.0/chapter03/

12/13

2010-5-5

URL

Python Django Internet


Web
Django debug debug
Django debug

HTML

Django

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter03/

13/13

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |


HTML
Python
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)

HTML

Python Python
Python
Python HTML
HTML/CSSPython

Python
Python HTML
Python Django

(Template System)


HTMLDjango

HTML

<html>
<head><title>Ordering notice</title></head>
<body>
<h1>Ordering notice</h1>
<p>Dear {{ person_name }},</p>
<p>Thanks for placing an order from {{ company }}. It's scheduled to
ship on {{ ship_date|date:"F j, Y" }}.</p>
<p>Here are the items you've ordered:</p>

djangobook.py3k.cn/2.0/chapter04/

1/25

2010-5-5

<ul>
{% for item in item_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% if ordered_warranty %}
<p>Your warranty information will be included in the packaging.</p>
{% else %}
<p>You didn't order a warranty, so you're on your own when
the products inevitably stop working.</p>
{% endif %}
<p>Sincerely,<br />{{ company }}</p>
</body>
</html>

HTML
{{ person_name }} (variable)

( {% if ordered_warranty %} ) (template tag) (tag)

for {% for item in item_list %} if
{% if ordered_warranty %}
forPythonfor if
tagordered_warrantyTrue{% if
ordered_warranty %}{% else %}{% else %}{% endif %}{% else %}

filter
{{ship_date|date:F j, Y }}ship_datedateF
j,Ydate (|)Unix
Django tagsfilters,. Ftagsfilters,
. tagfilters9


PythonDjango
PythonDjango
1. Template Django

Template ;
2. rendercontext

context

djangobook.py3k.cn/2.0/chapter04/

2/25

2010-5-5

>>> from django import template


>>> t = template.Template('My name is {{ name }}.')
>>> c = template.Context({'name': 'Adrian'})
>>> print t.render(c)
My name is Adrian.
>>> c = template.Context({'name': 'Fred'})
>>> print t.render(c)
My name is Fred.

Template Template django.template


Python
project djangoadmin.py startproject
python manage.py shell

Python
Pythonpython manage.py shellpython
manage.py shell Django
DjangoDjango

DjangoDJANGO_SETTINGS_MODULE
settings.pymysitePython
DJANGO_SETTINGS_MODULEmysite.settings
python manage.py shellDJANGO_SETTINGS_MODULE
`` python manage.py shell``

Django`` manage.py shell``


.bash_profile DJANGO_SETTINGS_MODULE

>>> from django.template import Template


>>> t = Template('My name is {{ name }}.')
>>> print t

<django.template.Template object at 0xb7d5f24c>


0xb7d5f24c Python Template ID

Template
Template() TemplateSyntaxError
>>> from django.template import Template
>>> t = Template('{% notatag %}')

djangobook.py3k.cn/2.0/chapter04/

3/25

2010-5-5

Traceback (most recent call last):


File "<stdin>", line 1, in ?
...
django.template.TemplateSyntaxError: Invalid block tag: 'notatag'

(block tag)`` {% notatag %}``


TemplateSyntaxError
tags

Template context context

contextDjango Context django.template


Template render() context
>>> from django.template import Context, Template
>>> t = Template('My name is {{ name }}.')
>>> c = Context({'name': 'Stephane'})
>>> t.render(c)
u'My name is Stephane.'

t.render(c)UnicodePython
u DjangoUnicode
Django
DjangoUnicode
A-Z
Contexts
Python Context Context

A-Za-z

>>> from django.template import Template, Context


>>> raw_template = """<p>Dear {{ person_name }},</p>

djangobook.py3k.cn/2.0/chapter04/

4/25

2010-5-5

...
... <p>Thanks for placing an order from {{ company }}. It's scheduled to
... ship on {{ ship_date|date:"F j, Y" }}.</p>
...
... {% if ordered_warranty %}
... <p>Your warranty information will be included in the packaging.</p>
... {% else %}
... <p>You didn't order a warranty, so you're on your own when
... the products inevitably stop working.</p>
... {% endif %}
...
... <p>Sincerely,<br />{{ company }}</p>"""
>>> t = Template(raw_template)
>>> import datetime
>>> c = Context({'person_name': 'John Smith',
...

'company': 'Outdoor Equipment',

...

'ship_date': datetime.date(2009, 4, 2),

...

'ordered_warranty': False})

>>> t.render(c)
u"<p>Dear John Smith,</p>\n\n<p>Thanks for placing an order from Outdoor
Equipment. It's scheduled to\nship on April 2, 2009.</p>\n\n\n<p>You
didn't order a warranty, so you're on your own when\nthe products
inevitably stop working.</p>\n\n\n<p>Sincerely,<br />Outdoor Equipment
</p>"

import Template Context django.template


raw_template

t raw_template Template
Python datetime
Context c Context Python
person_name 'John Smith' , company Outdoor Equipment
render() context

warranty paragraph ordered_warranty True . April 2, 2009


, 'F j, Y'
Python('\n' )
Python t.render(c)

'\n' print print t.render(c)


Django Template Context render()

context
>>> from django.template import Template, Context
>>> t = Template('Hello, {{ name }}')

djangobook.py3k.cn/2.0/chapter04/

5/25

2010-5-5

>>> print t.render(Context({'name': 'John'}))


Hello, John
>>> print t.render(Context({'name': 'Julie'}))
Hello, Julie
>>> print t.render(Context({'name': 'Pat'}))
Hello, Pat

context render()

# Bad
for name in ('John', 'Julie', 'Pat'):
t = Template('Hello, {{ name }}')
print t.render(Context({'name': name}))
# Good
t = Template('Hello, {{ name }}')
for name in ('John', 'Julie', 'Pat'):
print t.render(Context({'name': name}))

Django
XML XML Django

context datetime.date
listdictionary
Django (.)
Python

>>> from django.template import Template, Context


>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
u'Sally is 43 years old.'

Python datetime.date year month day

>>> from django.template import Template, Context


>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)
u'The month is 5 and the year is 1993.'

(dots)

djangobook.py3k.cn/2.0/chapter04/

6/25

2010-5-5

>>> from django.template import Template, Context


>>> class Person(object):
...
def __init__(self, first_name, last_name):
...

self.first_name, self.last_name = first_name, last_name

>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')


>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
u'Hello, John Smith.'

* * Python upper() isdigit()

>>> from django.template import Template, Context


>>> t = Template('{{ var }} {{ var.upper }} {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
u'hello HELLO False'
>>> t.render(Context({'var': '123'}))
u'123 123 True'

* *

>>> from django.template import Template, Context


>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
u'Item 2 is carrots.'

{{ items.1 }} `` TemplateSyntaxError``
Python
Python0 01

foo["bar"] )
( foo.bar )
foo.bar() )
( foo[bar] )

{{person.name.upper}}
person['name'] ) upper() ):
>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name.upper }} is {{ person.age }} years old.')

djangobook.py3k.cn/2.0/chapter04/

7/25

2010-5-5

>>> c = Context({'person': person})


>>> t.render(c)
u'SALLY is 43 years old.'


silent_variable_failure
True :
>>> t = Template("My name is {{ person.first_name }}.")
>>> class PersonClass3:
...
...

def first_name(self):
raise AssertionError, "foo"

>>> p = PersonClass3()
>>> t.render(Context({"person": p}))
Traceback (most recent call last):
...
AssertionError: foo
>>> class SilentAssertionError(AssertionError):
...

silent_variable_failure = True

>>> class PersonClass4:


...
...

def first_name(self):
raise SilentAssertionError

>>> p = PersonClass4()
>>> t.render(Context({"person": p}))
u'My name is .'

BankAccount delete()
{{ account.delete }} `` account`` BankAccount

account
alters_data
def delete(self):
# Delete the account
delete.alters_data = True


{{ account.delete }} delete() delete() alters_data=True

delete()


>>> from django.template import Template, Context
>>> t = Template('Your name is {{ name }}.')
>>> t.render(Context())
u'Your name is .'
>>> t.render(Context({'var': 'hello'}))
u'Your name is .'

djangobook.py3k.cn/2.0/chapter04/

8/25

2010-5-5

>>> t.render(Context({'NAME': 'hello'}))


u'Your name is .'
>>> t.render(Context({'Name': 'hello'}))
u'Your name is .'


web

(context)
(full populated) Context() (Context)
Python(syntax)``(Context)`` :
1

>>> from django.template import Context


>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
Traceback (most recent call last):
...
KeyError: 'foo'
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'

if/else
{% if %} (evaluate)

{% if %} {% endif %}
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% endif %}
{% else %}
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% else %}
<p>Get back to work.</p>
{% endif %}

Python
PythonDjangoFalse
([] )

djangobook.py3k.cn/2.0/chapter04/

9/25

2010-5-5

(() )
({} )
('' )
(0 )
None
False
(python)

`` True``
1

{% if %} and or not not )


{% if athlete_list and coach_list %}
Both athletes and coaches are available.
{% endif %}
{% if not athlete_list %}
There are no athletes.
{% endif %}
{% if athlete_list or coach_list %}
There are some athletes or some coaches.
{% endif %}
{% if not athlete_list or coach_list %}
There are no athletes or there are some coaches.
{% endif %}
{% if athlete_list and not coach_list %}
There are some athletes and absolutely no coaches.
{% endif %}
{% if %} and or


{% if athlete_list and coach_list or cheerleader_list %}


{% if %}
{% if athlete_list %}
{% if coach_list or cheerleader_list %}
We have athletes, and either coaches or cheerleaders!
{% endif %}
{% endif %}
1


{% if athlete_list or coach_list or parent_list or teacher_list %}

djangobook.py3k.cn/2.0/chapter04/

10/25

2010-5-5

{% elif %} `` {% if %}``
{% if athlete_list %}
<p>Here are the athletes: {{ athlete_list }}.</p>
{% else %}
<p>No athletes are available.</p>
{% if coach_list %}
<p>Here are the coaches: {{ coach_list }}.</p>
{% endif %}
{% endif %}

{% endif %} {% if %}

for
{% for %} Python for for X in Y Y

X {% for %}
{% endfor %}

athlete_list
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>

reversed
{% for athlete in athlete_list reversed %}
...
{% endfor %}

{% for %}
{% for athlete in athlete_list %}
<h1>{{ athlete.name }}</h1>
<ul>
{% for sport in athlete.sports_played %}
<li>{{ sport }}</li>
{% endfor %}
</ul>
{% endfor %}

{% if athlete_list %}
{% for athlete in athlete_list %}
<p>{{ athlete.name }}</p>
{% endfor %}
{% else %}
<p>There are no athletes. Only computer programmers.</p>
{% endif %}

`` for`` `` {% empty %}``



{% for athlete in athlete_list %}
<p>{{ athlete.name }}</p>

djangobook.py3k.cn/2.0/chapter04/

11/25

2010-5-5

{% empty %}
<p>There are no athletes. Only computer programmers.</p>
{% endfor %}

Django
Djangocontinue

`` {% for %}```` forloop``


forloop.counter 1

forloop.counter 1
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
forloop.counter0 forloop.counter 0

0
forloop.revcounter forloop.revcounter

1
forloop.revcounter0 forloop.revcounter 0

1
1

forloop.first ````

System Message: WARNING/2 (<string>, line 1071); backlink


Inline literal start-string without end-string.
{% for object in objects %}
{% if forloop.first %}<li class="first">{% else %}<li>{% endif %}
{{ object }}
</li>
{% endfor %}
forloop.last True

|
{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}

Link1 | Link2 | Link3 | Link4

Favorite places:
{% for p in places %}{{ p }}{% if not forloop.last %}, {% endif %}{% endfor %}
forloop.parentloop forloop

{% for country in countries %}

djangobook.py3k.cn/2.0/chapter04/

12/25

2010-5-5

<table>
{% for city in country.city_list %}
<tr>
<td>Country #{{ forloop.parentloop.counter }}</td>
<td>City #{{ forloop.counter }}</td>
<td>{{ city }}</td>
</tr>
{% endfor %}

</table>
{% endfor %}
forloop {% endfor %} forloop

Contextforloop
{% for %} forloop Django
forloop.parentloop forloop

{% for %} forloop.parentloop

ifequal/ifnotequal
DjangoPython

Django {% ifequal %}
{% ifequal %} {% ifequal %} {% endifequal %}

user currentuser :
{% ifequal user currentuser %}
<h1>Welcome!</h1>
{% endifequal %}

{% ifequal section 'sitenews' %}


<h1>Site News</h1>
{% endifequal %}
{% ifequal section "community" %}
<h1>Community</h1>
{% endifequal %}

{% if %} {% ifequal %} {% else%}
{% ifequal section 'sitenews' %}
<h1>Site News</h1>
{% else %}
<h1>No News Here</h1>
{% endifequal %}

{% ifequal %}
{% ifequal variable 1 %}
{% ifequal variable 1.23 %}
{% ifequal variable 'foo' %}
{% ifequal variable "foo" %}

Python {% ifequal %}

djangobook.py3k.cn/2.0/chapter04/

13/25

2010-5-5

{% ifequal variable True %}


{% ifequal variable [1, 2, 3] %}
{% ifequal variable {'key': 'value'} %}

{% if %} {% ifequal %}

HTMLPythonDjango {# #}
{# This is a comment #}



This is a {# this is not
a comment #}
test.
1

`` {% comment %}``
{% comment %}
This is a
multiline comment.
{% endcomment %}

{{ name|lower }}

{{ name }} lower
* *

{{ my_list|first|upper }}


{{ bio|truncatewords:"30" }}

bio 30
F
addslashes : JavaScript

date : date datetime


{{ pub_date|date:"F j, Y" }}

djangobook.py3k.cn/2.0/chapter04/

14/25

2010-5-5

F
length :

Python
__len__()

Django


Python
Python

Django Django
FULL-StackWeb Django
Python
Django
Django World Online
Django

Django Python
Django
Python

HTML/XML Django HTML


HTML XML XML
Django XML
XML

HTML Dreamweaver
Django
HTML

Python
Python
Python
Python

djangobook.py3k.cn/2.0/chapter04/

15/25

2010-5-5

mysite.views
current_datetime
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)

Django
from django.template import Template, Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
t = Template("<html><body>It is now {{ current_date }}.</body></html>")
html = t.render(Context({'current_date': now}))
return HttpResponse(html)


Python

Python
/home/djangouser/templates/mytemplate.html :
from django.template import Template, Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
# Simple way of using templates from the filesystem.
# This is BAD because it doesn't account for missing files!
fp = open('/home/djangouser/templates/mytemplate.html')
t = Template(fp.read())
fp.close()
html = t.render(Context({'current_date': now}))
return HttpResponse(html)

mytemplate.html open()
IOError


open() fp.read() fp.close()

djangobook.py3k.cn/2.0/chapter04/

16/25

2010-5-5

Django API

API
ROOT_URLCONF settings.py
settings.pyTEMPLATE_DIRS
tuple
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)

Django
TEMPLATE_DIRS
TEMPLATE_DIRS = (
'/home/django/mysite/templates',
)

Web
Django templates
mysite
TEMPLATE_DIRS
Bad:
2

# Missing comma!
TEMPLATE_DIRS = (
'/home/django/mysite/templates'
)

Good:
# Comma correctly in place.
TEMPLATE_DIRS = (
'/home/django/mysite/templates',
)

Python
1

Windows Unix/,

TEMPLATE_DIRS = (
'C:/www/django/templates',
)


Django Python TEMPLATE_DIRS

djangobook.py3k.cn/2.0/chapter04/

17/25

2010-5-5

import os.path
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
)
1

Python __file__ Python


`` os.path.dirname(__file__)`` settings.py
os.path.join templates windows
/
python
Django-powered

TEMPLATE_DIRS Django
current_datetime
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
t = get_template('current_datetime.html')
html = t.render(Context({'current_date': now}))
return HttpResponse(html)

django.template.loader.get_template()
get_template()
Template

current_datetime.html.html

get_template() TEMPLATE_DIRS
TEMPLATE_DIRS '/home/django/mysite/templates'
get_template() /home/django/mysite/templates/current_datetime.html

get_template() TemplateDoesNotExist
Django python manage.py runserver
Django current_datetime
http://127.0.0.1:8000/time/ DEBUG True current_datetime.html

Django TemplateDoesNotExist

djangobook.py3k.cn/2.0/chapter04/

18/25

2010-5-5

4-1:

Django

current_datetime.html
<html><body>It is now {{ current_date }}.</body></html>

render_to_response()
ContextHttpResponse
get_template()
Django
HttpResponse
django.shortcuts render_to_response()
``\ ``````
System Message: WARNING/2 (<string>, line 1736); backlink
Inline literal start-string without end-string.
System Message: WARNING/2 (<string>, line 1736); backlink
Inline literal start-string without end-string.
System Message: WARNING/2 (<string>, line 1736); backlink
Inline literal start-string without end-string.
render_to_response() current_datetime
from django.shortcuts import render_to_response
import datetime
def current_datetime(request):
now = datetime.datetime.now()
return render_to_response('current_datetime.html', {'current_date': now})


get_template Template Context HttpResponse
django.shortcuts.render_to_response import datetime .

djangobook.py3k.cn/2.0/chapter04/

19/25

2010-5-5

current_datetime now
HttpResponse render_to_response() render_to_response()

HttpResponse return
render_to_response()

Context render_to_response()

locals()
current_datetime :
def current_datetime(request):
now = datetime.datetime.now()
return render_to_response('current_datetime.html', {'current_date': now})

now

Python locals()

def current_datetime(request):
current_date = datetime.datetime.now()
return render_to_response('current_datetime.html', locals())

context locals()
now current_date
locals()

locals()
locals() request

get_template()

Django

get_template()

t = get_template('dateapp/current_datetime.html')

render_to_response() get_template() render_to_response()

return render_to_response('dateapp/current_datetime.html', {'current_date': now})

djangobook.py3k.cn/2.0/chapter04/

20/25

2010-5-5

Windows get_template() Unix

include

{% include %}
/
{% include %}

nav.html /
{% include 'nav.html' %}
{% include "nav.html" %}

includes/nav.html :
{% include 'includes/nav.html' %}

template_name
{% include template_name %}

get_template() TEMPLATE_DIRS

context
# mypage.html
<html>
<body>
{% include "includes/nav.html" %}
<h1>{{ title }}</h1>
</body>
</html>
# includes/nav.html
<div id="nav">
You are in: {{ current_section }}
</div>

current_section mypage.html
include
1

{% include %}Django
DEBUG True Django TemplateDoesNotExist
DEBUG False

HTML Django
HTML Web

djangobook.py3k.cn/2.0/chapter04/

21/25

2010-5-5

includes HTML
Django {% include %} Django

current_datetime.html current_datetime

<!DOCTYPE HTML PUBLIC "//W3C//DTD HTML 4.01//EN">


<html lang="en">
<head>
<title>The current time</title>
</head>
<body>
<h1>My helpful timestamp site</h1>
<p>It is now {{ current_date }}.</p>
<hr>
<p>Thanks for visiting my site.</p>
</body>
</html>

hours_ahead
<!DOCTYPE HTML PUBLIC "//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title>Future time</title>
</head>
<body>
<h1>My helpful timestamp site</h1>
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
<hr>
<p>Thanks for visiting my site.</p>
</body>
</html>

HTML
JavaScript HTML
include
include header.html
<!DOCTYPE HTML PUBLIC "//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>

footer.html :
<hr>
<p>Thanks for visiting my site.</p>
</body>
</html>

djangobook.py3k.cn/2.0/chapter04/

22/25

2010-5-5

include
<h1>My helpful timestamp site</h1> header.html
<title> <h1> <title>


Django include



<!DOCTYPE HTML PUBLIC "//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<h1>My helpful timestamp site</h1>
{% block content %}{% endblock %}
{% block footer %}
<hr>
<p>Thanks for visiting my site.</p>
{% endblock %}
</body>
</html>

base.html HTML
template
base.html .
{% block %} {% block %}
{% block %}

current_datetime.html
{% extends "base.html" %}
{% block title %}The current time{% endblock %}
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}

hours_ahead
{% extends "base.html" %}
{% block title %}Future time{% endblock %}
{% block content %}
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
{% endblock %}


base.html
current_datetime.html {% extends %}

djangobook.py3k.cn/2.0/chapter04/

23/25

2010-5-5

base.html
base.html {% block %} block
{ block title %} {% block content %}
{% block title %} {% block content %}
footer {% block %}


1. base.html
2. base_SECTION.html (, base_photos.html base_forum.html )

base.html
3.

{% extends %}

{% block %}

{% block %}
{{ block.super }}

{% block %} block
block
{% block %}
{% extends %} get_template()

TEMPLATE_DIRS
{% extends %}

djangobook.py3k.cn/2.0/chapter04/

24/25

2010-5-5

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter04/

25/25

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

5
Django URLConf

Web
Web

Amazon.com
HTML

Python Django
Django
Django
SQL

HTML HTML
Python SQL

MySQLdb http://www.djangoproject.com/r/python-mysql/
MySQL
from django.shortcuts import render_to_response
import MySQLdb
def book_list(request):
db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost')
cursor = db.cursor()
cursor.execute('SELECT name FROM books ORDER BY name')
names = [row[0] for row in cursor.fetchall()]
db.close()
return render_to_response('book_list.html', {'names': names})

Django

djangobook.py3k.cn/2.0/chapter05/

1/19

2010-5-5

MySQL MySQL PostgreSQL


psycopg MySQLdb SQL
SQL
Django

Django Django API

from django.shortcuts import render_to_response


from mysite.books.models import Book
def book_list(request):
books = Book.objects.order_by('name')
return render_to_response('book_list.html', {'books': books})

MTV
Django Web
Django


Model-View-Controller
(MVC) Model View
Controller

MVC

MVC
Django MVC MVC Django MV C

M django
1

V
C Django URLconf URL
Python
C Django Model(Template)Views
Django MTV MTV

M Model

djangobook.py3k.cn/2.0/chapter05/

2/19

2010-5-5

T (Template)

V View

MVC Web Ruby on Rails Django


Django MVC Django MVC
, Ruby on Rails

Django
Django
CREATE DATABASE
SQLiteSQLite
TEMPLATE_DIRS Django settings.py

DATABASE_ENGINE = ''
DATABASE_NAME = ''
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''

DATABASE_ENGINE Django Django DATABASE_ENGINE

Table 5-1
5-1.

`` postgresql``

PostgreSQL

psycopg 1.x http://www.djangoproject.com/r/pythonpgsql/1/

postgresql_psycopg2

PostgreSQL

psycopg 2.x http://www.djangoproject.com/r/pythonpgsql/

mysql

M ySQL

MySQLdb , http://www.djangoproject.com/r/python-mysql/.

sqlite3

SQLite

Python 2.5+ pysqlite


http://www.djangoproject.com/r/python-sqlite/

oracle

Oracle

cx_Oracle , http://www.djangoproject.com/r/python-oracle/.

5-1
Linux
`` python-postgresql`` `` python-psycopg``

djangobook.py3k.cn/2.0/chapter05/

3/19

2010-5-5

DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_NAME Django
DATABASE_NAME = 'mydb'

SQLite
DATABASE_NAME = '/home/django/mydata.db'

SQLite/home/django
DATABASE_USER Django SQLite
DATABASE_PASSWORD Django SQLite
DATABASE_HOST Django Django

SQLite
MySQL MySQL '/' MySQL
Unix socket
DATABASE_HOST = '/var/run/mysql'
1

`` mysite``
`` python manage.py shell`` `` manager.py shell``
DjangoPython Django

>>> from django.db import connection


>>> cursor = connection.cursor()

5-2

5-2.

You havent set the

`` DATABASE_ENGINE`` 5-1

DATABASE_ENGINE setting
yet.
Environment variable
`` python manager.py shell`` `` python``
DJANGO_SETTINGS_MODULE
is undefined.
Error loading _____ module:
No module named _____.
_____ isnt an available
database backend.

(, psycopg MySQLdb )Django

DATABASE_ENGINE

database _____ does not exist `` DATABASE_NAME`` ``


CREATE DATABASE``
role _____ does not exist
could not connect to server

`` DATABASE_USER``
DATABASE_HOSTDATABASE_PORT

djangobook.py3k.cn/2.0/chapter05/

4/19

2010-5-5

Django app-Django
PythonDjango
project , project app

projectDjango app
project, app
TEMPLATE_DIRS

appDjangoPython
Djangoapp app
projectproject
Django Web
app
app
app
views.pyURLconf
apps
app Django Django app
apps app
`` mysite`` `` books`` app
python manage.py startapp books

mysite books
books/
__init__.py
models.py
tests.py
views.py

app
models.py views.py models.py
importDjango app

Python
MTVM DjangoPython
CREATE TABLE Python SQL
DjangoSQLPython Django
SQL
Python SQL Django

djangobook.py3k.cn/2.0/chapter05/

5/19

2010-5-5

API Django
Python

-

Django
MySQL,

PythonPython
/ SQLPython
SQL

SQL EmailURL
Django
SQL WebPython
MySQL, PostgreSQL, and SQLiteCREATE TABLE
Python Django

,Django
18

//
SQL

email

[many-to-many]
[one-to-many][foreign key]
Python `` startapp`` models.py
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)

djangobook.py3k.cn/2.0/chapter05/

6/19

2010-5-5

address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()

class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()

django.db.models.Model
Model
Django

CharField varchar Publisher

PostgreSQL CREATE TABLE


CREATE TABLE "books_publisher" (
"id" serial NOT NULL PRIMARY KEY,
"name" varchar(30) NOT NULL,
"address" varchar(50) NOT NULL,
"city" varchar(60) NOT NULL,
"state_province" varchar(30) NOT NULL,
"country" varchar(50) NOT NULL,
"website" varchar(200) NOT NULL
);

Django CREATE TABLE


Book
authors Book authors

Django
B
Django
Djangoid

Django
books app
settings.py INSTALLED_APPS INSTALLED_APPS Django app

INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',

djangobook.py3k.cn/2.0/chapter05/

7/19

2010-5-5

'django.contrib.sites',

# app
MIDDLEWARE_CLASSES
INSTALLED_APPSapps `` mysite.books`` `` INSTALLED_APPS``

MIDDLEWARE_CLASSES = (
# 'django.middleware.common.CommonMiddleware',
# 'django.contrib.sessions.middleware.SessionMiddleware',
# 'django.contrib.auth.middleware.AuthenticationMiddleware',
)
INSTALLED_APPS = (
# 'django.contrib.auth',
# 'django.contrib.contenttypes',
# 'django.contrib.sessions',
# 'django.contrib.sites',
'mysite.books',
)

(TEMPLATE_DIRSINSTALLED_APPS
tuple
)
'mysite.books' books app INSTALLED_APPS app Python

.

python manage.py validate
validate 0 errors found


python manage.py validate

CREATE TABLE Unix

python manage.py sqlall books

books app manage.py startapp


BEGIN;
CREATE TABLE "books_publisher" (
"id" serial NOT NULL PRIMARY KEY,
"name" varchar(30) NOT NULL,
"address" varchar(50) NOT NULL,
"city" varchar(60) NOT NULL,
"state_province" varchar(30) NOT NULL,
"country" varchar(50) NOT NULL,
"website" varchar(200) NOT NULL
)
;
CREATE TABLE "books_author" (

djangobook.py3k.cn/2.0/chapter05/

8/19

2010-5-5

"id" serial NOT NULL PRIMARY KEY,


"first_name" varchar(30) NOT NULL,
"last_name" varchar(40) NOT NULL,
"email" varchar(75) NOT NULL

)
;
CREATE TABLE "books_book" (
"id" serial NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL,
"publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id") DEFERRABLE INITIALLY DEFER
"publication_date" date NOT NULL
)
;
CREATE TABLE "books_book_authors" (
"id" serial NOT NULL PRIMARY KEY,
"book_id" integer NOT NULL REFERENCES "books_book" ("id") DEFERRABLE INITIALLY DEFERRED,
"author_id" integer NOT NULL REFERENCES "books_author" ("id") DEFERRABLE INITIALLY DEFERRED,
UNIQUE ("book_id", "author_id")
)
;
CREATE INDEX "books_book_publisher_id" ON "books_book" ("publisher_id");
COMMIT;

app books publisher , book , author )


B
Django id
Django "_id"
REFERENCES
CREATE TABLE
MySQLauto_incrementPostgreSQL,serialSQLiteinteger primary key
PostgreSQL

sqlall SQLDjango

SQLUnix
`` python manager.py sqlall books | psql mydb`` Django
SQL `` syncdb``
python manage.py syncdb

Creating table books_publisher


Creating table books_author
Creating table books_book
Installing index for books.Book model
syncdb INSTALLED_APPS app

syncdb

djangobook.py3k.cn/2.0/chapter05/

9/19

2010-5-5

syncdb

python manage.py syncdb app


python manage.py syncdb SQL
1

SQLDjango
PostgreSQL`` psql`` `` python manage.py dbshell``
`` DATABASE_SERVER``

DjangoPython API python manage.py shell

>>> from books.models import Publisher


>>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',
...

city='Berkeley', state_province='CA', country='U.S.A.',

...

website='http://www.apress.com/')

>>> p1.save()
>>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.',
...

city='Cambridge', state_province='MA', country='U.S.A.',

...

website='http://www.oreilly.com/')

>>> p2.save()
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: Publisher object>, <Publisher: Publisher object>]


Publisher
`` Publisher`` `` name, address``
save() Django INSERT
`` Publisher.objects``
`` Publisher.objects.all()`` `` Publisher``
DjangoSQL `` SELECT``
Django modle API
Django`` save()``
1

p1 = Publisher(...)
# At this point, p1 is not saved to the database yet!
p1.save()
# Now it is.

`` objects.create()``

>>> p1 = Publisher.objects.create(name='Apress',
...

address='2855 Telegraph Avenue',

...

city='Berkeley', state_province='CA', country='U.S.A.',

djangobook.py3k.cn/2.0/chapter05/

10/19

2010-5-5

...

website='http://www.apress.com/')

>>> p2 = Publisher.objects.create(name="O'Reilly",
...
...

address='10 Fawcett St.', city='Cambridge',


state_province='MA', country='U.S.A.',

...

website='http://www.oreilly.com/')

>>> publisher_list = Publisher.objects.all()


>>> publisher_list

DjangoAPI

publisher````
System Message: WARNING/2 (<string>, line 872); backlink
Inline literal start-string without end-string.
System Message: WARNING/2 (<string>, line 872); backlink
Inline literal start-string without end-string.
[<Publisher: Publisher object>, <Publisher: Publisher object>]

Publisher __unicode__() __unicode__()


Pythonunicode __unicode__()

from django.db import models


class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
**def __unicode__(self):**
**return self.name**
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
**def __unicode__(self):**
**return u'%s %s' % (self.first_name, self.last_name)**
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
**def __unicode__(self):**
**return self.title**

__unicode__()
Publisher Book __unicode__() Author __unicode__()

djangobook.py3k.cn/2.0/chapter05/

11/19

2010-5-5

first_namelast_name
__unicode__()unicode `` __unicode__()`` Unicode
Python`` TypeError`` coercing to
Unicode: need string or buffer, int found
Unicode
Unicode
unicodePythonLatin
Latin
pythonASCIIISO-8859-1UTF-8
1280-9A-ZASCII
Python

??? ??????

UnicodeUnicode Python
Unicode
Django Unicode
Unicode Unicode Unicode

Unicode
http://www.joelonsoftware.com/articles/Unicode.html
Python Shell python manage.py shell
`` Publisher``
>>> from books.models import Publisher
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: Apress>, <Publisher: O'Reilly>]

__unicode__() Django
__unicode__()
1

__unicode__() Django
__unicode__()


>>> p = Publisher(name='Apress',
...
...

address='2855 Telegraph Ave.',


city='Berkeley',

...

state_province='CA',

...

country='U.S.A.',

djangobook.py3k.cn/2.0/chapter05/

12/19

2010-5-5

...

website='http://www.apress.com/')

`` save()``
>>> p.save()

SQL
INSERT INTO books_publisher
(name, address, city, state_province, country, website)
VALUES
('Apress', '2855 Telegraph Ave.', 'Berkeley', 'CA',
'U.S.A.', 'http://www.apress.com/');

Publisher id save()

>>> p.id
52
# this will differ based on your own data

save() UPDATE SQL


INSERT
>>> p.name = 'Apress Publishing'
>>> p.save()

save() SQL
UPDATE books_publisher SET
name = 'Apress Publishing',
address = '2855 Telegraph Ave.',
city = 'Berkeley',
state_province = 'CA',
country = 'U.S.A.',
website = 'http://www.apress.com'
WHERE id = 52;

UPDATE books_publisher SET


name = 'Apress Publishing'
WHERE id=52;

Web

>>> Publisher.objects.all()
[<Publisher: Apress>, <Publisher: O'Reilly>]

SQL
SELECT id, name, address, city, state_province, country, website
FROM books_publisher;

djangobook.py3k.cn/2.0/chapter05/

13/19

2010-5-5

Django SELECT*
SELECT* Python

Python() :-Python import this


Publisher.objects.all()
Publisher

objects 10

objects
all()
list QuerySet C
QuerySet

Django API
`` filter()``
>>> Publisher.objects.filter(name='Apress')
[<Publisher: Apress>]
filter() WHERE SQL
SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = 'Apress';

filter()
>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: Apress>]

AND SQL
SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE country = 'U.S.A.'
AND state_province = 'CA';

SQL =
>>> Publisher.objects.filter(name__contains="press")
[<Publisher: Apress>]

name contains PythonDjango


containsDjangoLIKE

djangobook.py3k.cn/2.0/chapter05/

14/19

2010-5-5

SELECT id, name, address, city, state_province, country, website


FROM books_publisher
WHERE name LIKE '%press%';

icontains(LIKE),startswithendswith, range(SQLBETWEEN
C

`` filter()``
`` get()``
>>> Publisher.objects.get(name="Apress")
<Publisher: Apress>

QuerySet)

>>> Publisher.objects.get(country="U.S.A.")
Traceback (most recent call last):
...
MultipleObjectsReturned: get() returned more than one Publisher
it returned 2! Lookup parameters were {'country': 'U.S.A.'}

>>> Publisher.objects.get(name="Penguin")
Traceback (most recent call last):
...
DoesNotExist: Publisher matching query does not exist.

DoesNotExist Publisher model Publisher.DoesNotExist

try:
p = Publisher.objects.get(name='Apress')
except Publisher.DoesNotExist:
print "Apress isn't in the database yet."
else:
print "Apress is in the database."

Django
order_by()
>>> Publisher.objects.order_by("name")
[<Publisher: Apress>, <Publisher: O'Reilly>]

all() SQL
SELECT id, name, address, city, state_province, country, website
FROM books_publisher
ORDER BY name;

djangobook.py3k.cn/2.0/chapter05/

15/19

2010-5-5

>>> Publisher.objects.order_by("address")
[<Publisher: O'Reilly>, <Publisher: Apress>]
>>> Publisher.objects.order_by("state_province")
[<Publisher: Apress>, <Publisher: O'Reilly>]

>>> Publisher.objects.order_by("state_province", "address")


[<Publisher: Apress>, <Publisher: O'Reilly>]


>>> Publisher.objects.order_by("name")
[<Publisher: O'Reilly>, <Publisher: Apress>]

order_by()
Django
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
**class Meta:**
**ordering = ['name']**

class Meta Publisher class Publisher


class Meta 4 Python
Meta B Meta
ordering order_by()
Django API Publisher name

>>> Publisher.objects.filter(country="U.S.A.").order_by("name")
[<Publisher: O'Reilly>, <Publisher: Apress>]

SQL WHERE ORDER BY


SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE country = 'U.S.A'
ORDER BY name DESC;

djangobook.py3k.cn/2.0/chapter05/

16/19

2010-5-5


Python
>>> Publisher.objects.order_by('name')[0]
<Publisher: Apress>

SELECT id, name, address, city, state_province, country, website


FROM books_publisher
ORDER BY name
LIMIT 1;

Pythonrange-slicing
>>> Publisher.objects.order_by('name')[0:2]

SQL
SELECT id, name, address, city, state_province, country, website
FROM books_publisher
ORDER BY name
OFFSET 0 LIMIT 2;

Python(negative slicing)
>>> Publisher.objects.order_by('name')[1]
Traceback (most recent call last):
...
AssertionError: Negative indexing is not supported.

order_by()
>>> Publisher.objects.order_by('name')[0]

save()

Apress PublisherApressApress Publishing


save()
>>> p = Publisher.objects.get(name='Apress')
>>> p.name = 'Apress Publishing'
>>> p.save()

SQL
SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = 'Apress';
UPDATE books_publisher SET
name = 'Apress Publishing',
address = '2855 Telegraph Ave.',
city = 'Berkeley',

djangobook.py3k.cn/2.0/chapter05/

17/19

2010-5-5

state_province = 'CA',
country = 'U.S.A.',
website = 'http://www.apress.com'

WHERE id = 52;

ApressID52
Djangosave()name
namename
QuerySetupdate()
>>> Publisher.objects.filter(id=52).update(name='Apress Publishing')

SQL
UPDATE books_publisher
SET name = 'Apress Publishing'
WHERE id = 52;

update()QuerySet
PublishercountryU.S.AUSA
>>> Publisher.objects.all().update(country='USA')
2

update() 2

delete()
>>> p = Publisher.objects.get(name="O'Reilly")
>>> p.delete()
>>> Publisher.objects.all()
[<Publisher: Apress Publishing>]

delete()update()

>>> Publisher.objects.filter(country='USA').delete()
>>> Publisher.objects.all().delete()
>>> Publisher.objects.all()
[]

Django
all()
>>> Publisher.objects.delete()
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Manager' object has no attribute 'delete'

all()
>>> Publisher.objects.all().delete()

all()

djangobook.py3k.cn/2.0/chapter05/

18/19

2010-5-5

>>> Publisher.objects.filter(country='USA').delete()

Django
Django

Web
Django
the GNU Free Document License Hosting graciously provided by

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter05/

19/19

2010-5-5

Admin

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

Django

Django Django

Django

adminDjango
admin

django.contrib
Djangodjango.contribdjango.contribDjango
Django(add-on) django.contrib
Python Django

django.contribdjango.contrib.admin
django.contrib(django.contrib.auth)
(django.contrib.sessioins)(django.contrib.comments)
Djangodjango.contrib Django
django.contrib

Django

settings
1. 'django.contrib.admin'settingINSTALLED_APPS INSTALLED_APPS

,
2. INSTALLED_APPS

'django.contrib.auth''django.contrib.contenttypes''django.contrib.sessions'Django

djangobook.py3k.cn/2.0/chapter06/

1/15

2010-5-5

Admin
3 (mysite
INSTALLED_APPS)

3. MIDDLEWARE_CLASSES 'django.middleware.common.CommonMiddleware'

'django.contrib.sessions.middleware.SessionMiddleware'
'django.contrib.auth.middleware.AuthenticationMiddleware' (mysite
)
python manage.py syncdb
'django.contrib.auth'INSTALLED_APPSsyncdb,
python manage.py createsuperuseradmin
admin (: INSTALLED_APPS
'django.contrib.auth'python manage.py createsuperuser.)
adminURLconf(urls.py). djangoadmin.py startproject
urls.pyDjango admin

# Include these import statements...


from django.contrib import admin
admin.autodiscover()
# And include this URLpattern...
urlpatterns = patterns('',
# ...
(r'^admin/', include(admin.site.urls)),
# ...
)

Django (`` python


manage.py runserver`` )http://127.0.0.1:8000/admin/

6-1

djangobook.py3k.cn/2.0/chapter06/

2/15

2010-5-5

Admin

6-1. Django
`` python manage.py
createsuperuser``

-(Groups)
(Users)

6-2 Django admin


Django* change list* * edit form*

Django
`` django.middleware.locale.LocaleMiddleware`` ``
MIDDLEWARE_CLASSES``
django.contrib.sessions.middleware.SessionMiddleware* *

Change passwordLog outGroupsUsers Django
Django

djangobook.py3k.cn/2.0/chapter06/

3/15

2010-5-5

Admin

UersChange

6-3.
`` SELECT * FROM
auth_user;``

djangobook.py3k.cn/2.0/chapter06/

4/15

2010-5-5

Admin

6-4.
change
password form
/


Add


6-5

6-5.

6-6

djangobook.py3k.cn/2.0/chapter06/

5/15

2010-5-5

Admin

6-6. Django

ModelsAdmin

`` book``
Publisher Author Book

`` books`` (`` mysite/books`` )`` admin.py``


from django.contrib import admin
from mysite.books.models import Publisher, Author, Book
admin.site.register(Publisher)
admin.site.register(Author)
admin.site.register(Book)

`` http://127.0.0.1:8000/admin/`` BooksAuthorsBooks
Publishers (`` runserver`` )
1


Publisher

`` Book``
`` Book``
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __unicode__(self):
return self.title

Add book`` http://127.0.0.1:8000/admin/books/book/add/`` `` `` publisher


`` `` author
Publisherpublisher
publisherAdd book .

Admin
djangobook.py3k.cn/2.0/chapter06/

6/15

2010-5-5

Admin


Django`` url.py`` URLconf`` admin.autodiscover()``
INSTALLED_APPS admin.py appadmin.py

`` books`` `` admin.py`` `` admin.site.register()``


/
1

`` django.contrib.auth`` `` admin.py`` UsersGroups


django.contribdjango.contrib.redirectsDjango

DjangoURLpatterns
URLconf Djangodjango/contrib/admin
URLpatterns
Django

Authoremail

emailBookmysite/books/models.py
emailblank=True
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(**blank=True** )

Django blank=False

__unicode__()
PythonCREATE TABLE blank=True
Author email
VARCHAR
blank=TrueAdd author edit form
(http://127.0.0.1:8000/admin/books/author/add/ )Email

This field is required

blank=True
SQLNULLNULL

djangobook.py3k.cn/2.0/chapter06/

7/15

2010-5-5

Admin

SQL NULLPythonNone""
VARCHARNULL
NULL
NULL

DjangoCREATE TABLENOT NULL


Author
CREATE TABLE "books_author" (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(40) NOT NULL,
"email" varchar(75) NOT NULL
)
;

Django
* *NULL
1


PostgreSQL
MySQL
NULL Djangonull=TrueNULL
DateFieldTimeFieldDateTimeField
IntegerFieldDecimalFieldFloatFieldnull=True * * blank=True
Book publication_date
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField(**blank=True, null=True** )

null=Trueblank=Truenull=TrueCREATE TABLE
publication_dateNOT NULL
DjangoALTER TABLE
manage.py dbshell
NOT NULL:
ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;
2

SQLPostgreSQL

bookpublication date

djangobook.py3k.cn/2.0/chapter06/

8/15

2010-5-5

Admin


Bookpublication_datePublication date

verbose_name
Author.emaile-mail
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(blank=True, **verbose_name='email'** )

author
verbose_name"USA state"Django
verbose_name

class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(**'email',**

blank=True)

ManyToManyField ForeignKey
verbose_name
1

ModelAdmi
blank=Truenull=Trueverbose_name

Django ModelAdmin

classes

Author
__unicode__() Author__unicode__()
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
1

email = models.EmailField(blank=True, verbose_name='email')


**def __unicode__(self):**
**return u'%s %s' % (self.first_name, self.last_name)**

6-7

6-7.

djangobook.py3k.cn/2.0/chapter06/

9/15

2010-5-5

Admin

AuthorModelAdmin
admin.py
from django.contrib import admin
from mysite.books.models import Publisher, Author, Book
**class AuthorAdmin(admin.ModelAdmin):**
**list_display = ('first_name', 'last_name', 'email')**
admin.site.register(Publisher)
**admin.site.register(Author, AuthorAdmin)**
admin.site.register(Book)

AuthorAdmindjango.contrib.admin.ModelAdmin
list_display

admin.site.register()AuthorAuthorAdmin
AuthorAdminAuthor
admin.site.register() ModelAdmin Django

PublisherBook
author
6-8

6-8. author
AuthorAdminsearch_fields
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
**search_fields = ('first_name', 'last_name')**
1

6-9.

"bar"BarneyHobarson

6-9. search_fieldsauthor
Book
from django.contrib import admin
from mysite.books.models import Publisher, Author, Book
class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
search_fields = ('first_name', 'last_name')
**class BookAdmin(admin.ModelAdmin):**
**list_display = ('title', 'publisher', 'publication_date')**

djangobook.py3k.cn/2.0/chapter06/

10/15

2010-5-5

Admin
**list_filter = ('publication_date',)**

admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
**admin.site.register(Book, BookAdmin)**

ModelAdminBookAdmin
list_display list_filter
Django
6-10

6-10. book
`` `` `` `` `` `` `` ``

date_hierarchy
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
**date_hierarchy = 'publication_date'**

6-11.

6-11. date_hierarchybook
date_hierarchy* *
publication date class Meta
orderingordering
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
**ordering = ('publication_date',)**

orderingclass Metaordering
(-)
book Publication date 6-12.

6-12 book

djangobook.py3k.cn/2.0/chapter06/

11/15

2010-5-5

Admin


ModelAdminfields
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('publication_date',)
**fields = ('title', 'authors', 'publisher', 'publication_date')**



fieldsfields field(s)
admi
bookpublication_date
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('publication_date',)
**fields = ('title', 'authors', 'publisher')**

publication date

Djangopublication_dateNone
null=True
1

book`` ``
HTML
Ctrlcommand help_text

filter_horizontalBookAdmin
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('publication_date',)
**filter_horizontal = ('authors',)**

fields
bookAuthorJavaScript
authorsAvailableChosen

6-13. filter_horizontalbook
`` `` filter_horizontal
filter_horizontal
ModelAdmin filter_vertical filter_horizontal

djangobook.py3k.cn/2.0/chapter06/

12/15

2010-5-5

Admin


filter_horizontal filter_vertical , ForeignKey

`` `` `` `` `` ``
bookpublishersbook
publishe`` ``
`` raw_id_fields``
`` `` `` `` 6-14
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'publisher', 'publication_date')
list_filter = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('publication_date',)
filter_horizontal = ('authors',)
**raw_id_fields = ('publisher',)**

6-14. raw_id_fieldsbook
publisherID ID

publishe


booksauthorspublishers

djangobook.py3k.cn/2.0/chapter06/

13/15

2010-5-5
1

Admin


publishers

Django documentation

Django * * *
* * *
Django
Django

Django

djangobook.py3k.cn/2.0/chapter06/

14/15

2010-5-5

Admin

* *

` <../chapter07/>`__

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter06/

15/15

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

7
GoogleBlogHTML
Django
HttpRequestForm

Request
ViewHttpRequest
viewHttpRequesthello():
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world")

HttpRequestrequest
viewrequest

URL
HttpRequestURL
/

request.path

"/hello/"

request.get_host()

"127.0.0.1:8000" or
"www.example.com"

request.get_full_path()
request.is_secure()

HTTPSTrue False

"/hello/?print=true"
True False

viewURL

# BAD!
def current_url_view_bad(request):
return HttpResponse("Welcome to the page at /current/")
# GOOD
def current_url_view_good(request):
return HttpResponse("Welcome to the page at %s" % request.path)

request
request.META PythonHTTPHeaderIPAgent
HeaderHeader
Header
1

djangobook.py3k.cn/2.0/chapter07/

1/18

2010-5-5

HTTP_REFERER REFERRER

HTTP_USER_AGENT user-agent
"Mozilla/5.0 (X11; U; Linux i686; frFR; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17" .

REMOTE_ADDR IP"12.345.67.89" (

IP"12.345.67.89,23.456.78.90" )
request.META Python
KeyError HTTP header
Header
try/except Python get()
# BAD!
def ua_display_bad(request):
ua = request.META['HTTP_USER_AGENT']

# Might raise KeyError!

return HttpResponse("Your browser is %s" % ua)


# GOOD (VERSION 1)
def ua_display_good1(request):
try:
ua = request.META['HTTP_USER_AGENT']
except KeyError:
ua = 'unknown'
return HttpResponse("Your browser is %s" % ua)
# GOOD (VERSION 2)
def ua_display_good2(request):
ua = request.META.get('HTTP_USER_AGENT', 'unknown')
return HttpResponse("Your browser is %s" % ua)

view request.META
view
def display_meta(request):
values = request.META.items()
values.sort()
html = []
for k, v in values:
html.append('<tr><td>%s</td><td>%s</td></tr>' % (k, v))
return HttpResponse('<table>%s</table>' % '\n'.join(html))

viewDjango
HTML request.path HttpRequest

HttpRequest request.GET
request.POSTGETPOST

request.GETrequest.POSTPython
request.GETrequest.POSTget()keys()values()
for key in request.GET

djangobook.py3k.cn/2.0/chapter07/

2/18

2010-5-5

request.GETrequest.POST

Pythonread()
Python
POSTHTMLformGETformURL
(the query string)

view

HTMLview
view
from django.shortcuts import render_to_response
def search_form(request):
return render_to_response('search_form.html')

viewPython
books/views.py
search_form.html
<html>
<head>
<title>Search</title>
</head>
<body>
<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
</body>
</html>

urls.py URLpattern
from mysite.books import views
urlpatterns = patterns('',
# ...
(r'^searchform/$', views.search_form),
# ...
)
1

viewsimport from mysite.views import search_form


import
runserver http://127.0.0.1:8000/searchform/

formDjango 404 FormURL /search/

djangobook.py3k.cn/2.0/chapter07/

3/18

2010-5-5

URL
3

# urls.py
urlpatterns = patterns('',
# ...
(r'^searchform/$', views.search_form),
(r'^search/$', views.search),
# ...
)
# views.py
def search(request):
if 'q' in request.GET:
message = 'You searched for: %r' % request.GET['q']
else:
message = 'You submitted an empty form.'
return HttpResponse(message)

Django

1. HTMLqqGET(method=get)URL

/search/
2. /search/search()request.GETq

qrequest.GETrequest.META

KeyError
# BAD!
def bad_search(request):
# The following line will raise KeyError if 'q' hasn't
# been submitted!
message = 'You searched for: %r' % request.GET['q']
return HttpResponse(message)

GET/search/?q=django
requet.GET DjangoURLconfDjangoURL
PHP/JavaURLURL
request.GETURLhours=3
POSTGETrequest.POSTrequest.GETPOSTGET
GET
e-mailPOST
GET (GETPOST
http://www.w3.org/2001/tag/doc/whenToUseGet.html)

views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response

djangobook.py3k.cn/2.0/chapter07/

4/18

2010-5-5

from mysite.books.models import Book


def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
books = Book.objects.filter(title__icontains=q)
return render_to_response('search_results.html',
{'books': books, 'query': q})
else:
return HttpResponse('Please submit a search term.')

qrequest.GETreuqest.GET[q]
Book.objects.filter(title__icontains=q)q icontains
Bq
icontains

booksBook search_results.html

<p>You searched for: <strong>{{ query }}</strong></p>


{% if books %}
<p>Found {{ books|length }} book{{ books|pluralize }}.</p>
<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul>
{% else %}
<p>No books matched your search criteria.</p>
{% endif %}

pluralizes

search()Please submit a search term.



Django

else
from django.http import HttpResponse
from django.shortcuts import render_to_response
from mysite.books.models import Book
def search_form(request):
return render_to_response('search_form.html')

djangobook.py3k.cn/2.0/chapter07/

5/18

2010-5-5

def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
books = Book.objects.filter(title__icontains=q)
return render_to_response('search_results.html',
{'books': books, 'query': q})
else:
**return render_to_response('search_form.html', {'error': True})**

search_form()
search()search_form.html
error search_form.htmlerror
<html>
<head>
<title>Search</title>
</head>
<body>
**{% if error %}**
**<p style="color: red;">Please submit a search term.</p>**
**{% endif %}**
<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
</body>
</html>

search_form()search_form()error
search_form
search_form()
/search/GET
search()/search/
search_form()URLpattern
def search(request):
error = False
if 'q' in request.GET:
q = request.GET['q']
if not q:
error = True
else:
books = Book.objects.filter(title__icontains=q)
return render_to_response('search_results.html',
{'books': books, 'query': q})
return render_to_response('search_form.html',
{'error': error})

/search/GET

URLs/search/
search_form.htmlaction
URL

djangobook.py3k.cn/2.0/chapter07/

6/18

2010-5-5

<form action="/search/" method="get">

<form action="" method="get">

action=URL search()
action


HTML
email foo e-mail
5U.S 123
YYYY-MM-DD
8
JavaScript
Javascript
JavaScript

JavaScript

search()20
20

def search(request):
error = False
if 'q' in request.GET:
q = request.GET['q']
if not q:
error = True
**elif len(q) > 20:**
**error = True**
else:
books = Book.objects.filter(title__icontains=q)
return render_to_response('search_results.html',
{'books': books, 'query': q})
return render_to_response('search_form.html',
{'error': error})

20
search_form.htmlPlease submit a search term.

djangobook.py3k.cn/2.0/chapter07/

7/18

2010-5-5

<html>
<head>
<title>Search</title>
</head>
<body>
{% if error %}
<p style="color: red;">Please submit a search term 20 characters or shorter.</p>
{% endif %}
<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
</body>
</html>


20


def search(request):
**errors = []**
if 'q' in request.GET:
q = request.GET['q']
if not q:
**errors.append('Enter a search term.')**
elif len(q) > 20:
**errors.append('Please enter at most 20 characters.')**
else:
books = Book.objects.filter(title__icontains=q)
return render_to_response('search_results.html',
{'books': books, 'query': q})
return render_to_response('search_form.html',
{**'errors': errors** })

search_form.htmlerrors
<html>
<head>
<title>Search</title>
</head>
<body>
**{% if errors %}**
**<ul>**
**{% for error in errors %}**
**<li>{{ error }}</li>**
**{% endfor %}**
**</ul>**
**{% endif %}**
<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
</body>
</html>

Contact

qDjango

djangobook.py3k.cn/2.0/chapter07/

8/18

2010-5-5


e-mail
e-mail
contact_form.html
<html>
<head>
<title>Contact us</title>
</head>
<body>
<h1>Contact us</h1>
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="/contact/" method="post">
<p>Subject: <input type="text" name="subject"></p>
<p>Your email (optional): <input type="text" name="email"></p>
<p>Message: <textarea name="message" rows="10" cols="50"></textarea></p>
<input type="submit" value="Submit">
</form>
</body>
</html>

e-mail e-mail
method=postmethod=get
e-mail search_form.html
search()contact()
from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
def contact(request):
errors = []
if request.method == 'POST':
if not request.POST.get('subject', ''):
errors.append('Enter a subject.')
if not request.POST.get('message', ''):
errors.append('Enter a message.')
if request.POST.get('email') and '@' not in request.POST['email']:
errors.append('Enter a valid email address.')
if not errors:
send_mail(
request.POST['subject'],
request.POST['message'],
request.POST.get('email', 'noreply@example.com'),
['siteowner@example.com'],
)
return HttpResponseRedirect('/contact/thanks/')
return render_to_response('contact_form.html',
{'errors': errors})

djangobook.py3k.cn/2.0/chapter07/

9/18

2010-5-5

contact()books/views.py
contact()books
URLconfURLDjango contact
books__init__.pyviews.py

request.methodPOST
request.methodGET
GETPOSTrequest.method
request.POSTrequest.GET contact_form.html
method=postPOSTrequest.GET
subject message
request.POST.get()

email
@ Django

django.core.mail.send_maile-mail
send_mailDjangoEmailMessageEmailMessage

send_mail()Django
http://docs.djangoproject.com/en/dev/topics/email/
HttpResponseRedirect
/URL/
render_to_response()
POST
POST

POST web
contact()
if


HTML
# views.py
def contact(request):
errors = []
if request.method == 'POST':
if not request.POST.get('subject', ''):
errors.append('Enter a subject.')

djangobook.py3k.cn/2.0/chapter07/

10/18

2010-5-5

if not request.POST.get('message', ''):


errors.append('Enter a message.')
if request.POST.get('email') and '@' not in request.POST['email']:
errors.append('Enter a valid email address.')
if not errors:
send_mail(
request.POST['subject'],
request.POST['message'],
request.POST.get('email', `'noreply@example.com`_'),
[`'siteowner@example.com`_'],
)
return HttpResponseRedirect('/contact/thanks/')
return render_to_response('contact_form.html', {
'errors': errors,
**'subject': request.POST.get('subject', ''),**
**'message': request.POST.get('message', ''),**
**'email': request.POST.get('email', ''),**
})

# contact_form.html
<html>
<head>
<title>Contact us</title>
</head>
<body>
<h1>Contact us</h1>
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="/contact/" method="post">
<p>Subject: <input type="text" name="subject" **value="{{ subject }}"** ></p>
<p>Your email (optional): <input type="text" name="email" **value="{{ email }}"** ></p>
<p>Message: <textarea name="message" rows="10" cols="50">**{{ message }}**</textarea></p>
<input type="submit" value="Submit">
</form>
</body>
</html>

Form
Djangoformdjango.formsHTML
formcontact
Djangonewforms
1

Djangodjango.newformsdjango.newforms
django.forms
Djangodjango.forms
django.newforms Django
1.0django.formsdjango.newforms

djangobook.py3k.cn/2.0/chapter07/

11/18

2010-5-5

django.forms
HTML`` <Form>`` Form
`` <Form>`` Form `` views.py``
Form forms.py`` views.py``

from django import forms


class ContactForm(forms.Form):
subject = forms.CharField()
email = forms.EmailField(required=False)
message = forms.CharField()
1

Form
FieldCharFieldEmailField email
required=False
Python HTML
>>> from contact.forms import ContactForm
>>> f = ContactForm()
>>> print f
<tr><th><label for="id_subject">Subject:</label></th><td><input type="text" name="subject" id="id_
<tr><th><label for="id_email">Email:</label></th><td><input type="text" name="email" id="id_email"
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_

Django`` <label>``
HTML<`` table`` >
>>> print f.as_ul()
<li><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /><
<li><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /><
>>> print f.as_p()
<p><label for="id_subject">Subject:</label> <input type="text" name="subject" id="id_subject" /></
<p><label for="id_email">Email:</label> <input type="text" name="email" id="id_email" /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></

<table><ul><form>

HTML
>>> print f['subject']
<input type="text" name="subject" id="id_subject" />
>>> print f['message']
<input type="text" name="message" id="id_message" />
Form Form

>>> f = ContactForm({'subject': 'Hello', 'email': 'adrian@example.com', 'message': 'Nice site!'})

Formform
>>> f.is_bound

djangobook.py3k.cn/2.0/chapter07/

12/18

2010-5-5

True

formis_valid()
Form
>>> f.is_valid()
True

emailrequired=False
>>> f = ContactForm({'subject': 'Hello', 'message': 'Nice site!'})
>>> f.is_valid()
True

subjectmessageForm
>>> f = ContactForm({'subject': 'Hello'})
>>> f.is_valid()
False
>>> f = ContactForm({'subject': 'Hello', 'message': ''})
>>> f.is_valid()
False

>>> f = ContactForm({'subject': 'Hello', 'message': ''})


>>> f['message'].errors
[u'This field is required.']
>>> f['subject'].errors
[]
>>> f['email'].errors
[]
1

Formerrors
>>> f = ContactForm({'subject': 'Hello', 'message': ''})
>>> f.errors
{'message': [u'This field is required.']}

Formcleaned_data
DjangoformPython

>>> f = ContactForm({subject': Hello, email: adrian@example.com, message: Nice site!})


>>> f.is_valid()
True
>>> f.cleaned_data
{message': uNice site!, email: uadrian@example.com, subject: uHello}

contact formUnicodeform
Pythondatetime.date

Form
1

Formcontact()
formscontact()
# views.py

djangobook.py3k.cn/2.0/chapter07/

13/18

2010-5-5

from django.shortcuts import render_to_response


from mysite.contact.forms import ContactForm
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(
cd['subject'],
cd['message'],
cd.get('email', 'noreply@example.com'),
['siteowner@example.com'],
)
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm()
return render_to_response('contact_form.html', {'form': form})
# contact_form.html
<html>
<head>
<title>Contact us</title>
</head>
<body>
<h1>Contact us</h1>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
</body>
</html>

DjangoformsHTML


send_mail()

message`` input type=text``


<`` textarea`` >* widget*
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField()
email = forms.EmailField(required=False)
message = forms.CharField(**widget=forms.Textarea** )

djangobook.py3k.cn/2.0/chapter07/

14/18

2010-5-5

formswidget

Field* * * *

ContactFormsubject100
CharFieldmax_length
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(**max_length=100** )
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)

min_length

subject* * "I love your site!"


Forminitial
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(
cd['subject'],
cd['message'],
cd.get('email', `'noreply@example.com`_'),
[`'siteowner@example.com`_'],
)
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm(
**initial={'subject': 'I love your site!'}**
)
return render_to_response('contact_form.html', {'form': form})

subject
* * * * * *
unbound

email

Djangoform
form.

djangobook.py3k.cn/2.0/chapter07/

15/18

2010-5-5

`` message`` `` clean_message()`` `` Form``


1

from django import forms


class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
def clean_message(self):
message = self.cleaned_data['message']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError("Not enough words!")
return message

Djangoformclean_

clean_message()* *
CharFieldself.cleaned_data

len()split()
forms.ValidationError
1


Python None

HTMLemail
"Email" modelverbose_name

label
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False, **label='Your email address'** )
message = forms.CharField(widget=forms.Textarea)

Form
`` contact_form.html`` `` {{form.as_table}}``

formCSS
`` <ul class=errorlist>``CSS CSS
<style type="text/css">
ul.errorlist {
margin: 0;
padding: 0;
}
.errorlist li {
backgroundcolor: red;

djangobook.py3k.cn/2.0/chapter07/

16/18

2010-5-5

color: white;
display: block;
fontsize: 10px;
margin: 0 0 3px;
padding: 4px 5px;
}

</style>

HTML {{form.as_table}}
formform
(<input type=text>, <select>, <textarea>, ){{form.}}

<html>
<head>
<title>Contact us</title>
</head>
<body>
<h1>Contact us</h1>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">
<div class="field">
{{ form.subject.errors }}
<label for="id_subject">Subject:</label>
{{ form.subject }}
</div>
<div class="field">
{{ form.email.errors }}
<label for="id_email">Your email address:</label>
{{ form.email }}
</div>
<div class="field">
{{ form.message.errors }}
<label for="id_message">Message:</label>
{{ form.message }}
</div>
<input type="submit" value="Submit">
</form>
</body>
</html>
{{ form.message.errors }} <ul class="errorlist"> form

form.message.errors list

<div class="field{% if form.message.errors %} errors{% endif %}">


{% if form.message.errors %}
<ul>
{% for error in form.message.errors %}
<li><strong>{{ error }}</strong></li>
{% endfor %}
</ul>
{% endif %}
<label for="id_message">Message:</label>

djangobook.py3k.cn/2.0/chapter07/

17/18

2010-5-5

{{ form.message }}

</div>

, divclasserrors


Django
Django

URLconfs
Document License`_.

Hosting graciously provided by

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter07/

18/18

2010-5-5

URL

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

URL
DjangoURL

URLconf
URLconf Django Python

(Streamlining)
URLconf:
from django.conf.urls.defaults import *
from mysite.views import hello, current_datetime, hours_ahead
urlpatterns = patterns('',
(r'^hello/$', hello),
(r'^time/$', current_datetime),
(r'^time/plus/(\d{1,2})/$', hours_ahead),
)

URLconf

Django URLconf (
view) views
URLconf
from django.conf.urls.defaults import *
**from mysite import views**
urlpatterns = patterns('',
(r'^hello/$', **views.hello** ),
(r'^time/$', **views.current_datetime** ),
(r'^time/plus/(d{1,2})/$', **views.hours_ahead** ),
)

Django URLconf
:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^hello/$', **'mysite.views.hello'** ),
(r'^time/$', **'mysite.views.current_datetime'** ),
(r'^time/plus/(d{1,2})/$', **'mysite.views.hours_ahead'** ),
)

( 'mysite.views.current_datetime'

djangobook.py3k.cn/2.0/chapter08/

1/17

2010-5-5

URL

mysite.views.current_datetime )

Django

URLconf
``\ \ ``
System Message: WARNING/2 (<string>, line 99); backlink
Inline literal start-string without end-string.
from django.conf.urls.defaults import *
urlpatterns = patterns(**'mysite.views'** ,
(r'^hello/$', **'hello'** ),
(r'^time/$', **'current_datetime'** ),
(r'^time/plus/(d{1,2})/$', **'hours_ahead'** ),
)

("." ) Django

:

Python URLconf
:
(wrap)
Pythonic Python
URLconf

URLconf
patterns() :
:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^hello/$', 'mysite.views.hello'),
(r'^time/$', 'mysite.views.current_datetime'),
(r'^time/plus/(\d{1,2})/$', 'mysite.views.hours_ahead'),
(r'^tag/(\w+)/$', 'weblog.views.tag'),
)

djangobook.py3k.cn/2.0/chapter08/

2/17

2010-5-5

URL

from django.conf.urls.defaults import *


urlpatterns = patterns('mysite.views',
(r'^hello/$', 'hello'),
(r'^time/$', 'current_datetime'),
(r'^time/plus/(\d{1,2})/$', 'hours_ahead'),
)
urlpatterns += patterns('weblog.views',
(r'^tag/(\w+)/$', 'tag'),
)

urlpatterns
patterns()

urlpatterns Django URLconf


DEBUG :
from django.conf import settings
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^$', views.homepage),
(r'^(\d{4})/([az]{3})/$', views.archive_month),
)
if settings.DEBUG:
urlpatterns += patterns('',
(r'^debuginfo/$', views.debug),
)

URL/debuginfo/ DEBUG True

URLconf URL
Django
URL

Python

:
def sell(item, price, quantity):
print "Selling %s unit(s) of %s at %s" % (quantity, item, price)

sell('Socks', '$2.50', 6)

djangobook.py3k.cn/2.0/chapter08/

3/17

2010-5-5

URL

sell(item='Socks', price='$2.50', quantity=6)


sell(item='Socks', quantity=6, price='$2.50')
sell(price='$2.50', item='Socks', quantity=6)
sell(price='$2.50', quantity=6, item='Socks')
sell(quantity=6, item='Socks', price='$2.50')
sell(quantity=6, price='$2.50', item='Socks')


:
sell('Socks', '$2.50', quantity=6)
sell('Socks', price='$2.50', quantity=6)
sell('Socks', quantity=6, price='$2.50')

Python (?P<name>pattern) name


pattern

URLconf :
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^articles/(\d{4})/$', views.year_archive),
(r'^articles/(\d{4})/(\d{2})/$', views.month_archive),
)

URLconf:
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^articles/(?P<year>\d{4})/$', views.year_archive),
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive),
)

/articles/2006/03/
month_archive(request, '2006', '03')

month_archive(request, year='2006', month='03')

URLconfsBUG
URL
month_archive URL

/
djangobook.py3k.cn/2.0/chapter08/

4/17

2010-5-5

URL

URLconfURLconf
DjangoURL
URLconf :
Django
Django
Django

# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^foo/$', views.foo_view),
(r'^bar/$', views.bar_view),
)
# views.py
from django.shortcuts import render_to_response
from mysite.models import MyModel
def foo_view(request):
m_list = MyModel.objects.filter(is_new=True)
return render_to_response('template1.html', {'m_list': m_list})
def bar_view(request):
m_list = MyModel.objects.filter(is_new=True)
return render_to_response('template2.html', {'m_list': m_list})

URLURL

# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^(foo)/$', views.foobar_view),
(r'^(bar)/$', views.foobar_view),
)
# views.py
from django.shortcuts import render_to_response
from mysite.models import MyModel

djangobook.py3k.cn/2.0/chapter08/

5/17

2010-5-5

URL

def foobar_view(request, url):


m_list = MyModel.objects.filter(is_new=True)
if url == 'foo':
template_name = 'template1.html'
elif url == 'bar':
template_name = 'template2.html'
return render_to_response(template_name, {'m_list': m_list})

URL /foo/ /fooey/

URL URLconf

# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}),
(r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),
)
# views.py
from django.shortcuts import render_to_response
from mysite.models import MyModel
def foobar_view(request, template_name):
m_list = MyModel.objects.filter(is_new=True)
return render_to_response(template_name, {'m_list': m_list})

URLconf template_name
URLconf
Django11
URLconf

URLconf
URL
URLconfURL
URL
/mydata/jan/01/
/mydata/jan/02/
/mydata/jan/03/
# ...
/mydata/dec/30/
/mydata/dec/31/

URLconf
urlpatterns = patterns('',
(r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view),

djangobook.py3k.cn/2.0/chapter08/

6/17

2010-5-5

URL

def my_view(request, month, day):


# ....

my_view
month/dayURL
URL /mydata/birthday/ URL /mydata/jan/06/
URLconf
urlpatterns = patterns('',
(r'^mydata/birthday/$', views.my_view, {'month': 'jan', 'day': '06'}),
(r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view),
)


monthday

Python
def say_hello(person_name):
print 'Hello, %s' % person_name
def say_goodbye(person_name):
print 'Goodbye, %s' % person_name

def greet(person_name, greeting):


print '%s, %s' % (greeting, person_name)

URLconfDjango
Event
BlogEntry

# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^events/$', views.event_list),
(r'^blog/entries/$', views.entry_list),
)
# views.py
from django.shortcuts import render_to_response
from mysite.models import Event, BlogEntry

djangobook.py3k.cn/2.0/chapter08/

7/17

2010-5-5

URL

def event_list(request):
obj_list = Event.objects.all()
return render_to_response('mysite/event_list.html', {'event_list': obj_list})
def entry_list(request):
obj_list = BlogEntry.objects.all()
return render_to_response('mysite/blogentry_list.html', {'entry_list': obj_list})


# urls.py
from django.conf.urls.defaults import *
from mysite import models, views
urlpatterns = patterns('',
(r'^events/$', views.object_list, {'model': models.Event}),
(r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}),
)
# views.py
from django.shortcuts import render_to_response
def object_list(request, model):
obj_list = model.objects.all()
template_name = 'mysite/%s_list.html' % model.__name__.lower()
return render_to_response(template_name, {'object_list': obj_list})


object_list

model URLconf

model.objects.all()
model.__name__.lower() Python __name__
BlogEntry
__name__ 'BlogEntry'


blogentry_list event_list
Django
Django

Django
URLconf

djangobook.py3k.cn/2.0/chapter08/

8/17

2010-5-5

URL

def my_view(request, template_name):


var = do_something()
return render_to_response(template_name, {'var': var})


URLconf URLconf
URLconfURLconf
URLconf
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^mydata/(?P<id>\d+)/$', views.my_view, {'id': 3}),
)

id id
/mydata/2/ /mydata/432432/ id 3 URL
id

# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^blog/$', views.page),
(r'^blog/page(?P<num>\d+)/$', views.page),
)
# views.py
def page(request, num='1'):
# Output the appropriate page of blog entries, according to num.
# ...

URL views.page
page() num "1" page()
num
`` 1`` `` 1`` ``
num``

def my_view(request, template_name='mysite/my_view.html'):

djangobook.py3k.cn/2.0/chapter08/

9/17

2010-5-5

URL
var = do_something()
return render_to_response(template_name, {'var': var})

URLconfURLURL
URLconf
URLpatternDjango
urlpatterns = patterns('',
# ...
('^([^/]+)/([^/]+)/add/$', views.add_stage),
# ...
)

/myblog/entries/add/ /auth/groups/add/ URL


/auth/user/add/

def add_stage(request, app_label, model_name):


if app_label == 'auth' and model_name == 'user':
# do specialcase code
else:
# do normal code

URL
URLconf
urlpatterns = patterns('',
# ...
('^auth/user/add/$', views.user_add_stage),
('^([^/]+)/([^/]+)/add/$', views.add_stage),
# ...
)

/auth/user/add/ user_add_stage URL


URL
Python
URLConf
(r'^articles/(?P<year>\d{4})/$', views.year_archive),

\d{4} year views.year_archive()

Python
Python
datetime.date
>>> import datetime
>>> datetime.date('1993', '7', '9')
Traceback (most recent call last):
...

djangobook.py3k.cn/2.0/chapter08/

10/17

2010-5-5

URL

TypeError: an integer is required


>>> datetime.date(1993, 7, 9)
datetime.date(1993, 7, 9)

URLconf
# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^articles/(\d{4})/(\d{2})/(\d{2})/$', views.day_archive),
)
# views.py
import datetime
def day_archive(request, year, month, day):
# The following statement raises a TypeError!
date = datetime.date(year, month, day)

day_archive()
def day_archive(request, year, month, day):
date = datetime.date(int(year), int(month), int(day))

int() ValueError
URLconf

URLconf
DjangoURLPythonURLconf
Unicode GET POST URL

http://www.example.com/myapp/ Django myapp/


http://www.example.com/myapp/?page=3 Django myapp/

URLconf POST GET HEAD URL


URLconf/view :
# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
# ...
(r'^somepage/$', views.some_page),
# ...
)
# views.py

djangobook.py3k.cn/2.0/chapter08/

11/17

2010-5-5

URL

from django.http import Http404, HttpResponseRedirect


from django.shortcuts import render_to_response
def some_page(request):
if request.method == 'POST':
do_something_for_post()
return HttpResponseRedirect('/someurl/')
elif request.method == 'GET':
do_something_for_get()
return render_to_response('page.html')
else:
raise Http404()

`` some_page()`` `` POST`` `` GET``


URL `` /somepage/.```` POST`` ``
GET``
`` POST`` `` GET``

`` some_page()``
# views.py
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render_to_response
def method_splitter(request, GET=None, POST=None):
if request.method == 'GET' and GET is not None:
return GET(request)
elif request.method == 'POST' and POST is not None:
return POST(request)
raise Http404
def some_page_get(request):
assert request.method == 'GET'
do_something_for_get()
return render_to_response('page.html')
def some_page_post(request):
assert request.method == 'POST'
do_something_for_post()
return HttpResponseRedirect('/someurl/')
# urls.py
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
# ...
(r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_p
# ...
)

`` method_splitter()`` `` request.method``
`` GET`` `` POST`` * * ``
request.method`` `` GET`` `` GET`` `` request.method``

djangobook.py3k.cn/2.0/chapter08/

12/17

2010-5-5

URL
`` POST`` `` POST`` `` request.method`` ``
HEAD`` `` GET`` `` POST`` `` Http404``

URLconf`` /somepage/`` `` method_splitter()``


`` GET`` `` POST``
`` some_page()`` `` some_page_get()`` ``
some_page_post()``
`` request.method`` `` method_splitter()``
`` some_page_post()`` `` request.method``
`` post`` ``
request.method``
`` request.method``
`` method_splitter()``
`` method_splitter`` `` Get``
`` POST`` `` request`` `` method_splitter``
URL
Python

def method_splitter(request, *args, **kwargs):


get_view = kwargs.pop('GET', None)
post_view = kwargs.pop('POST', None)
if request.method == 'GET' and get_view is not None:
return get_view(request, *args, **kwargs)
elif request.method == 'POST' and post_view is not None:
return post_view(request, *args, **kwargs)
raise Http404

,method_splitter(),GETPOST,*args**kwargs(*
) Python
,*,. ,
*,,

def foo(*args, **kwargs):


print "Positional arguments are:"
print args
print "Keyword arguments are:"
print kwargs

>>> foo(1, 2, 3)
Positional arguments are:
(1, 2, 3)
Keyword arguments are:
{}
>>> foo(1, 2, name='Adrian', framework='Django')
Positional arguments are:
(1, 2)

djangobook.py3k.cn/2.0/chapter08/

13/17

2010-5-5

URL

Keyword arguments are:


{'framework': 'Django', 'name': 'Adrian'}

method_splitter()*args**kwargs
any kwargs.pop()GETPOST (
popNone,KeyError)

python

def my_view1(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
# ...
return render_to_response('template1.html')
def my_view2(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
# ...
return render_to_response('template2.html')
def my_view3(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
# ...
return render_to_response('template3.html')

request.user
/accounts/login/ (,request.user,14.
,request.user)


1

def requires_login(view):
def new_view(request, *args, **kwargs):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
return view(request, *args, **kwargs)
return new_view

requires_login,view,new_view.new_view
requires_login request.user.is_authenticated(),view

,viewsif not request.user.is_authenticated().URLconf


requires_login.
1

from django.conf.urls.defaults import *


from mysite.views import requires_login, my_view1, my_view2, my_view3
urlpatterns = patterns('',
(r'^view1/$', requires_login(my_view1)),
(r'^view2/$', requires_login(my_view2)),
(r'^view3/$', requires_login(my_view3)),

djangobook.py3k.cn/2.0/chapter08/

14/17

2010-5-5

URL

, ,requires_login()

URLconf
DjangoURLconf
URLconfURLconf URL
URLconfURLConf
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^weblog/', include('mysite.blog.urls')),
(r'^photos/', include('mysite.photos.urls')),
(r'^about/$', 'mysite.views.about'),
)

6Djangoadmininclude. adminURLconf,
include.
include() $
Django include() URL
URLconf
URLconf mysite.blog.urls
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^(\d\d\d\d)/$', 'mysite.blog.views.year_detail'),
(r'^(\d\d\d\d)/(\d\d)/$', 'mysite.blog.views.month_detail'),
)

URLconf
/weblog/2007/ URLconf r'^weblog/' include() Django

'weblog/' URL 2007/ mysite.blog.urls


URLconf URL 2007/ , mysite.blog.urlsURL

/weblog//2007/() URLconf,r^weblog/
include(),django,weblog/ /2007/ (
),mysite.blog.urls.
/about/ : URLconf mysite.views.about

include()
URLconfparent URLconfs:
# root urls.py

djangobook.py3k.cn/2.0/chapter08/

15/17

2010-5-5

URL

from django.conf.urls.defaults import *


urlpatterns = patterns('',
(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
)
# foo/urls/blog.py
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^$', 'foo.views.blog_index'),
(r'^archive/$', 'foo.views.blog_archive'),
)

username URLconfURLconf

URLconf

URLconfinclude()
URLconf include() , URLconf
URLconf
1

URLconf

# urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^blog/', include('inner'), {'blogid': 3}),
)
# inner.py
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^archive/$', 'mysite.views.archive'),
(r'^about/$', 'mysite.views.about'),
(r'^rss/$', 'mysite.views.rss'),
)

# urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^blog/', include('inner')),
)
# inner.py

djangobook.py3k.cn/2.0/chapter08/

16/17

2010-5-5

URL

from django.conf.urls.defaults import *


urlpatterns = patterns('',
(r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
(r'^about/$', 'mysite.views.about', {'blogid': 3}),
(r'^rss/$', 'mysite.views.rss', {'blogid': 3}),
)


URLconf

URLconf

URLconfs Chapter 9,
djangos
GNU Free Document License. Hosting

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter08/

17/17

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |


Django

Django
django

DjangoDjango
Django

DjangoPython


iffor ),
{% %}
{% if is_logged_in %}
Thanks for logging in!
{% else %}
Please log in.
{% endif %}


{{ }}
My first name is {{ first_name }}. My last name is {{ last_name }}.

context Python
context

RequestContextContext
context django.template.Context Django
django.template.RequestContext RequestContext
context HttpRequest

djangobook.py3k.cn/2.0/chapter09/

1/19

2010-5-5

RequestContext

from django.template import loader, Context


def view_1(request):
# ...
t = loader.get_template('template1.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am view 1.'
})
return t.render(c)
def view_2(request):
# ...
t = loader.get_template('template2.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the second view.'
})
return t.render(c)

render_to_response()
context
appuserip_address
RequestContext context Context
context render_to_response()
RequestContext Context
context RequestContext context
processors
from django.template import loader, RequestContext
def custom_proc(request):
"A context processor that provides 'app', 'user' and 'ip_address'."
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
}
def view_1(request):
# ...
t = loader.get_template('template1.html')
c = RequestContext(request, {'message': 'I am view 1.'},
processors=[custom_proc])
return t.render(c)
def view_2(request):
# ...
t = loader.get_template('template2.html')
c = RequestContext(request, {'message': 'I am the second view.'},

djangobook.py3k.cn/2.0/chapter09/

2/19

2010-5-5

processors=[custom_proc])
return t.render(c)

custom_proc context HttpRequest


context
RequestContext Context context
RequestContext HttpRequest
request RequestContext processors context
curstom_proc
context app user ip_address custom_proc

message

render_to_response() loader.get_template() ,
Context render() context
render_to_response() render_to_response() context
context_instance
from django.shortcuts import render_to_response
from django.template import RequestContext
def custom_proc(request):
"A context processor that provides 'app', 'user' and 'ip_address'."
return {
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR']
}
def view_1(request):
# ...
return render_to_response('template1.html',
{'message': 'I am view 1.'},
context_instance=RequestContext(request, processors=[custom_proc]))
def view_2(request):
# ...
return render_to_response('template2.html',
{'message': 'I am the second view.'},
context_instance=RequestContext(request, processors=[custom_proc]))


processors
processors context
Django context TEMPLATE_CONTEXT_PROCESSORS

djangobook.py3k.cn/2.0/chapter09/

3/19

2010-5-5

context processors RequestContext processors


TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
)

custom_proc
requestcontext request
context
context

Djangocontext

django.core.context_processors.auth
TEMPLATE_CONTEXT_PROCESSORS RequestContext
user django.contrib.auth.models.User AnonymousUser

messages
request.user.get_and_delete_messages()

perms django.core.context_processors.PermWrapper

userspermissionsmessages14

django.core.context_processors.debug
TEMPLATE_CONTEXT_PROCESSORS
RequestContext
debug DEBUG True False debug

sql_queries ``{sql: , time: ``

SQL
System Message: WARNING/2 (<string>, line 315); backlink
Inline literal start-string without end-string.
context
DEBUG True

djangobook.py3k.cn/2.0/chapter09/

4/19

2010-5-5

ip INTERNAL_IPS

debugFalseDEBUGFalsedebug
RequestContext

django.core.context_processors.i18n
RequestContext
LANGUAGES LANGUAGES

LANGUAGE_CODE request.LANGUAGE_CODE LANGUAGE_CODE

django.core.context_processors.request
RequestContext request HttpRequest

HttpRequest:
{{ request.REMOTE_ADDR }}

Context

context

TEMPLATE_CONTEXT_PROCESSORS context processor settings.py


processor

Python
TEMPLATE_CONTEXT_PROCESSORS
context_processors.py

html
htmlhtml

Hello, {{ name }}.

<script>alert('hello')</script>

djangobook.py3k.cn/2.0/chapter09/

5/19

2010-5-5

Hello, <script>alert('hello')</script>

JavaScript

Hello, <b>username

(XSS) 20

escapehtml
Django

Djangohtml
django
1

``\ ``
System Message: WARNING/2 (<string>, line 491); backlink
Inline literal start-string without end-string.
> >
' '

" ()"

& is converted to &

django

html
html
Djangohtmle-mail

djangobook.py3k.cn/2.0/chapter09/

6/19

2010-5-5

safe
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}

safesafe from further escapingHTML


''
This will be escaped: &lt;b&gt;
This will not be escaped: <b>

,autoescape(),
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}

autoescape onoff ,,

Autoescaping is on by default. Hello {{ name }}


{% autoescape off %}
This will not be autoescaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Autoescaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}

auto-escaping include,block

# base.html
{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}
# child.html
{% extends "base.html" %}
{% block title %}This & that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}
1

base,child.,HTML,
greetingHello!
<h1>This & that</h1>
<b>Hello!</b>

djangobook.py3k.cn/2.0/chapter09/

7/19

2010-5-5

,. Pyhton(VIEWS)
,,
,escape
escapeescape

,.
{{ data|default:"This is a string literal." }}

,safe
,

{{ data|default:"3 &lt; 2" }}

{{ data|default:"3 < 2" }}

< Bad! Don't do this.

,,

template loaders

Django
django.template.loader.get_template(template_name) get_template

Template TemplateDoesNotExist
django.template.loader.select_template(template_name_list) select_template
get_template

TemplateDoesNotExist
TEMPLATE_DIRS

TEMPLATE_LOADERS TEMPLATE_LOADERS
Django
django.template.loaders.filesystem.load_template_source : TEMPLATE_DIRS

django.template.loaders.app_directories.load_template_source : Django

INSTALLED_APPS templates

djangobook.py3k.cn/2.0/chapter09/

8/19

2010-5-5

Django
Django
INSTALLED_APPS ('myproject.polls','myproject.music') get_template('foo.html')

/path/to/myproject/polls/templates/foo.html

/path/to/myproject/music/templates/foo.html

INSTALLED_APPS
templates

django.template.loaders.eggs.load_template_source : app_directories

Python eggs eggs


Python eggsPython
Django TEMPLATE_LOADERS

/ Django

Django

Django manage.py startapp


filter

INSTALLED_APPS
Django templatetags models.py views.py

books/
__init__.py
models.py
templatetags/
views.py

templatetags __init__.py Python Python


/

djangobook.py3k.cn/2.0/chapter09/

9/19

2010-5-5

/ poll_extras.py
{% load poll_extras %}
{% load %} INSTALLED_APPS Django

Django

/ templatetags Django
templatetags
{%load%}Python/
PythonPython
registertemplate.Library

from django import template
register = template.Library()

Django
django/template/defaultfilters.py django/template/defaulttags.py django.contrib

register

Python:
()

{{ var|foo:"bar" }} foo var bar

def cut(value, arg):


"Removes all values of arg from the given string"
return value.replace(arg, '')

{{ somevariable|cut:" " }}


def lower(value): # Only one argument.

djangobook.py3k.cn/2.0/chapter09/

10/19

2010-5-5

"Converts a string into all lowercase"


return value.lower()

Library Django
register.filter('cut', cut)
register.filter('lower', lower)
Library.filter()

Python 2.4register.filter()
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter
def lower(value):
return value.lower()

name Django
cut
from django import template
register = template.Library()
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')

Django

Django django.template.Node
render()
Hello, {{ person.name }}.
{% ifequal name.birthday today %}
Happy birthday!
{% else %}
Be sure to come back on your birthday
for a splendid surprise message.
{% endifequal %}

"Hello, "

djangobook.py3k.cn/2.0/chapter09/

11/19

2010-5-5

person.name
: ".\n\n"
IfEqual: name.birthdaytoday

render() context
render()
render()

template tag
python Node
{% current_time %} strftime
http://www.djangoproject.com/r/python/strftime/

<p>The time is {% current_time "%Y%m%d %I:%M %p" %}.</p>

, Django {% now %}

Node :
from django import template
register = template.Library()
def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrentTimeNode(format_string[1:1])

parsertokenparser
token
token.contents
'current_time "%Y%m%d %I:%M %p"'

token.split_contents()

djangobook.py3k.cn/2.0/chapter09/

12/19

2010-5-5

token.contents.split() Python

django.template.TemplateSyntaxError

token.split_contents()[0]

CurrentTimeNode
"%Y%m%d %I:%M %p"
format_string[1:1]

Node

render() Node
CurrentTimeNode
import datetime
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = str(format_string)
def render(self, context):
now = datetime.datetime.now()
return now.strftime(self.format_string)

__init__() render()
render()

Library
template.Library tag()
register.tag('current_time', do_current_time)
tag() :

Python2.4 register.tag
@register.tag(name="current_time")
def do_current_time(parser, token):

djangobook.py3k.cn/2.0/chapter09/

13/19

2010-5-5

# ...

@register.tag
def shout(parser, token):
# ...

name Django

render() context
CurrentTimeNode current_time
class CurrentTimeNode2(template.Node):
def __init__(self, format_string):
self.format_string = str(format_string)
def render(self, context):
now = datetime.datetime.now()
context['current_time'] = now.strftime(self.format_string)
return ''

(do_current_time2current_time2)
render() render()
render()

{% current_time2 "%Y%M%d %I:%M %p" %}


<p>The time is {{ current_time }}.</p>

CurrentTimeNode2 : current_time
{{ current_time }} {% current_time2 %}

{% get_current_time "%Y%M%d %I:%M %p" as my_current_time %}


<p>The current time is {{ my_current_time }}.</p>

Node
import re
class CurrentTimeNode3(template.Node):
def __init__(self, format_string, var_name):
self.format_string = str(format_string)
self.var_name = var_name
def render(self, context):
now = datetime.datetime.now()
context[self.var_name] = now.strftime(self.format_string)
return ''
def do_current_time(parser, token):
# This version uses a regular expression to parse tag contents.

djangobook.py3k.cn/2.0/chapter09/

14/19

2010-5-5

try:
# Splitting by None == splitting by spaces.
tag_name, arg = token.contents.split(None, 1)
except ValueError:
msg = '%r tag requires arguments' % token.contents[0]
raise template.TemplateSyntaxError(msg)
m = re.search(r'(.*?) as (\w+)', arg)
if m:
fmt, var_name = m.groups()
else:
msg = '%r tag had invalid arguments' % tag_name
raise template.TemplateSyntaxError(msg)
if not (fmt[0] == fmt[1] and fmt[0] in ('"', "'")):
msg = "%r tag's argument should be in quotes" % tag_name
raise template.TemplateSyntaxError(msg)
return CurrentTimeNode3(fmt[1:1], var_name)

do_current_time() CurrentTimeNode3

{% if %} {% for %}
parser.parse()
{% comment %}
def do_comment(parser, token):
nodelist = parser.parse(('endcomment',))
parser.delete_first_token()
return CommentNode()
class CommentNode(template.Node):
def render(self, context):
return ''
parser.parse()

django.template.NodeListNode
.
nodelist {% comment %} {% endcomment %}
{% comment %} {% endcomment %}

parser.parse() {% endcomment %}
parser.delete_first_token()

CommentNode.render() {% comment %} {% endcomment %}

do_comment() {% comment %} {% endcomment %}

{% upper %}{% endupper %}

djangobook.py3k.cn/2.0/chapter09/

15/19

2010-5-5

{% upper %}
This will appear in uppercase, {{ user_name }}.
{% endupper %}

parser.parse() nodelist Node


def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context)
return output.upper()

UpperNode.render() self.nodelist.render(context)
Node render()

django/template/defaulttags.py {% if %} {% for %} {% ifequal %}


{% ifchanged %}

current_time

Djangosimple_tagdjango.template.Library
render

current_time
def current_time(format_string):
try:
return datetime.datetime.now().strftime(str(format_string))
except UnicodeEncodeError:
return ''
register.simple_tag(current_time)

Python 2.4
@register.simple_tag
def current_time(token):
# ...

simple_tag

djangobook.py3k.cn/2.0/chapter09/

16/19

2010-5-5

Unicode

Django
/



{% books_for_author author %}

<ul>
<li>The Cat In The Hat</li>
<li>Hop On Pop</li>
<li>Green Eggs And Ham</li>
</ul>



def books_for_author(author):
books = Book.objects.filter(authors__id=author.id)
return {'books': books}


<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul>

Library inclusion_tag()
polls/result_snippet.html
register.inclusion_tag('book_snippet.html')(books_for_author)

Python 2.4
@register.inclusion_tag('book_snippet.html')
def books_for_author(author):
# ...

context Django
takes_context

Python context
home_link home_title Python

@register.inclusion_tag('link.html', takes_context=True)
def jump_link(context):

djangobook.py3k.cn/2.0/chapter09/

17/19

2010-5-5

return {
'link': context['home_link'],
'title': context['home_title'],
}

context
link.html
Jump directly to <a href="{{ link }}">{{ title }}</a>.

{% jump_link %}

Djangos

PythonSubversionZIP
TEMPLATE_LOADERS
load_template_source(template_name, template_dirs=None)

template_name ( loader.get_template() loader.select_template()


), template_dirs TEMPLATE_DIRS
, (template_source, template_path)
template_source template_path

django.template.TemplateDoesNotExist
is_usable
Python pkg_resources eggs
python eggs is_usable False pkg_resources eggs

ZIP
TEMPLATE_ZIP_FILES TEMPLATE_DIRS
ZIP
from django.conf import settings
from django.template import TemplateDoesNotExist
import zipfile
def load_template_source(template_name, template_dirs=None):
"Template loader that loads templates from a ZIP file."
template_zipfiles = getattr(settings, "TEMPLATE_ZIP_FILES", [])
# Try each ZIP file in TEMPLATE_ZIP_FILES.
for fname in template_zipfiles:
try:
z = zipfile.ZipFile(fname)
source = z.read(template_name)

djangobook.py3k.cn/2.0/chapter09/

18/19

2010-5-5

except (IOError, KeyError):


continue
z.close()
# We found a template, so return the source.
template_path = "%s:%s" % (fname, template_name)
return (source, template_path)
# If we reach here, the template couldn't be loaded
raise TemplateDoesNotExist(template_name)

# This loader is always usable (since zipfile is included with Python)


load_template_source.is_usable = True

TEMPLATE_LOADERS
mysite.zip_loadermysite.zip_loader.load_template_source
TEMPLATE_LOADERS

Django

Django DJANGO_SETTINGS_MODULE
PythonDjango

D
Django.conf.settings.configure()
TEMPLATE_DIRS DEFAULT_CHARSET
utf8 TEMPLATE_DEBUG D TEMPLATE_

Django

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter09/

19/19

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

10
5DjangoAPI
Django

(book)
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __unicode__(self):
return self.title

5, ,ID50,
:
>>> from mysite.books.models import Book
>>> b = Book.objects.get(id=50)
>>> b.title
u'The Django Book'

,ForeignKey ManyToManyField,

(Foreign Key)
ForeignKey , :

djangobook.py3k.cn/2.0/chapter10/

1/9

2010-5-5

>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'

`` ForeignKey``
`` publisher`` books publisher.book_set.all()
>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]

book_set QuerySet5QuerySet,

>>> p = Publisher.objects.get(name='Apress Publishing')


>>> p.book_set.filter(name__icontains='django')
[<Book: The Django Book>, <Book: Pro Django>]

book_set(book)_set

(Many-to-Many Values)
QuerySet ,

>>> b = Book.objects.get(id=50)
>>> b.authors.all()
[<Author: Adrian Holovaty>, <Author: Jacob KaplanMoss>]
>>> b.authors.filter(first_name='Adrian')
[<Author: Adrian Holovaty>]
>>> b.authors.filter(first_name='Adam')
[]

,author.book_set ,:
>>> a = Author.objects.get(first_name='Adrian', last_name='Holovaty')
>>> a.book_set.all()
[<Book: The Django Book>, <Book: Adrian's Other Book>]

, ForeignKeybook_set(model)_set

(Database Schema)
5 syncdb , syncdb
, ,

Django
Django Django
API
Django

djangobook.py3k.cn/2.0/chapter10/

2/9

2010-5-5


Django

Python

(model)Django
model Django
,SQLDjango
manage.py sqlall , (:

Django

SQL ,)
- (/
?)
()
1.
2. manage.py sqlall [yourapp] CREATE TABLE
3. (, psql mysql , manage.py dbshell )
ALTER TABLE
4. Pythonmanage.py shell ( MyModel.objects.all()[:5] )

,,

1.
2. ALTER TABLE
3.

Subversionsvn update
4. Web server

num_pagesBook

class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
**num_pages = models.IntegerField(blank=True, null=True)**
def __unicode__(self):
return self.title

(
blank=Truenull=True)

djangobook.py3k.cn/2.0/chapter10/

3/9

2010-5-5

manage.py sqlall books CREATE TABLE



CREATE TABLE "books_book" (
"id" serial NOT NULL PRIMARY KEY,
"title" varchar(100) NOT NULL,
"publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"),
"publication_date" date NOT NULL,
"num_pages" integer NULL
);

"num_pages" integer NULL

PostgreSQL psql,
ALTER TABLE books_book ADD COLUMN num_pages integer;

NULL
num_pages blank=True null=True

NULL
NOT NULL
BEGIN;
ALTER TABLE books_book ADD COLUMN num_pages integer;
UPDATE books_book SET num_pages=0;
ALTER TABLE books_book ALTER COLUMN num_pages SET NOT NULL;
COMMIT;

blank=True null=True
ALTER TABLEpython
>>> from mysite.books.models import Book
>>> Book.objects.all()[:5]

ALTER TABLE
web

Model
web

ALTER TABLE books_book DROP COLUMN num_pages;

Django

djangobook.py3k.cn/2.0/chapter10/

4/9

2010-5-5

ManyToManyFieldweb

DROP TABLE books_book_authors;


web models.py

DROP TABLE books_book;

books_book

Managers
Book.objects.all()objects 5
manager managers
managerDjango Django
managermanager
manager manager/manager
QuerySet

Manager
manager

,Booktitle_count()
managers
# models.py
from django.db import models
# ... Author and Publisher models here ...
**class BookManager(models.Manager):**
**def title_count(self, keyword):**
**return self.filter(title__icontains=keyword).count()**
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
num_pages = models.IntegerField(blank=True, null=True)

djangobook.py3k.cn/2.0/chapter10/

5/9

2010-5-5


**objects = BookManager()**
def __unicode__(self):
return self.title

manager
>>> Book.objects.title_count('django')
4
>>> Book.objects.title_count('python')
18

BookManagerdjango.db.models.Manager
title_count() self.filter()selfmanager
BookManager()objects managerobjects
objectsmanager

title_count()?

Manager QuerySets
managerQuerySet ,`` Book.objects.all()`` book

Manager.get_query_set()managerQuerySet get_query_set()
QuerySet
,* * managerRoald Dahl
from django.db import models
**# First, define the Manager subclass.**
**class DahlBookManager(models.Manager):**
**def get_query_set(self):**
**return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')**
**# Then hook it into the Book model explicitly.**
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
# ...
**objects = models.Manager() # The default manager.**
**dahl_objects = DahlBookManager() # The Dahlspecific manager.**

,Book.objects.all(),Book.dahl_objects.all().
objectsmanagermanager
dah1_objects
,get_query_set()QuerySetfilter()exclude()
QuerySet

djangobook.py3k.cn/2.0/chapter10/

6/9

2010-5-5

Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()

manager
manager()
:
class MaleManager(models.Manager):
def get_query_set(self):
return super(MaleManager, self).get_query_set().filter(sex='M')
class FemaleManager(models.Manager):
def get_query_set(self):
return super(FemaleManager, self).get_query_set().filter(sex='F')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
people = models.Manager()
men = MaleManager()
women = FemaleManager()

`` Person.men.all()`` `` Person.women.all()`` `` Person.people.all()``

ManagerDjangoManager()
DjangoManager Manager Django(
admin)manager manager
get_query_set()

manager
table-wide


from django.contrib.localflavor.us.models import USStateField
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
state = USStateField() # Yes, this is U.S.centric...
def baby_boomer_status(self):
"Returns the person's babyboomer status."
import datetime
if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
return "Baby boomer"
if self.birth_date < datetime.date(1945, 8, 1):

djangobook.py3k.cn/2.0/chapter10/

7/9

2010-5-5


return "Preboomer"
return "Postboomer"
def is_midwestern(self):
"Returns True if this person is from the Midwest."
return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')
def _get_full_name(self):
"Returns the person's full name."
return u'%s %s' % (self.first_name, self.last_name)
full_name = property(_get_full_name)

property
http://www.python.org/download/releases/2.2/descrintro/#property

>>> p = Person.objects.get(first_name='Barack', last_name='Obama')


>>> p.birth_date
datetime.date(1961, 8, 4)
>>> p.baby_boomer_status()
'Baby boomer'
>>> p.is_midwestern()
True
>>> p.full_name

# Note this isn't a method it's treated as an attribute

u'Barack Obama'

SQL
DjangoAPISQL
django.db.connection
connection.cursor() cursor.execute(sql, [params])SQL
cursor.fetchone()cursor.fetchall() :
>>> from django.db import connection
>>> cursor = connection.cursor()
>>> cursor.execute("""
...

SELECT DISTINCT first_name

...

FROM people_person

...
WHERE last_name = %s""", ['Lennon'])
>>> row = cursor.fetchone()
>>> print row
['John']
connection cursor Python DB-API` http://www.python.org/peps/pep-

0249.html <http://www.python.org/peps/pep-0249.html>`__ Python DB-API


cursor.execute() SQL`` %s`` SQL

django.db.connectionmanager
manager
from django.db import connection, models
class PersonManager(models.Manager):
def first_names(self, last_name):
cursor = connection.cursor()
cursor.execute("""
SELECT DISTINCT first_name

djangobook.py3k.cn/2.0/chapter10/

8/9

2010-5-5

FROM people_person
WHERE last_name = %s""", [last_name])
return [row[0] for row in cursor.fetchone()]
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
objects = PersonManager()

:
>>> Person.objects.first_names('Lennon')
['John', 'Cynthia']

Django

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter10/

9/9

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

11
Web
Django Web

Django


URLConf
Django

8 event_list entry_list
event
// Django Weblogs
(http://www.djangoproject.com/weblog/)

URLconfURLconf

URLconf
from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
(r'^about/$', direct_to_template, {
'template': 'about.html'
})
)


direct_to_template
about
URL /about// about/.html URL

djangobook.py3k.cn/2.0/chapter11/

1/8

2010-5-5

from django.conf.urls.defaults import *


from django.views.generic.simple import direct_to_template
**from mysite.books.views import about_pages**
urlpatterns = patterns('',
(r'^about/$', direct_to_template, {
'template': 'about.html'
}),
**(r'^about/(\w+)/$', about_pages),**
)

about_pages
from django.http import Http404
from django.template import TemplateDoesNotExist
from django.views.generic.simple import direct_to_template
def about_pages(request, page):
try:
return direct_to_template(request, template="about/%s.html" % page)
except TemplateDoesNotExist:
raise Http404()
1

direct_to_template HttpResponse

TemplateDoesNotExist404


(template="about/%s.html" % page ) directory traversal
20
page page URL
URL \w+ URL page \w
. / URL

direct_to_template Django

Django
Publisher
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Meta:

djangobook.py3k.cn/2.0/chapter11/

2/8

2010-5-5

ordering = ['name']

URL
from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher
publisher_info = {
'queryset': Publisher.objects.all(),
}
urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info)
)

Python
template_nameobject_list
from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher
publisher_info = {
'queryset': Publisher.objects.all(),
**'template_name': 'publisher_list_page.html',**
}
urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info)
)

template_nameobject_list
"books/publisher_list.html" booksapp publisher

context object_list

{% extends "base.html" %}
{% block content %}
<h2>Publishers</h2>
<ul>
{% for publisher in object_list %}
<li>{{ publisher.name }}</li>
{% endfor %}
</ul>
{% endblock %}

(base.html
D


Django

djangobook.py3k.cn/2.0/chapter11/

3/8

2010-5-5

Context
object_list
publisher_list

template_object_name
from django.conf.urls.defaults import *
from django.views.generic import list_detail
from mysite.books.models import Publisher
publisher_info = {
'queryset': Publisher.objects.all(),
'template_name': 'publisher_list_page.html',
'template_object_name': 'publisher',
}
urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info)
)
1

template_object_name_list

template_object_name

Context

object_detail context

extra_context
context info

publisher_info = {
'queryset': Publisher.objects.all(),
'template_object_name': 'publisher',
**'extra_context': {'book_list': Book.objects.all()}**
}

{{ book_list }} context

BUG
2

extra_context
Publisher.objects.all() URLconfURLconf

WebQuerySet
C

djangobook.py3k.cn/2.0/chapter11/

4/8

2010-5-5

queryset Django QuerySet

extra_context callback
extra_context

**def get_books():**
**return Book.objects.all()**
publisher_info = {
'queryset': Publisher.objects.all(),
'template_object_name': 'publisher',
'extra_context': **{'book_list': get_books}**
}

Publisher.objects.all

publisher_info = {
'queryset': Publisher.objects.all(),
'template_object_name': 'publisher',
'extra_context': **{'book_list': Book.objects.all}**
}

Book.objects.all

queryset queryset
QuerySet B

book_info = {
'queryset': Book.objects.order_by('publication_date'),
}
urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info),
**(r'^books/$', list_detail.object_list, book_info),**
)

**apress_books = {**
**'queryset': Book.objects.filter(publisher__name='Apress Publishing'),**
**'template_name': 'books/apress_list.html'**
**}**
urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info),
**(r'^books/apress/$', list_detail.object_list, apress_books),**
)

djangobook.py3k.cn/2.0/chapter11/

5/8

2010-5-5

queryset


URLURL

URL URLconf

object_list URL
urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info),
**(r'^books/(\w+)/$', books_by_publisher),**
)

books_by_publisher
from django.shortcuts import get_object_or_404
from django.views.generic import list_detail
from mysite.books.models import Book, Publisher
def books_by_publisher(request, name):
# Look up the publisher (and raise a 404 if it can't be found).
publisher = get_object_or_404(Publisher, name__iexact=name)
# Use the object_list view for the heavy lifting.
return list_detail.object_list(
request,
queryset = Book.objects.filter(publisher=publisher),
template_name = 'books/books_by_publisher.html',
template_object_name = 'book',
extra_context = {'publisher': publisher}
)

Python
HttpResponse

extra_context

Author last_accessed author


object_detail

URL
from mysite.books.views import author_detail

djangobook.py3k.cn/2.0/chapter11/

6/8

2010-5-5

urlpatterns = patterns('',
# ...
**(r'^authors/(?P<author_id>\d+)/$', author_detail),**
# ...
)

import datetime
from django.shortcuts import get_object_or_404
from django.views.generic import list_detail
from mysite.books.models import Author
def author_detail(request, author_id):
# Delegate to the generic view and get an HttpResponse.
response = list_detail.object_detail(
request,
queryset = Author.objects.all(),
object_id = author_id,
)
# Record the last accessed date. We do this *after* the call
# to object_detail(), not before it, so that this won't be called
# unless the Author actually exists. (If the author doesn't exist,
# object_detail() will raise Http404, and we won't reach this point.)
now = datetime.datetime.now()
Author.objects.filter(id=author_id).update(last_accessed=now)
return response

last_accessed Author books/author_detail.html

author

def author_list_plaintext(request):
response = list_detail.object_list(
request,
queryset = Author.objects.all(),
mimetype = 'text/plain',
template_name = 'books/author_list.txt'
)
response["ContentDisposition"] = "attachment; filename=authors.txt"
return response

HttpResponse HTTP
ContentDisposition

Django C

, Django

djangobook.py3k.cn/2.0/chapter11/

7/8

2010-5-5

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter11/

8/8

2010-5-5

Django

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book


1

| | | | |

Django
django
runserver runserver django
Apache ()
.

runserver **

Debug.
2, djangoadmin.py startproject , settings.py DEBUG
True . django DEBUG . DEBUG
True , :
django.db.connection.queries .
!
404django404(3)404

python
Django 404
`` DEBUG`` `` True`` Django Internet
`` DEBUG`` `` False``

Debug
TEMPLATE_DEBUGFalse `` True``
Django
1

404
`` DEBUG`` `` True`` Django404 `` DEBUG`` ``
False`` `` 404.html``

`` 404.html`` `` base.html``,
titlecontent
{% extends "base.html" %}

djangobook.py3k.cn/2.0/chapter12/

1/18

2010-5-5

Django

{% block title %}Page not found{% endblock %}


{% block content %}
<h1>Page not found</h1>
<p>Sorry, but the requested page could not be found.</p>
{% endblock %}

404.htmlDEBUG `` False`` URL


`` sunserver``

500
`` DEBUG`` `` False`` DjangPython
`` 500.html`` `` 404.html``

500.html`` ``


`` 500.html``
<!DOCTYPE html PUBLIC "//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Page unavailable</title>
</head>
<body>
<h1>Page unavailable</h1>
<p>Sorry, but the requested page is unavailable due to a
server hiccup.</p>
<p>Our engineers have been notified, so check back later.</p>
</body>
</html>

Django Django
Email
ADMINSE-mailE-mail
(, Email)
ADMINS = (
('John Lennon', 'jlennon@example.com'),
('Paul McCartney', 'pmacca@example.com'),
)

postfix,sendmailDjango
, EMAIL_HOST.
localhost, . ,
EMAIL_HOST_USER,EMAIL_HOST_PASSWORD,EMAIL_PORTEMAIL_USE_TLS

djangobook.py3k.cn/2.0/chapter12/

2/18

2010-5-5

Django

EMAIL_SUBJECT_PREFIXDjango error e-mail


'[Django] '

CommonMiddleware(MIDDLEWARE_CLASSES
django.middleware.common.CommonMiddleware
CommonMiddleware),Django
404.
SEND_BROKEN_LINK_EMAILS True(False),MANAGERS
. MANAGERSADMINS .:
MANAGERS = (
('George Harrison', 'gharrison@example.com'),
('Ringo Starr', 'ringo@example.com'),
)

Email

settings.pydjango-admin.py startproject

DEBUGFalse TrueDjango

))
.
Python


settings.pysettings_production.py
),DEBUG


# settings.py
DEBUG = True
TEMPLATE_DEBUG = DEBUG
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_NAME = 'devdb'
DATABASE_USER = ''

djangobook.py3k.cn/2.0/chapter12/

3/18

2010-5-5

Django

DATABASE_PASSWORD = ''
DATABASE_PORT = ''
# ...
# settings_production.py
from settings import *
DEBUG = TEMPLATE_DEBUG = False
DATABASE_NAME = 'production'
DATABASE_USER = 'app'
DATABASE_PASSWORD = 'letmein'

settings_production.py settings.py
DEBUG False
DEBUG


# settings.py
import socket
if socket.gethostname() == 'mylaptop':
DEBUG = TEMPLATE_DEBUG = True
else:
DEBUG = TEMPLATE_DEBUG = False
# ...

pythonsocket

pythonpython

) Django
settings.py
settings.pysettings_dev.pysettings/dev.pyfoobar.pyDjango

django-admin.py startproject settings.pymanage.py


settings
manage.py import settings django-admin.py
manage.py, DJANGO_SETTINGS_MODULE
python .(mysite.settings

DJANGO_SETTINGS_MODULE
(Apache)
Web
DJANGO_SETTINGS_MODULE,Django DJANGO_SETTINGS_MODULE
ROOT_URLCONF,ROOT_URLCONF

djangobook.py3k.cn/2.0/chapter12/

4/18

2010-5-5

Django

DJANGO_SETTINGS_MODULEpython mysitePython
DJANGO_SETTINGS_MODULEmysite.settings

Apachemod_pythonDjango
Apachemod_pythonDjango
mod_python (http://www.djangoproject.com/r/mod_python/)ApachePythonApache
Python (
Django Apaceh 2.x mod_python 3.x

Apache
Apache :
Apache http://www.djangoproject.com/r/apache/docs/

Pro Apache (Apress, 2004),Peter Wainwright,


http://www.djangoproject.com/r/books/pro-apache/

Apache: The Definitive Guide, (OReilly, 2002),Ben LauriePeter Laurie,


http://www.djangoproject.com/r/books/apache-pra/

mod_python Django mod_python Apache


LoadModule Apache
LoadModule python_module /usr/lib/apache2/modules/mod_python.so

Then, edit your Apache configuration file and add a <Location> directive that ties a specific URL path
to a specific Django installation.
<Location "/">
SetHandler pythonprogram
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug Off
</Location>

DJANGO_SETTINGS_MODULE mysite.settings
Apache / URL Django mod_python
DJANGO_SETTINGS_MODULE mod_python

```` ```` ````


System Message: WARNING/2 (<string>, line 403); backlink
Inline literal start-string without end-string.

djangobook.py3k.cn/2.0/chapter12/

5/18

2010-5-5

Django

System Message: WARNING/2 (<string>, line 403); backlink


Inline literal start-string without end-string.
System Message: WARNING/2 (<string>, line 403); backlink
Inline literal start-string without end-string.
System Message: WARNING/2 (<string>, line 403); backlink
Inline literal start-string without end-string.
System Message: ERROR/3 (<string>, line 405)
Unexpected indentation.
Web URL ````
System Message: WARNING/2 (<string>, line 405); backlink
Inline literal start-string without end-string.
System Message: WARNING/2 (<string>, line 405); backlink
Inline literal start-string without end-string.
Apache
sys.path mod_python Django
PythonPath "['/path/to/project', '/path/to/django'] + sys.path"

PythonAutoReload Off mod_python

PythonDebug Off PythonDebug On


Python PythonDebug On,mod_python
,)Python
Apache <VirtualHost>
Djanog

Apache Django
Apache Django Web

VirtualHost
NameVirtualHost *
<VirtualHost *>
ServerName www.example.com
# ...
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</VirtualHost>

djangobook.py3k.cn/2.0/chapter12/

6/18

2010-5-5

Django

<VirtualHost *>
ServerName www2.example.com
# ...
SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
</VirtualHost>

VirtualHost Django mod_python


PythonInterpreter <Location>
1

<VirtualHost *>
ServerName www.example.com
# ...
<Location "/something">
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonInterpreter mysite
</Location>
<Location "/otherthing">
SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
PythonInterpreter mysite_other
</Location>
</VirtualHost>

PythonInterpreter Location

mod_python
mod_python Python mod_python Django
Apache
MaxRequestsPerChild 1 Apache

Django
print print mod_python
Apache mod_python
Python Pythons standard logging package
http://docs.python.org/lib/module-logging.html

ApacheDjangoMedia
Djangomedia
Djangomedia
DjangoApache VirtualHost media
mod_python
<Location "/media/">
SetHandler None
</Location>

Location media
<LocationMatch> Django
media .jpg .gif .png URL:
<Location "/">
SetHandler pythonprogram
PythonHandler django.core.handlers.modpython

djangobook.py3k.cn/2.0/chapter12/

7/18

2010-5-5

Django
SetEnv DJANGO_SETTINGS_MODULE mysite.settings

</Location>
<Location "/media/">
SetHandler None
</Location>
<LocationMatch "\.(jpg|gif|png)$">
SetHandler None
</LocationMatch>

DocumentRoot apache

Apache/mod_python Django Apache


Apache
Django
Apache Python

ApacheDjango Django

pyexpat XMLApache
http://www.djangoproject.com/r/articles/expat-apache-crash/.
Apachemod_python mod_phpMySQL
PHPPythonMySQL mod_pythonFAQ

mod_pythonmod_pythonDjango
mod_python
http://www.djangoproject.com/r/articles/getting-modpython-working/.
djangoimport
views,models,URLconf,RSS importshandler
URL crashimportdjango imports
imports
linuxldconfigMac OSotoolwindowsListDLLsform sysInternals

mod_wsgi
mod_pythonmod_wsgi(http://code.google.com/p/modwsgi/),
mod_pythonDjango
Django

FastCGIDjango
djangobook.py3k.cn/2.0/chapter12/

8/18

2010-5-5

Django

Apachemod_pythonDjango
FastCGI
FastCGImod_python
ApacheFastCGI

FastCGI
WEB FastCGI!

mod_pythonFastCGI,CGI
mod_pythonweb

mod_*Apache PHP
Python/mod_pythonPerl/mod_perlapacheApache

ApacheApacheApache
Django FastCGIPythonDjango

FastCGIFastCGIWeb

DjangoFastCGI flup Python


FastCGI flup

FastCGI
FastCGI/FastCGI Web
Apache,lighttpdDjango-FastCGI
Fast-CGI

Web server-managed FastCGI


ApacheDjango
1

webFastCGI Unix domain socket(win32 )


TCP socket.TCP socket
What you choose is a manner of preference; a TCP socket is usually easier due to permissions
issues.
manage.py
manage.py runfcgi

djangobook.py3k.cn/2.0/chapter12/

9/18

2010-5-5

Django

./manage.py runfcgi [options]

runfcgi manage.py runfcgi help


socket host port Web
FastCGIsockethost/port

TCP
./manage.py runfcgi method=threaded host=127.0.0.1 port=3033

Unix socketprefork
./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid

./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock

FastCGI
FastCGICtrl+C
Unix kill Unix
kill

manage.py runfcgi pidfile FastCGI


kill `cat $PIDFILE`
$PIDFILE pidfile

UnixFastCGI
#!/bin/bash
# Replace these three settings.
PROJDIR="/home/user/myproject"
PIDFILE="$PROJDIR/mysite.pid"
SOCKET="$PROJDIR/mysite.sock"
cd $PROJDIR
if [ f $PIDFILE ]; then
kill `cat $PIDFILE`
rm f $PIDFILE
fi
exec /usr/bin/env

PYTHONPATH="../python:.."

./manage.py runfcgi socket=$SOCKET pidfile=$PIDF

ApacheFastCGIDjango
ApacheFastCGIDjangoApachemod_fastcgi Apache
mod_fastcgi http://www.djangoproject.com/r/mod_fastcgi/
httpd.conf ApacheApacheDjango FastCGI

djangobook.py3k.cn/2.0/chapter12/

10/18

2010-5-5

Django
FastCGIExternalServer FastCGI
mod_rewrite FastCGIURL

FastCGI Server
FastCGIExternalServer ApacheFastCGI FastCGIExternalServer

http://www.djangoproject.com/r/mod_fastcgi/FastCGIExternalServer/ socket host

# Connect to FastCGI via a socket/named pipe:


FastCGIExternalServer /home/user/public_html/mysite.fcgi socket /home/user/mysite.sock
# Connect to FastCGI via a TCP host/port:
FastCGIExternalServer /home/user/public_html/mysite.fcgi host 127.0.0.1:3033

/home/user/public_html/ /home/user/public_html/mysite.fcgi
WebURLURLFastCGI

mod_rewriteFastCGIURL
ApacheURLFastCGI mod_rewrite
URL mysite.fcgi FastCGIExternalServer

ApacheFastCGI(
<VirtualHost 12.34.56.78>
ServerName example.com
DocumentRoot /home/user/public_html
Alias /media /home/user/python/django/contrib/admin/media
RewriteEngine On
RewriteRule ^/(media.*)$ /$1 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !f
RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
</VirtualHost>

FastCGI lighttpd
lighttpd (http://www.djangoproject.com/r/lighttpd/) Web
FastCGIApachelighttpd

mod_fastcgi mod_rewrite mod_access mod_accesslog

lighttpd
server.documentroot = "/home/user/public_html"
fastcgi.server = (
"/mysite.fcgi" => (
"main" => (
# Use host / port instead of socket for TCP fastcgi
# "host" => "127.0.0.1",
# "port" => 3033,

djangobook.py3k.cn/2.0/chapter12/

11/18

2010-5-5

Django
"socket" => "/home/user/mysite.sock",
"checklocal" => "disable",
)
),

)
alias.url = (
"/media/" => "/home/user/django/contrib/admin/media/",
)
url.rewriteonce = (
"^(/media.*)$" => "$1",
"^/favicon\.ico$" => "/media/favicon.ico",
"^(/.*)$" => "/mysite.fcgi$1",
)

lighttpdDjango
lighttpd FastCGIFastCGI

# If the hostname is 'www.example1.com'...


$HTTP["host"] == "www.example1.com" {
server.documentroot = "/foo/site1"
fastcgi.server = (
...
)
...
}
# If the hostname is 'www.example2.com'...
$HTTP["host"] == "www.example2.com" {
server.documentroot = "/foo/site2"
fastcgi.server = (
...
)
...
}

fastcgi.server Django
FastCGI

ApacheDjango
httpd.conf
WebDjango

FastCGI Apache

Web .htaccess
AddHandler fastcgiscript .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !f
RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]

ApacheFastCGI mysite.fcgi

djangobook.py3k.cn/2.0/chapter12/

12/18

2010-5-5

Django

Web
#!/usr/bin/python
import sys, os
# Add a custom Python path.
sys.path.insert(0, "/home/user/python")
# Switch to the directory of your project. (Optional.)
# os.chdir("/home/user/myproject")
# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings"
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")

pythonFastCGI Apache
mysite.fcgi Django
mysite.fcgi
Django
Unix touch
touch mysite.fcgi

DjangoDjango

Apachemod_python
FastCGIApache

20-1

20-1 Django

djangobook.py3k.cn/2.0/chapter12/

13/18

2010-5-5

Django

3000
Web
RAM, CPU

Django DATABASE_HOST
IPDNS IPDNSDNS

20-2

20-2
n-tier Web



Django20-3

djangobook.py3k.cn/2.0/chapter12/

14/18

2010-5-5

Django

20-3
Web lighttpdtux
(http://www.djangoproject.com/r/tux/) Apache


Djangoadmin
MEDIA_ROOT

Django
Django

1000

20-3

Web Django
Apache
load balancer

Apaches mod_proxy memcached


.(15)

FastCGIwebFastCGI
FastCGI
Apache/mod_python/Django
20-4

djangobook.py3k.cn/2.0/chapter12/

15/18

2010-5-5

Django

20-4
Web
Web

MySQL
PostgreSQLSlony (http://www.djangoproject.com/r/slony/) pgpool
(http://www.djangoproject.com/r/pgpool/)
round-robinDNS

cachecache

20-5

20-5 Django

djangobook.py3k.cn/2.0/chapter12/

16/18

2010-5-5

Django

Django

Django
Django

RAM
RAM RAM
Web90%IO
RAM


2GB
Web

Keep-Alive
KeepAlive HTTPHTTPTCP

TCPHTTPHTTPTCP
Django
10 HTTPkeep-alive
HTTP

memcached
Djangocache memcached
memcached

memcached
memcached Chapter 15 is your best
friend here: Djangocache

DjangoLinuxApachePostgreSQLMySQL
1%

Django Django

djangobook.py3k.cn/2.0/chapter12/

17/18

2010-5-5

Django

Django

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter12/

18/18

2010-5-5

HTML

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

HTML
HTML WebHTMLWeb
RSSPDF
HTML Django

DjangoHTML
RSS/Atom
XMLGoogle

MIME
WebWebPython
WebHTML404 XML

Django
HttpRequest
HttpResponse
HTML HttpResponse mimetype
MIME
PNG

from django.http import HttpResponse


def my_image(request):
image_data = open("/path/to/my/image.png", "rb").read()
return HttpResponse(image_data, mimetype="image/png")

open()

HttpResponsePython(API)
PythonHttpResponse
Django CSV

djangobook.py3k.cn/2.0/chapter13/

1/15

2010-5-5

HTML

CSV
CSV
(CSV (comma-separated values) )CSV

Year,Unruly Airline Passengers


1995,146
1996,184
1997,235
1998,200
1999,226
2000,251
2001,299
2002,273
2003,281
2004,304
2005,203
2006,134
2007,147


CSV CSV
Python CSV csv
csv HttpResponse
import csv
from django.http import HttpResponse
# Number of unruly passengers each year 1995 2005. In a real application
# this would likely come from a database or some other backend data store.
UNRULY_PASSENGERS = [146,184,235,200,226,251,299,273,281,304,203]
def unruly_passengers_csv(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(mimetype='text/csv')
response['ContentDisposition'] = 'attachment; filename=unruly.csv'
# Create the CSV writer using the HttpResponse as the "file."
writer = csv.writer(response)
writer.writerow(['Year', 'Unruly Airline Passengers'])
for (year, num) in zip(range(1995, 2006), UNRULY_PASSENGERS):
writer.writerow([year, num])
return response

text/csv MIME text/html CSV


ContentDisposition CSV

djangobook.py3k.cn/2.0/chapter13/

2/15

2010-5-5

HTML

HttpResponseHttpResponse
CSVAPI response csv.writer
csv.writer HttpResponse
writer.writerow list tuple CSV

CSV writerow()

HTML HttpResponse
MIME

PDF
(PDF) Adobe pixel-perfect
2D You can think of a PDF document as the digital equivalent of a printed
document; indeed, PDFs are often used in distributing documents for the purpose of printing them.
Python Django PDF ReportLab
(http://www.reportlab.org/rl_toolkit.html) PDF
PDF The advantage of generating PDF files dynamically is
that you can create customized PDFs for different purposes say, for different users or different pieces
of content.
Django ReportLab KUSports.com NCAA
(tournament brackets)

ReportLab
PDF ReportLab Its usually simple: just
download and install the library from http://www.reportlab.org/downloads.html.
Note
Linux
ReportLab
Ubuntu aptget install pythonreportlab

PDF http://www.reportlab.org/rsrc/userguide.pdf

Python
>>> import reportlab

djangobook.py3k.cn/2.0/chapter13/

3/15

2010-5-5

HTML

CSV Django PDF ReportLab API


Hello World
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['ContentDisposition'] = 'attachment; filename=hello.pdf'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response

MIME application/pdf PDF


HTML HTML
If you leave off this information, browsers will probably interpret the response
as HTML, which will result in scary gobbledygook in the browser window.
ReportLab API response canvas.Canvas
PDF PDF p response
PDF showPage() save() PDF

PDF
PDF cStringIO PDF
cStringIO C
cStringIO Hello World
from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['ContentDisposition'] = 'attachment; filename=hello.pdf'
temp = StringIO()

djangobook.py3k.cn/2.0/chapter13/

4/15

2010-5-5

HTML
# Create the PDF object, using the StringIO object as its "file."
p = canvas.Canvas(temp)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the StringIO buffer and write it to the response.
response.write(temp.getvalue())
return response

Python
Here are a few more ideas and some pointers to libraries you could use to implement them:
ZIP Python zipfile ZIP
TAR tarfile

Python (PIL; http://www.pythonware.com/products/pil/)


(PNG, JPEG, GIF )
Web

Python

matplotlib (http://matplotlib.sourceforge.net/) matlab Mathematica

pygraphviz (https://networkx.lanl.gov/wiki/pygraphviz) Graphviz

(http://graphviz.org/) Python
Django The possibilities are immense.
HTML Django
HTML

DjangoRSSAtom feeds
RSS Atom
RSSAtomXMLfeed RSS
http://www.whatisrss.com/, Atom http://www.atomenabled.org/.
(syndication feed)python
(feed)
feed/feeds/DjangoURL(/feeds/)

djangobook.py3k.cn/2.0/chapter13/

5/15

2010-5-5

HTML

feed Django uses the remainder of the URL (everything after /feeds/ ) to determine
which feed to return.
sitemap Sitemap URLconf

Djangosyndication feeds, URLconf:


(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}
),

DjangoRSS "feeds/" URL. ( "feeds/"


. )
URLConf {'feed_dict': feeds}URLfeed
syndication framework
feed_dictfeedslug(URL)Feed URL
feed_dict You can define the feed_dict in the URLconf itself. Heres a full
example URLconf:
from django.conf.urls.defaults import *
from mysite.feeds import LatestEntries, LatestEntriesByCategory
feeds = {
'latest': LatestEntries,
'categories': LatestEntriesByCategory,
}
urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)

feed:
LatestEntries````feeds/latest/ .

LatestEntriesByCategory`` ``feeds/categories/ .

Feed
Feed pythonsyndication feed. feed (
feedblog)(blog
feed category ).
Feeddjango.contrib.syndication.feeds.Feed

Feed
This simple example describes a feed of the latest five blog entries for a given blog:

djangobook.py3k.cn/2.0/chapter13/

6/15

2010-5-5

HTML

from django.contrib.syndication.feeds import Feed


from mysite.blog.models import Entry
class LatestEntries(Feed):
title = "My Blog"
link = "/archive/"
description = "The latest news about stuff."
def items(self):
return Entry.objects.order_by('pub_date')[:5]

:
django.contrib.syndication.feeds.Feed .
title , link , description RSS <title> , <link> , <description> .

items() feed <item> list Djangos

database API NewsItem , items() model Although this example


returns Entry objects using Djangos database API, items() doesnt have to return model
instances.
RSS feed(item)(title)(link)(description)
In an RSS feed, each <item> has a <title> , <link> , and <description> . We need to
tell the framework what data to put into those elements.
<title> <description> DjangoChapter 4
feeds/latest_title.html feeds/latest_description.html URLConffeed
slug .html Note that the .html extension is required.

RSS2
obj : ( items() )

site : django.models.core.sites.Site {{ site.domain }}


{{ site.name }}

"{{ obj }}"


(For model objects, this will be the __unicode__() method.
Feed title_template description_template

<link> Django items() get_absolute_url()


Feed item_link() item
get_absolute_url() item_link() PythonURL

LatestEntries feed latest_title.html


{{ obj.title }}

latest_description.html :

djangobook.py3k.cn/2.0/chapter13/

7/15

2010-5-5

HTML

{{ obj.description }}

Feed
feeds
For example, say your blog offers an RSS feed for every distinct tag youve used to categorize your
entries. Feed
feeds URL
Your tag-specific feeds could use URLs like this:
http://example.com/feeds/tags/python/ : Returns recent entries tagged with python

http://example.com/feeds/tags/cats/ : Returns recent entries tagged with cats

"beats"
feeds
from django.core.exceptions import ObjectDoesNotExist
from mysite.blog.models import Entry, Tag
class TagFeed(Feed):
def get_object(self, bits):
# In case of "/feeds/tags/cats/dogs/mice/", or other such
# clutter, check that bits has only one member.
if len(bits) != 1:
raise ObjectDoesNotExist
return Tag.objects.get(tag=bits[0])
def title(self, obj):
return "My Blog: Entries tagged with %s" % obj.tag
def link(self, obj):
return obj.get_absolute_url()
def description(self, obj):
return "Entries tagged with %s" % obj.tag
def items(self, obj):
entries = Entry.objects.filter(tags__id__exact=obj.id)
return entries.order_by('pub_date')[:30]

RSSURL /rss/beats/0613/
URL /rss/beats/0613/ URLslug ("/" )
Feed get_object()
['0613'] /rss/beats/0613/foo/bar/ URL
['0613', 'foo', 'bar']
get_object() bits

djangobook.py3k.cn/2.0/chapter13/

8/15

2010-5-5
HTML
In this case, it uses the Django database API to retrieve the Tag . Note that get_object() should raise
django.core.exceptions.ObjectDoesNotExist if given invalid parameters. Beat.objects.get()

try /except Beat.DoesNotExist Beat.DoesNotExist


ObjectDoesNotExist
<title> <link> <description> feeds Django title() , link() ,
description()

title link description Django

1. get_object() obj
2.
3.

items() obj items


items(obj) items() items
Feed Django

(http://www.djangoproject.com/documentation/0.96/syndication_feeds/)

Feed
, RSS 2.0. , Feed feed_type . To change that,
add a feed_type attribute to your Feed class:
from django.utils.feedgenerator import Atom1Feed
class MyFeed(Feed):
feed_type = Atom1Feed

feed_type Feed11-1
11-1. Feed
Feed

django.utils.feedgenerator.Rss201rev2Feed

RSS 2.01 (default)

django.utils.feedgenerator.RssUserland091Feed

RSS 0.91

django.utils.feedgenerator.Atom1Feed

Atom 1.0

feedMP3 feeds item_enclosure_url


item_enclosure_length item_enclosure_mime_type
from myproject.models import Song
class MyFeedWithEnclosures(Feed):
title = "Example feed with enclosures"
link = "/feeds/examplewithenclosures/"
def items(self):
return Song.objects.all()[:30]

djangobook.py3k.cn/2.0/chapter13/

9/15

2010-5-5

HTML
def item_enclosure_url(self, item):
return item.song_url
def item_enclosure_length(self, item):
return item.song_length
item_enclosure_mime_type = "audio/mpeg"

song_url song_length Song

Feed <language> (RSS 2.0) xml:lang (Atom).


LANGUAGE_CODE . This comes directly from your LANGUAGE_CODE setting.

URLs
link /URL "/blog/" URL
"http://www.example.com/blog/" link SITE_ID

(See Chapter 16 for more on SITE_ID and the sites framework.)


Atom feeds <link rel="self"> feeds The syndication framework populates this
automatically.

Atom and RSS


AtomRSS Django feed
feed_type URLconf Heres a full example:
from django.contrib.syndication.feeds import Feed
from django.utils.feedgenerator import Atom1Feed
from mysite.blog.models import Entry
class RssLatestEntries(Feed):
title = "My Blog"
link = "/archive/"
description = "The latest news about stuff."
def items(self):
return Entry.objects.order_by('pub_date')[:5]
class AtomLatestEntries(RssLatestEntries):
feed_type = Atom1Feed

URLconf
from django.conf.urls.defaults import *
from myproject.feeds import RssLatestEntries, AtomLatestEntries
feeds = {
'rss': RssLatestEntries,
'atom': AtomLatestEntries,
}
urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...

djangobook.py3k.cn/2.0/chapter13/

10/15

2010-5-5

HTML

Sitemap
sitemap XML

Django (http://www.djangoproject.com/sitemap.xml)sitemap
<?xml version="1.0" encoding="UTF8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.djangoproject.com/documentation/</loc>
<changefreq>weekly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>http://www.djangoproject.com/documentation/0_90/</loc>
<changefreq>never</changefreq>
<priority>0.1</priority>
</url>
...
</urlset>

sitemaps , http://www.sitemaps.org/.
Django sitemap Python XML
`` Sitemap`` URLconf

sitemap , :
1. 'django.contrib.sitemaps' INSTALLED_APPS .
2. 'django.template.loaders.app_directories.load_template_source' TEMPLATE_LOADERS

, , ,
3. sites (14).

Note
sitemap . INSTALLED_APPS :
load_template_source . The only reason it needs to go into
INSTALLED_APPS is so the load_template_source template loader can find the default templates.

Initialization
Djangositemap, URLconf :
(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})

This line tells Django to build a sitemap when a client accesses /sitemap.xml . Note that the dot
character in sitemap.xml is escaped with a backslash, because dots have a special meaning in regular
expressions.
sitemap sitemapURL

djangobook.py3k.cn/2.0/chapter13/

11/15

2010-5-5

HTML

sitemap.xml URL
sitemap /content/sitemap.xml /content/ URL
sitemap {'sitemaps': sitemaps} . sitemaps should be a dictionary that
maps a short section label (e.g., blog or news ) to its Sitemap class (e.g., BlogSitemap or NewsSitemap ). It
may also map to an instance of a Sitemap class (e.g., BlogSitemap(some_var) ).

Sitemap
Sitemap Python., Sitemap

For example, one Sitemap class could represent all the entries of your
weblog, while another could represent all of the events in your events calendar.
sitemap.xml

Sitemap django.contrib.sitemaps.Sitemap .

blog Entry modelblog


Sitemap
from django.contrib.sitemaps import Sitemap
from mysite.blog.models import Entry
class BlogSitemap(Sitemap):
changefreq = "never"
priority = 0.5
def items(self):
return Entry.objects.filter(is_draft=False)
def lastmod(self, obj):
return obj.pub_date

Sitemap Feed
Feed Sitemap

Sitemap /:
items ( )

location()

lastmod() changefreq() priority()


location URL URL

: '/foo/bar/' '/foo/bar/'

: 'example.com/foo/bar/' 'example.com/foo/bar/'

Bad: 'http://example.com/foo/bar/'

location , items() get_absolute_url() .

djangobook.py3k.cn/2.0/chapter13/

12/15

2010-5-5

HTML

lastmod (): , Python datetime . The objects last modification

date, as a Python datetime object.


changefreq Sitemaps
'always'

'hourly'

'daily'

'weekly'

'monthly'

'yearly'

'never'

priority 0.0 and 1.0

sitemap

FlatPageSitemap
django.contrib.sitemaps.FlatPageSitemap flat pagesitemap

location lastmod changefreq priority


16flat page.

GenericSitemap
GenericSitemap 9

info_dict queryset
date_field queryset lastmod

FlatPageSitemap and GenericSiteMap Entry URLconf


from django.conf.urls.defaults import *
from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap
from mysite.blog.models import Entry
info_dict = {
'queryset': Entry.objects.all(),
'date_field': 'pub_date',
}
sitemaps = {
'flatpages': FlatPageSitemap,

djangobook.py3k.cn/2.0/chapter13/

13/15

2010-5-5

HTML
'blog': GenericSitemap(info_dict, priority=0.6),

}
urlpatterns = patterns('',
# some generic view using info_dict
# ...
# the sitemap
(r'^sitemap\.xml$',
'django.contrib.sitemaps.views.sitemap',
{'sitemaps': sitemaps})
)

Sitemap
sitemap sitemaps sitemap
URLconf : django.contrib.sitemaps.views.index
django.contrib.sitemaps.views.sitemap . `` django.contrib.sitemaps.views.index`` ``

django.contrib.sitemaps.views.sitemap``
django.contrib.sitemaps.views.sitemap section .

URLconf :
(r'^sitemap.xml$',
'django.contrib.sitemaps.views.index',
{'sitemaps': sitemaps}),
(r'^sitemap(?P<section>.+).xml$',
'django.contrib.sitemaps.views.sitemap',
{'sitemaps': sitemaps})

sitemap.xml , sitemapflatpages.xml sitemapblog.xml . Sitemap


sitemaps .

Google
sitemapGoogle
django.contrib.sitemaps.ping_google()
ping_google() sitemap_url URL

sitemap URL, ping_google() django.contrib.sitemaps.SitemapNotFound


save() ping_google()
from django.contrib.sitemaps import ping_google
class Entry(models.Model):
# ...
def save(self, *args, **kwargs):
super(Entry, self).save(*args, **kwargs)
try:
ping_google()
except Exception:
# Bare 'except' because we could get a variety
# of HTTPrelated exceptions.

djangobook.py3k.cn/2.0/chapter13/

14/15

2010-5-5

HTML
pass

cron ping_google() HttpGoogle


save() The function makes an HTTP request to
Googles servers, so you may not want to introduce that network overhead each time you call save()
.
Finally, if 'django.contrib.sitemaps' is in your INSTALLED_APPS , then your manage.py will include a new
command, ping_google . This is useful for command-line access to pinging. For example:
python manage.py ping_google /sitemap.xml

, Django ` <../chapter14/>`__
sessions, users authentication.

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter13/

15/15

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |


Web

()

HTTP
(IP)
(cookies)

Cookies
HTTPs Web
(cookies) cookies Web
cookies
google.com GoogleHTTP

GET / HTTP/1.1
Host: google.com
...

GoogleHTTP
HTTP/1.1 200 OK
ContentType: text/html
SetCookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671;
expires=Sun, 17Jan2038 19:14:07 GMT;
path=/; domain=.google.com
Server: GWS/2.1
...

SetCookie cookie(
PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671 ) google

cookie Google
GET / HTTP/1.1
Host: google.com
Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671
...

Cookies GoogleGoogle
key Google

djangobook.py3k.cn/2.0/chapter14/

1/17

2010-5-5

Cookies
Djangosession / user
cookies
cookies
cookies `` HttpRequest`` `` COOKIES``
viewcookies
def show_color(request):
if "favorite_color" in request.COOKIES:
return HttpResponse("Your favorite color is %s" %

request.COOKIES["favorite_co

else:
return HttpResponse("You don't have a favorite color.")

cookies HttpResponse set_cookie() GET


favorite_color

cookie

def set_color(request):
if "favorite_color" in request.GET:
# Create an HttpResponse object...
response = HttpResponse("Your favorite color is now %s" %

request.GET["favorit

# ... and set a cookie on the response


response.set_cookie("favorite_color",
request.GET["favorite_color"])
return response
else:
return HttpResponse("You didn't give a favorite color.")

response.set_cookie() cookie14-1
System Message: ERROR/3 (<string>, line 145)
Error parsing content block for the table directive: exactly one table expected.
.. table:: 141: Cookie
+++
|
|
|
+=================================+===========================+================================
|``None``
|cookie
+++
|``max_age``

|``expires``
|``None``
|cookie/
+++
|``path``

|``"/"``

|cookie co
|

+++
|``domain``
|

|``None``
|

|cookie
|

|
|\ `` None`` coo
+++
|

|``False``

djangobook.py3k.cn/2.0/chapter14/

|``False``

| ``True`` HT

2/17

2010-5-5


+++

Cookies
cookies
cookiecookie
cookies cookiesWeb

cookies cookies
cookie
Cookie(HTTPS) HTTP
cookies cookies
cookie
cookie 19

cookie cookies
mechanize(http://wwwsearch.sourceforge.net/mechanize/)
HTTP
cookies cookies IsLoggedIn=1

Django Session
cookiesWeb Django
session
1

session cookie
CookiesIDcookie
session

Sessions
Sessions (17)(model) sessions

1. MIDDLEWARE_CLASSES MIDDLEWARE_CLASSES
'django.contrib.sessions.middleware.SessionMiddleware'
2. INSTALLED_APPS 'django.contrib.sessions' (
manage.py syncdb )

startproject
session
session MIDDLEWARE_CLASSES SessionMiddleware INSTALLED_APPS

djangobook.py3k.cn/2.0/chapter14/

3/17

2010-5-5

'django.contrib.sessions'

Session
SessionMiddleware (view)``HttpRequest`` session

(view)
# Set a session value:
request.session["fav_color"] = "blue"
# Get a session value this could be called in a different view,
# or many requests later (or both):
fav_color = request.session["fav_color"]
# Clear an item from the session:
del request.session["fav_color"]
# Check if the session has a given key:
if "fav_color" in request.session:
...

keys() items() request.session


Django sessions
key request.session
SessionkeyDjangokey
sessionDjango
Django
`` _fav_color`` (session key)
request.session['_fav_color'] = 'blue' # Don't do this!

request.session Python

request.session = some_other_object # Don't do this!


request.session.foo = 'bar' # Don't do this!

has_commented
True
def post_comment(request):
if request.method != 'POST':
raise Http404('Only POSTs are allowed')
if 'comment' not in request.POST:
raise Http404('Comment not submitted')
if request.session.get('has_commented', False):
return HttpResponse("You've already commented.")
c = comments.Comment(comment=request.POST['comment'])
c.save()
request.session['has_commented'] = True
return HttpResponse('Thanks for your comment!')

djangobook.py3k.cn/2.0/chapter14/

4/17

2010-5-5

(view)
def login(request):
if request.method != 'POST':
raise Http404('Only POSTs are allowed')
try:
m = Member.objects.get(username=request.POST['username'])
if m.password == request.POST['password']:
request.session['member_id'] = m.id
return HttpResponseRedirect('/youareloggedin/')
except Member.DoesNotExist:
return HttpResponse("Your username and password didn't match.")

`` login()``
def logout(request):
try:
del request.session['member_id']
except KeyError:
pass
return HttpResponse("You're logged out.")

(authentication )

Cookies
cookie Django
cookie (view) request.session.set_test_cookie()

(view)(view) request.session.test_cookie_worked()
set_test_cookie() test_cookie_worked() cookie
cookie
cookie
cookie delete_test_cookie()
cookie

def login(request):
# If we submitted the form...
if request.method == 'POST':
# Check that the test cookie worked (we set it below):
if request.session.test_cookie_worked():
# The test cookie worked, so delete it.
request.session.delete_test_cookie()
# In practice, we'd need some logic to check username/password
# here, but since this is an example...
return HttpResponse("You're logged in.")

djangobook.py3k.cn/2.0/chapter14/

5/17

2010-5-5


# The test cookie failed, so display an error message. If this
# were a real site, we'd want to display a friendlier message.
else:
return HttpResponse("Please enable cookies and try again.")
# If we didn't post, send the test cookie along with the login form.
request.session.set_test_cookie()
return render_to_response('foo/login_form.html')

(View)Session
sessionDjango model django.contrib.sessions.models )
session32cookie
DjangoAPIsession
>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)

get_decoded() session
>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}

Session
Djangosession
# Session is modified.
request.session['foo'] = 'bar'
# Session is modified.
del request.session['foo']
# Session is modified.
request.session['foo'] = {}
# Gotcha: Session is NOT modified, because this alters
# request.session['foo'] instead of request.session.
request.session['foo']['bar'] = 'baz'

SESSION_SAVE_EVERY_REQUEST True TrueDjango


session
cookie SESSION_SAVE_EVERY_REQUEST True
cookie cookie expires

vs
Googlecookie expires=Sun, 17Jan2038 19:14:07 GMT; cookie

djangobook.py3k.cn/2.0/chapter14/

6/17

2010-5-5

cookie cookie
cookie SESSION_EXPIRE_AT_BROWSER_CLOSE session

SESSION_EXPIRE_AT_BROWSER_CLOSE False cookie


SESSION_COOKIE_AGE 1,209,600

SESSION_EXPIRE_AT_BROWSER_CLOSE True Djangocookie

Session
Django sessioncookie 14-2.
14-2. cookie

SESSION_COOKIE_DOMAIN

cookiesession cookies

None

`` .example.com`` crossdomaincookie`` None``


SESSION_COOKIE_NAME

cookie

SESSION_COOKIE_SECURE

sessioncookie True , cookie False


cookieHTTPS

"sessionid"

session
session Python Pythonpickle
Session django_session
Session request.session Django

Django cookie
cookie( SESSION_SAVE_EVERY_REQUEST True )
Django session cookie IDURL
(PHP,JSP)
sessionURL
Referer headersession ID
django.contrib.sessions

Authentication
session session

Django Django
cookie auth/auth ()

djangobook.py3k.cn/2.0/chapter14/

7/17

2010-5-5

1. () ()
2.

()

Django /

:
: (yes/no)
:
Messages :
admin(6)admin

sessionDjango django.contrib session

1. session cookiesesson

2. 'django.contrib.auth' INSTALLED_APPS manage.py syncdb

3. SessionMiddleware MIDDLEWARE_CLASSES
'django.contrib.auth.middleware.AuthenticationMiddleware' SessionMiddleware

(view)user users request.user


AnonymousUser()
is_authenticated()
if request.user.is_authenticated():
# Do something for authenticated users.
else:
# Do something for anonymous users.

User
User request.user
AnonymousUser

user

user.is_authenticated() 14-314-4`` User`` fields)


1

14-3. User

username

30

first_name

; 30

djangobook.py3k.cn/2.0/chapter14/

8/17

2010-5-5

last_name

; 30

email

password

Django See the Passwords section for more about


this value.

is_staff

is_active

. False

is_superuser

last_login

date_joined

System Message: ERROR/3 (<string>, line 735)


Error parsing content block for the table directive: exactly one table expected.
.. table:: 144. ``User``
++
|

+=============================================================================================+
|``is_authenticated()``

|
|
++
|``is_anonymous()``

++
|``get_full_name()``
|
++
|``set_password(passwd)``

++
|check_password(passwd)

++
|``get_group_permissions()``
|
++
|``get_all_permissions()``

++
|``has_perm(perm)``

++
|has_perms(perm_list)
|
++
|``has_module_perms(app_label)``

++
|get_and_delete_messages()

++
|``email_user(subj, msg)``
|
++

`` User`` many-to-many `` groups`` `` permissions`` many-tomany`` User``


# Set a user's groups:
myuser.groups = group_list
# Add a user to some groups:
myuser.groups.add(group1, group2,...)
# Remove a user from some groups:
myuser.groups.remove(group1, group2,...)

djangobook.py3k.cn/2.0/chapter14/

9/17

2010-5-5

# Remove a user from all groups:


myuser.groups.clear()
# Permissions work the same way
myuser.permissions = permission_list
myuser.permissions.add(permission1, permission2, ...)
myuser.permissions.remove(permission1, permission2, ...)
myuser.permissions.clear()

Django (view) ()
Djangodjango.contrib.auth\ : authenticate()

login()
authenticate() username
password User authenticate()
None
>>> from django.contrib import auth
>>> user = auth.authenticate(username='john', password='secret')
>>> if user is not None:
...

print "Correct!"

... else:
...

print "Invalid password."

authenticate() login()
HttpRequest User Django session ID

authenticate() login()
from django.contrib import auth
def login_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None and user.is_active:
# Correct password, and the user is marked "active"
auth.login(request, user)
# Redirect to a success page.
return HttpResponseRedirect("/account/loggedin/")
else:
# Show an error page
return HttpResponseRedirect("/account/invalid/")

django.contrib.auth.logout() HttpRequest

from django.contrib import auth


def logout_view(request):
auth.logout(request)
# Redirect to a success page.
return HttpResponseRedirect("/account/loggedout/")

logout()

djangobook.py3k.cn/2.0/chapter14/

10/17

2010-5-5

/
URLconf
from django.contrib.auth.views import login, logout
urlpatterns = patterns('',
# existing patterns here...
(r'^accounts/login/$',

login),

(r'^accounts/logout/$', logout),
)
/accounts/login/ /accounts/logout/ DjangoURL

login registragiton/login.html ( template_name


) username password template

{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p class="error">Sorry, that's not a valid username or password</p>
{% endif %}
<form action="" method="post">
<label for="username">User name:</label>
<input type="text" name="username" value="" id="username">
<label for="password">Password:</label>
<input type="password" name="password" value="" id="password">
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next|escape }}" />
</form>
{% endblock %}

/accounts/profile URLnext
GETnext

logout registration/logged_out.html
next_page

request.user.is_authenticated() ,
from django.http import HttpResponseRedirect
def my_view(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/?next=%s' % request.path)
# ...

djangobook.py3k.cn/2.0/chapter14/

11/17

2010-5-5

def my_view(request):
if not request.user.is_authenticated():
return render_to_response('myapp/login_error.html')
# ...

, login_required :
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
# ...
login_required :

, /accounts/login/ , URL next ,


/accounts/login/?next=/polls/3/
,

login
request.user
polls.can_vote
def vote(request):
if request.user.is_authenticated() and request.user.has_perm('polls.can_vote')):
# vote here
else:
return HttpResponse("You can't vote in this poll.")

Django user_passes_test
def user_can_vote(user):
return user.is_authenticated() and user.has_perm("polls.can_vote")
@user_passes_test(user_can_vote, login_url="/login/")
def vote(request):
# Code here can assume a loggedin user with the correct permission.
...
user_passes_test User
True user_passes_test User

login_url URL
/accounts/login/ user_passes_test login_url

Django
permission_required()
from django.contrib.auth.decorators import permission_required

djangobook.py3k.cn/2.0/chapter14/

12/17

2010-5-5

@permission_required('polls.can_vote', login_url="/login/")
def vote(request):
# ...

, permission_required() login_url , '/accounts/login/'

Django
URLconf
from django.contrib.auth.decorators import login_required
from django.views.generic.date_based import object_detail
@login_required
def limited_object_detail(*args, **kwargs):
return object_detail(*args, **kwargs)

, login_required

Users, Permissions Groups


Django

API

create_user :
>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user(username='john',
...

email='jlennon@beatles.com',

...

password='glass onion')

user User create_user()


save() create_user()

>>> user.is_staff = True


>>> user.save()

set_password()
>>> user = User.objects.get(username='john')
>>> user.set_password('goo goo goo joob')
>>> user.save()

password salthash

User password
hashtype$salt$hash

djangobook.py3k.cn/2.0/chapter14/

13/17

2010-5-5

salt$
hashtype sha1 md5 Salt

:
sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4
User.set_password() User.check_password()

salt

rainbow tables
rainbow tables
hash salt
saltrainbow table
salthash


Django
, , Django
, :
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect("/books/")
else:
form = UserCreationForm()
return render_to_response("registration/register.html", {
'form': form,
})

registration/register.html
{% extends "base.html" %}

djangobook.py3k.cn/2.0/chapter14/

14/17

2010-5-5

{% block title %}Create an account{% endblock %}


{% block content %}
<h1>Create an account</h1>
<form action="" method="post">
{{ form.as_p }}
<input type="submit" value="Create the account">
</form>
{% endblock %}

RequestContext context9

RequestContext TEMPLATE_CONTEXT_PROCESSORS
django.core.context_processors.auth
context TEMPLATE_CONTEXT_PROCESSORS "django.core.context_processors.auth"
context
RequestContext , ( User AnonymousUser )
{{ user }} :
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}

{{ perms }}
perms {{ perms.polls }}
{{ perms.polls.can_vote }}

{% if %} :
{% if perms.polls %}
<p>You have permission to do something in the polls app.</p>
{% if perms.polls.can_vote %}
<p>You can vote!</p>
{% endif %}
{% else %}
<p>You don't have permission to do anything in the polls app.</p>
{% endif %}

Djangoadmin

djangobook.py3k.cn/2.0/chapter14/

15/17

2010-5-5

Djangoadmin
add
change
delete
Mary
MaryID

Django manage.py syncdb


auth_permission
"<app>.<action>_<object_name>"
Django django.contrib.auth.models
DjangoAPI

Site editors can_edit_home_page

'Special users'
VIPVIP
admin Django
django.contrib.auth.models DjangoAPI

User
Djangoadmin
admin The object was created successfully
API API
user.message_set.create(message='message_text')
/ user.get_and_delete_messages() Message

playlist
def create_playlist(request, songs):
# Create the playlist with the given songs.

djangobook.py3k.cn/2.0/chapter14/

16/17

2010-5-5


# ...
request.user.message_set.create(
message="Your playlist was added successfully."
)
return render_to_response("playlists/create.html",
context_instance=RequestContext(request))

RequestContext {{ messages }}
context
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}

RequestContext get_and_delete_messages


` <../chapter15/>`__ Django

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter14/

17/17

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |

washingtonpost.com
Slashdot

given a URL, try finding that page in the cache


if the page is in the cache:
return the cached page
else:
generate the page
save the generated page in the cache (for next time)
return the generated page

Django
Django

DjangoSquid(http://www.squid-cache.org)
(HTTP)

settings CACHE_BACKEND CACHE_BACKEND

MemcachedDjangoMemcached
LiveJournal.comDanga Interactive
Facebook
Memcachedhttp://danga.com/memcached

djangobook.py3k.cn/2.0/chapter15/

1/12

2010-5-5

MemcachedMemcached PythonDjango

cmemcachehttp://gijsbert.org/cmemcache
cmemcachepython - Memcached
ftp://ftp.tummy.com/pub/python-memcached/Memcached
http://www.danga.com/memcached/APIPython
MemcachedDjangoCACHE_BACKENDmemcached/ / IPport/IP
MemcachedIPportMemcached
Memcached (127.0.0.1),11211
CACHE_BACKEND = 'memcached://127.0.0.1:11211/'

Memcached
Memcached
CACHE_BACKEND
IP172.19.26.240172.19.26.24211211Memcached
:
CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'

172.19.26.240(11211)172.19.26.242(11212)172.19.26.244(
11213)Memcached:
CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.244:11213/'

Memcached

Django

python manage.py createcachetable [cache_table_name]

[cache_table_name]
Django
CACHE_BACKENDdb://tablenametablename
my_cache_table:
my_cache_table
CACHE_BACKEND = 'db://my_cache_table'
1

settings .

djangobook.py3k.cn/2.0/chapter15/

2/12

2010-5-5

CACHE_BACKENDfile://
/var/tmp/django_cache
CACHE_BACKEND = 'file:///var/tmp/django_cache'

file:///var/tmp/django_cache
Windowsfile://
file://c:/foo/bar

**
Web
apache/var/tmp/django_cacheapache
/var/tmp/django_cache
Pythonpickle(pickled)

Memcached
CACHE_BACKEND locmem:/// :
CACHE_BACKEND = 'locmem:///'

Django
/
CACHE_BACKEND
CACHE_BACKEND = 'dummy:///'

Django Django
Python importCACHE_BACKEND URI

CACHE_BACKEND = 'path.to.backend://'

Django
django/core/cache/backends/
Django

djangobook.py3k.cn/2.0/chapter15/

3/12

2010-5-5

CACHE_BACKEND
CACHE_BACKEND
timeout : 300

max_entries
300
cull_percentage : max_entries , 1/cull_percentage ,

cull_frequency=2 max_entries
cull_frequency 0 max_entries ,
,
timeout 60
CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60"

timeout 30 max_entries 400 :


CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"

Cache

django.middleware.cache.UpdateCacheMiddleware
django.middleware.cache.FetchFromCacheMiddlewareMIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
)

fectch
MIDDLEWARE_CLASSES
Django settings
CACHE_MIDDLEWARE_SECONDS :

CACHE_MIDDLEWARE_KEY_PREFIX Django

Djangokey

GETPOST

djangobook.py3k.cn/2.0/chapter15/

4/12

2010-5-5

CACHE_MIDDLEWARE_ANONYMOUS_ONLYTrue
user-specific pagesDjangos
CACHE_MIDDLEWARE_ANONYMOUS_ONLY
AuthenticationMiddleware
HttpResponse
()Last-Modified/
Expires/CACHE_MIDDLEWARE_SECONDS
Cache-ControlCACHE_MIDDLEWARE_SECONDS

17
CacheControl
CACHE_MIDDLEWARE_SECONDSdjango.views.decorators.cache
cache_controlnever_cache

django.views.decorators.cache
cache_page :
from django.views.decorators.cache import cache_page
def my_view(request):
# ...
my_view = cache_page(my_view, 60 * 15)

Python2.4
@cache_page(60 * 15)
def my_view(request):
# ...
cache_page my_view() 15

60 * 15 60 * 15 900 15
60
URL URL
my_view URLconf
urlpatterns = ('',
(r'^foo/(\d{1,2})/$', my_view),
)

/foo/1/ /foo/23/
/foo/23/ URL

djangobook.py3k.cn/2.0/chapter15/

5/12

2010-5-5

URLconf
cache_page my_view

URLconf

URLconf cache_page
URLconf : URLconf
urlpatterns = ('',
(r'^foo/(\d{1,2})/$', my_view),
)

URLconf cache_page my_view


from django.views.decorators.cache import cache_page
urlpatterns = ('',
(r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),
)

, URLconf cache_page

cache {% load cache %}

{% cache %} :

{% load cache %}
{% cache 500 sidebar %}
.. sidebar ..
{% endcache %}


{% cache %}
{% load cache %}
{% cache 500 sidebar request.user.username %}
.. sidebar for logged in user ..
{% endcache %}

{% cache %}
my_timeout600

{% cache 600 sidebar %} ... {% endcache %}


{% cache my_timeout sidebar %} ... {% endcache %}

API
djangobook.py3k.cn/2.0/chapter15/

6/12

2010-5-5

DjangoAPI API
pickle Python
Python pickling
django.core.cacheCACHE_BACKENDdjango.core.cache
>>> from django.core.cache import cache

set(key, value, timeout_seconds) get(key) :


>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'
timeout_seconds , CACHE_BACKEND timeout .

cache.get()None
# Wait 30 seconds for 'my_key' to expire...
>>> cache.get('my_key')
None

None None None

cache.get()
>>> cache.get('my_key', 'has expired')
'has expired'

add() set()

>>> cache.set('add_key', 'Initial value')


>>> cache.add('add_key', 'New value')
>>> cache.get('add_key')
'Initial value'

add() TrueFalse
get_many() get_many()
>>> cache.set('a', 1)
>>> cache.set('b', 2)
>>> cache.set('c', 3)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}

, cache.delete()
>>> cache.delete('a')

djangobook.py3k.cn/2.0/chapter15/

7/12

2010-5-5

incr()decr() 1
ValueError
>>> cache.set('num', 1)
>>> cache.incr('num')
2
>>> cache.incr('num', 10)
12
>>> cache.decr('num')
11
>>> cache.decr('num', 5)
6

incr() /decr() memcached

Web

ISP () http://example.com/
ISP example.com example.com
ISP example.com
Django Squid (http://www.squidcache.org/)


URL

ISP
ISP

HTTP HTTP

Vary
Vary

djangobook.py3k.cn/2.0/chapter15/

8/12

2010-5-5

Django "/stories/2005/jun/23/bank_robbed/"
cookie
Varycookie
Django vary_on_headers
from django.views.decorators.vary import vary_on_headers
# Python 2.3 syntax.
def my_view(request):
# ...
my_view = vary_on_headers(my_view, 'UserAgent')
# Python 2.4+ decorator syntax.
@vary_on_headers('UserAgent')
def my_view(request):
# ...

Django

vary_on_headers Vary response['Vary'] = 'useragent'


Vary

vary_on_headers()
@vary_on_headers('UserAgent', 'Cookie')
def my_view(request):
# ...

user-agent cookie
Mozilla user-agent foo=bar cookie Mozilla
user-agent foo=ham
cookie vary_on_cookie
@vary_on_cookie
def my_view(request):
# ...
@vary_on_headers('Cookie')
def my_view(request):
# ...

vary_on_headers "UserAgent" "useragent"


django.utils.cache.patch_vary_headers Vary header

from django.utils.cache import patch_vary_headers


def my_view(request):
# ...
response = render_to_response('template_name', context)
patch_vary_headers(response, ['Cookie'])
return response

djangobook.py3k.cn/2.0/chapter15/

9/12

2010-5-5

patch_vary_headers HttpResponse



Web

Django cache_control

from django.views.decorators.cache import cache_control
@cache_control(private=True)
def my_view(request):
# ...

HTTP
, HTTP :

Django cache_control cache_control


3600
from django.views.decorators.cache import cache_control
@cache_control(must_revalidate=True, max_age=3600)
def my_view(request):
# ...

cache_control() CacheControl HTTP


public=True

private=True

no_cache=True

no_transform=True

must_revalidate=True

proxy_revalidate=True

djangobook.py3k.cn/2.0/chapter15/

10/12

2010-5-5

max_age=num_seconds

s_maxage=num_seconds

CACHE_MIDDLEWARE_SETTINGS max-age cache_control


max_age
django.views.decorators.cache.never_cache

from django.views.decorators.cache import never_cache
@never_cache
def myview(request):
# ...

Django :
django.middleware.http.ConditionalGetMiddleware ETag
LastModified GET

django.middleware.gzip.GZipMiddleware

MIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES
Vary
UpdateCacheMiddleware last

UpdateCacheMiddlewareVary

Cookie SessionMiddleware
AcceptEncoding GZipMiddleware
AcceptLanguageLocaleMiddleware
FetchFromCacheMiddleware
FetchFromCacheMiddlewareVary
FetchFromCacheMiddleware

Django adminsession/user
Django

djangobook.py3k.cn/2.0/chapter15/

11/12

2010-5-5


| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter15/

12/12

2010-5-5

django.con

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book


1

| | | | |

django.contrib
Python Python
Django

Django
Django django.contrib
django.contrib
django.contrib

django.contrib : django.contrib Django

Django
django.contrib
django.contrib
admin : 6

admindocs :Django admin Django

auth : Django

comments :

Django.
Django
contenttypes : Django

DjangoDjango
django/contrib/contenttypes/
csrf : (CSRF) CSRF

databrowse Django Django

flatpages : HTML Flatpages

djangobook.py3k.cn/2.0/chapter16/

1/15

2010-5-5

django.con
formtools Django

gis DjangoGISGeographic Information Systems

Django
http://geodjango.org/
humanize : Django

localflavor

markup : Django

redirects :

sessions : Django 14

sitemaps : XML 13

sites : Django

syndication : RSS Atom 13

webdesign Django {% lorem %}

Django
django.contrib

Django Django

1
Django LJWorld.com Lawrance.com
LJWorld.com Lawrence.com

LJWorld.comLawrence.com


Django

djangobook.py3k.cn/2.0/chapter16/

2/15

2010-5-5

django.con

2/
LJWorld.com Lawrence.com


Site name ( 'LJWorld.com' )
domain ( 'www.ljworld.com' )

Django Django name domain


django.contrib.sites Site domain name
SITE_ID Site ID

Django

1. 'django.contrib.sites' INSTALLED_APPS
2. manage.py syncdb django_site

example.com
3. example.com Django adminPython APISite

Django Site
4. SITE_ID Site

ID

, Site
from django.db import models
from django.contrib.sites.models import Site
class Article(models.Model):
headline = models.CharField(max_length=200)
# ...
sites = models.ManyToManyField(Site)


Django Article article_detail

djangobook.py3k.cn/2.0/chapter16/

3/15

2010-5-5

django.con

from django.conf import settings


from django.shortcuts import get_object_or_404
from mysite.articles.models import Article
def article_detail(request, article_id):
a = get_object_or_404(Article, id=article_id, sites__id=settings.SITE_ID)
# ...

SITE_ID articles
LJWorld.coms SITE_ID 1 Lawrence.coms SITE_ID
2 LJWorld.coms
LJWorld.com

Site

from django.db import models


from django.contrib.sites.models import Site
class Article(models.Model):
headline = models.CharField(max_length=200)
# ...
site = models.ForeignKey(Site)

Django
from django.conf import settings
def my_view(request):
if settings.SITE_ID == 3:
# Do something.
else:
# Do something else.

ID
from django.conf import settings
from django.contrib.sites.models import Site
def my_view(request):
current_site = Site.objects.get(id=settings.SITE_ID)
if current_site.domain == 'foo.com':
# Do something
else:
# Do something else.

Site settings.SITE_ID Site (Site.objects )


get_current()
from django.contrib.sites.models import Site
def my_view(request):

djangobook.py3k.cn/2.0/chapter16/

4/15

2010-5-5

django.con
current_site = Site.objects.get_current()
if current_site.domain == 'foo.com':
# Do something
else:
# Do something else.

django.conf.settings

DRY()
Site name domain
from django.contrib.sites.models import Site
from django.core.mail import send_mail
def register_for_newsletter(request):
# Check form values, etc., and subscribe the user.
# ...
current_site = Site.objects.get_current()
send_mail('Thanks for subscribing to %s alerts' % current_site.name,
'Thanks for your subscription. We appreciate it.\n\nThe %s team.' % current_site.name,
'editor@%s' % current_site.domain,
[user_email])
# ...

LJWorld.com Lawrence.com Lawrence.com


Lawrence.com LJWorld.com LJWorld.com

Django Lawrence.com
LJWorld.com TEMPLATE_DIRS
from django.core.mail import send_mail
from django.template import loader, Context
def register_for_newsletter(request):
# Check form values, etc., and subscribe the user.
# ...
subject = loader.get_template('alerts/subject.txt').render(Context({}))
message = loader.get_template('alerts/message.txt').render(Context({}))
send_mail(subject, message, 'donotreply@example.com', [user_email])
# ...

LJWorld.com Lawrence.com subject.txt message.txt



Site

CurrentSiteManager

CurrentSiteManager
from django.db import models

djangobook.py3k.cn/2.0/chapter16/

5/15

2010-5-5

django.con

from django.contrib.sites.models import Site


from django.contrib.sites.managers import CurrentSiteManager
class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(max_length=100)
pub_date = models.DateField()
site = models.ForeignKey(Site)
objects = models.Manager()
on_site = CurrentSiteManager()

Photo.objects.all() Photo Photo.on_site.all()


SITE_ID Photo

Photo.objects.filter(site=settings.SITE_ID)
Photo.on_site.all()
CurrentSiteManager Photo Site site

site CurrentSiteManager
publish_on
from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager
class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(max_length=100)
pub_date = models.DateField()
publish_on = models.ForeignKey(Site)
objects = models.Manager()
on_site = CurrentSiteManager('publish_on')

CurrentSiteManager Django ValueError

CurrentSiteManager
B Django
objects = models.Manager()

Django Django
CurrentSiteManager
objects = models.Manager()

Django
Django
Django domain name SITE_ID
ID
Django
Django
SITE_ID

djangobook.py3k.cn/2.0/chapter16/

6/15

2010-5-5

django.con
site SITE_ID

flatpages ( Flatpages flatpage


flatpage site flatpage flatpage
SITE_ID
syndication 13 title description {{ site }}
Site domainURL
Sitedomain
django.contrib.auth.views.loginSite
{{ site_name }}{{ site }}

Flatpages()
Web
Apache Web
Apache
Django
django.contrib.flatpages Django flatpages
Django Django
Django
DjangoAPI
URL URL

1. 'django.contrib.flatpages' INSTALLED_APPS django.contrib.flatpages

django.contrib.sitesINSTALLED_APPS
2. 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' MIDDLEWARE_CLASSES

3. manage.py syncdb

django_flatpage django_flatpage_sites django_flatpage


URL django_flatpage_sites

FlatPage django/contrib/flatpages/models.py
from django.db import models
from django.contrib.sites.models import Site

djangobook.py3k.cn/2.0/chapter16/

7/15

2010-5-5

django.con

class FlatPage(models.Model):
url = models.CharField(max_length=100, db_index=True)
title = models.CharField(max_length=200)
content = models.TextField(blank=True)
enable_comments = models.BooleanField()
template_name = models.CharField(max_length=70, blank=True)
registration_required = models.BooleanField()
sites = models.ManyToManyField(Site)

url : URL ( /about/contact/ )

title :

content : ( HTML )

enable_comments :

template_name :

flatpages/default.html
registration_required : Djangos /

sites : Django

Django Django API

FlatpageFallbackMiddleware Django 404


URL
URL SITE_ID ID

flatpages/default.html flatpage

RequestContext
FlatpageFallbackMiddleware

404 500
MIDDLEWARE_CLASSES FlatpageFallbackMiddleware

djangobook.py3k.cn/2.0/chapter16/

8/15

2010-5-5

django.con

Django Flatpages

Python API
django/contrib/flatpages/models.py Django
DjangoAPI
>>> from django.contrib.flatpages.models import FlatPage
>>> from django.contrib.sites.models import Site
>>> fp = FlatPage.objects.create(
...
...

url='/about/',
title='About',

...

content='<p>About this site...</p>',

...

enable_comments=False,

...

template_name='',

...

registration_required=False,

... )
>>> fp.sites.add(Site.objects.get(id=1))
>>> FlatPage.objects.get(url='/about/')
<FlatPage: /about/ About>

flatpages/default.html FlatPage
template_name

flatpages/default.html flatpages
default.html

flatpage
flatpages/default.html :
<!DOCTYPE HTML PUBLIC "//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REChtml40/loose.dtd">
<html>
<head>
<title>{{ flatpage.title }}</title>
</head>
<body>
{{ flatpage.content|safe }}
</body>
</html>

safeflatpage.contentHTML

Django Django
Django /music/ /sections/arts/music/

djangobook.py3k.cn/2.0/chapter16/

9/15

2010-5-5

django.con

1. 'django.contrib.redirects' INSTALLED_APPS
2. 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' MIDDLEWARE_CLASSES

3. manage.py syncdb
manage.py syncdb django_redirect site_id

old_pathnew_path
Django Django API

RedirectFallbackMiddleware Django 404


URL
old_path SITE_ID ID
SITE_ID

new_path new_path
new_path 410 (Gone) HTTP

404 500
MIDDLEWARE_CLASSES RedirectFallbackMiddleware

Django

Python API
django/contrib/redirects/models.py Django Django
API

djangobook.py3k.cn/2.0/chapter16/

10/15

2010-5-5

django.con

>>> from django.contrib.redirects.models import Redirect


>>> from django.contrib.sites.models import Site
>>> red = Redirect.objects.create(
...
...

site=Site.objects.get(id=1),
old_path='/music/',

...

new_path='/sections/arts/music/',

... )
>>> Redirect.objects.get(old_path='/music/')
<Redirect: /music/ > /sections/arts/music/>

CSRF
django.contrib.csrf (CSRF).

CSRF,
URL

CSRF
example.com example.com/logout
example.com/logout
URL example.com/logout <iframe> , URL
example.com example.com/logout <iframe>
example.com Thus, if youre logged in to the example.com
webmail account and visit the malicious page that has an <iframe> to example.com/logout , the act of
visiting the malicious page will log you out from example.com .

CSRF
example.com HTTP GET
HTTP POST
POST CSRF

example.com <form> URL example.com/logout POST


<form>
<input type="hidden" name="confirm" value="true">

example.com/logoutPOST POST
example.com/logout truePOST confirm

CSRF
<iframe> Javascript

CSRF
GET
<iframe>

djangobook.py3k.cn/2.0/chapter16/

11/15

2010-5-5

django.con

POST POST form


ID
Django CSRF

CSRF
django.contrib.csrf middleware.py Django
CsrfMiddleware CSRF

'django.contrib.csrf.middleware.CsrfMiddleware' MIDDLEWARE_CLASSES
CSRF SessionMiddleware CsrfMiddleware
SessionMiddleware

CsrfMiddleware GZipMiddleware
MIDDLEWARE_CLASSES MIDDLEWARE_CLASSES

CsrfMiddleware
1. POST csrfmiddlewaretoken

ID ID

2. cookie POST csrfmiddlewaretoken

403 HTTP 403

POST
HTTP POST POST
GET

cookie POST

HTML ContentType
text/html application/xml+xhtml

CSRF
CsrfMiddleware Django 14

cookies
HTML Javascript document.write
HTML
CsrfMiddlewarecsrfmiddlewaretokenHTML
HTML
csrfmiddlewaretoken
CSRF http://en.wikipedia.org/wiki/CSRF

djangobook.py3k.cn/2.0/chapter16/

12/15

2010-5-5

django.con

django.contrib.humanize
'django.contrib.humanize'INSTALLED_APPS
{% load humanize %}

apnumber
1 9

1 one
2 two
10 10

intcomma

4500 4,500
45000 45,000
450000 450,000
4500000 4,500,000

intword

1000000 1.0 million


1200000 1.2 million
1200000000 1.2 billion
1,000,000,000,000,000

djangobook.py3k.cn/2.0/chapter16/

13/15

2010-5-5

django.con

ordinal

1 1st
2 2nd
3 3rd
254254th

django.contrib.markupDjango
textile : Textile (http://en.wikipedia.org/wiki/Textile_%28markup_language%29)

markdown : Markdown (http://en.wikipedia.org/wiki/Markdown)

restructuredtext : ReStructured Text (http://en.wikipedia.org/wiki/ReStructuredText)

textile
TextileHTML
{% load markup %}
{{ object.content|textile }}

'django.contrib.markup' INSTALLED_APPS
{% load markup %}
django/contrib/markup/templatetags/markup.py.

CSRF /
Django

GNU Free Document License

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter16/

14/15

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |


Djangorequest view
request
DjangoDjangorequest/response
plug-inDjango

12sessionuser(view
request.session request.user )

13cacheviewresponse
view
14 flatpages , redirects , csrf

Djangoproxy(20)
requestIP(request.META["REMOTE_IP"] )proxy
requestIP proxy XForwardedFor IP
proxy request.META["REMOTE_ADDR"]
IP
class SetRemoteAddrFromForwardedFor(object):
def process_request(self, request):
try:
real_ip = request.META['HTTP_X_FORWARDED_FOR']
except KeyError:
pass
else:
# HTTP_X_FORWARDED_FOR can be a commaseparated list of IPs.
# Take just the first one.
real_ip = real_ip.split(",")[0]
request.META['REMOTE_ADDR'] = real_ip

(Note: Although the HTTP header is called XForwardedFor , Django makes it available as
request.META['HTTP_X_FORWARDED_FOR'] . With the exception of contentlength and contenttype , any

HTTP headers in the request are converted to request.META keys by converting all characters to
uppercase, replacing any hyphens with underscores and adding an HTTP_ prefix to the name.)

djangobook.py3k.cn/2.0/chapter17/

1/6

2010-5-5

()request XForwardedFor
request.META['REMOTE_ADDR'] Djangoproxy

request.META['REMOTE_ADDR'] proxy
Django django.middleware.http ,

,

MIDDLEWARE_CLASSES MIDDLEWARE_CLASSES
Python djangoadmin.py startproject
MIDDLEWARE_CLASSES :
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)

Django MIDDLEWARE_CLASSES
requestviewDjango MIDDLEWARE_CLASSES
responseDjango Django
MIDDLEWARE_CLASSES view requestresponse

Initializer: __init__(self) __init__(self)


__init__()
__init__()
request
middleware __init__() __init__()
django.core.exceptions.MiddlewareNotUsed ,Djangomiddlewaremiddleware

middleware
__init__() self

Request: process_request(self, request) process_request(self, request)


DjangorequestURLview Django
HttpRequest
process_request() None HttpResponse .

djangobook.py3k.cn/2.0/chapter17/

2/6

2010-5-5


None , Djangorequest, view.
HttpResponse , Django ()view
Django HttpResponse .

View: process_view(self, request, view, args, kwargs)


process_view(self, request, view, args, kwargs)
Djangorequestviewview

15-1View
15-1. process_view()

request

The HttpRequest object.


The Python function that Django will call to handle this request. This is the actual function object

view

itself, not the name of the function as a string.


args

view
request ( view)

kwargs

view.

Just like process_request() , process_view() should return either None or an HttpResponse object.
If it returns None , Django will continue processing this request, executing any other middleware
and then the appropriate view.
If it returns an HttpResponse object, Django wont bother calling any other middleware (of any
type) or the appropriate view. Django will immediately return that HttpResponse .

Response: process_response(self, request, response)


process_response(self, request, response)
Djangoviewresponse Here, the processor can modify the
content of a response. One obvious use case is content compression, such as gzipping of the
requests HTML.
: request request response viewresponse request
is the request object, and response is the response object returned from the view.
None requestview, process_response() HttpResponse .
response() That response
could be the original one passed into the function (possibly modified) or a brand-new one.

Exception: process_exception(self, request, exception)


process_exception(self, request, exception)
requestview

djangobook.py3k.cn/2.0/chapter17/

3/6

2010-5-5

,
request view exception
process_exception() None HttpResponse .

None , Djangorequest
HttpResponse , Django response

Django()

Djangos wiki:
http://code.djangoproject.com/wiki/ContributedMiddleware
http://code.djangoproject.com/wiki/ContributedMiddleware

Django

: django.contrib.auth.middleware.AuthenticationMiddleware .
django.contrib.auth.middleware.AuthenticationMiddleware .

. HttpRequest request.user
It adds the request.user attribute, representing the currently logged-in user, to every incoming
HttpRequest object.

12

Middleware class: django.middleware.common.CommonMiddleware .


:

``DISALLOWED_USER_AGENTS`` user agent


requestuser-agent

import re
DISALLOWED_USER_AGENTS = (
re.compile(r'^OmniExplorer_Bot'),
re.compile(r'^Googlebot')
)

import re , DISALLOWED_USER_AGENTS ( re.compile()


)

djangobook.py3k.cn/2.0/chapter17/

4/6

2010-5-5


``APPEND_SLASH`` ``PREPEND_WWW`` URL APPEND_SLASH True ,
URLURLpath
foo.com/bar foo.com/bar/ , foo.com/bar/file.txt

PREPEND_WWW True , www.URLswww.URL will


be redirected to the same URL with a leading www..
URL URL URL
example.com/bar example.com/bar/ www.example.com/bar/

``USE_ETAGS`` Etag : ETags HTTP


USE_ETAGS True DjangoMD5Etag, Django

Not Modified (
GET , Etags

django.middleware.gzip.GZipMiddleware .
gzip()] Web

GET
Middleware class: django.middleware.http.ConditionalGetMiddleware .
GET response LastModified ETag request
IfNoneMatch IfModifiedSince responseresponse 304(Not
modified) ETag USE_ETAGS response ETag
response ETag As discussed above, the ETag header is set by the Common
middleware.
HEAD requestresponserequestresponse
Date ContentLength

(X-Forwarded-For)
Middleware class: django.middleware.http.SetRemoteAddrFromForwardedFor .
request.META['HTTP_X_FORWARDED_FOR']
request.META['REMOTE_ADDR'] request
REMOTE_ADDR 127.0.0.1 It sets request.META['REMOTE_ADDR']

based on request.META['HTTP_X_FORWARDED_FOR'] , if the latter is set. This is useful if youre sitting


behind a reverse proxy that causes each requests REMOTE_ADDR to be set to 127.0.0.1 .

middleware HTTP_X_FORWARDED_FOR
HTTP_X_FORWARDED_FOR

djangobook.py3k.cn/2.0/chapter17/

5/6

2010-5-5

HTTP_X_FORWARDED_FOR REMOTE_ADDR HTTP_X_FORWARDED_FOR


IP
HTTP_X_FORWARDED_FOR

Middleware class: django.contrib.sessions.middleware.SessionMiddleware .


. 12 See Chapter 14 for details.

Middleware classes: django.middleware.cache.UpdateCacheMiddleware and


django.middleware.cache.FetchFromCacheMiddleware .

Django 13

Middleware class: django.middleware.transaction.TransactionMiddleware .


COMMIT ROLLBACK request/response view
COMMIT view ROLLBACK
Django -
()view
C

Web In the next chapter, well


cover how to integrate with legacy systems, such as database schemas youve inherited from the
1980s.

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter17/

6/6

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |


Djangogreen-field
Django

DjangoPythonSQL schemasSQL schemas.


,model. ,Django
model. inspectdb,manage.py inspectdb.

inspectdb
inspectdb DjangoPython

Django

django-admin.py startproject mysite ( mysite )Django


mysite
, mysite/settings.py ,Django
DATABASE_NAME , DATABASE_ENGINE , DATABASE_USER , DATABASE_PASSWORD , DATABASE_HOST ,
DATABASE_PORT . ( 5)

python mysite/manage.py startapp myapp ( myapp )Django


myapp
python mysite/manage.py inspectdbDATABASE_NAME
inspectdb
shell models.py
python mysite/manage.py inspectdb > mysite/myapp/models.py

mysite/myapp/models.py models

Models

models :
model (model )
models ManyToManyField

djangobook.py3k.cn/2.0/chapter18/

1/5

2010-5-5

modelid model
Djangoid
id = models.IntegerField(primary_key=True)

CharFieldDateField VARCHAR,DATE
inspectdbmodelTextField
modelPython
Django Django

Pythonpassclassforinspectdb
_fielddb_columnpass,classfor
INTformodel
for_field = models.IntegerField(db_column='for')
inspectdb Python

model
model Bookmodel Author
modelmodel
model
PostgreSQL,MySQLSQLiteinspectdb
primary_key=True model
Djangomodelprimary_key=True
PostgreSQLMySQL
INTIntegerField

Django
LDAP
LDAPDjango

Django Diango

Django django.contrib.auth.authenticate()
(14)Django Django

djangobook.py3k.cn/2.0/chapter18/

2/5

2010-5-5

AUTHENTICATION_BACKENDS Python
Python Python
AUTHENTICATION_BACKENDS
('django.contrib.auth.backends.ModelBackend',)

Django
AUTHENTICATION_BACKENDSDjango

get_user(id) authenticate(**credentials)
get_user id id ID
User

authenticate
class MyBackend(object):
def authenticate(self, username=None, password=None):
# Check the username/password and return a User.

class MyBackend(object):
def authenticate(self, token=None):
# Check the token and return a User.

authenticate
User None None

14Django User
LDAPSQLDjango User
authenticate
setting.py usernamepassword
Django User
from django.conf import settings
from django.contrib.auth.models import User, check_password
class SettingsBackend(object):
"""
Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.
Use the login name, and a hash of the password. For example:
ADMIN_LOGIN = 'admin'
ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'
"""
def authenticate(self, username=None, password=None):
login_valid = (settings.ADMIN_LOGIN == username)
pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
if login_valid and pwd_valid:

djangobook.py3k.cn/2.0/chapter18/

3/5

2010-5-5


try:
user = User.objects.get(username=username)
except User.DoesNotExist:
# Create a new user. Note that we can set password
# to anything, because it won't be checked; the password
# from settings.py will.
user = User(username=username, password='get from settings.py')
user.is_staff = True
user.is_superuser = True
user.save()
return user
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None

, Django

Web
WebDjango
Apacheshttpd.confURL 12
Apache/mod_pythonDjango12
)
httpd.confDjangoURL
12Django
<Location "/">
SetHandler pythonprogram
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug On
</Location>

, <Location "/"> DjangoURL.


Django<location>
PHPPHP../admin/Django
<location>/admin/
<Location "/admin/">
SetHandler pythonprogram
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug On
</Location>

/admin/URLDjango

DiangoURL /admin/ URL


Django /admin/people/person/add/ URL
/people/person/add/ URLconf /admin/

djangobook.py3k.cn/2.0/chapter18/

4/5

2010-5-5

, Django admin 50!


Django ( Django ) ` <../chapter19/>`__
Django

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter18/

5/5

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | | |


Django40 Djano
Django

*


I18N(18InternationlizationIN18)
*

L10N
Django
Django50 Django

Python * *
Django
DjangoWeb
Django

DjangoWeb
:
Django GNU gettext (http://www.gnu.org/software/gettext/)Python
gettext
:
DjangoDjango
USE_I18N = False USE_I18N False Django

TEMPLATE_CONTEXT_PROCESSORS 'django.core.context_processors.i18n'
Django:

djangobook.py3k.cn/2.0/chapter19/

1/14

2010-5-5

1. Python
2.
3. Django settings

1
Python

Python

ugettext() _ .
"Welcome to my site"
from django.utils.translation import ugettext as _
def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)


from django.utils.translation import ugettext
def my_view(request):
output = ugettext("Welcome to my site.")
return HttpResponse(output)


def my_view(request):
words = ['Welcome', 'to', 'my', 'site.']
output = _(' '.join(words))
return HttpResponse(output)


def my_view(request):
sentence = 'Welcome to my site.'
output = _(sentence)
return HttpResponse(output)

Django
makemessages.py makemessages

_() gettext() Python


def my_view(request, m, d):
output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}
return HttpResponse(output)

djangobook.py3k.cn/2.0/chapter19/

2/14

2010-5-5


"Today is November 26." "Hoy es 26 de Noviembre."

%(day)s
%s or %d

django.utils.translation.gettext_noop()

django.utils.translation.gettext_lazy()
gettext_lazy()

help_text
from django.utils.translation import ugettext_lazy
class MyThing(models.Model):
name = models.CharField(help_text=ugettext_lazy('This is the help text'))

ugettext_lazy()
Django
Pythonunicode unicode
ugettext_lazy() ugettext_lazy()


unicode Python
# This is fine: putting a unicode proxy into a unicode string.
u"Hello %s" % ugettext_lazy("people")
# This will not work, since you cannot insert a unicode object
# into a bytestring (nor can you insert our unicode proxy there)
"Hello %s" % ugettext_lazy("people")

"hello"ugettext_lazy()

gettext_lazy _
from django.utils.translation import ugettext_lazy as _
class MyThing(models.Model):
name = models.CharField(help_text=_('This is the help text'))

Django
Metaverbose_naneverbose_name_plural
Djangoverbose_nameverbose_name_pluralmodel

djangobook.py3k.cn/2.0/chapter19/

3/14

2010-5-5

from django.utils.translation import ugettext_lazy as _


class MyThing(models.Model):
name = models.CharField(_('name'), help_text=_('This is the help text'))
class Meta:
verbose_name = _('my thing')
verbose_name_plural = _('mythings')

django.utils.translation.ungettext()
from django.utils.translation import ungettext
def hello_world(request, count):
page = ungettext('there is %(count)d object',
'there are %(count)d objects', count) % {
'count': count,
}
return HttpResponse(page)
ngettext count

DjangoPython
{% load i18n %}

{% trans %} ()
<title>{% trans "This is the title." %}</title>
<title>{% trans myvar %}</title>

noop
<title>{% trans "myvar" noop %}</title>

{% trans %} (
placeholders) {% blocktrans %}
{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}

{% blocktrans with value|filter as myvar %}


This will have {{ myvar }} inside.
{% endblocktrans %}

blocktrans and
{% blocktrans with book|title as book_t and author|title as author_t %}
This is {{ book_t }} by {{ author_t }}
{% endblocktrans %}

{% blocktrans %} {% endblocktrans %} {% plural %}

{% blocktrans count list|length as counter %}

djangobook.py3k.cn/2.0/chapter19/

4/14

2010-5-5

There is only one {{ name }} object.


{% plural %}
There are {{ counter }} {{ name }} objects.
{% endblocktrans %}

gettext ngettext
RequestContext
{{ LANGUAGES }}

LANGUAGE_CODE enusDjango

LANGUAGE_BIDI True

False
RequestContext3
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_current_language_bidi as LANGUAGE_BIDI %}

{% load i18n %}
hook _()

{% some_special_tag _("Page not found") value|yesno:_("yes,no") %}

:
"yes,no""yes""no"
"yes,no"
"ja,nein" ()

ugettext_lazy()ungettext_lazy()

string_concat()
Python(''.join([...]) )
django.utils.translation.string_concat()

from django.utils.translation import string_concat
# ...
name = ugettext_lazy(u'John Lennon')

djangobook.py3k.cn/2.0/chapter19/

5/14

2010-5-5

instrument = ugettext_lazy(u'guitar')
result = string_concat([name, ': ', instrument])

System Message: ERROR/3 (<string>, line 519)


Error in cnid directive: no content permitted.
.. cnid:: 109

System Message: WARNING/2 (<string>, line 523)


Explicit markup ends without a blank line; unexpected unindent.
result result ()

allow_lazy()
Django(
django.utils )

django.utils.functional.allow_lazy()

from django.utils.functional import allow_lazy


def fancy_utility_function(s, ...):
# Do some conversion on string 's'
# ...
fancy_utility_function = allow_lazy(fancy_utility_function, unicode)
allow_lazy()

(*args ) unicode Unicode

Django
Django
Django DjangoDjango core

djangobook.py3k.cn/2.0/chapter19/

6/14

2010-5-5


.po
Django bin/makemessages.py

djangoadmin.py makemessages l de

de
pt_BR de_AT

Django
Django
django Subversion $PYTHONPATH

Django

locale/LANG/LC_MESSAGES de

locale/de/LC_MESSAGES/django.po
djangoadmin.py makemessages .html
extension e
djangoadmin.py makemessages l de e txt

eextension
djangoadmin.py makemessages l de e html,txt e xml

JavaScriptDjangonot e js
gettext?
gettext makemessages.py gettext
( conf/locale/en/LC_MESSAGES/django.po )

Windows
WindowsGNU gettext djangoadmin makemessages
Windowsgettext
.po .po

Django "Welcome to my site."


_("Welcome to my site.")

djangobook.py3k.cn/2.0/chapter19/

7/14

2010-5-5

djangoadmin.py makemessages .po


#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr ""

msgid

msgstr

# msgid
msgstr msgid

djangoadmin.py makemessages a

gettext
djangoadmin.py compilemessages
.po .mo gettext
djangoadmin.py makemessagesdjangoadmin.py compilemessages
djangoadmin.py compilemessages

Django
Django
Django
LANGUAGE_CODEDjango

Django LANGUAGE_CODE

LocaleMiddleware LocaleMiddleware Django



LocaleMiddleware MIDDLEWARE_CLASSES
'django.middleware.locale.LocaleMiddleware'

djangobook.py3k.cn/2.0/chapter19/

8/14

2010-5-5

LocalMiddleware session SessionMiddleware


CacheMiddleware,LocaleMiddleware

MIDDLE_CLASSES
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
)

17
LocaleMiddleware :

session django_language
cookie
HTTP AcceptLanguage
Django
, LANGUAGE_CODE

ptbr
Django deat
Django de de
LANGUAGES
LANGUAGES
LANGUAGES = (
('de', _('German')),
('en', _('English')),
)

dech enus
LANGUAGES
django.utils.translation gettext() settings django.utils.translation

settings gettext()
gettext() settings
ugettext = lambda s: s
LANGUAGES = (

djangobook.py3k.cn/2.0/chapter19/

9/14

2010-5-5


('de', ugettext('German')),
('en', ugettext('English')),

makemessages.py
LANGUAGES ugettext()
LocaleMiddleware Django Django

Django
ID
.po
ID ID:
DATETIME_FORMAT DATE_FORMAT TIME_FORMAT
now
LocaleMiddlewarerequest.LANGUAGE_CODEHttpRequest

def hello_world(request):
if request.LANGUAGE_CODE == 'deat':
return HttpResponse("You prefer to read Austrian German.")
else:
return HttpResponse("You prefer to read another language.")

settings.LANGUAGE_CODE
request.LANGUAGE_CODE

Django
Django locale

Django locale
Django django/conf/locale



$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)

$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)

settings LOCALE_PATHS
<language>/LC_MESSAGES/django.(po|mo)

djangobook.py3k.cn/2.0/chapter19/

10/14

2010-5-5


$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)

djangoadmin.py makemessages.py Django


conf/locale locale/
compilemessages.py gettext django.mo
djangoadmin.py compilemessages settings=path.to.settings
LOCALE_PATHS

LocaleMiddle Django
Django

makemessages
ID

makemessages

set_language

Django django.views.i18n.set_language

URLconf
(r'^i18n/', include('django.conf.urls.i18n')),

/i18n/setlang/
GET language session
session django_languagecookie(
LANGUAGE_COOKIE_NAME)
Django
Django POST
next DjangoHTML Referer
Referer Referer /

HTML
<form action="/i18n/setlang/" method="post">
<input name="next" type="hidden" value="/next/page/" />
<select name="language">
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}">{{ lang.1 }}</option>
{% endfor %}
</select>
<input type="submit" value="Go" />

djangobook.py3k.cn/2.0/chapter19/

11/14

2010-5-5

</form>

JavaScript
JavaScript
JavaScript gettext
JavaScript .po .mo
JavaScript
Django JavaScriptJavaScript
gettext
javascript_catalog

javascript_catalog JavaScript
gettext info_dictURl
Django

js_info_dict = {
'packages': ('your.app.package',),
}
urlpatterns = patterns('',
(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
)
packages Python INSTALLED_APPS

locale
JavaScript
urlpatterns
urlpatterns = patterns('',
(r'^jsi18n/(?P<packages>\S+)/$', 'django.views.i18n.javascript_catalog'),
)

URL +

django.conf INSTALLED_APPS

JavaScript

<script type="text/javascript" src="/path/to/jsi18n/"></script>

JavaScript gettext

djangobook.py3k.cn/2.0/chapter19/

12/14

2010-5-5

document.write(gettext('this is to be translated'));

ngettext
var object_cnt = 1 // or 0, or 2, or 3, ...
s = ngettext('literal for the singular case',
'literal for the plural case', object_cnt);

function interpolate(fmt, obj, named);

Pythoninterpolate
objJavaScriptfmt

fmts = ngettext('There is %s object. Remaining: %s',
'There are %s objects. Remaining: %s', 11);
s = interpolate(fmts, [11, 20]);
// s is 'There are 11 objects. Remaining: 20'

TRUEname obj JavaScript



d = {
count: 10
total: 50
};
fmts = ngettext('Total: %(total)s, there is %(count)s object',
'there are %(count)s of a total of %(total)s objects', d.count);
s = interpolate(fmts, d, true);

JavaScript
Python ngettext

JavaScript

Djangodjango-admin.py makemessages
d djangojs
djangoadmin.py makemessages d djangojs l de

JavaScript Django
compilemessages.py

gettext
gettext Django
django djangojs
/usr/share/locale/ django Python

djangojs JavaScript

djangobook.py3k.cn/2.0/chapter19/

13/14

2010-5-5


Django xgettext Pythonxgettextmsgfmt

Windowsgettext

gettext
http://sourceforge.net/projects/gettextzip
gettextruntimeX.bin.woe32.zip

gettexttoolsX.bin.woe32.zip

libiconvX.bin.woe32.zip

3 C:\Program Files\gettextutils )

> > >

PathEdit
;C:\Program Files\gettextutils\bin

xgettext versiongettext 0.14.4


Djangogettextwindows
`` xgettext version ``xgettext.exe
windows
System Message: WARNING/2 (<string>, line 1346); backlink
Inline literal start-string without end-string.

| | | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter19/

14/14

2010-5-5

About | Comment help | Contact us | Errata | Buy the print version on Amazon.com

The Django Book

| | | |


Internet

Web WebWeb

Django web
Django
web
Django

Web

HTTP

Web
HTTPcookies

SQL
SQL SQLweb GET /POST URL
SQL
SQL
emailemail

def user_contacts(request):
user = request.GET['username']
sql = "SELECT * FROM user_contacts WHERE username = '%s';" % username
# execute the SQL here...

djangobook.py3k.cn/2.0/chapter20/

1/8

2010-5-5

email
"' OR 'a'='a"
SELECT * FROM user_contacts WHERE username = '' OR 'a' = 'a';

SQL OR
"'; DELETE FROM user_contacts WHERE 'a' = 'a'"

SELECT * FROM user_contacts WHERE username = ''; DELETE FROM user_contacts WHERE 'a' = 'a';

SQL

DjangoAPI PostSQLMySQL
SQL
API
foo.get_list(bar__exact="' OR 1=1")

Django
SELECT * FROM foos WHERE bar = '\' OR 1=1'

DjangoAPI
extra() where ( C) SQL
API ()


from django.db import connection
def user_contacts(request):
user = request.GET['username']
sql = "SELECT * FROM user_contacts WHERE username = %s"
cursor = connection.cursor()
cursor.execute(sql, [user])
# ... do something with the results

execute SQLSQL%s

djangobook.py3k.cn/2.0/chapter20/

2/8

2010-5-5

execute * always* SQL


SQL
POST
Django django.db.backend.quote_name

(XSS)
Web (XSS)HTML
<script> HTML
XSScookie

Hello World
from django.http import HttpResponse
def say_hello(request):
name = request.GET.get('name', 'world')
return HttpResponse('<h1>Hello, %s!</h1>' % name)

GEThello.html
http://example.com/hello/?name=Jacob
<h1>Hello, Jacob!</h1>

http://example.com/hello/?name=<i>Jacob</i>
<h1>Hello, <i>Jacob</i>!</h1>

<i>HTML
XSS


MySpaceXSS
JavaScript

MySpace
MySpaceMySpace

MySpace


Django

djangobook.py3k.cn/2.0/chapter20/

3/8

2010-5-5

# views.py
from django.shortcuts import render_to_response
def say_hello(request):
name = request.GET.get('name', 'world')
return render_to_response('hello.html', {'name': name})
# hello.html
<h1>Hello, {{ name }}!</h1>

`` http://example.com/hello/name=Jacob``
<h1>Hello, &lt;i&gt;Jacob&lt;/i&gt;!</h1>

Django Django

XSS

(CSRF)WebURL

Django 16


ID
cookie
cookie cookie

cookie cookie `
<../chapter14/>`__ cookies
cookies
Web IsLoggedIn=1 LoggedInAsUser=jacob cookie
cookie
cookies

ID
PHPURL http://example.com/?PHPSESSID=fa90197ca25f6ab40bb1374c510d7a32
ID

djangobook.py3k.cn/2.0/chapter20/

4/8

2010-5-5

Web
cookie
XSS

URLsession
Djangosession` <../chapter14/>`__ sessionURL
cookie sessionsession ID
Djangosession request.session session
cookiesession IDsession
session XSS
session
session
IDDjango
ID
ID

HTTPS
SSL SESSION_COOKIE_SECURE True DjangoHTTPS
cookie

SQLWeb
Web

from

"hello\ncc:spamvictim@example.com" "\n"

To: hardcoded@example.com
Subject: hello
cc: spamvictim@example.com

djangobook.py3k.cn/2.0/chapter20/

5/8

2010-5-5

SQL

SQL
Django django.core.mail
django.core.mail.send_mail
DjangoBadHeaderError
Django
django.core.mail SateMIMEText Django

Web
/

def dump_file(request):
filename = request.GET["filename"]
filename = os.path.join(BASE_PATH, filename)
content = open(filename).read()
# ...

BASE_PATH os.path.join
.. BASE_PATH
../../../../../etc/passwd

URL
Ruby on Rails 2006Rails http://example.com/person/poke/1 URL
URL


Django django.views.static
import os
import posixpath
# ...
path = posixpath.normpath(urllib.unquote(path))
newpath = ''

djangobook.py3k.cn/2.0/chapter20/

6/8

2010-5-5

for part in path.split('/'):


if not part:
# strip empty path components
continue
drive, part = os.path.splitdrive(part)
head, part = os.path.split(part)
if part in (os.curdir, os.pardir):
# strip '.' and '..' in path
continue
newpath = os.path.join(newpath, part).replace('\\', '/')

Django static.serve

URLconfDjango
URLDjangoURLconf

Djangodebug

Django

Python
debug

12Django`` DEBUG``
`` False``
Apachemod_pythonApache PythonDebug Off
Django

Web

Web
Web

Djang.
Djangogoogle

djangobook.py3k.cn/2.0/chapter20/

7/8

2010-5-5

| | | |
Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This w ork is licensed under the GNU Free Document License.
Hosting graciously provided by
Chinese translate hosting by py3k.cn.

djangobook.py3k.cn/2.0/chapter20/

8/8

You might also like