Вы находитесь на странице: 1из 395

DjangoBook

DjangoBook


1. Django ................................................................................................. 1
? ........................................................................... 1
MVC ................................................................................ 3
Django .............................................................................................. 4
...................................................................................... 6
............................................ 6
Python ........................................................ 6
Django ........................................................................ 7
................................................................................. 7
..................................................................................... 7
................................................................................................ 8
....................................................................................... 8
................................................................................................... 9
2. ............................................................................................................ 11
Python ........................................................................................... 11
Python ........................................................................................ 11
.............................................................................................. 11
Django .......................................................................................... 12
........................................................... 12
.................................................................. 12
Django ........................................................................... 14
................................................................................ 14
Django PostgreSQL ...................................................... 15
Django SQLite 3 .......................................................... 16
Django MySQL ............................................................ 16
Django ................................................ 16
............................................................................................... 16
.................................................................... 18
......................................................................................................... 19
................................. 20
..................................................................... 21
................................................. 22
.............................................................................. 23
................................................................................... 23
.............................................................................................. 24
3. URL ......................................................................... 25
Django: , ............................................ 25
.................................................................. 25
URL .................................................................. 26
404 ........................................................................ 30
............................................................................. 31
Django ................................................................... 31
: .............................. 32
URL .............................................................. 34
: URL .......................................... 35
..................................................................... 39
4. ........................................................................................................... 42
......................................................................... 42
............................................................. 44
............................................................. 44
.............................................................................. 46
................................... 48
........................................................... 48
....................................................... 52
.......................................................... 52

iii

DjangoBook
...................................................................................................... 52
............................................................................................... 59
........................................................................... 60
................................................. 61
....................................................................................... 63
render_to_response() ............................................................................. 66
locals() ....................................................................................... 66
get_template() ................................................................ 67
include ......................................................................... 68
............................................................................... 69
5. ............................................................................................................... 74
.............................. 74
MTV ( MVC) ............................................................................ 75
................................................................................ 77
.............................................................................. 81
Python ..................................................................... 82
..................................................................................... 83
......................................................................................... 85
.......................................................................................... 88
................................................ 89
........................................................................ 91
......................................................................................... 92
.............................................................................. 93
.................................................................... 95
............................................................................... 96
.......................................................... 97
................................................................... 98
................................. 99
...................................................................................... 100
6. Django .................................................................. 102
django.contrib .................................................................................. 102
...................................................... 103
............................................... 103
......................... 109
.................................................... 110
.................................................................... 111
.................................... 111
................................................................................ 113
ModelAdmin ................................................................ 114
...................................................... 114
........................................................ 120
, .................................................................... 123
,
.............................................................................................................. 124
? ................................................................................................ 125
7. .............................................................................................................. 126
........................................................ 126
URL ........................................................................... 126
........................................................ 127
.................................................... 128
............................................................. 128
........................... 132
........................................................................... 134
........................................... 136
........................................................................... 140
......................................................... 143
...................................................... 144
..................................................... 144

iv

DjangoBook
................................................................... 145
................................................................... 145
..................................................................................... 146
.......................................................................... 147
? ................................................................................................ 148
8. URL ......................................... 150
URL: ..................................................................... 150
..................................................... 150
................... 152
URL .................................................. 152
.................................................... 153
/ ................................. 155
....... 155
............... 160
...................................................... 161
.......................................................... 162
, URL ................................... 163
URL ................................................................... 163
include() ................... 164
include() .......... 165
9. .................................................................................... 167
....................................................... 167
................................................................ 169
........................................................... 170
............................... 170
.............................................. 171
............................................................. 172
- ................... 173
.................................................. 174
10. ............................................................. 176
................................................................................ 176
RequestContext Context .......................................................... 177
django.core.context_processors.auth ..................................... 181
django.core.context_processors.debug .................................................... 181
django.core.context_processors.i18n ....................................................... 181
django.core.context_processors.request .................................................. 182
? ............................................................. 182
...................................................................................... 182
................................................................ 183
........................................................ 183
.............................................. 185
..................................................... 186
........................................................... 192
................................................................................... 193
................................................. 195
................................ 196
...................................................................... 197
11. , HTML ........................................................... 199
: MIME- ......................................................... 199
CSV ............................................................................................ 200
PDF ............................................................................................ 201
ReportLab ........................................................................... 202
..................................................................... 202
PDF ................................................................... 203
................................................................................... 204
.................................................................................. 204
.................................................................................. 205
........................................................................... 206

DjangoBook
................................................................. 207
................................................................. 209
............................................................................................ 209
.................................................................................................... 210
URL ..................................................................................................... 210
Atom RSS ............................................. 210
...................................................................... 211
............................................................................................. 211
........................................................................................... 212
................................................................................................. 212
............................................................................................. 214
...................................................... 215
Google ............................................................................ 215
12. , ............................................................... 217
Cookie .......................................................................................................... 217
........................................................................ 218
................................................................................. 219
......................................................................................................... 220
........................................................................................... 220
......................................... 221
cookie ................................................................... 222
............................ 223
................................................................... 224
........................................................................... 224
.................................................................... 225
.................................................................. 226
........................................................................................... 226
User ............................................................... 227
.......................................................................... 229
........................ 231
........................... 232
, ............................. 233
.......................... 237
: , , ..................................... 237
.................................................................................................. 238
................................................................................................ 239
.......................................................................................... 239
........................................................................................... 240
13. .................................................................................................. 242
.......................................................................................... 242
Memcached .......................................................................................... 243
............................................................... 244
.................................................... 244
.................................................. 245
( ) .............................................. 245
( ) .......................................... 245
CACHE_BACKEND ............................................................ 245
................................................................... 246
.................................................... 247

URL ...................................................................................................... 248
API ..................................................................................... 249
................................................................................. 251
Vary .......................................................... 251
.................................. 253
.............................................................................................. 254
MIDDLEWARE_CLASSES ........................................................... 255
14. .................................................................. 256

vi

DjangoBook
Django .................................................................. 256
...................................................... 257
.......................................................................................................... 265
1: ................... 265
2: .................. 266
.......................................................................... 266
....................................................................................... 266
CurrentSiteManager .............................................................................. 270
Django ............................... 271
................................................................................ 272
.................................................................................... 272
, ..................................................... 274
.................................................................... 274
........................................................................................ 275
.................................................................................... 275
, ..................................................... 276
CSRF .......................................................................................... 276
.................................................................................. 276
....................................................................... 277
................................................................................. 277
............................................................................. 278
apnumber ............................................................................................. 279
intcomma ............................................................................................. 279
intword ................................................................................................ 279
ordinal ................................................................................................. 279
...................................................................................... 280
15. .................................................................................................... 281
? ............................................................................... 281
.................................................................................................... 282
....................................................................................................... 282
........................................................................................ 283
......................................................................... 283
.............................................................. 283
....................................................................... 284
................................................................ 284
............................................................................. 284
............................................. 285
..................................................................... 285
....................................................................... 286
GET .................................................................. 286
............................................ 286
............................................................. 286
..................................................... 287
..................................................... 287
X-View ............................................................................... 287
16. ....................................................................... 288
.............................................. 288
inspectdb .................................................................... 288
.................................................... 289
.................................................... 290
.............................................. 290
........................................... 290
................................... 292
17. ....................................................... 294
........................................................................... 294
... ............................................................... 294
... ... ................................................................................. 295
... .................................................... 295

vii

DjangoBook
Full Stop .............................................................................................. 295
............................................................... 296
..................................... 297
JavaScript ................................................................................... 298
................................................................... 298
............................................. 301
18. ................................................................................... 303
..................................................... 304
................................................... 304
................................................ 305
.......................................................................... 305
................................................... 306
............................................... 307
.................................................................. 308
........................................................ 309
.................................................. 310
Django ................................................... 311
set_language ........................................................................ 313
............................................... 314
JavaScript ................................................................................. 315
javascript_catalog ......................................................... 315
................................................ 316
............................................................................... 317
, gettext ............................................... 317
19. ................................................................................................... 318
............................................................................ 318
SQL ............................................................................................ 318
.............................................................................................. 319
(XSS) ................................................................... 321
.............................................................................................. 322
HTTP ............................................................................ 322
......................................................................................... 322
.............................................................................................. 323
E-mail ........................................................................ 324
.............................................................................................. 325
Directory Traversal ....................................................................................... 325
.............................................................................................. 325
............................................................... 326
.............................................................................................. 327
........................................................ 327
20. Django .................................................................................... 328
............................................................................................ 329
Django? ................................................... 330
Django Apache mod_python ........................................... 330
.............................................................................. 331
Django Apache .......................... 332
mod_python .......................................... 333
Django Apache..... 333
.............................................................................. 334
, Apache ........................... 334
Django Apache mod_wsgi ............................................... 335
Apache ......................................................... 335
Python ......................................................... 336
............................................................................... 336
.......................................................................... 336
........................................................................ 337
A. ............................................................................................ 339
B. .................................................................... 340

viii

DjangoBook
C. API ........................................ 341
D. ........................................................ 342
E. ............................................................................... 343
F. .......................................................... 344
............................................................. 344
autoescape ........................................................................................... 344
block .................................................................................................... 344
comment .............................................................................................. 344
csrf_token ............................................................................................ 344
cycle .................................................................................................... 344
debug ................................................................................................... 346
extends ................................................................................................ 346
filter ..................................................................................................... 346
firstof ................................................................................................... 347
for ....................................................................................................... 348
for ... empty .......................................................................................... 349
if .......................................................................................................... 349
.............................................................................................. 352
......................................................................... 353
ifchanged .............................................................................................. 353
ifequal .................................................................................................. 354
ifnotequal ............................................................................................. 355
include ................................................................................................. 355
load ..................................................................................................... 356
now ...................................................................................................... 356
regroup ................................................................................................ 356
spaceless .............................................................................................. 358
ssi ........................................................................................................ 359
templatetag .......................................................................................... 359
url ....................................................................................................... 360
widthratio ............................................................................................ 362
with ..................................................................................................... 362
...................................................... 362
add ...................................................................................................... 362
addslashes ............................................................................................ 363
capfirst ................................................................................................. 363
center .................................................................................................. 364
cut ....................................................................................................... 364
date ..................................................................................................... 364
default .................................................................................................. 365
default_if_none .................................................................................... 365
dictsort ................................................................................................. 365
dictsortreversed .................................................................................... 366
divisibleby ............................................................................................ 366
escape .................................................................................................. 366
escapejs ................................................................................................ 367
filesizeformat ........................................................................................ 367
first ...................................................................................................... 367
fix_ampersands .................................................................................... 368
floatformat ........................................................................................... 368
force_escape ......................................................................................... 369
get_digit .............................................................................................. 369
iriencode .............................................................................................. 369
join ...................................................................................................... 370
last ...................................................................................................... 370
length .................................................................................................. 370
length_is .............................................................................................. 370
linebreaks ............................................................................................. 371

ix

DjangoBook
linebreaksbr .......................................................................................... 371
linenumbers .......................................................................................... 371
ljust ..................................................................................................... 372
lower .................................................................................................... 372
make_list ............................................................................................. 372
phone2numeric ..................................................................................... 372
pluralize ............................................................................................... 373
pprint ................................................................................................... 373
random ................................................................................................ 373
removetags ........................................................................................... 374
rjust ..................................................................................................... 374
safe ...................................................................................................... 374
safeseq ................................................................................................. 374
slice ..................................................................................................... 374
slugify .................................................................................................. 375
stringformat .......................................................................................... 375
striptags ............................................................................................... 375
time ..................................................................................................... 376
timesince .............................................................................................. 376
timeuntil ............................................................................................... 377
title ...................................................................................................... 377
truncatewords ....................................................................................... 377
truncatewords_html .............................................................................. 377
unordered_list ...................................................................................... 378
upper ................................................................................................... 378
urlencode ............................................................................................. 378
urlize .................................................................................................... 379
urlizetrunc ............................................................................................ 379
wordcount ............................................................................................ 379
wordwrap ............................................................................................. 380
yesno ................................................................................................... 380
.......................................... 380
django.contrib.humanize ....................................................................... 380
django.contrib.markup .......................................................................... 381
django.contrib.webdesign ...................................................................... 381
G. django-admin ...................................................................................... 382
H. HttpRequest HttpResponse .............................................................. 383


4.1. , ............................ 65
6.1. ....................................................... 104
6.2. ............................................. 105
6.3. .............................................................. 106
6.4. ............................................................ 107
6.5. .............................................................. 108
6.6. ........................................................................ 109
6.7. ...................................................... 115
6.8. list_display ..................... 116
6.9. search_fields ................... 117
6.10. list_filter ............................ 118
6.11. date_hierarchy .................... 119
6.12. .................................. 120
6.13. filter_horizontal. ................. 122
6.14. raw_id_fields. .................... 123
17.1. ............................................................. 297
17.2. ..................................................................................... 301

xi


3.1. .................................................... 30
5.1. ................................................................... 78
5.2. ...................... 80
7.1. URL ...................................................................................... 126
11.1. ......................................................................................... 209
12.1. cookie ................................................................................................. 219
12.2. , cookie ................................................. 225
12.3. User ...................................................................................... 227
12.4. User .................................................................................. 227
15.1. process_view() .............................................. 283
17.1. ...................................... 296
F.1. ........................................................................................ 348
F.2. ........................................................................................ 360
F.3. .............................................................................................. 368
F.4. ............................................................................. 368
F.5. .............................................................................. 369
F.6. ......................................................................................................... 380

xii

1. Django
<ruslan.popov gmail>
Django, 1 WEB2 ,
. Django,
.
.
, . Django
,
. ,
.
Django ,
.
Django.
. , , Django
. , ,
,
? ,

.

?
Django ,
?
,
Python .
,
, ,
.
, ( )
. , - ,
, .
,
Python Common Gateway Interface (CGI),
, 1998 . :
Python, HTML,
.cgi,
. .
CGI , Python,
. ,
:

#!/usr/bin/env python
import MySQLdb
1

Django , .
, .., .

Django
print
print
print
print
print
print

"Content-Type: text/html"
"<html><head><title></title></head>"
"<body>"
"<h1></h1>"
"<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>"
connection.close()

-, CGI, Content-Type,
. HTML ,
.
, . ,
HTML .
, ,
. -,
3
.cgi .
, .
:
,
? ,
CGI .
.
ContentType ?

.
.
, ,
?
, .
, ,
Python, ?
. , ,
HTML.
HTML
.
, .
,
3

production (FIXME) WEB-.

Django
, ,
. , Django.

MVC
,
, .
CGI , Django.
:
models.py .

from django.db import models


class Book(models.Model):
name = models.CharField(max_length=50)
pub_date = models.DateField()

views.py .

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})

urls.py URL .

from django.conf.urls.defaults import *


import views
urlpatterns = patterns('',
(r'^latest/$', views.latest_books),
)

latest_books.html HTML ,
.

<html><head><title></title></head>
<body>
<h1></h1>
<ul>
{% for book in book_list %}

Django
<li>{{ book.name }}</li>
{% endfor %}
</ul>
</body></html>

.
. Django :
models.py ,
Python. .
, ,
, Python
SQL .
views.py
latest_books(). .

urls.py
URL, . URL /latest/
latest_books(). ,
example.com, http://example.com/latest/
latest_books().
latest_books.html HTML ,
.
{% for book in book_list %}.
,
-- [http://ru.wikipedia.org/wiki/MVC/] (Model-ViewController, MVC). , MVC
()
(),
().

. , ,
Django, , ..,
. ,
URL .
HTML ,
.
, ,
.
MVC .

Django
,
Django. ,
,
. , ,
Django, Django , .
,
, CGI, .
:

Django
1. .
2. .
3. .
4. , .
5. 2-4 .
6. .
Django!
Django ,
, , .
2003 Lawrence Journal-World,
(Adrian Holovaty) (Simon Willison),
Python . World Online,
,
, . ,
LJWorld.com, Lawrence.com KUsports.com, ,

, . ,
,
,
.

:
Python [http://www.python.org/dev/
peps/pep-0008/].
[http://docs.python.org/tutorial/index.html].
2005, ,
World Online, , - (Jacob
Kaplan-Moss),
. 2005 Django
(Django Reinhardt).
, , Django
,
. World Online
( )
,
. World Online ,
, /
(http://www.djangoproject.com/).
, .
Django. Django ,
( ,
Django ),
- , Amazon.com, craigslist.org
washingtonpost.com,
. -
.

Django
, Django
. Django
, ,
,
. , Django
. , Django
,
. ,

.



, .
, , Django
, ,
. - ,
- , .
, .
Django,
. ,
Django, .
. ,
http://www.djangoproject.com/, ,
.


-
: (if, while, for), (,
/), , .
, , ,
.
.

Python
, Django ,
Python. Django
Python, . Django
Python
Django.
Python,
. , Django - (..
, ).
Django API .
Python, .
! ,
Python, .
http://docs.python.org/
tut/.

Django
Python [http://ru.diveintopython.org/toc.html], Apress
.

Django
1., .. 1.0, 1.0.2 1.1.
Django .
, Django 1.0,
1.1, 1.2, 1.9 , 1.
Django 2.0,
. , 1.0 . (
Python ,
Python 2.0, 2.6, Python 3.0).
, Django 1.x
.


Django
. Django:
, , , .
django-users
. http://www.djangoproject.com/
r/django-users.
IRC ,
. #django FreeNode IRC.



contributing/#coding-style.

http://www.djangoproject.com/documentation/

, :
, PEP 8 [http://
www.python.org/peps/pep-0008.html].
pep8.py [http://svn.browsershots.org/
trunk/devtools/pep8/pep8.py] .
.
(_),
, (.., poll.get_unique_voters(),
poll.getUniqueVoters()).
,
(, InitialCaps).
.
.
, :

Django

def foo():
"""
Calculates something and returns the result.
"""
pass

def foo():
"""
Calculate something and return the result.
"""
pass

. Django
AUTHORS.


.
:

{{ foo }}

{{foo}}

request.
:

def my_view(request, foo):


# ...

Django
:

def my_view(req, foo):


# ...


.
:

class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)

class Person(models.Model):
FirstName = models.CharField(max_length=20)
Last_Name = models.CharField(max_length=40)

Meta ,
.
:

class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)
class Meta:
verbose_name_plural = 'people'

class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)
class Meta:
verbose_name_plural = 'people'

Django

class Person(models.Model):
class Meta:
verbose_name_plural = 'people'
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)


( ):
.
class Meta.
class Admin.
def __unicode__().
def __str__().
def save().
def get_absolute_url().
.
choices,
, .
. :

GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)

10

2.
<ruslan.popov gmail>
Django -
. ,
.
- , Django Python, ,
Python, !
Django. ,
.
, Django , Django
.

Python
Django Python, ,
, Python .

Python
Django Python 2.3 2.7
. GIS 2.4
2.7.
, Python
,
2.: .. 2.7. , Django
,
Python
,
. ,
, ,
, Python 2.3, ,
.

Django Python 3.0


Python 3.0, Django
. Python 3.0 , , ,
, Django,
.
Python , Python 2.x
Python 3.x, Python 2.x.

Linux Mac OS X, Python.


python (Application/Utilities/Terminal)
OS X). , Python :

11


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:
. , ,
. Django
, ,
Django, ?
, ,
,
.


1.0.3 1.1,
http://www.djangoproject.com/download/. ,
, Django-1.0.2final.tar.gz. , setup.py install,
Python.
Unix :
1. tar xzvf Django-1.0.2-final.tar.gz
2. cd Django-*
3. sudo python setup.py install
Linux, Django,
.
.
Windows 7-Zip (http://www.djangoproject.com/
r/7zip/) .tar.gz . DOS
(Command Prompt)
, Django-:

python setup.py install


Django (trunk)
Subversion Django.
,
Django.

12


Subversion
, CVS. Django
. Subversion
Django
.
, , ,
Django .
.
:
1. , Subversion.
http://subversion.tigris.org/
http://svnbook.red-bean.com/.
2. :
svn co http://code.djangoproject.com/svn/django/trunk djtrunk
3. site-packages/django.pth djtrunk
PYTHONPATH, djtrunk.
4. djtrunk/django/bin PATH.
, django-admin.py.

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

:
python setup.py install
!
- , Django ,
, .
djtrunk :
svn update

,
Subversion

http://
code.djangoproject.com, Django
, . .
, ,
, .
, Django
.
, , .
, , svn info Django
Revision:.
Django, ,

13


, - .
Django , : Django [
]..

Django
Django
. (.., ,
django) Python, python.
, django:

>>> import django


>>> django.VERSION
(1, 1, 0, 'alpha', 0)


Python
, .
python.
Python
.
(>>>), .
, .

(...), :

>>> 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

,
. ,
. ,
.


Django,
Django
Python. ,

14


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

Django. GIS,
PostgreSQL, .
-
, PostgreSQL,
, , .
:
-, .
,
.
, ,
.
-, Python
. , Python
.
.
Django
, SQLite. SQLite
, , ,
, Python 2.5. SQLite
, Python 2.5
.
Windows
. , Django,
Python 2.5 SQLite.

Django PostgreSQL
PostgreSQL, psycopg
psycopg2, http://www.djangoproject.com/r/python-pgsql/
. psycopg2,
. ,
, 1- 2-, .
PostgreSQL Windows,
psycopg http://www.djangoproject.com/r/python-pgsql/windows/.
Linux,
python-psycopg2, psycopg2-python, pythonpostgresql .

15

Django SQLite 3
Python 2.5 , :
, Python SQLite.
.
Python 2.4 , SQLite 3 ( 2-)
http://www.djangoproject.com/r/sqlite/ pysqlite http://www.djangoproject.com/
r/python-sqlite/. , pysqlite
2.0.3.
Windows SQLite,
pysqlite.
Linux,
python-sqlite3, sqlite-python, pysqlite
.
, Debian Linux, Ubuntu .. :

apt-get install python-pysqlite2

Django MySQL
Django MySQL, 4.0. MySQL 4.0
SQL .
MySQLdb http://www.djangoproject.com/r/
python-mysql/.
Linux,
python-mysql, python-mysqldb, mysql-python
.

Django
, Django .
,
, .
,
Django . ,
,
. .


Python, Django ()
Python ,
, .
Django,
, Django .

16


Django ,
. ,
, /home/username/djcode/.


PHP,
(, /var/www). Django
. ,
. .
-
.
django-admin.py startproject
mysite. mysite .

django-admin.py ,
Django setup.py.
,
djtrunk/django/bin. djangoadmin.py, . Unix
, :
sudo ln -s /path/to/django/bin/django-admin.py \
/usr/local/bin/django-admin.py
Windows PATH.
Django Linux, djangoadmin.py django-admin.
permission denied1 django-admin.py
startproject, .
django-admin.py (, /usr/
local/bin) chmod +x django-admin.py.
:
mysite/
__init__.py
manage.py
settings.py
urls.py
:
__init__.py: , Python
, .., .
- .
manage.py: ,
. python manage.py
1

17


help .
, .
settings.py: Django.
,
.
urls.py: URL Django,
. (FIXME: -
.)
,
Django.


Django ,
.
Django ( runserver, ,
) ,
. Django ,

(.., Apache) .

,
.
mysite (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 CONTROL-C.
8000.
. ,
http://127.0.0.1:8000/ . Welcome to
Django2. !
. ,
,
.
.
, Django
, Django.
2

Django.

18


, runserver 8000,
. ,
:
python manage.py runserver 8000
IP ,
. ,
. IP 0.0.0.0
:
python manage.py runserver 0.0.0.0:8000
,
Django IP ,
, http://192.168.1.103:8000/. ,
IP
. Unix ifconfig.
Windows ipconfig.
, http://127.0.0.1:8000/
. Welcome to Django. !

http://simonwillison.net/2008/May/22/debugging/.
Django .
, ,
, ,

http://dpaste.com/,
IRC . ,
GET, POST COOKIE
META HTTP ( ,
HTTP_REFERER).
,
, :

assert False

, :

assert False, request.GET

19



. , ,
assert False ,
.


,
,
print. print
. JavaScript alert().
,
Python,
. settings.py:

import logging
logging.basicConfig(
level = logging.DEBUG,
format = '%(asctime)s %(levelname)s %(message)s',
)

def my_view(request):
import logging
logging.debug("A log message")
...

,
. , ,
:

logging.basicConfig(
level = logging.DEBUG,
format = '%(asctime)s %(levelname)s %(message)s',
filename = '/tmp/myapp.log',
filemode = 'w'
)

tail -f /tmp/myapp.log
.
, .
, ,
Python. [http://
docs.python.org/lib/module-logging.html],

20


,
POST -.
,
,
, , ,
. [http://docs.python.org/lib/
module-traceback.html] ,
:

import logging, traceback, pprint


def my_buggy_function(arg):
...
if error_condition:
stack = pprint.pformat(traceback.extract_stack())
logging.debug('An error occurred: %s' % stack)

, traceback.extract_stack(),
, Python, ..
.



pdb [http://docs.python.org/lib/module-pdb.html].
Python .
,
:

import pdb; pdb.set_trace()

,
, .

,
.
, , ,
?
,
. ? , .
[http://www.onlamp.com/pub/a/
python/2005/09/01/debugger.html] ,
:
list .

.
n .

21


s , .
r .
u , ..,
.
locals() ,
.

, ,
.
, .
c, ,
.
,
. Django.
:

>>> def function_that_raises_an_exception():


...
assert False
...
>>> function_that_raises_an_exception()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in function_that_raises_an_exception
AssertionError
>>> import pdb; pdb.pm()
> <stdin>(2)function_that_raises_an_exception()
(Pdb)

pdb.pm()
,
.
:
, ./manage.py. :

python -i manage.py buggy_command

-i ,
. ,
pdb.pm() .


Django (.., DEBUG
False)
, ADMINS.

22


404 SEND_BROKEN_LINK_EMAILS,
, MANAGERS.
Django.
, , djangodb-log [http://code.google.com/p/django-db-log/] (David Cramer),
. -
MD5 .
,
process_exception Django .


ProfilerMiddleware [http://www.djangosnippets.org/snippets/727/]
cProfile [http://docs.python.org/lib/module-profile.html]
URL, ?prof.
DebugFooter [http://www.djangosnippets.org/snippets/766/]
SQL .



TestClient [http://www.djangoproject.com/documentation/
testing/]. , - Django,
.
. :

>>> from django.test.client import Client


>>> c = Client()
>>> response = c.get("/") # The homepage
>>> response
<django.http.HttpResponse object at 0x2300470>
>>> print response
Vary: Cookie
Content-Type: text/html; charset=utf-8
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
...

HttpResponse,
.
,
setup_test_environment(). :

>>>
>>>
>>>
>>>

from django.test.utils import setup_test_environment


setup_test_environment()
from django.test.client import Client
c = Client()

23


>>> response = c.get("/")
>>> response.template
[<django.template.Template object at 0x2723dd0>,
<django.template.Template object at 0x2723f30>,
<django.template.Template object at 0x273ee10>]
>>> response.context
[ list of Context objects ]

HTML,
, ,
.

django-admin.py startproject megaproject

, . ,
.
,
. ./megaproject
:

python manage.py startapp gigaapp

./gigaapp models.py,
.

24

3.
URL
<ruslan.popov gmail>

.
Django.

Django: ,

, ,
: , .
,
Django, ,
hello.html . ,
, : (
, ) URL (http://www.example.com/hello.html/).
Django, , .
, URL
URL.
.


mysite, django-admin.py
startproject , views.py.
, . ,
. Django
. ,
, .
, .
views.py:

# -*- coding: utf-8 -*from django.http import HttpResponse


def hello(request):
return HttpResponse(", ")

, :
HttpResponse,
django.http. ,
.

25


URL
, hello .
,
request. ,
, .
django.http.HttpRequest.
, , ,
.
,
. hello,
,
hello_wonderful_beautiful_world . ,
URL , , Django .
. HttpResponse ,
, .
, Python,
HttpRequest
HttpResponse. , Python
Django, .
, .

URL
python manage.py runserver,
Welcome to Django .
, mysite hello.
Django,
URL. ( HTML
, HTML ,
.) URL Django
URL.
URL
. , URL
, URL.
Django: URL, , URL
. , - URL /foo/,
foo_view(), views.py.
django-admin.py startproject ,
: 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'

26


URL
# 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)),

,
, .
, :

from django.conf.urls.defaults import *


urlpatterns = patterns('',
)

:
django.conf.urls.defaults,
.
patterns.
patterns
urlpatterns. patterns
. (
,
URL .)
urlpatterns,
Django .
URL , URL. , , Django
. ( Django ,
Welcome to Django. , Django ,
, , .)
, URL ,
, URL .
hello:

from django.conf.urls.defaults import *


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

( , .
, .)

27


URL
:
hello mysite/
views.py, mysite.views.
, ('^hello/$', hello) urlpatterns.
URL. Python,
,
, .
, Django, URL /hello/
hello.

PYTHONPATH
PYTHONPATH ,
Python
import.
, , :

['', '/usr/lib/python2.4/site-packages', '/home/username/djcode/']

from foo import bar

foo.py .
( ,
.) ,
/usr/lib/python2.4/site-packages, /home/username/
djcode/. , ,
ImportError.
,
:

>>> import sys


>>> print sys.path

.
Python Django, . ( ,
, manage.py.)
URL,
. , /hello/,
. :

28


URL
Django URL,
. , /hello/.
(, ,
, ,
URL .)
^ $.
, : ^ ,
, $ ,
.
.
'^hello/' ( $), URL, /hello/
. , /hello/foo hello/bar, /hello/.
, ^ (.., 'hello/$'), Django
URL, hello/. , foo/
bar/hello/. 'hello/', ^ $,
URL, hello/. ,
/foo/hello/bar. ,
. /hello/,
.
URL
.
.
, , -
URL /hello ( , ).
, URL . , ,
URL, ,
URL . (
Django APPEND_SLASH,
D FIXME.)
, URL
( Django), ,
URL
APPEND_SLASH True.
( ), APPEND_SLASH False.
. URL
hello , .
Python ( ):
, ,
. , ?
, ,
, ,
python manage.py runserver. ( ,
.
, ,
.) http://127.0.0.1:8000/,
http://127.0.0.1:8000/hello/.
, .
! Django.

29


URL


1 .
URL Django
URL,
.

.

3.1.

. ()

\d

[A-Z]

( )

[a-z]

( )

[A-Za-z]

( )

, .. \d+

[^/]+

, .. \d?

{1, 3}

()

404
: ,
URL URL.
URL?

http://127.0.0.1:8000/goodbye/ http://127.0.0.1:8000/hello/subdirectory/,
http://127.0.0.1:8000/ ( ).
(. FIXME). Django ,
URL, .

404.
Django .
, 404.
, , .
, ,
.
404 ,
. .
, Django
, , Django
404.

http://www.djangoproject.com/r/python/re-module/
http://docs.python.org/lib/re-syntax.html.

30


URL


, 404 ,
URL http://127.0.0.1:8000/. Django
. URL - .
,
.
, .
, '^$',
. :

from mysite.views import hello, my_homepage_view


urlpatterns = patterns('',
('^$', my_homepage_view),
# ...
)

Django
,
, Django. , Django ,
http://127.0.0.1:8000/hello/?
. python manage.py
runserver, settings.py ,
manage.py.
Django,
: TEMPLATE_DIRS, DATABASE_NAME .
ROOT_URLCONF. Django Python
.
, django-admin.py startproject settings.py urls.py.
ROOT_URLCONF
. settings.py . :

ROOT_URLCONF = 'mysite.urls'

mysite/urls.py.
URL , /hello/ Django
, ROOT_URLCONF.
, -, URL
, . , Django
, ,
HttpRequest . (
HttpRequest .)
,
HttpResponse. , Django

31


URL
: Python
HTTP (.., ).
:
/hello/.
Django ,
ROOT_URLCONF.
Django ,
URL.
, Django
.
HttpResponse.
Django HttpResponse HTTP ,
.
Django.

.

,
Django, ,
. , ,
. HTML .
-
, .
,
,
/, .
, ,
.
:
HttpResponse, .
Python, , datetime
. :

>>> import datetime


>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2008, 12, 13, 14, 9, 39, 2731)
>>> print now
2008-12-13 14:09:39.002731

Django. Python.
( , Python

32


URL
, Django. , Django, ,
Python ,
Django.)
, ,
, datetime.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)

hello,
views.py. , hello
, :

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
current_datetime:
import datetime , .
current_datetime ,
datetime.datetime, now.
HTML ,
Python . %s
, %s
now. now
datetime.datetime, , %s
, "2008-12-13 14:09:39.002731".
HTML "<html><body>It is now 2008-12-13
14:09:39.002731.</body></html>".

33


URL
(, HTML ,
.)
, HttpResponse,
, hello.
views.py, urls.py,
Django URL
. - /time/:

from django.conf.urls.defaults import *


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

.
current_datetime . , ,
URL /time/, .
runserver http://127.0.0.1:8000/
time/ . .

Django
.
, Django ,
Django America/Chicago. ( , Django
.) ,
settings.py. ,
.

URL
URL Django :
. ,
,
. ,
,
.
URL Django
. Django- URL ,
. , , URL

.
.
current_datetime.
URL , , /time/ /
current-time/, ,

34


URL
. ,
-
URL, .
,
URL, ,
URL, . ,
current_datetime URL:

urlpatterns = patterns('',
('^hello/$', hello),
('^time/$', current_datetime),
('^another-time-page/$', current_datetime),
)

URL .
.

:
URL
current_datetime
, URL .
web- URL ,
. ,
URL, /books/243/ /books/81196/.
,
. ,
URL /time/plus/1/
, URL /time/plus/2/ .
,
, 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),
)

, .
, ,
, ,
. ,
,
URL, .
.

35


URL

URL
web-,
PHP Java, : ,
! - /time/plus?hours=3,
hours URL.
Django ( 7 FIXME),
Django URL. URL /
time/plus/3/ , , , ... , . URL
web-.
URL Django URL,
URL, .

? .
, URL . ,
\d+ :

urlpatterns = patterns('',
# ...
(r'^time/plus/\d+/$', hours_ahead),
# ...
)

( #..., , ,
.)
URL URL, /
time/plus/2/, /time/plus/25/ /time/plus/100000000000/.
99- . , -
.
\d{1,2}:

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

web-,

.
99- .
, , r
. Python,
.
Python, ,
, \n . r,
, Python , r'\n'

36


URL
, n.

.
Python. ,
URL, ,
.
URL
,

.
URL. ,
URL, , \d{1,2},
:

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

, .
.
URL :

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.


URL, .
, ,
URL. ?
, .
,
URL ,
, .
, , ,
,
.
,
, ,
URL. .

37


URL
, .
.
hours_ahead current_datetime,
, :
. :

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,
return HttpResponse(html)

:
, hours_ahead, : request
offset.

request

HttpRequest,

hello current_datetime.
: HttpRequest
.
offset , URL.
, URL /time/plus/3/, offset
'3'. /time/plus/21/ '21'. ,
, ,
.
(, Unicode,
Python, .)
offset,
, , Python
. .
, ,
request. ( URL
. 8 FIXME.)
, int() offset.
.
, Python ValueError,
int() , ,
'foo'. , ValueError,
django.http.Http404, , ,
404
:
ValueError, , (\d{1,2})

38


URL
, , offset
? , ,
URL , ,
,
- .
,
. ?
,
.
datetime.datetime.now() current_datetime.
, ,
datetime.timedelta datetime.datetime.
dt.
int() offset
datetime.timedelta , hours
.
HTML , ,
current_datetime.
,
, . , %s
, : (offset, dt)..
, HttpResponse. .
URL,
Django ( ) 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
. http://127.0.0.1:8000/time/plus/ ( )
404.


web-, .
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,
return HttpResponse(html)

http://127.0.0.1:8000/time/plus/3/
. ,
, TypeError :

39


URL

"unsupported type for timedelta hours component: unicode"

? datetime.timedelta ,
hours , ,
offset. TypeError
datetime.timedelta. .
Django
. ,
.
:
:
; , ( "unsupported
type"); ,
.
.
,
, . ()
Django /,
.
,
, .
Local vars ,
.
.
Switch to copy-and-paste view
Traceback.
, .


djangobook@conference.jabber.ru .
Share this traceback on a public Web site
. http://
www.dpaste.com/, URL
.
Request information web-,
: GET POST , cookie
, CGI .
Request information Settings
. ( ROOT_URLCONF
.)

, , .
, Django. ,
hours_ahead,
.

40


URL
,
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,
return HttpResponse(html)

,
Django
Internet. -
web- .
Django
.
, . ,
.

41

4.
<ruslan.popov gmail>
- ,
. , HTML Python,
:

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

,
,
. :
.
, .
, .
Python HTML
web-
(
). HTML/CSS
Python .
Python
,
,
.
,
.
Django, .


Django ,
.
( ),
. , HTML,
Django .
. HTML ,
, .
:

<html>
<head><title>Ordering notice</title></head>
<body>

42


<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>
<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 }}) .
. (
? .)
(.., {% if ordered_warranty
%}) . :
-.
for ({% for item in item_list %}) if ({% if
ordered_warranty %}).
for for Python,
. if,
, if. ,
True ordered_warranty. ,
, {% if ordered_warranty %}
{% else %}. , {% else %}
{% endif %}. , {% else %} .
,
,
. , {{ ship_date|date:"F j, Y" }},
ship_date date, "F j, Y".
date .
|, Unix .
Django
, .

43


F FIXME , ,
.
, 9 FIXME.


Django ,
, ,
. ,
Django. (
:
, ,
Python, ,
Django.)
Django
Python:
1. Template, .
2. render() Template ().
,
.
:

>>> 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.
mysite, django-admin.py startproject
( ), python manage.py shell
.


Python , ,
python manage.py shell, python.
, :
, Django
. Django,

44


,
, .
, .
Django DJANGO_SETTINGS_MODULE,
settings.py. ,
DJANGO_SETTINGS_MODULE mysite.settings,
, mysite Python.
python manage.py shell DJANGO_SETTINGS_MODULE
.
.

Django,


DJANGO_SETTINGS_MODULE .bash_profile
.
:

>>> from django.template import Template


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

,
:

<django.template.Template object at 0xb7d5f24c>

0xb7d5f24c ,
. Python,
Template.
Template
, .
, Template()
TemplateSyntaxError:

>>> from django.template import Template


>>> t = Template('{% notatag %}')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
...
django.template.TemplateSyntaxError: Invalid block tag: 'notatag'

block tag1 {% notatag %}.


.
1

45


TemplateSyntaxError
:
;
;
;
;
;
( , ).


, Template ,
. ,
.
.
Django Context,
django.template.
, .
render() Template
:

>>> 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)
Unicode, Python. ,
u . Django Unicode .
, . ,
Unicode
.


Python
. Context ,
, 9 FIXME.
(A-Z a-z)
, , . (
, .) .
, ,
:

>>> from django.template import Template, Context

46


>>> raw_template = """<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>
...
... {% 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>"

:
Template Context,
django.template.
raw_template.
, ,
. , ,
, .
, t, raw_template
Template.
datetime Python,
.
, c. Context
, . ,
, person_name 'John Smith', company 'Outdoor
Equipment' .
render() ,
. , ..,
.
, You didnt order a warranty ,
ordered_warranty False.
, April 2, 2009, 'F
j, Y'. ( date .)
Python,
(\n), ,

47


. -
Python: t.render(c) , ,
,
. , print:
print t.render(c).
Django:
, Template, Context
render().


, Template,
. :

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

Django .
.
, XML, XML
Django.


,
, . ,
, ,
.
. ().
, , .
. , ,
.
:

>>> 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.'

48


, . ,
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.'

,
:

>>> 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(),
Django :

>>> 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'

, .
,
, . (
.)
, , :

49

>>> 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
: Python .
0, 1 .
,
,
:
(.., foo["bar"]);
(.., foo.bar);
(.., foo.bar());
(.., foo[2]).
, .
. ,
{{ 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.')
>>> c = Context({'person': person})
>>> t.render(c)
u'SALLY is 43 years old.'


,
. , :
,
.
silent_variable_failure True.
silent_variable_failure,
, :

>>> t = Template("My name is {{ person.first_name }}.")

50


>>> 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, !
, alters_data:

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

, .
,
{{ account.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 .'

51


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

, ,
.
.
, web- - .


, Context
Context().
Context , Python:

>>> 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 %} True (..,
, False), {% if %}
{% endif %}, :

{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% endif %}

{% else %} :

52

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

Python
Python Django
False Boolean:
([]);
(());
({});
(0);
None;
False ( );
, Boolean
( ).
True.
{% if %} and, or 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 ,
. :

53

{% 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 %}

,
. :

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

{% 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 %}

{% if %} {% endif %}.
Django TemplateSyntaxError.

for
{% for %} .
for Python, for X in Y, Y ,
X , .
, , {%
for %} {% endfor %}.
,
, athlete_list:

54

<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>
{% empty %}
<p>There are no athletes. Only computer programmers.</p>

55


{% endfor %}

.
, ,
, . , continue,
. (
,
.)
{% for %}
forloop. ,
:
forloop.counter ,
, . ,
, 1.
:

{% for item in todo_list %}


<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}

forloop.counter0 forloop.counter,
. , 0.
forloop.revcounter ,
.
, ,
1.
forloop.revcounter0 forloop.revcounter,
. ,
,
0.
forloop.first Boolean True
. :

{% for object in objects %}


{% if forloop.first %}<li class="first">{% else %}<li>{% endif %}
{{ object }}
</li>
{% endfor %}

forloop.last Boolean True


. :

{% for link in links %}{{ link }}

56


{% 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 %}


<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 .

forloop
Inside the {% for %} block, the existing variables are moved out of the way to
avoid overwriting the magic forloop variable. Django exposes this moved context
in forloop.parentloop FIXME.
, forloop (
),
forloop.parentloop {% for %}.

ifequal/ifnotequal
Django
, ,
Python. (
.) ,

57



. 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
ifequal
ifequal

variable
variable
variable
variable

1 %}
1.23 %}
'foo' %}
"foo" %}

, ,
{% ifequal %}.
:

58


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

- ,
{% if %} {% ifequal %}.

HTML Python, Django


. {# #}:

{# This is a comment #}

.
, , .
.
(..,
):

This is a {# this is not


a comment #}
test.

,
{% comment %}, :

{% comment %}
This is a
multi-line comment.
{% endcomment %}

,
.
|:

{{ name|lower }}

{{ name }},
lower, .

59


. ,
:

{{ my_list|first|upper }}

.
. :

{{ bio|truncatewords:"30" }}

bio.
. F FIXME
.
addslashes: : ,
.
JavaScript.
date: date datetime
, , :

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

F FIXME.
length: .
. . ( ,
Python, , ..,
__len__().)


, Django,
, .

.
, Python , .

. ( ,
Python !
, . .)
, , Django ,
. , Django
,
,

60


, Python.
.
,
Django.
,
Django. World Online
Django. :
- .

, .
, .
Python
Django.
.
,
Python .
HTML/XML. ,
Django HTML,
HTML ,
. XML,
XML, Django
. XML
- .
, XML
.
, HTML.
,
WYSIWYG , Dreamweaver.
. Django
, HTML .
, Python .
,
, , , ,
Python.
, ,
Python .
Python (
9 FIXME).
.
, ,
.


.
. current_datetime
mysite.views, .
:

from django.http import HttpResponse

61


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
.
, , /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 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)

, , :
. /home/djangouser/
templates/mytemplate.html ,
open() IOError.

62


.
, .
, !
.
open(), fp.read() fp.close() .

, .


Django API
.
API
.
settings.py, ,
ROOT_URLCONF.
, settings.py
TEMPLATE_DIRS. , ,
:

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

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

# Missing comma!
TEMPLATE_DIRS = (

63

'/home/django/mysite/templates'

# Comma correctly in place.


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

, Python ,
.
.
Windows, Unix-
, :
TEMPLATE_DIRS = (
'C:/www/django/templates',
)
(.. ,
).
, ,
Django Python
TEMPLATE_DIRS , :
import os.path
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
)
__file__,
Python,
. , settings.py
(os.path.dirname), templates
(os.path.join) , ,
( Windows).
Python , ,
.
, , .
TEMPLATE_DIRS,
Django ,
.
current_datetime, :

64


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, .
current_datetime (.. http://127.0.0.1:8000/time/
). DEBUG True
current_datetime.html, ,
TemplateDoesNotExist.

4.1. ,

,
URL ,

65


: Template-loader postmortem.
.
, /home/django/templates/current_datetime.html
, :

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

render_to_response()
, Context
HttpResponse . ,
get_template() . -
.
Django ,
.
render_to_response(),
django.shortcuts. render_to_response()
,
.
current_datetime,
render_to_response():
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.
datetime .
current_datetime now, ,
, HttpResponse
render_to_response().
HttpResponse,
.
render_to_response()
. , , ,
.
, .

locals()
current_datetime:

66

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())
, , ,
locals(),
. , now
current_date, , .
locals() ,
,
.
locals() ,
. ,
. , locals() request.
, .

get_template()
.
,
. , .
Django ( ,
, HTML )
.
.
get_template(), ,
:
t = get_template('dateapp/current_datetime.html')
render_to_response() get_template(),

render_to_response().
.
.

67

Windows (/)
(\). get_template()
.

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.
,
. , :

# mypage.html
<html>
<body>
{% include "includes/nav.html" %}
<h1>{{ title }}</h1>
</body>
</html>

68

# includes/nav.html
<div id="nav">
You are in: {{ current_section }}
</div>

mypage.html ,
current_section,
, .
, Django
:
DEBUG True,
TemplateDoesNotExist .
DEBUG False,
, .


HTML,
, Django
.
,
, ?

, HTML ,
. , Django
{% include %}.
Django
.
,
, ,
-.
,
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>

69

, ,
, , hours_ahead URL .
, , HTML ,
:

<!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
.

,
. ,
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>

,
. . ,
<title> <h1>My helpful timestamp</h1>
header.html, .. . <h1>

70


, <title>,
. , ?
Django .

. ,
.
,
.
:

<!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 ,
.
, .
( , .)
, : {% 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
URL . ( , ,
hours_ahead .)
:

71

{% 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 %}, , .
, , base.html.
, {% block %} base.html
. , ,
{% block title %} , {%
block title %} , , {% block content %}
{% block content %}.
, footer,
.
{% block %} .
. ,
.
, .
-
:
1. base.html,
. , .
2. base_SECTION.html (..
base_photos.html base_forum.html). base.html
.
3. ,
.
.

, , .
:
{% extends %} ,
. , .
, {% block %} , .
,
.

72


, , .
.
, ,
{% block %} .
,
{{ block.super }} . ,
, .
{% block %}
. ,
. ,
, ,
. {% block %}
, , .
, {% extends %} ,
get_template(). ,
TEMPLATE_DIRS.
, {% extends %} .
,
. .

73

5.
<ruslan.popov gmail>
URL
Django: URL
. ,
.
.
-
. , ,
, ,
.
.
.
, http://www.amazon.com/ .
, ,
Amazon, HTML. ,
.
Django ,
, .., ,
Python.
: Django .
, SQL
Django, .
. , ,
.

URL
(
),
. :
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')

74


names = [row[0] for row in cursor.fetchall()]
db.close()
return render_to_response('book_list.html', {'names': names})

,
:
.
Django.
: , ,
. ,
.
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 ( MVC)
,
- Django.
, Django
. ,

. , ,
- .
,
.
, -
, --

75


(Model-View-Controller, MVC) .
;
, ,
; ,
, ,
.

?
, MVC,
. ,
:
,
,
: MVC.
Django MVC , .., MVC
. M, V C Django:
M, , ,
.
V, , ,
.
C, ,
, ,
URL, Python URL.
C Django
, , Django MTV . MTV- :
M (Model), .
: , ,
.
T (Template), .
:
.
V (View), -.
, .
.
MVC
, Ruby on Rails,
Django , Django .
MVC. Django
, .
, . , Ruby
on Rails ,
, ,
,
.
.
.

76


, Django
. ,
. Django
.

UTF-8, MySQL
(. )
/etc/mysql/my.cnf.
[client] :
default-character-set=utf8
[mysqld] :
default-character-set=utf8
collation_server=utf8_unicode_ci

.

(. )
:

mysql> show variables like 'coll%';


+----------------------+-----------------+
| Variable_name
| Value
|
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
| collation_database
| utf8_unicode_ci |
| collation_server
| utf8_unicode_ci |
+----------------------+-----------------+
3 rows in set (0.00 sec)
mysql> show variables like 'char%';
+--------------------------+----------------------------+
| Variable_name
| Value
|
+--------------------------+----------------------------+
| character_set_client
| utf8
|
| character_set_connection | utf8
|
| character_set_database
| utf8
|
| character_set_filesystem | binary
|
| character_set_results
| utf8
|
| character_set_server
| utf8
|
| character_set_system
| utf8
|
| character_sets_dir
| /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

77

, ,
. MySQL:

CREATE USER user@localhost IDENTIFIED BY "topsecret";


CREATE DATABASE mysite;
GRANT ALL ON mysite.* TO user@localhost;

SQLite : ,
SQLite .
TEMPLATE_DIRS ,
,
settings.py. :
DATABASE_ENGINE = ''
DATABASE_NAME = ''
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
:
DATABASE_ENGINE .
.

5.1.

postgresql

PostgreSQL

psycopg 1., http://


www.djangoproject.com/r/pythonpgsql/1/

postgresql_psycopg2

PostgreSQL

psycopg 2., http://


www.djangoproject.com/r/pythonpgsql/

mysql

MySQL

MySQLdb, http://
www.djangoproject.com/r/pythonmysql/

sqlite3

SQLite

Python
2.5+ .
http://
www.djangoproject.com/r/pythonsqlite/

oracle

Oracle

cx_Oracle, http://
www.djangoproject.com/r/pythonoracle/

,
. ,

78


, .
Linux,
. (, python-postgresql
python-psycopg.)
:

DATABASE_ENGINE = 'postgresql_psycopg2'

DATABASE_NAME Django . :

DATABASE_NAME = 'mydb'

SQLite,
. :

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

/home/django ,
, .
DATABASE_USER Django
. SQLite,
.
DATABASE_PASSWORD Django
. SQLite,
.
DATABASE_HOST Django
.
(.., localhost), . SQLite,
.
MySQL .
(/) MySQL,
UNIX , :
DATABASE_HOST = '/var/run/mysql'
(. ) ,
.
DATABASE_PORT Django
. SQLite,
. ,

79


( ) .
, .
, .
, python manage.py shell, ,
mysite. ( manage.py shell
Python
Django . , Django

.)

:

>>> from django.db import connection


>>> cursor = connection.cursor()

, . ,
, .

.

5.2.


DATABASE_ENGINE. (You haven't set the
DATABASE_ENGINE setting yet.)


DATABASE_ENGINE.
.


DJANGO_SETTINGS_MODULE.
(Environment variable
DJANGO_SETTINGS_MODULE is
undefined.)

python manage.py
shell python.

_____.

_____. (Error
, .. psycopg
loading _____ module: No module named MySQLdb.
_____.)
_____

. (_____ isn't an DATABASE_ENGINE,
available database backend.
,
.
?
_____ .
(database _____ does not exist.)

DATABASE_NAME,

,
CREATE
DATABASE .

_____ . (role _____


does not exist.)

DATABASE_USER,



.

80

. (could
not connect to server.)

,
DATABASE_HOST DATABASE_PORT
, ,
.


, ,
Django- ,
, Python
Django-.
, .
, ?
, , :
Django-
.

, ,
, .
,
,
Python.
, Django ,
.
,
.
.
, .
, , ,
.
,
, .
views.py,
URL .
.
, :
Django API ,
. . ,
,
.
mysite
books:

python manage.py startapp books

81

, books mysite.
:

books/
__init__.py
models.py
views.py

.
models.py views.py.
, models.py.
.

Python
, M MTV
(Model). Django , ,
Python.
SQL CREATE TABLE Python SQL
. Django
SQL Python
, . Django
, SQL
.
, :
Python SQL? Django
:
. ,
API , Django -
. :
Python. :
.
,
, . ,
.

, -,
. (
, Django
.
.) -, ,
MySQL,
.
Python
,
. /,

82


. SQL, Python,
SQL, .
, ,
.
.
SQL
.

URL. Django .
.
SQL .
-, Python,
, CREATE
TABLE MySQL, PostgreSQL SQLite.
, , , Python
.
, .
.
, , Django ,
.
.



: , , .
,

SQL. ,
!
, :
(, , ), , ,
.
, , , , .
.
( --) (
--, , ).

Python. models.py, startapp,
:

from django.db import models


class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)

83


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):
salutation = models.CharField(max_length=10)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
headshot = models.ImageField(upload_to='/tmp')
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()

, . ,
Python,
django.db.models.Model. , Model,
.

. , ,
Django.
, ,
.
, (.., CharField)
(.., varchar). , Publisher (
PostgreSQL):

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
, Django ,
.

.

84


, , .
, Django id
. , Django ,
.


. .
.
books
.
settings.py INSTALLED_APPS.
Django .
, :
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
)
#. (
,
.) , MIDDLEWARE_CLASSES
TEMPLATE_CONTEXT_PROCESSORS. ,
. 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',
)

( - ,
. ,
, ,
.
.)
mysite.books books, .
, INSTALLED_APPS,
, , .

85


,
. ,
:
python manage.py validate
validate .
, 0 errors found. , ,
.
.
, ,
python manage.py validate. .
, , Django
CREATE TABLE books (
, Unix):
python manage.py sqlall books
books .
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_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
);
CREATE TABLE "books_author" (
"id" serial NOT NULL PRIMARY KEY,
"salutation" varchar(10) NOT NULL,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(40) NOT NULL,
"email" varchar(75) NOT NULL,
"headshot" varchar(100) NOT NULL
);
CREATE TABLE "books_book_authors" (
"id" serial NOT NULL PRIMARY KEY,
"book_id" integer NOT NULL REFERENCES "books_book" ("id"),
"author_id" integer NOT NULL REFERENCES "books_author" ("id"),
UNIQUE ("book_id", "author_id")

86


);
CREATE INDEX books_book_publisher_id ON "books_book" ("publisher_id");
COMMIT;

:
,
(books) (publisher, book author).
,
.
, Django
id. .
Django _id .
, .
REFERENCES.
CREATE TABLE ,
, auto_increment (MySQL), serial
(PostgreSQL) integer primary key (SQLite) .
(..,
). PostgreSQL.
sqlall
SQL ,
. ,
.
, Django SQL .
syncdb:

python manage.py syncdb

Creating table books_publisher


Creating table books_book
Creating table books_author
Installing index for books.Book model

syncdb .
,
INSTALLED_APPS,
. , syncdb
. ,
syncdb . (More on this in the Making
Changes to a Database Schema section toward the end of this chapter. FIXME)
python manage.py syncdb ,
books

87


INSTALLED_APPS. ,
.
,
. (.., psql
PostgreSQL) python manage.py dbshell,
, DATABASE_ENGINE.
.


Django API
. , python manage.py shell
:

>>> from books.models import Publisher


>>> p1 = Publisher(name='Addison-Wesley', address='75 Arlington Street',
...
city='Boston', state_province='MA', 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.
, .
, name,
address .
, save(). Django
SQL INSERT.
, ,
Publisher.objects, .
Publisher
Publisher.objects.all(). Django SQL SELECT.
, .
Django
, save():

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

88


, objects.create().
:

>>>
...
...
...
>>>
...
...
...
>>>
>>>

p1 = Publisher.objects.create(name='Apress',
address='2855 Telegraph Avenue',
city='Berkeley', state_province='CA', country='U.S.A.',
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

, API ,
.


, ,
:

[<Publisher: Publisher object>, <Publisher: Publisher object>]

, __unicode__()
Publisher. __unicode__() Python
. :

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):
salutation = models.CharField(max_length=10)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()

89


headshot = models.ImageField(upload_to='/tmp')
def __unicode__(self):
return '%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__() ,
. , __unicode__()
Publisher Book , ,
__unicode__() Author first_name
last_name.
__unicode__()
Unicode. , , , Python
TypeError coercing to Unicode: need string or buffer,
int found.

Unicode
Unicode?
Unicode ,
,
.
Python , ,
: ASCII, ISO-8859-1 UTF-8.
( ,
ASCII),
, .

,
.
,
??? ?????? .
.
Unicode . ,
, Unicode.
Unicode Python, ,
.
Django Unicode .
Unicode, Unicode ,
Unicode. ,
. .
, Unicode.
.
http://www.joelonsoftware.com/articles/Unicode.html.

90


,
python manage.py shell. (
.) Publisher :

>>> from books.models import Publisher


>>> publisher_list = Publisher.objects.all()
>>> publisher_list
[<Publisher: Addison-Wesley>, <Publisher: O'Reilly>]

, __unicode__().
, Django
.
, , __unicode__()
. Django
, .
__unicode__()
.


: ,
, :

>>> p = Publisher(name='Apress',
...
address='2855 Telegraph Ave.',
...
city='Berkeley',
...
state_province='CA',
...
country='U.S.A.',
...
website='http://www.apress.com/')

.
save():

>>> p.save()

SQL :

INSERT INTO book_publisher


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

91

Publisher
id, save()
id:

>>> p.id
52
#

save() ,
(.., SQL UPDATE INSERT):

>>> p.name = 'Apress Publishing'


>>> p.save()

SQL :

UPDATE book_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;

, , , ,
. ,
(race condition).
, :

UPDATE books_publisher SET


name = 'Apress Publishing'
WHERE id=52;


, , ,
,
.
:

92

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

SQL :

SELECT
id, name, address, city, state_province, country, website
FROM book_publisher;

, Django SELECT *
, .
: SELECT *
, ,
Python:
.

Python Python
import this.
Publisher.objects.all():
Publisher. :
.
objects. .

. ,
, ,
.
objects.
.
, all(). objects,
, , . ,
, (QuerySet) ,
.
API .
.

, , .


,
.
. filter():

93

>>> Publisher.objects.filter(name='Apress')
[<Publisher: Apress>]

filter() ,
SQL- WHERE.
:

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>]

SQL AND.
:

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. Python


Django .
__contains SQL LIKE:

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


FROM books_publisher

94


WHERE name LIKE '%press%';

, icontains (
LIKE), startswith endswith, range (SQL BETWEEN).
API
.


filter() QuerySet,
.
. 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.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."

95


,
.
, .
,
- , , .
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;

>>> 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>]

96

, 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"]

: Meta,
Publisher ( ).
Meta ,
. B FIXME,
ordering. ,
order_by(), Publisher
name.


.
? :

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

, SQL :

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


FROM books_publisher
WHERE country = 'U.S.A'
ORDER BY name DESC;

1.
1

(. ).

97


. ,
,
.
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;

,
Python :

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

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


FROM books_publisher
ORDER BY name
OFFSET 0 LIMIT 2;

, :

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

.
order_by():

98

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


, save()
.
.
, Publisher name Apress
Apress 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',
state_province = 'CA',
country = 'U.S.A.',
website = 'http://www.apress.com'
WHERE id = 52;

( , ,
52.)
, save()
, name. ,
, , .
update() QuerySet. :

>>> Publisher.objects.filter(id=52).update(name='Apress Publishing')

SQL :

99


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

update() QuerySet ,
. country
U.S.A. USA Publisher:

>>> Publisher.objects.all().filter(country='U.S.A.').update(country='USA')
2

update() ,
.


delete():

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

,
delete() QuerySet.
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'

100


, all():

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

,
all(). :

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

101

6.
Django
aka Alerion <alerion.um gmail>
<ruslan.popov gmail>
-
. -, ,
,
. :
; ;
, -
, .
.
- , ,
.
, ,
. .
Django ?
, . Django
.
.
,
,
. , ,
.
,
Django, ,
Django.

django.contrib

, django.contrib Django,
Django. django.contrib Django
Python ,
.
Django, .
django.contrib,
. , django.contrib.admin.
django.contrib (django.contrib.auth),
(django.contrib.sessions),
(django.contrib.comments).
django.contrib, Django.
.
, Django ,
django.contrib.

102


Django


Django ,
.
.
:
1. django.contrib.admin INSTALLED_APPS. (
INSTALLED_APPS ,
, .)
2. ,

INSTALLED_APPS

django.contrib.auth,
django.contrib.sessions django.contrib.contenttypes.
. (
mysite, ,
. .)
3. ,

MIDDLEWARE_CLASSES

django.middleware.common.CommonMiddleware

django.contrib.sessions.middleware.SessionMiddleware

django.contrib.auth.middleware.AuthenticationMiddleware. (
mysite.)
python manage.py syncdb.
, .
syncdb django.contrib.auth INSTALLED_APPS,
. ,
python manage.py createsuperuser.
.
URL ( urls.py, ?).
-, urls.py django-admin.py startproject,
Django,
. , :

# Include these import statements...


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

,
. (python manage.py runserver,
) http://127.0.0.1:8000/admin/.

, ,

103


Django
. ,
.
, , ,
.

6.1.

,
. ,
python manage.py createsuperuser.
, ,
.
, .
,
, - .

104


Django

6.2.


. ,
, .

.
django.middleware.locale.LocaleMiddleware

MIDDLEWARE_CLASSES.
django.contrib.sessions.middleware.SessionMiddleware.
.
,


. Django .
Django .
,
.

105


Django

6.3.

.
SQL- SELECT * FROM auth_user;.
, ,
, .
: , .
,
, .
, ,
.

106


Django

6.4.

, , ,
. (
, , ).
, ()
, / ,
, .
,
.
, , , ,
. (, ,
!).

.
, .
,
. , ,

.

107


Django

6.5.


. ,
, .
.

108


Django

6.6.

, .
, ,
.
, : 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)

Django
.

(http://127.0.0.1:8000/admin/), Books

109


Django
Authors, Books Publishers. (
, .)

. !
.
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

(http://127.0.0.1:8000/admin/books/book/add/),
(ForeignKey) , (ManyToManyField)
.
,
. ,
, , .
, ,
. .


? .
Django URL urls.py ,
admin.autodiscover(),
. INSTALLED_APPS
admin.py . admin.py
, .
admin.py books, admin.site.register()
,
.
django.contrib.auth admin.py

. django.contrib, django.contrib.redirects
,
Django,
.
,
Django, , ,

110


Django
URL.
URL, .
, URL, django/contrib/admin
Django, - ,
. (
, ,
, ,
.)


, ,
,
, , .
, , email Author ,
. , ,
.
, email
Author (, , mysite/books/
models.py). blank=True email:

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__,
- SQL- CREATE TABLE.
blank=True
.
Author ,
. email VARCHAR
, .
, blank=True,
(http://127.0.0.1:8000/admin/books/author/add/) , Email,
. ,
. , Email ,
- .


blank=True /
. .
SQL
NULL. NULL , .

111


Django
SQL NULL , Python
None (). ,
(, VARCHAR) NULL, .
:
NULL, ? ?
? :
NULL, ?
, Django
CREATE TABLE ( ), NOT
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), .
,
, , , .
,
, , .
(PostgreSQL, , ; MySQL ,
, .) ,
NULL .
Django, , NULL,
null=True .
:
( , DateField, TimeField, DateTimeField) (
IntegerField, DecimalField, FloatField), blank=True,
null=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=True , blank=True,
null=True , CREATE

112


Django
TABLE, NOT NULL publication_date. ,
.
Django
, ALTER
TABLE , .
, manage.py dbshell,
. ,
:

ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL;

( , PostgreSQL.)

.
, .
.



. : Django
, ,
publication_date Book Publication date.
,
,
. , verbose_name
.
, Author.email
e-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='e-mail')

,
.
, ,
(, USA state). Django
, verbose_name
, .
, , verbose_name

. :

113


Django

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

ManyToManyField ForeignKey,
.
verbose_name.

ModelAdmin
, null=True, blank=True verbose_name
, .
, ,
Django ,
.
,
.
ModelAdmin.


, ,
Author. -,
__unicode__()
. __unicode__()
Author , :

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='e-mail')
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)

Author ,
:

114


Django

6.7.

,
. , ,
.
ModelAdmin Author.
,
,
. 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)

, :
1.

AuthorAdmin.

django.contrib.admin.ModelAdmin,
. list_display,
,
. ,
.

115


Django
2. admin.site.register(), AuthorAdmin Author.
: Author
AuthorAdmin.
admin.site.register() ModelAdmin
, . (
Book Publisher), Django -
.
, ,
, , email. ,
. (.
list_display ):

6.8.
list_display

. search_fields AuthorAdmin,
:

class AuthorAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'email')
search_fields = ('first_name', 'last_name')

. (.
search_fields .)
, ,

116


Django
first_name last_name. ,
. bar,
Barney, Hobarson.

6.9.
search_fields

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')
list_filter = ('publication_date',)
admin.site.register(Publisher)
admin.site.register(Author, AuthorAdmin)
admin.site.register(Book, BookAdmin)

,
ModelAdmin BookAdmin. list_display
. list_filter,
, .

117


Django
, Django : ,
7 , , Django
.
list_filter , :

6.10. list_filter

list_filter , DateField.
(, , BooleanField ForeignKey.)
, .

date_hierarchy:

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


,
date_hierarchy . , .

118


Django

6.11.
date_hierarchy

, date_hierarchy ,
,
.
-,
, .
-, ordering
Meta (. ), ordering ,
.

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

ordering ,
Meta, , .
-,
.
. ,
, .
(. .)

119


Django

6.12.

. ,
.


, ,
.
. -,
, .
fields , ModelAdmin:

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')

.
, . ,
. .
, fields
.
, . ,

120


Django


. , ,
publication_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')

,
. , ,
, . (,
.)
, Django
publication_date None ,
null=True.

--.
, ManyToManyField
,
HTML
. ,
Ctrl . ,
,
.
filter_horizontal.
BookAdmin :

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.)
,
javascript- ,
.

121


Django

6.13.
filter_horizontal.

filter_horizontal
ManyToManyField 10 .
filter_horizontal , .
ModelAdmin filter_vertical. ,
filter_horizontal, . ,
.
filter_horizontal filter_vertical ManyToManyField,
ForeignKey. -, <select>
ForeignKey, , ManyToManyField,
. ,
,
.
raw_id_fields.
ForeignKey
(<input type="text">) <select>. (.
raw_id_fields. .)

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',)

122


Django

6.14.
raw_id_fields.

? . ,
,
, ,
.

,
,
, . ,

.
,
.

,
.
,
(..,
).
,
.
, .
, ,
, , ,

123


Django
.
:
is active () .
,
.
is staff ()
(..,
). ,
, , (
),
.
is superuser ()
,
. .
..,
.
, (.., , )
: ,
. .
,
. ,
, .
, ,
. ,
,
Apress. ,
, Django.


. - ,
,
, !
.
.
, .
.


,
, ,
. ,
, .
Django ,
,
. , Django ,
, ,
, - :

124


Django
, ,
.

.
.
, .
.
Django,
( !).
, (raison d'tre)
Django ( )
( ).
, ,
:
: ,
.
.
: ,
, (,
),
.
,
.
RAD :

, . , ,
. ,
.
,
. , ,
, .
, . ,
.
.

?

. : .

125

7.
<ruslan.popov gmail>
HTML -,
Google
. Django
, .
HttpRequest Form.


HttpRequest
URL ,
. ,
HttpRequest , hello():

from django.http import HttpResponse


def hello(request):
return HttpResponse("Hello world")

HttpRequest , request,
,
, .
(..,
, )
.

URL
HttpRequest URL:

7.1. URL
/

request.path

, ,
.

/hello/

request.get_host()

(.., ).

127.0.0.1:8000
www.example.com

request.get_full_path() path,
( ).

/hello/?print=true

request.is_secure()

True False

True
HTTPS. False.

/ URL
.
. :

126


# 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.META , HTTP
, IP
( ). ,
,
-.
:
HTTP_REFERER ,
.
HTTP_USER_AGENT .
: "Mozilla/5.0 (X11; U; Linux i686; fr-FR; rv:1.8.1.17) Gecko/20080829
Firefox/2.0.0.17".
REMOTE_ADDR IP , .., "12.245.67.89". (
, :
"12.245.67.89,23.45.78.90".)
, request.META Python,
KeyError,
. ( HTTP
,
,
.) try/except 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)

127


,
request.META, .
:

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))

,
Django, HTML.


, HttpRequest ,
: request.GET request.POST.
,
GET POST.


, request.GET request.POST
, ,
Python, . , request.GET
request.POST get(), keys() values()
, for key in request.GET.
? ,
, . .

, read(),
.
POST HTML <form>, GET
, URL.


, ,
,
.
, :
HTML ,
. . ,
:

from django.shortcuts import render_to_response

128


def search_form(request):
return render_to_response('search_form.html')

URL ,
, PYTHONPATH.
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>

URL urls.py :

from mysite.books import views


urlpatterns = patterns('',
# ...
(r'^search-form/$', views.search_form),
# ...
)

( , views ,
from mysite.views import search_form, .

URL .)
runserver http://127.0.0.1:8000/search-form/,
. .
, , 404.
URL /search/, .
:

# urls.py
urlpatterns = patterns('',
# ...
(r'^search-form/$', views.search_form),

129

(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)

, ,
,
. :
1. <form> q. ,
GET (method="get") URL /search/.
2. URL /search/ (search())
q request.GET.
, q request.GET.
, ,
. ,
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),
request.GET ,
. URL
URL, Django URL
PHP/Java URL, , /time/plus?hours=3
.

request.GET.
POST GET request.POST
request.GET. GET POST? GET
, 1. POST
,
1

POST (. ).

130


, ,
. GET,
. ( http://www.w3.org/2001/tag/doc/
whenToUseGet.html, GET POST).
,
( , views.py):

from django.http import HttpResponse


from django.shortcuts import render_to_response
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.')

, :
q request.GET, ,
request.GET['q'] , .
Book.objects.filter(title__icontains=q)
, .
icontains (
B FIXME)
, q,
.
.
icontains ,
. ( ,
.
, .)
books, Book, .
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 %}

131



, .
.
-, search()
Please submit a search term.,
. ,
, Django.
,
.
, :

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')
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, .
, .
search_form.html,
error:

<html>
<head>
<title>Search</title>
</head>
<body>
{% if error %}
<p style="color: red;">Please submit a search term.</p>
{% endif %}

132


<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
</body>
</html>

-
, search_form(), error
, .
, :
search_form()? , URL /search/ (
GET) ( ).
search_form() URL,
search() ,
, - URL GET :

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 ,
.
q, c . , ,
q,
.
, .

URL, . :

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

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

133


action="" URL .
, action
URL.


,
.
. HTML
. :
, . 'foo'
.
, . '123'
.
, DD-MM-YYYY.
, , 8
.

JavaScript
, JavaScript
, . ,
, .
JavaScript,
,
JavaScript .
,
, , (..,
). JavaScript
,
.
search() ,
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',

134


{'error': error})

, 20 ,
. search_form.html Please
submit a search term. ,
:

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

- .
.
20- ? .
, error,
.
:

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.html ,
error, :

135

<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>

,
, : , q. Django.
- :
.
, ,
.
,
.
, 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>

136

<p>Your e-mail (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>

: , .
. , method="post",
.
,
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 e-mail 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})

( ,
books/views.py.
, ? ,
. Django , URL.
, contact books
__init__.py views.py.)
:
, request.method 'POST'.
, ,
. ( , request.method 'GET',
GET, POST.)

137



.
request.GET request.POST
. , <form> contact_form.html
method="post". POST,
request.GET .
, subject message,
. , POST
get() .
, :
.
, email ,
, .
@.
( Django , ).
send_mail django.core.mail
.
: , ,
. send_mail Django
EmailMessage, , ,
, multipart
.
, send_mail
Django
. http://docs.djangoproject.com/en/dev/topics/email/
.

,
HttpResponseRedirect.
( / URL/),
, ,
, render_to_response() .
: ,
POST, .
, ,

. ,
.
POST
.
, ,
.
?
.
,
, , ,
(
). POST ,
HTML
.

138


views.py:

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 e-mail 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 e-mail (optional): <input type="text" name="email" value="{{ ema
<p>Message: <textarea name="message" rows="10" cols="50">**{{ message }}
<input type="submit" value="Submit">
</form>
</body>
</html>

139


.
,
, - .


Django ,
django.forms ,
.
, .

newforms
Django , django.newforms.
django.forms
.
. Django
,
django.forms.
django.newforms, , .
Django 1.0 , django.newforms
django.forms.
Form
<form> . ,
, .
, views.py, ,
Django , forms.py.
views.py :

from django import forms


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

.
Field CharField EmailField
Form. ,
, 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
<tr><th><label for="id_email">Email:</label></th><td><input type="text" name="em
<tr><th><label for="id_message">Message:</label></th><td><input type="text" name

140

Django <label>. ,
.
,
:

>>> print f.as_ul()


<li><label for="id_subject">Subject:</label> <input type="text" name="subject" i
<li><label for="id_email">Email:</label> <input type="text" name="email" id="id_
<li><label for="id_message">Message:</label> <input type="text" name="message" i
>>> print f.as_p()
<p><label for="id_subject">Subject:</label> <input type="text" name="subject" id
<p><label for="id_email">Email:</label> <input type="text" name="email" id="id_e
<p><label for="id_message">Message:</label> <input type="text" name="message" id

, <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!'})

>>> f.is_bound
True

is_valid() Form, , .
,
:

141

>>> f.is_valid()
True

email, - ,
required=False :

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


>>> f.is_valid()
True

subject message, :

>>> 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
[]

Form errors,
:

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


>>> f.errors
{'message': [u'This field is required.']}

, Form, ,
cleaned_data.
.

142


, ,
Python.

>>> f = ContactForm({subject: Hello, email: adrian@example.com, message


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

,
Unicode IntegerField DateField,
cleaned_data
datetime.date .


contact(),
Form.
views.py:

from django.core.mail import send_mail


from django.shortcuts import render_to_response
from mysite.books.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>

143

{% 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>

, !
, ,
.
. , ,
,
. (,
, send_mail,
.)


, ,
message ,
<textarea> <input type="text">.
widget:

from django import forms


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

.
,
.
Field ,
.


.
subject . ,
max_length CharField :

144

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! ( .)
initial :

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 .
,
, . ,
, ,
2.


,
. -
, .
: , .
2

,
, initial, .
.

145


.
,
. ,
Form.
message,
clean_message() :

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

, clean_
. ,
.
clean_message()
( , CharField).
, self.cleaned_data.
, , ,
.
len() split()
. ,
ValidationError forms. , ,
.
, .
( Python)
. return,
None .




email Email. (? ,
Django verbose_name
. .)
,
. label, :

class ContactForm(forms.Form):

146


subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False, label='Your e-mail address')
message = forms.CharField(widget=forms.Textarea)


contact_form.html {{ form.as_table }}
,
.
CSS.
,
<ul class="errorlist">, :

<style type="text/css">
ul.errorlist {
margin: 0;
padding: 0;
}
.errorlist li {
background-color: red;
color: white;
display: block;
font-size: 10px;
margin: 0 0 3px;
padding: 4px 5px;
}
</style>

. {{ form.as_table }}
,
, .
(<input type="text">, <select>, <textarea> )
{{ form.fieldname }} ,
, ,
{{ form.fieldname.errors }}. ,
:

<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 %}

147

<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 e-mail 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.message.errors
. :

<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>
{{ form.message }}
</div>

, <div> errors
.

?
. ,
URL ,
,
Django, .

, Django .
.

148


URL
URL (
URL ).

149

8.
URL
.
!
<radz yandex ru>
URL
Django URL, URL
. .

URL:
URL , Django,
Python. ,
.


URL::
from django.conf.urls.defaults import *
from mysite.views import current_datetime, hours_ahead, hours_behind,
now_in_chicago, now_in_london
urlpatterns = patterns('',
(r'^now/$', current_datetime),
(r'^now/plus(\d{1,2})hours/$', hours_ahead),
(r'^now/minus(\d{1,2})hours/$', hours_behind),
(r'^now/in_chicago/$', now_in_chicago),
(r'^now/in_london/$', now_in_london),
)
URL ,
URL ,
. ,
.
Django , URL ,
. (
,
.) ,
views. :
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^now/$', views.current_datetime),
(r'^now/plus(\d{1,2})hours/$', views.hours_ahead),
(r'^now/minus(\d{1,2})hours/$', views.hours_behind),

150


URL

(r'^now/in_chicago/$', views.now_in_chicago),
(r'^now/in_london/$', views.now_in_london),

Django
URL. ,
, .
:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^now/$', 'mysite.views.current_datetime'),
(r'^now/plus(\d{1,2})hours/$', 'mysite.views.hours_ahead'),
(r'^now/minus(\d{1,2})hours/$', 'mysite.views.hours_behind'),
(r'^now/in_chicago/$', 'mysite.views.now_in_chicago'),
(r'^now/in_london/$', 'mysite.views.now_in_london'),
)
!
,
. Django
,
.
,
. , mysite.views, ..
.
patterns(), :
from django.conf.urls.defaults import *
urlpatterns = patterns('mysite.views',
(r'^now/$', 'current_datetime'),
(r'^now/plus(\d{1,2})hours/$', 'hours_ahead'),
(r'^now/minus(\d{1,2})hours/$', 'hours_behind'),
(r'^now/in_chicago/$', 'now_in_chicago'),
(r'^now/in_london/$', 'now_in_london'),
)
,
.
Django.
?
.
:
, .. .
URL ,
.
:

151


URL
. Wrapping View
Functions FIXME (- ) .
Python, ,
.
. ,
URL. .


, URL
. , .
patterns(), :
#
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^/?$', 'mysite.views.archive_index'),
(r'^(\d{4})/([a-z]{3})/$', 'mysite.views.archive_month'),
(r'^tag/(\w+)/$', 'weblog.views.tag'),
)
#
from django.conf.urls.defaults import *
urlpatterns = patterns('mysite.views',
(r'^/?$', 'archive_index'),
(r'^(\d{4})/([a-z]{3})/$', 'archive_month'),
)
urlpatterns += patterns('weblog.views',
(r'^tag/(\w+)/$', 'tag'),
)
, ,
urlpatterns. ,
.

URL
urlpatterns,
URL
Django . ,
DEBUG , :
from django.conf.urls.defaults import*
from django.conf import settings
urlpatterns = patterns('',
(r'^$', 'mysite.views.homepage'),
(r'^(\d{4})/([a-z]{3})/$', 'mysite.views.archive_month'),

152


URL
)
if settings.DEBUG:
urlpatterns += patterns('',
(r'^debuginfo$', 'mysite.views.debug'),
)
URL /debuginfo/ , DEBUG
True.


,
. URL ,
, .

URL
.


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

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

.
:
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')
, ,
.
:

153


URL
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 .
URL,
:
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),
)
,
:

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')
, URL
.
.
, URL,

154


URL
, ,
month_archive.

.
, .

. ,
, Django
. , ,
URL, .

/
URL ,
.
, Django , , , ,
. ,
URL
:
,
.
, .

. .

,
. , ,
, , :
# 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):

155


URL
m_list = MyModel.objects.filter(is_new=True)
return render_to_response('template2.html', {'m_list': m_list})
.
URL,
URL , ,
, :
# 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
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. :
.
, :
# 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

156


URL
def foobar_view(request, template_name):
m_list = MyModel.objects.filter(is_new=True)
return render_to_response(template_name, {'m_list': m_list})
, URL .

.
Django ,
, .

.

Faking Captured URLconf Values


, , ,
URL, ,
. , URL
URL
.
, ,
, URL:
/mydata/jan/01/
/mydata/jan/02/
/mydata/jan/03/
# ...
/mydata/dec/30/
/mydata/dec/31/
, :

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

:
def my_view(request, month, day):
# ....
, .
URL,
my_view, URL month / day.
, URL, /mydata/birthday/,
/mydata/jan/06/.
:

157


URL

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),
)

, -
. month day,
URL .



. , , 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)
Django,
URL.
,
. ,
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

158


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_l
: .
, , :
# 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.
Python
, .
model.objects.all() FIXME:
, .
, model,
model objects, all().
model.__name__.lower() , .
Python __name__, .
,
. , __name__ BlogEntry
BlogEntry.
,
object_list .
blogentry_list event_list, .
, ,
, Django ,

159


URL
.
Django .

Giving a View Configuration Options


Django ,
.
,
,
.
URL.
:
def my_view(request, template_name):
var = do_something()
return render_to_response(template_name, {'var': var})

Understanding Precedence of Captured Values vs. Extra Options


,
URL .
, ,
,
.
:

from django.conf.urls.defaults import *


urlpatterns = patterns('',
(r'^mydata/(?P<id>\d+)/$', views.my_view, {'id': 3}),
)

id
. .
, (.., /mydata/2/ /mydata/432432/)
- id 3,
URL.
, id
,
id .
, ,
.


. ,
.

160


URL
:

# urls.py
from django.conf.urls.defaults import *
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, URL.
, page()
(num=1). , page()
num
.
,
.
Giving a View Configuration Options ,
template_name:
def my_view(request, template_name='mysite/my_view.html'):
var = do_something()
return render_to_response(template_name, {'var': var})


, URL,
URL, .
.
,
URL :

Django

urlpatterns = patterns('',
# ...
('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
# ...
)
URL /myblog/entries/add/ /auth/groups/add/.
(/auth/user/add/)
,

161


URL
.
, :
def add_stage(request, app_label, model_name):
if app_label == 'auth' and model_name == 'user':
# do special-case code
else:
# do normal code
, :
URL .
, URL
:
urlpatterns = patterns('',
# ...
('^auth/user/add/$', 'django.contrib.admin.views.auth.user_add_stage'),
('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
# ...
)
/auth/user/add/ user_add_stage.
, URL ,
.


, URL
. :

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

year views.year_archive()
, , , \d{4}
.
.
Python .
datetime.date,
, :

>>> import datetime


>>> datetime.date('1993', '7', '9')
Traceback (most recent call last):
...
TypeError: an integer is required
>>> datetime.date(1993, 7, 9)
datetime.date(1993, 7, 9)

162


URL

URL :
# urls.py
from django.conf.urls.defaults import *
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)
:
def day_archive(request, year, month, day)
date = datetime.date(int(year), int(month), int(day))
, int() ValueError
, .
, URL
.

, URL
Django URL
Python ( Unicode ). GET
POST .
, URL .
, http://www.example.com/myapp/ Django
URL myapp/. http://www.example.com/myapp/?page=3 Django
myapp/.
(.. GET, POST, HEAD)
URL. , .

.

URL
Django ,
URL ,
.
.
URL . :

163


URL
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'),
)
: ,
include() $, .
Django include() URL
.
1:
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'),
)
URL, :
/weblog/2007/: r'^weblog/'.
include(), Django ,
weblog/. URL (.. 2007/)
mysite.blog.urls.
/weblog//2007/: r'^weblog/'.
include(), Django ,
weblog/. URL (.. /2007/, )
mysite.blog.urls.
/about/: mysite.views.about
, ,
.


include()
,
:

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

. . include('mysite.blog.urls').

164


URL
# foo/urls/blog.py
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^$', 'foo.views.blog_index'),
(r'^archive/$', 'foo.views.blog_archive'),
)

, username
, ,
.
,
, ,
. ,
, ,
.


include()
,
, ,
. ,
.
, .
:
# 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

165


URL
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^blog/', include('inner')),
)
# inner.py
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}),
)
( ),

, ,
. , ,
,
.

166

9.
.
!
<radz yandex ru>
:
. , Django
,
.
Django
. ,
,
. ,

.
URL
.
, , ,
.
URL.
Django :
:
.
.
event_list entry_list
URL , .
,
.
,
.
Django (http://www.djangoproject.com/weblog/) ,
.
,
.
,
.



URL
.
URL,
:
from django.conf.urls.defaults import *

167


from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
('^about/$', direct_to_template, {
'template': 'about.html'
})
)
, ,
! ,
URL : direct_to_template

.
, ,
, ,
. ,
URL /about/-/
about/-.html. :
from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
from mysite.books.views import about_pages
urlpatterns = patterns('',
('^about/$', direct_to_template, {
'template': 'about.html'
}),
('^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()
direct_to_template .
HttpResponse, .
. ,
, TemplateDoesNotExist
404.

?
:
, (template="about/
%s.html" % page). ,

168


(directory traversal) (
). ?
. page
, , page
URL, . URL:
\w+ page URL,
\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()
class Meta:
ordering = ["-name"]
class Admin:
pass
def __unicode__(self):
return self.name
1
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)
)
1

, . , , .

169


Python, . ,
. object_list
, template_name
. Django
, . ,
books/publisher_list.html books ,
, publisher
.
,
object_list Book.
:

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

.
, .

.
.


,
. ,
.
, , Django,

.

.
, .


,
object_list. ,
: ,
. publisher_list,
.

template_object_name:

170


publisher_info = {
"queryset" : Publisher.objects.all(),
"template_object_name" : "publisher",
}
urlpatterns = patterns('',
(r'^publishers/$', list_detail.object_list, publisher_info)
)
.
, , .


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

. .
, ?
extra_context.
URL, Book.objects.all()2
, . ,
, ,
(. "Caching and
QuerySets" API

QuerySet).

queryset .
Django ,
,
.
(callback) extra_context
. , extra_context,
2

. .

171


, .
:

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

, ,
, Book.objects.all :

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

Book.objects.all.
, (
).


queryset, .

, (
, API
).
,
:

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

, . ,
, .

172


, ,
:

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),
)

, queryset
. ,
vanilla FIXME ,
.
, ,
.
, URL,
? .

404 books/apress/, ,
Apress Publishing.
allow_empty
.
.


-
URL. URL, ,
,
? object_list
, . , :

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

, books_by_publisher:

from django.http import Http404

173


from django.views.generic import list_detail
from mysite.books.models import Book, Publisher
def books_by_publisher(request, name):
# ( 404, ).
try:
publisher = Publisher.objects.get(name__iexact=name)
except Publisher.DoesNotExist:
raise Http404
# object_list view.
return list_detail.object_list(
request,
queryset = Book.objects.filter(publisher=publisher),
template_name = "books/books_by_publisher.html",
template_object_name = "books",
extra_context = {"publisher" : publisher}
)


Python. ,

HttpResponse. ,
,
( , . )
.

,
, extra_context.
. .


, ,
.
, last_accessed Author,

. object_detail, ,
,
.
, URL,
:

from mysite.books.views import author_detail


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

174

, :

import datetime
from mysite.books.models import Author
from django.views.generic import list_detail
from django.shortcuts import get_object_or_404
def author_detail(request, author_id):
# 404.
author = get_object_or_404(Author, pk=author_id)
# .
author.last_accessed = datetime.datetime.now()
author.save()
# .
return list_detail.object_detail(
request,
queryset = Author.objects.all(),
object_id = author_id,
)

last_accessed
Author books/author_detail.html.
,
.
,
:

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["Content-Disposition"] = "attachment; filename=authors.txt"
return response

,
HttpResponse, HTTP
. Content-Disposition, , ,
, .

175

10.

.
!
<radz yandex ru>
,
Django ,
.
Django.
, ,
.
Django
(.., ),
.


, :
Python,
Django.
.
, -
. . ,
, ( if
loop),
.
{% %}:

{% if is_logged_in %}
!
{% else %}
, .
{% endif %}

, .
{{ }}:

{{ first_name }} {{ last_name }}.

- (
Python), .

176



,
.

. ,
, .

RequestContext Context
.
django.template.Context, Django
django.template.RequestContext, .
RequestContext HttpRequest .
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)
def view_3(request):
# ...
t = loader.get_template('template3.html')
c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the third view.'
})
return t.render(c)
def view_4(request):
# ...
t = loader.get_template('template4.html')

177



c = Context({
'app': 'My app',
'user': request.user,
'ip_address': request.META['REMOTE_ADDR'],
'message': 'I am the fourth view.'
})
return t.render(c)

, render_to_response()
,
. .
, app, user
ip_address, . .
RequestContext
. ,
,
render_to_response().
RequestContext Context .

RequestContext.
:

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.'},
processors=[custom_proc])
return t.render(c)
def view_3(request):
# ...
t = loader.get_template('template3.html')
c = RequestContext(request, {'message': 'I am the third view.'},
processors=[custom_proc])
return t.render(c)

178



def view_4(request):
# ...
t = loader.get_template('template4.html')
c = RequestContext(request, {'message': 'I am the fourth view.'},
processors=[custom_proc])
return t.render(c)

:
custom_proc. ,
HttpRequest
. .
,
RequestContext Context.
. , RequestContext ,
HttpRequest,
(request). , RequestContext processors,
,
. custom_proc
, .

app, user ip_address ,
custom_proc.

, .
message .
render_to_response(),
loader.get_template(), Context,
render() . ,
,
render_to_response().
. 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]))

179



def view_2(request):
# ...
return render_to_response('template2.html',
{'message': 'I am the second view.'},
context_instance=RequestContext(request, processors=[custom_proc]))
def view_3(request):
# ...
return render_to_response('template3.html',
{'message': 'I am the third view.'},
context_instance=RequestContext(request, processors=[custom_proc]))
def view_4(request):
# ...
return render_to_response('template4.html',
{'message': 'I am the fourth view.'},
context_instance=RequestContext(request, processors=[custom_proc]))


.
This is an improvement, but, evaluating the conciseness of this code, we have to admit we're
now almost overdosing on the other end of the spectrum. FIXME.
( )
( processors).
.
Django
. TEMPLATE_CONTEXT_PROCESSORS1 ,
RequestContext.
processors RequestContext.
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',
)

FIXME???,
, custom_proc
, ,
. ,
TEMPLATE_CONTEXT_PROCESSORS ,
( Python).
. ,
,
, .
1

. settings.py .

180



Django ,
:

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,
.
,
, .

django.core.context_processors.debug
.
TEMPLATE_CONTEXT_PROCESSORS ,
RequestContext :
debug: DEBUG (True False).
.
sql_queries: {'sql': ..., 'time': ...} SQL
,
. .
,

:
DEBUG True.
IP INTERNAL_IPS.

django.core.context_processors.i18n
, RequestContext
:
LANGUAGES: LANGUAGES .
LANGUAGE_CODE: request.LANGUAGE_CODE,
. LANGUAGE_CODE
.

.

181

django.core.context_processors.request
, RequestContext
request,
HttpRequest. , ,
.

?
:

. ,

.
, ,
TEMPLATE_CONTEXT_PROCESSORS, ,
. , ,
.
,
(.., ) ,
.
, ,
. ,
context_processors.py .


, ,

.
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.
, .
Django:
django.template.loaders.filesystem.load_template_source:
, TEMPLATE_DIRS.
.

182



django.template.loaders.app_directories.load_template_source:

Django .
INSTALLED_APPS,
templates. , 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, [http://www.pyobject.ru/
blog/post/cooking-python-eggs/] ;), .
.
, .
Django
TEMPLATE_LOADERS, , .


, ,
.
/
. , Django
,
, .
, .


, ,
, ,
Django.
:
-, Django
. python manage.py
startapp, ,
.
, ,
INSTALLED_APPS. .
-, templatetags
Django. , models.py, views.py
. :

183

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

: __init__.py,
Python , ; ,
. .
, poll_extras.py,
:

{% load poll_extras %}

{% load %} INSTALLED_APPS

.
, Python

Django.
,
,
, templatetags.
,
templatetags. , {% load %}
, .
, ,
, .
, ,
register, template.Library.
Library ,
. , :

from django import template


register = template.Library()


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

184



register,
.


Python,
:
();
, .
, {{ var|foo:"bar" }}, foo
var "bar".
- .
, .., . ,
, ,
.
:

def cut(value, arg):


" arg value"
return value.replace(arg, '')

, :

{{ somevariable|cut:"0" }}

. ,
:

def lower(value): # Only one argument.


" "
return value.lower()


Library, Django:

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

185



filter() Library :
;
.
Python 2.4 ,
register.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(). ,
Node.
render() ,
render() Node ,
. .
, ,
.
:

186


,
.
Node, .
, {% current_time %},
,
, strftime (. http://docs.python.org/library/
datetime.html#datetime.date.strftime).
. , :

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

, , Django {%
now %} .
.
Node :

from django import template


def do_current_time(parser, token):
try:
# split_contents() ,
tag_name, format_string = token.split_contents()
except ValueError:
# ,
# token.split_contents()[0], .
msg = '%r tag requires a single argument' % token.contents[0]
raise template.TemplateSyntaxError(msg)
return CurrentTimeNode(format_string[1:-1])

:
parser .
.
token.contents .
current_time "%Y-%m-%d %I:%M %p".
token.split_contents() ,
. token.contents.split(),
. ,
.
django.template.TemplateSyntaxError
.

187



.
token.split_contents()[0] ,
.
CurrentTimeNode (
), , . ,
"%Y-%m-%d %I:%M %p".
format_string[1:-1].
Node.
.


Node,
render(). , CurrentTimeNode:

import datetime
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = 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() :
. ,
.
.

188



,
( Python 2.4+):

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

name, , Django
.


.
.
,
.
, ,
render().
CurrentTimeNode:

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

, render() .
. ,
.
:

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


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

CurrentTimeNode2 current_time
. , ,
{{ current_time }}, {% current_time2 %}
.

189




, :

{% 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 = 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.
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() .

190



{% 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 ''

parse() ,
. django.template.NodeList,
Node,
.
, nodelist {%
comment %} {% endcomment %}.
parse() {% endcomment
%}, delete_first_token(),
.
CommentNode.render() . ,
{% comment %} {% endcomment %} .


, do_comment() ,
{% comment %} {% endcomment %}. .
, {% upper %},
{% endupper %}:

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

parser.parse().
nodelist Node:

@register.tag
def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):

191



self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context)
return output.upper()

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


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


,
, ,
.
, current_time, ,
. , .
, Django
-, simple_tag. django.template.Library,
, render()
.
current_time :

def current_time(format_string):
return datetime.datetime.now().strftime(format_string)
register.simple_tag(current_time)

, :

@register.simple_tag
def current_time(token):
...

simple_tag :
.
,
.
( ) , ..,
.

192


,
. , Django
FIXME.
, ,
.
, .
.
. ,
, Poll.
:

{% show_results poll %}

<ul>
<li>First choice</li>
<li>Second choice</li>
<li>Third choice</li>
</ul>

, ,
. ,
. :

def show_books_for_author(author):
books = author.book_set.all()
return {'books': books}

, .
, :

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

, inclusion_tag()
Library.

193



, polls/
result_snippet.html, :

register.inclusion_tag('books/books_for_author.html')(show_books_for_author)

, Python 2.4+ :

@register.inclusion_tag('books/books_for_author.html')
def show_books_for_author(show_books_for_author):
...

,
. Django
takes_context. ,
,
.
, ,
, home_link home_title,
. :

@register.inclusion_tag('link.html', takes_context=True)
def jump_link(context):
return {
'link': context['home_link'],
'title': context['home_title'],
}

context.
link.html :

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

, ,
:

{% jump_link %}

194


Django (
) ,
. ,
Subversion,
ZIP .
, ,
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.
, ,
. , ,
[http://www.pyobject.ru/blog/post/cooking-python-eggs/]
;) False , pkg_resources
, .
.
, ZIP .
TEMPLATE_ZIP_FILES
TEMPLATE_DIRS , ZIP ,
:

import zipfile
from django.conf import settings
from django.template import TemplateDoesNotExist
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.

195



for fname in template_zipfiles:
try:
z = zipfile.ZipFile(fname)
source = z.read(template_name)
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_loader,
mysite.zip_loader.load_template_source TEMPLATE_LOADERS.

Django
.
, .
,
.
: , , .

.
. URL
.
, URL :
.
, .
, .
, .

object_list,
django/views/generic/list_detail.py.
Django
, ,
.
, , ,
, .

196

,
.
Django,
.
Django
, ,
, DJANGO_SETTINGS_MODULE. ,
Django,
.
,
.
HTML,
.
. , HTML
Django. ,
.
,
. ,
PYTHONPATH , Django,
, .
, ,
DJANGO_SETTINGS_MODULE (, ,
, Django ), .
( ):

import django
django.conf.settings.configure(TEMPLATE_DIRS = ('/home/rad/devel/cpr_report',))

, , .
TEMPLATE_DIRS (
), DEFAULT_CHARSET ( UTF-8
) TEMPLATE_DEBUG.
, ,
TEMPLATE_.
:

import django
from django.template import Context, loader
django.conf.settings.configure(TEMPLATE_DIRS = ('/home/rad/devel/cpr_report',))
template = loader.get_template('cpr_report_template.html')
context = Context({'problems': info_problems or '',
'plans': info_plans or '',
'done': info_done or ''})

197



html = template.render(context)

198

11. ,
HTML
.
!
<radz yandex ru>
, , HTML. ,
HTML .
: RSS, PDF, .
HTML,
Django
.
Django ,
, HTML:

RSS/Atom.
( XML , Google,
).
,
.

: MIME-
URL :
, , Python,
. HTML
, , 404, 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")

199

,
HTML
! open()
,
, .
, HttpResponse
API . , HttpResponse
, .
, , Django
CSV.

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

.
. . http://
www.faa.gov/data_statistics/passengers_cargo/unruly_passengers/.
, CSV , .
CSV,
. , Python
CSV.
, csv ,
HttpResponse:

import csv
from django.http import HttpResponse

# 1995 - 2005
# .
UNRULY_PASSENGERS = [146,184,235,200,226,251,299,273,281,304,203]

200

,
HTML
def unruly_passengers_csv(request):
# HttpResponse CSV .
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=unruly.csv'
# CSV, HttpResponse ""
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/html MIME- text/csv. ,
CSV .
Content-Disposition,
CSV . , ,
, ,
. ,
....
API CSV : response
csv.writer. csv.writer
HttpResponse .
CVS
writer.writerow, ,
.
csv .
writerow() .

HTML: HttpResponse ( MIME-),
-, .
.

PDF
PDF, Adobe,
,
. PDF
. , PDF
,
.
PDF Python Django
ReportLab [http://www.reportlab.org/rl_toolkit.html].
PDF ,
, ,
.

201

,
HTML
, Django ReportLab KUSports.com
NCAA .

ReportLab
PDF
ReportLab. : http://
www.reportlab.org/downloads.html.
( PDF) http://www.reportlab.org/
rsrc/userguide.pdf .

Linux,
.
.
, () Ubuntu,
:
apt-get install python-reportlab

Python:

>>> import reportlab

,
.


CSV, PDF Django
, , API ReportLab
.
Hello World:

from reportlab.pdfgen import canvas


from django.http import HttpResponse
def hello_pdf(request):
# HttpResponse PDF .
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
# PDF, HttpResponse .
p = canvas.Canvas(response)
# PDF . PDF.

202

,
HTML
# ReportLab .
p.drawString(100, 100, "Hello world.")
# PDF.
p.showPage()
p.save()
return response

:
application/pdf MIME-.
, PDF , HTML.
, HTML
.
ReportLab API : response
canvas.Canvas. Canvas
HttpResponse .
PDF
PDF (. p ), response.
showPage() save() PDF ,
PDF .

PDF
PDF (
), cStringIO
PDF . cStringIO
, C
.
Hello World , cStringIO:

from cStringIO import StringIO


from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# HttpResponse PDF .
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
temp = StringIO()
# PDF, StringIO .
p = canvas.Canvas(temp)
# PDF . PDF.
# ReportLab .
p.drawString(100, 100, "Hello world.")
# PDF.
p.showPage()

203

,
HTML
p.save()
# StringIO .
response.write(temp.getvalue())
return response


,
Python. ,
:
ZIP : Python zipfile,
ZIP .
, ,
, .
TAR tarfile .
: Python, PIL [http://
www.pythonware.com/products/pil/]
( PNG, JPEG, GIF
).
,
.
: Python
,
.
, :

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

,
MatLab Methematica.
pygraphviz (https://networkx.lanl.gov/wiki/pygraphviz),
GraphViz [http://graphviz.org/],

, Python,
Django. .
HTML ,
. Django
-HTML .


Django ,
RSS Atom.

RSS? Atom?
RSS Atom , XML,

. RSS
http://www.whatisrss.com/, Atom http://www.atomenabled.org/.

204

,
HTML

syndication feed.

Python. , .
,
/feeds/. Django URL
(, /feeds/) ,
.
, Feed
URL ( URL
URL ).

,
:

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

Django, RSS
URL, feeds/. ( feeds/
.)
, feed_dict ,
( URL).
. :

from django.conf.urls.defaults import *


from myproject.feeds import LatestEntries, LatestEntriesByCategory
feeds = {
'latest': LatestEntries,
'categories': LatestEntriesByCategory,
}
urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)

:
, LatestEntries, feeds/latest/.

205

,
HTML
, LatestEntriesByCategory, feeds/
categories/.
Feed.
Feed Python .
(..
) (..
, ).

django.contrib.syndication.feeds.Feed. Feed
.


, http://chicagocrime.org/, ,
:

from django.contrib.syndication.feeds import Feed


from chicagocrime.models import NewsItem
class LatestEntries(Feed):
title = "Chicagocrime.org site news"
link = "/sitenews/"
description = "Updates on changes and additions to chicagocrime.org."
def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]

:
django.contrib.syndication.feeds.Feed.
title, link description RSS: <title>,
<link> <description>.
items() ,
<item>. ,
NewsItem API , items()
.
, Django,
items() .
-. RSS- <item>
<title>, <link> <description>.
.
<title> <description>,
(. ) feeds/latest_title.html feeds/
latest_description.html, latest ,
. ,
.html .
RSS ,
:

206

,
HTML
obj: ( items()).
site: django.models.core.sites.Site, .
{{ site.domain }} {{ site.name }}.
,
{{ obj }} , .. .
,
title_template description_template Feed.
<link> .
, items(), Django
get_absolute_url(). , Django
item_link() Feed, item,
.
, get_absolute_url() item_link(), URL
Python.
LatestEntries
:
# latest_title.html
{{ obj.title }}
#latest_description.html
{{ obj.description }}
...


http://chicagocrime.org RSS-
. , Feed
. DRY
.
, ,
URL.
URL,
:
http://www.chicagocrime.org/rss/beats/0613/:
0613.
http://www.chicagocrime.org/rss/beats/1424/:
1424.
beats.
URL beats 0613 1424 ,
URL .
. :

207

,
HTML
from django.core.exceptions import ObjectDoesNotExist
class BeatFeed(Feed):
def get_object(self, bits):
# In case of "/rss/beats/0613/foo/bar/baz/", or other such
# clutter, check that bits has only one member.
if len(bits) != 1:
raise ObjectDoesNotExist
return Beat.objects.get(beat__exact=bits[0])
def title(self, obj):
return "Chicagocrime.org: Crimes for beat %s" % obj.beat
def link(self, obj):
return obj.get_absolute_url()
def description(self, obj):
return "Crimes recently reported in police beat %s" % obj.beat
def items(self, obj):
crimes = Crime.objects.filter(beat__id__exact=obj.id)
return crimes.order_by('-crime_date')[:30]

RSS-.
URL /rss/beats/0613/:
1. URL /rss/beats/0613/ ,
URL. /
Feed get_object(), URL.
, ['0613']. /rss/beats/0613/foo/bar/'
['0613', 'foo', 'bar'].
2. get_object()
.
, API
.
, get_object()
django.core.exceptions.ObjectDoesNotExist .
try / except Beat.objects.get(),
.. .
Beat.DoesNotExist, ObjectDoesNotExist.
ObjectDoesNotExist get_object() Django,
404 .
3. <title>, <link> <description> Django
title(), link() description().
, ,
. title, link description Django
:
a. obj, obj
, get_object().
b. , .
c. , .

208

,
HTML
4. , items()
obj. items
items(obj), items()
items ( ).
Feed
Django (http://www.djangoproject.com/documentation/0.96/
syndication_feeds/).


RSS 2.0.
feed_type Feed:

from django.utils.feedgenerator import Atom1Feed


class MyFeed(Feed):
feed_type = Atom1Feed

, ,
. :

11.1.

django.utils.feedgenerator.Rss201rev2Feed

RSS 2.01 (
)

django.utils.feedgenerator.RssUserland091Feed

RSS 0.91

django.utils.feedgenerator.Atom1Feed

Atom 1.0

, (..
, MP3 ), 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/example-with-enclosures/"
def items(self):
return Song.objects.all()[:30]
def item_enclosure_url(self, item):
return item.song_url
def item_enclosure_length(self, item):
return item.song_length

209

,
HTML
item_enclosure_mime_type = "audio/mpeg"

, Song song_url song_length


( ).


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

URL
/ link URL (.. /blog/),
URL (.. http://www.example.com/blog/). link ,

SITE_ID.
Atom <link rel="self">,
. ,
SITE_ID.

Atom RSS
: RSS
Atom. Django :
feed feed_type - .
. :

from django.contrib.syndication.feeds import Feed


from chicagocrime.models import NewsItem
from django.utils.feedgenerator import Atom1Feed
class RssSiteNewsFeed(Feed):
title = "Chicagocrime.org site news"
link = "/sitenews/"
description = "Updates on changes and additions to chicagocrime.org."
def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]
class AtomSiteNewsFeed(RssSiteNewsFeed):
feed_type = Atom1Feed

from django.conf.urls.defaults import *


from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed

210

,
HTML
feeds = {
'rss': RssSiteNewsFeed,
'atom': AtomSiteNewsFeed,
}
urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)


XML ,

.
.
, Django (http://www.djangoproject.com/
sitemap.xml):

<?xml version="1.0" encoding="UTF-8"?>


<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>

http://
www.sitemaps.org/.
Django XML ,
Python. ,
Sitemap
URL.

,
:

1. django.contrib.sitemaps INSTALLED_APPS.

211

,
HTML
2. , django.template.loaders.app_directories.load_template_source
TEMPLATE_LOADERS.
, .
3. , sites framework FIXME (.
).


. ,
INSTALLED_APPS load_template_source
.


URL:

(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitema

Django, ,
/sitemap.xml.
,
.
URL . , sitemap.xml
, URL . ,
URL /content/sitemap.xml, URL,
/content/.
:
{'sitemaps': sitemaps}. sitemaps ,
(.. blog news) Sitemap (.. BlogSitemap
NewsSitemap). Sitemap
(.., BlogSitemap(some_var)).

Sitemap Python ,
. , Sitemap
,
.
sitemap.xml.
,
, .
Sitemap django.contrib.sitemaps.Sitemap
.
, , ,
Entry. , .
Sitemap:

212

,
HTML
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,
Django.
Feed, Sitemap ,
. .
Sitemap :
items .
. ,
location(), lastmod(), changefreq() priority().
location URL
. URL URL,
. :
: /foo/var/.
: example.com/foo/bar/.
: http://example.com/foo/bar/.
location , get_absolute_url()
, items().
lastmod
datetime.
changefreq ,
. ,
, :
always
hourly
daily
weekly
monthly
yearly
never

213

,
HTML
priority 0.0 1.0.
0.5.
http://sitemaps.org/.


. .

FlatPageSitemap
django.contrib.sitemaps.FlatPageSitemap ,
.
location.

.

GenericSitemap
GenericSitemap (.
), .
, ,
info_dict, .
, queryset.
date_field,
queryset. lastmod .
priority changefreq
GenericSitemap, URL.
, FlatPageSitemap
GenericSitemap ( Entry, ):

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,
'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})

214

,
HTML
)



, ,
sitemaps. :

:
django.contrib.sitemaps.views.index django.contrib.sitemaps.views.sitemap.

django.contrib.sitemaps.views.sitemap
section.

(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 sitemap-blog.xml. Sitemap sitemaps


.

Google
Google ,
, .
django.contrib.sitemaps.ping_google().

Google .
, , Yahoo / MSD
.
, ping_google()

ping_search_engines().

http://www.djangoproject.com/
documentation/0.96/sitemaps/.
ping_google() sitemap_url,
URL (.. /sitemap.xml).
, .

ping_google()

django.contrib.sitemaps.SitemapNotFound, URL
.

215

,
HTML
ping_google() save() :

from django.contrib.sitemaps import ping_google


class Entry(models.Model):
# ...
def save(self):
super(Entry, self).save()
try:
ping_google()
except Exception:
# ,
# , HTTP.
pass

, ping_google() cron
. HTTP
Google
save().

216

12. ,

.
!
<radz yandex ru>
:
.
HTML,
Django
.
,
.
, . , ,
( , ). .
, .
,
.
, . HTTP , .
, - .
. ,
- (IP , )
.
.
(cookes) ,
.

Cookie
,
HTTP .
cookie. Cookie ,
.
, cookie.
.
http://google.com/, HTTP Google,
:

GET / HTTP/1.1
Host: google.com
...

Google :

217

,

HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671;
expires=Sun, 17-Jan-2038 19:14:07 GMT;
path=/; domain=.google.com
Server: GWS/2.1
...

Set-Cookie. cookie
(PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671)
, Google. ,
Google, :

GET / HTTP/1.1
Host: google.com
Cookie: PREF=ID=5b14f22bdaf1e81c:TM=1167000671:LM=1167000671
...

Google Cookie ,
, . , ,
, . Google (
) .


Django
/ ,
. ,
cookie . ,
. ,
cookie .
cookie .
COOKIES, .
cookie, :

def show_color(request):
if "favorite_color" in request.COOKIES:
return HttpResponse("Your favorite color is %s" % \
request.COOKIES["favorite_color"])
else:
return HttpResponse("You don't have a favorite color.")

cookie . set_cookie()
HttpResponse. cookie favorite_color,
GET:

def set_color(request):

218

,

if "favorite_color" in request.GET:
# Create an HttpResponse object...
response = HttpResponse("Your favorite color is now %s" % \
request.GET["favorite_color"])
# ... 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(), cookie,
cookie :

12.1. cookie

max_age

None

( ) cookie.
None, cookie
.

expires

None

cookie.
Wdy, DD-Mth-YY HH:MM:SS GMT.
,
max_age.

path

cookie.
cookie ,
.

cookie .
,
.

domain

None

cookie.
cookie
. , domain=".example.com"
cookie,
www.example.com, www2.example.com
an.other.sub.domain.example.com.
None, cookie
.

secure

False

True,
cookie HTTPS.


cookie.
:

219

,

cookie .
.
cookie. cookie ,
cookie.
, cookie .
, ,
cookie .
, cookie.
,
cookie.
Cookie , ,
HTTPS. Cookie , ,
. ,
, cookie . ,
cookie.
, ,
cookie , . 19 FIMXE
.
Cookie , .

cookie,
, mechanize [http://wwwsearch.sourceforge.net/mechanize/]
HTTP .
, cookie ,
. cookie IsLogged=1 cookie .

. .


, , cookie
. Django
, ,
, .

.
cookie . Cookie
, ,
cookie.

.

(. )
Django. :
1. MIDDLEWARE_CLASSES,
django.contrib.sessions.middleware.SessionMiddleware.

220

,

2. INSTALLED_APPS django.contrib.sessions.
manage.py syncdb .
, startproject
,
.

SessionMiddleware MIDDLEWARE_CLASSES
django.contrib.sessions INSTALLED_APPS.
,
.


SessionMiddleware HttpRequest
Django session
. :

# :
request.session["fav_color"] = "blue"
# --
#
# ( ):
fav_color = request.session["fav_color"]
# :
del request.session["fav_color"]
# :
if "fav_color" in request.session:
...

, keys() items()
request.session.
Django:
request.session Python
. ,
, , .
, ,
Django.
,
, .
request.session .
Python.
.
has_commented True ,
. ( )
:

221

def post_comment(request, new_comment):


if request.session.get('has_commented', False):
return HttpResponse(" ")
c = comments.Comment(comment=new_comment)
c.save()
request.session['has_commented'] = True
return HttpResponse(' !')

def login(request):
try:
m = Member.objects.get(username__exact=request.POST['username'])
if m.password == request.POST['password']:
request.session['member_id'] = m.id
return HttpResponse(" .")
except Member.DoesNotExist:
return HttpResponse(" .")

def logout(request):
try:
del request.session['member_id']
except KeyError:
pass
return HttpResponse(" .")

.
.
.

cookie
, ,
cookie. , , Django
cookie.
request.session.set_test_cookie()
( ),
request.session.test_cookie_worked().
-
cookie. cookie,
, cookie .
.

222

delete_test_cookie().
cookie.
:

def login(request):
# ...
if request.method == 'POST':
# , cookie:
if request.session.test_cookie_worked():
# , cookie.
request.session.delete_test_cookie()
#
# , ...
return HttpResponse("You're logged in.")
# , .
# .
else:
return HttpResponse("Please enable cookies and try again.")
# , cookie
# .
request.session.set_test_cookie()
return render_to_response('foo/login_form.html')

, .


, Django,
django.contrib.sessions.models.
32- , cookie. ,
API
:

>>> 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()
. ,
:

223

>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}


Django
, ..
:

# .
request.session['foo'] = 'bar'
# .
del request.session['foo']
# .
request.session['foo'] = {}
# : ,
# request.session['foo'], request.session.
request.session['foo']['bar'] = 'baz'

SESSION_SAVE_EVERY_REQUEST True. Django


,
.
, cookie ,
. SESSION_SAVE_EVERY_REQUEST
True, cookie . ,
expires cookie.


, cookie, Google expires=Sun,
17-Jan-2038 19:14:07 GMT;. Cookie
, , cookie.
cookie , ,
.
SESSION_EXPIRE_AT_BROWSER_CLOSE.
SESSION_EXPIRE_AT_BROWSER_CLOSE
False, , cookie
SESSION_COOKIE_AGE (
1'209'600 ). ,
.

224

,

SESSION_EXPIRE_AT_BROWSER_CLOSE True, Django
cookie,
.


,
Django , cookie. ,
cookie :

12.2. , cookie

SESSION_COOKIE_DOMAIN None


cookie. ,
.lawrence.com
cookie None
.

SESSION_COOKIE_NAME

cookie
. .

sessionid

SESSION_COOKIE_SECURE False


cookie .

True, cookie

HTTPS.



:
Python,
pickle.
Python pickle.
django_session .
.
request.session, Django .
Django cookie .
, Django cookie (
SESSION_SAVE_EVERY_REQUEST).
cookie.
URL, PHP
JSP, cookie.

Django.

URL ,

Referrer.
, .
django.contrib.sessions, .

225


,
.
.
. , , , .
, .
Django (
). Django
, , ( cookie).
(auth/auth
). ,
. :
1. (), (,
).
2. ,
(, ).
:
: , .
: (/) ,
.
: .
:
.
: .
(
Django , .
,
.

,
Django django.contrib, . ,
, ,
:
1. , ,
, .
2. INSTALLED_APPS django.contrib.auth
manage.py syncdb.
3. , MIDDLEWARE_CLASSES
django.contrib.auth.middleware.AuthenticationMiddleware SessionMiddleware.

. ,
, request.user ,

226

,

.
, AnonymousUser (
).

is_authenticated():

if request.user.is_authenticated():
# .
else:
# .

User
User request.user,

. AnonymousUser ,
,
is_authenticated() .
User , User
User:

12.3. User

username

. . 30 .
, .

first_name

. . 30 .

last_name

. . 30 .

email

. .

password

. . (Django
).
.

is_staff

.
.

is_active

, , ..
. . False
.

is_superuser

.
.

last_login

.
.

date_joined

.
.

12.4. User

is_authenticated()

True
User.

227

.

.
.

is_anonymous()

True
AnonymousUser ( False
User). ,
is_authenticated().

get_full_name()

first_name last_name
.

set_password(passwd)

,
. .
User.

check_password(passwd)

True
.

get_group_permissions()

,

.

get_all_permissions()

,
.

has_perm(perm)

True,
,
package.codename. ,
False.

has_perms(perm_list)

True,
, .
,
False.

has_module_perms(app_label)

True,
app_label.
,
False.

get_and_delete_messages()

Message
.

email_user(subj, msg)

.
,
DEFAULT_FROM_EMAIL.
, from_email,
.

get_profile()

.
.

, User --: groups permissions.


User ,
:

# :
myuser.groups = group_list
# :

228

,

myuser.groups.add(group1, group2,...)
# :
myuser.groups.remove(group1, group2,...)
# :
myuser.groups.clear()
# :
myuser.permissions = permission_list
myuser.permissions.add(permission1, permission2, ...)
myuser.permissions.remove(permission1, permission2, ...)
myuser.permissions.clear()


Django
( ),
,
. Django django.contrib.auth
: authenticate() login().

authenticate().
, username password, User,
. None:

>>>
>>>
>>>
...
...
...

from django.contrib import auth


user = auth.authenticate(username='john', password='secret')
if user is not None:
print "!"
else:
print ", - !"

authenticate() .
login(). HttpRequest
User, ,
.

:

from django.contrib import auth


def login(request):
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None and user.is_active:
# ""

229

,

auth.login(request, user)
# ""
return HttpResponseRedirect("/account/loggedin/")
else:
#
return HttpResponseRedirect("/account/invalid/")

logout().
HttpRequest :

from django.contrib import auth


def logout(request):
auth.logout(request)
# .
return HttpResponseRedirect("/account/loggedout/")

, logout() ,
.
,

.

URL:

from django.contrib.auth.views import login, logout


urlpatterns = patterns('',
# ...
(r'^accounts/login/$', login),
(r'^accounts/logout/$', logout),
)

URL /accounts/login/
.

/accounts/logout/

, login registration/login.html
( ,
, template_name). username
password. :

{% extends "base.html" %}
{% block content %}

230

,

{% if form.errors %}
<p class="error">, </p>
{% endif %}
<form action='.' method='post'>
<label for="username">:</label>
<input type="text" name="username" value="" id="username">
<label for="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/. ,
next URL .
GET

next, .
-. ,
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('/login/?next=%s' % request.path)
# ...

, , :

def my_view(request):
if not request.user.is_authenticated():
return render_to_response('myapp/login_error.html')

231

,

# ...

login_required:

from django.contrib.auth.decorators import login_required


@login_required
def my_view(request):
# ...

:
, /accounts/login/,
URL next. : /accounts/login/?next=/
polls/3/.
, .
, .


,
- ,
, (. ).
request.user .
,
polls.can_vote ( ):

def vote(request):
if request.user.is_authenticated() and request.user.has_perm('polls.can_vote
#
else:
return HttpResponse("

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):
# ,
# .
...

232

user_passes_test : ,
User True,
. , user_passes_test
, .
login_url,
URL ( , /accounts/
login/).
, Django
: permission_required().
, :

from django.contrib.auth.decorators import permission_required


@permission_required('polls.can_vote', login_url="/login/")
def vote(request):
# ...

, permission_required()
login_url, , , /accounts/login/.


Django
.

URL, :

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 .

,

. Django
, ,
.
, API,
. .

233


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().
:

>>> user.is_staff = True


>>> user.save()


set_password():

>>> user = User.objects.get(username='john')


>>> user.set_password('goo goo goo joob')
>>> user.save()

password , , .
FIXME (.. )
.
password User :

hashtype$salt$hash

, , .
(hashtype) sha1 ( ), md5
, .
(salt) ,
, :

sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4

234

User.set_password() User.check_password()
.


?
, .
.
. ,
.
, .. , ,
, .
.
,
,
, . ,
, .
, , ..
.

.
, ,
.
,
.
,
, -
.



, .
,
Django . , .

.
Django ,
, :

from
from
from
from

django import oldforms as forms


django.http import HttpResponseRedirect
django.shortcuts import render_to_response
django.contrib.auth.forms import UserCreationForm

def register(request):
form = UserCreationForm()
if request.method == 'POST':

235

,

data = request.POST.copy()
errors = form.get_validation_errors(data)
if not errors:
new_user = form.save(data)
return HttpResponseRedirect("/books/")
else:
data, errors = {}, {}
return render_to_response("registration/register.html", {
'form' : forms.FormWrapper(form, data, errors)
})

registration/register.html.
:

{% extends "base.html" %}
{% block title %} {% endblock %}
{% block content %}
<h1> </h1>
<form action="." method="post">
{% if form.error_dict %}
<p class="error"> .</p>
{% endif %}
{% if form.username.errors %}
{{ form.username.html_error_list }}
{% endif %}
<label for="id_username">:</label> {{ form.username }}
{% if form.password1.errors %}
{{ form.password1.html_error_list }}
{% endif %}
<label for="id_password1">:</label> {{ form.password1 }}
{% if form.password2.errors %}
{{ form.password2.html_error_list }}
{% endif %}
<label for="id_password2"> ():</label> {{ form.password2 }}
<input type="submit" value="" />
</form>
{% endblock %}

django.contrib.auth.forms.UserCreationForm .
http://www.djangoproject.com/documentation/0.96/forms/
. ,
, .

236



RequestContext (.
).

, RequestContext
TEMPLATE_CONTEXT_PROCESSORS
django.core.context_processors.auth ( ). , .
.
RequestContext ( User,
AnonymousUser) {{ user }}:

{% if user.is_authenticated %}
<p> , {{ user.username }}. , .</p>
{% else %}
<p> , . ?</p>
{% endif %}

{{ perms }}.
,
, .
perm. , {{ perms.polls }} ,
. -
{{ perms.polls.can_vote }} , .
, {% if %}:

{% if perms.polls %}
<p> .</p>
{% if perms.polls.can_vote %}
<p> !</p>
{% endif %}
{% else %}
<p> .</p>
{% endif %}

: , ,

- .
.

237


, .
Django, .
Django :
.
, .
.
,
.
,
.
, .
, ,
, ,
, ,
.
,
Django, Admin.
auth_permission , manage.py
syncdb.
<app>.<action>_<object_name>. ,
polls Choice, :
polls.add_choice, polls.change_choice polls.delete_choice.
, Admin
manage.py syncdb, . Admin
, syncdb
.
,
permissions Meta.
:

class USCitizen(models.Model):
# ...
class Meta:
permissions = (
#
("can_drive",
("can_vote",
("can_drink",
)


" "),
" "),
" "),

syncdb,
.

238

,

, ,
django.contrib.auth.models. , API
.


.
.
, ,
. ,
can_edit_home_page, , .

. ,
,
, .
,
. , Django,
django.contrib.auth.models,
API .


. User.
.
Django
. ,
The object was created successfully .
API
. API :

user.message_set.create(message='message_text')

user.get_and_delete_messages(),
Message (
) .
, ,
:

def create_playlist(request, songs):


# .
# ...
request.user.message_set.create(
message=" ."

239

,

)
return render_to_response("playlists/create.html",
context_instance=RequestContext(request))

RequestContext

{{ messages }}. , :

{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}

, RequestContext get_and_delete_messages(),
, .
, ,
. ,
,
.

. ,
, , .
,
User.
. , Django
, .

, .
,
. Django
ForeignKey User.
user. .
:

from django.db import models


from django.contrib.auth.models import User
class MySiteProfile(models.Model):
# This is the only required field
user = models.ForeignKey(User, unique=True)
# The rest is completely up to you...
favorite_band = models.CharField(max_length=100, blank=True)

240

,

favorite_cheese = models.CharField(max_length=100, blank=True)
lucky_number = models.IntegerField()

, Django .
AUTH_PROFILE_MODULE,
. , myapp,
:

AUTH_PROFILE_MODULE = "myapp.mysiteprofile"


user.get_profile(). SiteProfileNotAvailable,
AUTH_PROFILE_MODULE ; DoesNotExist,
(
).

241

13.
.
!
<radz yandex ru>
,
, .
. ,

, -
. , .
.
http://washingtonpost.com/
SlashDot, .
.
.

,
. ,
:

URL,
:

:


Django ,
,
. Django
. ,
, .
Django , Squid (http://
www.squid-cache.org/ . ,
, (
HTTP ), .
, Django.
Slashdot', ,
.


. ,
: ,
. ,

242


(, ).
,
,
.
CACHE_BACKEND
. CACHE_BACKEND,
Django simple:///.
.

Memcached
Django
Memcached ,
LiveJournal (http://www.livejournal.com/
Danga Interactive (http://danga.com/).
Slashdot Wikipedia
.
Memcached http://danga.com/memcached/.
.
---
, .
,
.
Memcached
Python, Django.
memcache.py, http://www.tummy.com/
Community/software/python-memcached/.
Memcached Django
CACHE_BACKEND memcached://ip:port/, ip IP
Memcached, port , .
Memcached (127.0.0.1)
11211:
CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
Memcached
. ,
Memcached
,
. ,
Django, CACHE_BACKEND,
.
Memcached,
IP 172.19.26.240 172.19.26.242, 11211:
CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'
Memcached,
IP 172.19.26.240 ( 11211), 172.19.26.242 ( 11212)
172.19.26.244 (11213):

243

CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.2
,
. ,
. ,
,
.
Django
. .
, ,
, .



Django, .
, :
python manage.py createcachetable [cache_table_name]
[cache_table_name] , .
, ,
. Django
.
CACHE_BACKEND
db://tablename, tablename , .
, my_cache_table:
CACHE_BACKEND = 'db://my_cache_table'
,
. .


file://
CACHE_BACKEND, ,
.
, /var/tmp/django_cache
:
CACHE_BACKEND = 'file:///var/tmp/django_cache'
. file://,
/var/tmp/django_cache. Windows,
file://, : file://c:/foo/bar.
, ..
. .

244


,
, . ,
apache, , /var/
tmp/django_cache .
,

pickle .
.



, Memcached,
.
(thread-safe),
Memcached - .

CACHE_BACKEND locmem:///, :

CACHE_BACKEND = 'locmem:///'

( )
, ,
simple:///, :
CACHE_BACKEND = 'simple:///'
,
.

( )
, Django ,
.
,
, , .
CACHE_BACKEND dummy:///
, :
CACHE_BACKEND = 'dummy:///'
,
.

CACHE_BACKEND
.
CACHE_BACKEND. :

245


timeout: , , .
300 (5 ).
max_entries: : , ,
.
.
300.
cull_frequency: ,
max_entries. : 1/cull_frequency.
, cull_frequency=2,
50% .
0 ,
. ,
. 3.
, timeout 60:
CACHE_BACKEND = "locmem:///?timeout=60"
, timeout 30, max_entries 400:

CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"

- ,
.


, CACHE_BACKEND,
. ,
, GET POST,
.

django.middleware.cache.CacheMiddleware MIDDLEWARE_CLASSES,
:
MIDDLEWARE_CLASSES = (
'django.middleware.cache.CacheMiddleware',
'django.middleware.common.CommonMiddleware',
)

MIDDLEWARE_CLASSES
. MIDDLEWARE_CLASSES ,
.
Django:

246


CACHE_MIDDLEWARE_SECONDS:
.
CACHE_MIDDLEWARE_KEY_PREFIX:
Django,
,
Django, . ,
.
, GET POST .
,
GET POST,
. ,
.

CACHE_MIDDLEWARE_ANONYMOUS_ONLY.
True,
.
,
Django. ,
CACHE_MIDDLEWARE_ANONYMOUS_ONLY, ,
AuthenticationMiddleware CacheMiddleware
MIDDLEWARE_CLASSES.
, , CacheMiddleware
HttpResponse:
Last-Modified
() .

Expires

CACHE_MIDDLEWARE_SECONDS
.
Cache-Control
CACHE_MIDDLEWARE_SECONDS.



. ,
.
.
,

. cache_page
django.views.decorators.cache, :

from django.views.decorators.cache import cache_page


def my_view(request, param):
# ...
my_view = cache_page(my_view, 60 * 15)

247


, Python 2.4 ,
.
:

from django.views.decorators.cache import cache_page


@cache_page(60 * 15)
def my_view(request, param):
# ...

cache_page , ,
. , my_view()
15 . , 60 * 15
. 900.
, , URL.
URL , URL
. my_view(),
URL :

urlpatterns = ('',
(r'^foo/(\d{1,2})/$', my_view),
)

/foo/1/ /foo/23/ ,
. URL,
.


URL

, cache_page() my_view().
,
. ,
,
, ,
.

URL.
:
cache_page(). URL:

urlpatterns = ('',
(r'^foo/(\d{1,2})/$', my_view),
)

248

, cache_page():

from django.views.decorators.cache import cache_page


urlpatterns = ('',
(r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),
)


cache_page() URL.

API
, ,
.
, , ,
. ,
,
,
.
, Django
, django.core.cache.
API
, .
Python, pickle:
, , . (
Python , Python
pickle.)
API:

>>> 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.get()
None:

249

# 30 'my_key' ""...
>>> cache.get('my_key')
None
>>> cache.get('some_unset_key')
None

None ,
None ,
None.
cache.get() default. ,
:

>>> cache.get('my_key', 'has expired')


'has expired'


cache.get_many(). ,
. cache.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.get_many(['a', 'b', 'c', 'd'])


{'a': 1, 'b': 2, 'c': 3}

, delete().
:

>>> cache.delete('a')

250


delete()
.


.

. ,
,
.
:
, ,
http://example.com/,
, .
. ,
.
, Squid (http://www.squidcache.org/), .
, ,
, .
.
,

.
, .
,
, .
, URL,

.
,
.
,
, ( ) .
.
, HTTP . HTTP
, ,

. .

Vary
Vary
. ,
, .
Django ,
(.., /stories/2005/jun/23/bank_robbed/). ,
URL ,
(user-agent), cookie
. , ,

251


, cookie
, Vary,
.
Django
vary_on_headers, :

from django.views.decorators.vary import vary_on_headers


# Python 2.3.
def my_view(request):
# ...
my_view = vary_on_headers(my_view, 'User-Agent')
# Python 2.4+.
@vary_on_headers('User-Agent')
def my_view(request):
# ...

( Django)
.
vary_on_headers
Vary (- response['Vary'] = 'user-agent') ,
Vary ( ),
.
vary_on_headers():

@vary_on_headers('User-Agent', 'Cookie')
def my_view(request):
# ...

, ,
cookie. ,
Mozilla cookie foo=bar
Mozilla cookie foo=ham.
cookie ,
vary_on_cookie. , , :

@vary_on_cookie
def my_view(request):
# ...
@vary_on_headers('Cookie')
def my_view(request):
# ...

252


, vary_on_headers(), .
User-Agent user-agent.

django.utils.cache.patch_vary_headers.
Vary, :

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

patch_vary_headers() HttpResponse

.



.
: (
) ( ).
. .
, ,
. ,
, .
, . ,
Django cache_control:

from django.views.decorators.cache import cache_control


@cache_control(private=True)
def my_view(request):
# ...

HTTP
.
. , HTTP
:
.

, . (
,

253


, ,
.)
cache_control Django
. cache_control ,

3600 :

from django.views.decorators.cache import cache_control


@cache_control(must_revalidate=True, max_age=3600)
def my_view(request):
...

HTTP
cache_control(). :

Cache-Control

public=True
private=True
no_cache=True
no_transform=True
must_revalidate=True
proxy_revalidate=True
max_age=num_seconds
s_maxage=num_seconds

HTTP Cache-Control
http://www.w3.org/Protocols/rfc2616/rfc2616sec14.html#sec14.9.

max_age
CACHE_MIDDLEWARE_SETTINGS.
max_age cache_control(),

.

Django ,
:
django.middleware.http.ConditionalGetMiddleware

GET ,
ETag Last-Modified.

254


django.middleware.gzip.GZipMiddleware
, .

MIDDLEWARE_CLASSES
CacheMiddleware
MIDDLEWARE_CLASSES,
,
.
CacheMiddleware ,
- Vary, :
SessionMiddleware, Cookie.
GZipMiddleware, Accept-Encoding.

255

14.

.
!
<radz yandex ru>
Python
: Python,
, ,
- . Django
,
. .

Django
Django django.contrib.
.
, .
django.contrib.
( ,
), .
django.contrib
django.contrib, Django
. Django
,
django.contrib - .
django.contrib :
admin: .
Django .
auth: . ,
.
comments: .
.
contenttypes: ,
Django .

Django .
, django/contrib/contenttypes/.
csrf: Cross-Site Request Forgery (CSRF).
CSRF .
flatpages: HTML
. .
humanize: , .
.

256

markup: ,
. .
redirects: .
.
sessions: . ,
.
sitemaps: XML .
, HTML .
sites: Django.
.
syndication: RSS Atom.
.
django.contrib,
.


http://code.djangoproject.com/wiki/UsingFreeComment.
Django ,
,
, , .

Django. ,
INSTALLED_APPS :

INSTALLED_APPS = (
[...]
'django.contrib.comments',
)


,
urls.py.
, .

from django.contrib.comments.models import FreeComment

URL :

urlpatterns = patterns('',

257

[...]
(r'^comments/', include('django.contrib.comments.urls')),

, .
python manage.py syncdb.
,
, (
):

{% load comments %}



. ,
.

django.views.generic.list_detail.object_list
object_list ,
.
,
blog entry, title summary,
get_absolute_url(), URL
.

,
. , Entry,
blog.entry.

<ul>
{% for object in object_list %}
{% get_free_comment_count for blog.entry object.id as comment_count %}
<li>
<h2><a href="{{ object.url }}">{{ object.title }}</a></h2>
<p class="description">{{ object.summary}}</p>
<p class="details">
<a href="{{ object.get_absolute_url }}">
{{ comment_count }} Comments
</a>
</p>
</li>
{% endfor %}
</ul>

258

django.views.generic.date_based.archive_index
archive_index
, latest,
object_list:

<ul>
{% for object in latest %}
{% get_free_comment_count for blog.entry object.id as comment_count %}
[...]
{% endfor %}
</ul>

, ( archive_year archive_month),
, object_list. archive_index
latest.



.
,
.
, django.views.generic.list_detail.object_detail
django.views.generic.date_based.object_detail,
object.id,
:

{% get_free_comment_count for blog.entry object.id as comment_count %}

, ,
,
comment_list:

{% get_free_comment_list for blog.entry object.id as comment_list %}

object comment_list :
comment.person_name: .
comment.submit_date: .
date .
.
comment.comment: .
escape .
.

259

comment.is_public: (TODO:
).
comment.ip_address: IP .
comment.approved: (TODO:
).
:
comment.get_absolute_url: URL
. ,
/blog/some-slug/, URL /blog/some-slug/
#c4, 4 .
comment.get_content_object:
.
,
. .
:

{% get_free_comment_count for blog.entry object.id as comment_count %}


<h2><a href="{{ object.url }}">{{ object.title }}</a></h2>
<em>{{ object.description }}</em>
<div class="article_menu">
<b>Added on {{ object.add_date|date:"F j, Y" }}</b>
<a href="{{ object.get_absolute_url }}#comments">{{ comment_count }}
Comment{{ comment_count|pluralize }}</a>
</div>
{% get_free_comment_list for blog.entry object.id as comment_list %}
<h2 id="comments">Comments</h2>
{% for comment in comment_list %}
<div class="comment_{% cycle odd,even %}" id="c{{ comment.id }}">
<span class="comnum">
<a id="c{{ comment.id }}" href="#c{{ comment.id }}">
#{{ forloop.counter }}
</a>
</span>
<p>
<b>{{ comment.person_name|escape }}</b> commented,
on {{ comment.submit_date|date:"F j, Y" }}
at {{ comment.submit_date|date:"P" }}:
</p>
{{ comment.comment|escape|urlizetrunc:40|linebreaks }}
</div>
{% endfor %}
<h2>Post a comment</h2>
{% free_comment_form for blog.entry object.id %}

260

Django
.
, comments
.


(freeform.html) ,
. ,
:

<h2>Post a comment</h2>
{% free_comment_form for blog.entry object.id %}

{% if display_form %}
<form action="/comments/postfree/" method="post">
<p>Your name: <input type="text" id="id_person_name" name="person_name" /></
<p>Comment:<br /><textarea name="comment" id="id_comment" rows="10" cols="60
<input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" />
<p><input type="submit" name="preview" value="Preview comment" /></p>
</form>
{% endif %}


, name="preview" name="post".


(free_preview.html)
.
:

<h1>Preview your comment</h1>

<form action="/comments/postfree/" method="post">


{% if comment_form.has_errors %}
<p><strong style="color: red;">Please correct the following errors.</strong>
{% else %}

261

<div class="comment">
{{ comment.comment|escape|urlizetrunc:"40"|linebreaks }}
<p class="date small">Posted by <strong>{{ comment.person_name|escape }}</
</div>
<p><input type="submit" name="post" value="Post public comment" /></p>
<h1>Or edit it again</h1>
{% endif %}
{% if comment_form.person_name.errors %}
{{ comment_form.person_name.html_error_list }}
{% endif %}
<p><label for="id_person_name">Your name:</label> {{ comment_form.person_name
{% if comment_form.comment.errors %}
{{ comment_form.comment.html_error_list }}
{% endif %}
<p>
<label for="id_comment">Comment:</label>
<br />
{{ comment_form.comment }}
</p>
<input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" />
<p>
<input type="submit" name="preview" value="Preview revised comment" />
</p>
</form>


(posted.html)
.
object.
:

<h1>Comment posted successfully</h1>


<p>Thanks for contributing.</p>
{% if object %}
<ul>
</ul>
{% endif %}

<li><a href="{{ object.get_absolute_url }}">View your comment</a

262

Wrapping post_free_comment to change the redirect url

django.contrib.comments.views.comments

post_free_comment()
posted.html. ,
,
post_free_comment()
. URL
freeform.html. views.py:

from django.contrib.comments.views.comments import post_free_comment


from django.http import HttpResponseRedirect
def my_post_free_comment(request):
if request.has_key('url') and not request.has_key('preview'):
response = post_free_comment(request)
# Check there's a url to redirect to, and that post_free_comment worked
if len(request['url'].strip()) > 0 and
isinstance(response, HttpResponseRedirect):
return HttpResponseRedirect(request['url'])
# Fall back on the default post_free_comment response
return response
return post_free_comment(request)


. , :

(r'^comments/', include('django.contrib.comments.urls.comments')),

(r'^comments/postfree/', 'views.my_post_free_comment'),

URL.
URL ?
request settings.py:

from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS


TEMPLATE_CONTEXT_PROCESSORS += (
'django.core.context_processors.request',
)

263


request. request.get_full_path
URL. freeform.html:

{% load i18n %}
{% if display_form %}
<form action="/comments/postfree/" method="post">
<p>
<label for="id_person_name">{% trans "Your name:" %}</label>
<input type="text" id="id_person_name" name="person_name" />
</p>
<p>
<label for="id_comment">{% trans "Comment:" %}</label><br />
<textarea name="comment" id="id_comment" rows="10" cols="60"></textarea>
</p>
<p>
<input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" />
<input type="hidden" name="url" value="{{ request.get_full_path }}" />
<input type="submit" name="preview" value="{% trans "Preview comment" %}"
</p>
</form>
{% endif %}

free_preview.html :

<input type="hidden" name="url" value="{{ request.url }}" />

<p><input type="submit" name="preview" value="Preview revised comment" /></p>


.
,
:

<h1>Recent comments</h1>
<p>

264

{% if has_previous %}
<a href="?page={{ previous }}">Previous</a> |
{% endif %}
Page {{ page }} of {{ pages }}
{% if has_next %}
| <a href="?page={{ next }}">Next</a>
{% endif %}
</p>

{% for comment in object_list %}


<div class="comment" id="c{{ comment.id }}">
<h3>
<a href="{{ comment.get_absolute_url }}">
{{ comment.person_name|escape }}
<span class="small quiet">
{{ comment.submit_date|date:"F j, Y" }} at {{ comment.submit_date|date:"P" }}
</span>
</a>
</h3>
{{ comment.comment|escape|urlizetrunc:"40"|linebreaks }}
</div>
{% endfor %}
<p>
{% if has_previous %}
<a href="?page={{ previous }}">Previous</a> |
{% endif %}
Page {{ page }} of {{ pages }}
{% if has_next %}
| <a href="?page={{ next }}">Next</a>
{% endif %}
</p>

Django ,
Django.
,
Django .

1:

Django , LJWorld.com
Lawrence.com : Lawrence JournalWorld Lawrence, . LJWorld.com ,
Lawrence.com .
.

265

: .
.
?

--.
.

2:

LJWorld.com Lawrence.com
. :

: .
,
.
. Site,
, name (..,
LJWorld.com) domain (.., www.ljworld.com).
name
domain Django ,
.


, .
:
Site, django.contrib.sites, name
domain.
SITE_ID Site,
.
, , , Django
.
, ,
:
1. django.contrib.sites INSTALLED_APPS.
2. manage.py syncdb django_site
.
3. Site, Django
Python API. Site /,
Django.
4. SITE_ID .
Site ,
.

266


,
1: ,
ManyToManyField 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)


. ,
.
Article, article_detail:

from django.conf import settings


def article_detail(request, article_id):
try:
a = Article.objects.get(id=article_id, sites__id=settings.SITE_ID)
except Article.DoesNotExist:
raise Http404
# ...

,
, SITE_ID.
, SITE_ID LJWorld.com 1,
Lawrence.com 2.
LJWorld.com,
, LJWorld.com.


, Site --
ForeignKey.
, ,
:

from django.db import models


from django.contrib.sites.models import Site
class Article(models.Model):
headline = models.CharField(max_length=200)

267

# ...
site = models.ForeignKey(Site)

,
.

,
,
, :

from django.conf import settings


def my_view(request):
if settings.SITE_ID == 3:
# -.
else:
# - .

, .

:

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':
# -.
else:
# - .

Site
SITE_ID , Site (Site.objects)
get_current(). :

from django.contrib.sites.models import Site


def my_view(request):
current_site = Site.objects.get_current()
if current_site.domain == 'foo.com':
# -.
else:
# - .

268

django.conf.settings.



, 2:
, name domain Site.
:

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\n-The %s team.' % cur
'editor@%s' % current_site.domain,
[user_email])
# ...

LJWorld.com Lawrence.com,
Thanks for subscribing to lawrence.com alerts. LJWorld.com,
, Thanks for subscribing to LJWorld.com alerts.
.
( )
Django. , LJWorld.com
Lawrence.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, 'do-not-reply@example.com', [user_email])
# ...

subject.txt message.txt
. , ,
.

269

Site,
.

URL
get_absolute_url() URL ,
URL.
. :

>>> from django.contrib.sites.models import Site


>>> obj = MyModel.objects.get(id=3)
>>> obj.get_absolute_url()
'/mymodel/objects/3/'
>>> Site.objects.get_current().domain
'example.com'
>>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())
'http://example.com/mymodel/objects/3/'

CurrentSiteManager
Site ,
CurrentSiteManager . ,
,
,
.
CurrentSiteManager .
:

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()
site = models.ForeignKey(Site)
objects = models.Manager()
on_site = CurrentSiteManager()

, Photo.objects.all() Photo
, Photo.on_site.all() Photo,
( SITE_ID).
, :
Photo.objects.filter(site=settings.SITE_ID)
Photo.on_site.all()

270

CurrentSiteManager Photo Site?


site. ForeignKey
ManyToManyField 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.

( ) Manager
, CurrentSiteManager.
,
, Django
objects = models.Manager().
Django,
, ,
. , ,
( ,
), objects = models.Manager()
CurrentSiteManager.

Django
, ,
, Django
. Django
,
Site name domain,
SITE_ID.
, Django :
(
) .
Django ,
SITE_ID.

. , site
SITE_ID,

271

, ,
.
(
)
. site,
SITE_ID .
(
) title description
{{ site }}, Site. domain
Site URL ,
.
(
) django.contrib.auth.views.login
{{ site_name }}.


, ,
,
.
, , Apache,
HTML .
, Apache,

Django
.
,
django.contrib.flatpages.
Django
Django.
Django ,
, .
API
.
URL .
URL . (
.)

:
1. django.contrib.flatpages INSTALLED_APPS.
django.contrib.flatpages django.contrib.sites, ,
INSTALLED_APPS.
2. django.contrib.flatpages.middleware.FlatpageFallbackMiddleware
MIDDLEWARE_CLASSES.
3. manage.py syncdb
.
: django_flatpage
django_flatpage_sites. django_flatpage URL

272

. django_flatpage_sites -, .
FlatPage,
django/contrib/flatpages/models.py:

from django.db import models


from django.contrib.sites.models import Site
class FlatPage(models.Model):
url = models.CharField(max_length=100)
title = models.CharField(max_length=200)
content = models.TextField()
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:
. ,
.
sites: , .
, .
Django,
API . ,
.

FlatpageFallbackMiddleware. 404,
,
URL. , .
, (
flatpages/default.html).
, flatpage, .
RequestContext.

273

, .

404 (
), 500 ( ) - .
, MIDDLEWARE_CLASSES .
FlatpageFallbackMiddleware .

,
, :


Django,
Flatpages.

.

Python API
,
Django , django/contrib/flatpages/models.py.
, API
, :

>>> from django.contrib.flatpages.models import FlatPage


>>> from django.contrib.sites.models import Site
>>> fp = FlatPage(
...
url='/about/',
...
title='About',
...
content='<p>About this site...</p>',
...
enable_comments=False,
...
template_name='',
...
registration_required=False,
... )
>>> fp.save()
>>> fp.sites.add(Site.objects.get(id=1))
>>> FlatPage.objects.get(url='/about/')
<FlatPage: /about/ -- About>



flatpages/default.html,
template_name FlatPage.
flatpages/default.html .
flatpages .
, flatpage,
.
flatpages/default.html:

274

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"


"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>{{ flatpage.title }}</title>
</head>
<body>
{{ flatpage.content }}
</body>
</html>

Django
,
. ,
Django, /music/ /sections/arts/
music/.
. ,
.

:
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_path new_path.
Django,
API .
, .

RedirectFallbackMiddleware. 404,
,
URL. ,
old_path
, SITE_ID. (
SITE_ID .)
:
new_path -,
new_path.
, new_path ,
HTTP 410 (Gone).

275

, .
RedirectFallbackMiddleware 404,
.
,
MIDDLEWARE_CLASSES . RedirectFallbackMiddleware
,
404.

,
, :


Django,
Redirects.

.

Python API
,
Django , django/contrib/redirects/models.py.
, API
, :

>>> from django.contrib.redirects.models import Redirect


>>> from django.contrib.sites.models import Site
>>> red = Redirect(
...
site=Site.objects.get(id=1),
...
old_path='/music/',
...
new_path='/sections/arts/music/',
... )
>>> red.save()
>>> Redirect.objects.get(old_path='/music/')
<Redirect: /music/ ---> /sections/arts/music/>

CSRF
django.contrib.csrf HTTP (Cross-Site
Request Forgery), CSRF.
CSRF, session riding FIXME,
.
, , URL ,
. , .


example.com.
Log out, URL example.com/logout.
, example.com/logout.

276

URL example.com/logout
<iframe> . ,
example.com ,
<iframe> example.com/logout,
.
,
,
, , ,
.


example.com ,
(.. )
GET . POST
. CSRF.
, example.com
,
POST example.com/logout. ,
:

<input type="hidden" name="confirm" value="true" />

, POST example.com/logout
, confirm
true.

CSRF
. ,
<iframe>, JavaScript
.

?
, GET . ,
<iframe>,
.
POST .
, . ,
, ,
.
Django CSRF. .

CSRF
django.contrib.csrf middleware.py.
Django, CsrfMiddleware, CSRF.

CSRF

django.contrib.csrf.middleware.CsrfMiddleware MIDDLEWARE_CLASSES

277

.
SessionMiddleware, CsrfMiddleware
SessionMiddleware (
).
. , CsrfMiddleware
GZipMiddleware. MIDDLEWARE_CLASSES .
, CsrfMiddleware .
:
1.
POST. csrfmiddlewaretoken,
.
, ,
.
2. POST
csrfmiddlewaretoken.
, 403, : Cross Site
Request Forgery detected. Request aborted.
,
.
POST (
POST). , GET
, .
POST , , .
,
.
-HTML
Content-Type . text/html
application/xml+xhtml .


CsrfMiddleware
. ( ,
.)
, cookie ,
.
HTML
(.., HTML JavaScript document.write),
, .
. ( ,
CsrfMiddleware
csrfmiddlewaretoken HTML ,
HTML.)
,
csrfmiddlewaretoken .
CSRF http://en.wikipedia.org/wiki/CSRF.


Django,
.

278

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)/
, .

ordinal
.
:
1 1st.
2 2nd.

279

3 3rd
, .


:
textile:

Textile_(markup_language)).

Textile

(http://en.wikipedia.org/wiki/

markdown: Markdown (http://en.wikipedia.org/wiki/Markdown).


restructuredtext: ReStructured Text (http://en.wikipedia.org/wiki/
ReStructuredText).

. , textile
Textile HTML:

{% load markup %}
{{ object.content|textile }}

django.contrib.markup
INSTALLED_APPS. {%
load markup %} .
, django/contrib/
markup/templatetags/markup.py.

280

15.
.
!
<radz yandex ru>
,
Django.
,
.
Django .
, ,
Django.
.
, :
,
, , .
,
request.session request.user.
, ,
,
, .
, flatpages, redirects csrf,
,
.
,
.

?
Python,
API. API,
.
Django
( Django ).
, , IP
(request.META['REMOTE_IP']) ,
IP .
, X-Forwarded-For, IP ,
.
, ,
, IP request.META['REMOTE_IP']:

class SetRemoteAddrFromForwardedFor(object):
def process_request(self, request):
try:
real_ip = request.META['HTTP_X_FORWARDED_FOR']
except KeyError:

281


pass
else:
# HTTP_X_FORWARDED_FOR IP ,
# . .
real_ip = real_ip.split(",")[0]
request.META['REMOTE_ADDR'] = real_ip

( ),
X-Forwarded-For
request.META['REMOTE_ADDR']. ,
.
request.META['REMOTE_ADDR'] .
, Django.
, django.middleware.http,
.


.
. ,
.
MIDDLEWARE_CLASSES
. MIDDLEWARE_CLASSES
: . ,
MIDDLEWARE_CLASSES djangoadmin.py startproject:

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.doc.XViewMiddleware'
)

Django , .. MIDDLEWARE_CLASSES
, ,
CommonMiddleware, .
.
Django ,
MIDDLEWARE_CLASSES, Django
. , Django
MIDDLEWARE_CLASSES .
Django .

, ,
,
.

282

__init__(self) .

. ,
__init__(self) , .
__init__(self)
. __init__(self)
django.core.exceptions.MiddlewareNotUsed, Django
.
,
,
.
__init__(self),
, self.


Django
URL ,
. HttpRequest .
process_request() None HttpResponse:
None, Django ,
, .
HttpResponse, Django
, .


Django

, .
, ,
process_view() .

15.1. process_view()

request

HttpRequest

view

, Django
. , ,
.

args

,
, request (
).

kwargs

,
.

283


process_request(), None,
HttpResponse.
None, Django ,
, .
HttpResponse, Django
. Django
.


.
, .
, .., gzip
HTML.
: request
, response , .
,
None, process_response()
HttpResponse. , .. ,
(, ) .


, -
.
,
.
: request , , exception
Exception, .
process_exception() None, HttpResponse.
None, Django
.
HttpResponse, Django
, .

Django ,
.
.
.
Django
wiki: http://code.djangoproject.com/wiki/ContributedMiddleware.


Django ,
, .

284


django.contrib.auth.middleware.AuthenticationMiddleware.
.
request.user, ,
HttpRequest.
, .


: django.middleware.common.CommonMiddleware.
:
,
DISALLOWED_USER_AGENTS: ,

,
.
:

import re
DISALLOWED_USER_AGENTS = (
re.compile(r'^OmniExplorer_Bot'),
re.compile(r'^Googlebot')
)

import re,
( re.compile()).
Python,
include .
URL, APPEND_SLASH
PREPEND_WWW: APPEND_SLASH True, URL
(
) URL .
, foo.com/bar foo.com/bar/, foo.com/bar/file.txt
.
PREPEND_WWW True, URL,
www., URL .
URL. ,
URL .
URL example.com/bar example.com/
bar/, www.example.com/bar/.
URL ,
. URL
.
ETags USE_ETAGS: Etags
HTTP . USE_ETAGS

285


True, Django Etag ,
MD5- ,
, .
GET,
Etags - .


: django.middleware.gzip.GZipMiddleware.
,
gzip ( ).
,
.
- .
, ,
, .

GET
: django.middleware.http.ConditionalGetMiddleware.
GET.
Last-Modified ETag, If-None-Match If-Modified-Since,
304 ( ). ETag
USE_ETAGS ETag . ,
ETag .
HEAD ???
FIXME ??? Date Content-Length .


: django.middleware.http.SetRemoteAddrFromForwardedFor.

? . request.META['REMOTE_ADDR'],
request.META['HTTP_X_FORWARDED_FOR'], .
, ,
REMOTE_ADDR 127.0.0.1.

!
HTTP_X_FORWARDED_FOR.

.
HTTP_X_FORWARDED_FOR , , IP .
,
HTTP_X_FORWARDED_FOR.


: django.contrib.sessions.middleware.SessionMiddleware.

286


.
, .


: django.middleware.cache.CacheMiddleware.
Django .
.


: django.middleware.transaction.TransactionMiddleware.
COMMIT ROLLBACK /
. ,
COMMIT. , ROLLBACK.
.
- ( Django).
.
API
.

X-View
: django.middleware.doc.XViewMiddleware.
HTTP X-View HEAD,
IP , INTERNAL_IPS.
Django.

287

16.

.
!
<radz yandex ru>
Django , ..,
. ,
Django .
.


Django, , SQL
, ,
.
. Django ,
.
inspectdb :
python manage.py inspectdb

inspectdb
inspectdb ,
,
.

. , Django
.
1. Django python manage.py startproject mysite,
mysite .
2. , mysite/settings.py,
.
.
3. python manage.py startapp
myapp, myapp .
4. python manage.py inspectdb.
. .
5. mysite/myapp/models.py:

python mysite/manage.py inspectdb > mysite/myapp/models.py

288


6. mysite/myapp/models.py, .


,
.
:
1. . ,

-- ManyToManyField.
2. , id.
, , Django id primary key,
. ,
:

id = models.IntegerField(primary_key=True)

, ,
.
inspectdb ,
, AutoField
.
3. (.., CharField, DateField)
(.., VARCHAR, DATE). inspectdb
, TextField
. (This field type is a guess.) .
.
,
. Django ,
.
4. Python
(, pass, class for), inspectdb _field
db_column .
,
:

for,

for_field = models.IntegerField(db_column='for')

inspectdb ,
Python. (Field renamed
because it was a Python reserved word.) .
5. , (
),
. , Book
Author, Author Book.

289


, ,
, .
6. inspectdb
: PostgreSQL, MySQL SQLite. ,
primary_key=True, .
,
Django .
7. PostgreSQL
MySQL. IntegerField's,
assuming the foreign-key column was an INT column.


Django
.
, LDAP,
.
LDAP Django .
Django
.
, ,
.


, Django
. - django.contrib.auth.authenticate()
( , ), Django
, . Django
, .
, ,
AUTHENTICATION_BACKENDS.
, , ,
. , ,
$PYTHONPATH.
, AUTHENTICATION_BACKENDS :

('django.contrib.auth.backends.ModelBackend',)

, .
AUTHENTICATION_BACKENDS
. ,
, Django .


, :
get_user(id) authenticate(**credentials).

290


get_user() id,
, , ,
User.
authenticate()
. :

class MyBackend(object):
def authenticate(self, username=None, password=None):
# Check the username/password and return a User.

FIXME???, :

class MyBackend(object):
def authenticate(self, token=None):
# Check the token and return a User.

, authenticate()
User,
, .
None.
Django User,
, .
User ,
(.., LDAP, SQL
.). ,
authenticate() .
,
, ,
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:
try:

291


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
, , .

Apache, httpd.conf, URL
. ( ,
Django Apache,
.)
, Django
URL httpd.conf.
, Django , , Django
:

<Location "/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug On
</Location>

, <Location "/"> URL,


.
. ,
PHP ,
Django
/admin/ PHP . ,
<Location> /admin/:

292

<Location "/admin/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug On
</Location>

, URL, /admin/ Django.


.
, Django URL
Django, URL. Django
URL (.., /admin/people/person/add/), URL
(.., /people/person/add/). , URL
/admin/.

293

17.

<radz yandex ru>


.
!
Django
Django ,
.
,
Django ,
.

.
Django

. , .

.
,
(. ,
).
. ,
.
.
.

, .
, email() -
.


Django
.
, , .
,
.

...
,
, , . ,
, , Django ,
.
, , ,
,

294

.
, , ,
. - ,
,
.

... ...
Django
. ,
.
, ,
, .
(. , ). Django
,
, .
FIXME???
,
.
Django ,
.
: ,
, -,
.
,
.
, . ,
,
.

...
Django,
, .
, ,
. , ,
, .

Full Stop
, Django
.
.

Django, ( ,
).

(
),
- FIXME???
,
, . , Django

295

.
, - ,
, ,
.
, , Django
,
. ,
Django. -
Django, newforms-admin
.


Django
, ,
(
), .
(, ,
) . Django
: (
, )
.
,
. ,
,
,
.
.
, , ,
, Django
.
:

17.1.

admin/change_list.html

admin/change_form.html

admin/delete_confirmation.html

admin/object_history.html


, .., . ,
.
:
admin/<app_label>/<object_name>/<template>.html
admin/<app_label>/<template>.html
admin/<template>.html

296

, Book
books :
admin/books/book/change_form.html
admin/books/change_form.html
admin/change_form.html



.
, .
,
.
:

17.1.

admin/bookstore/
book/change_form.html :

{% extends "admin/change_form.html" %}
{% block form_top %}
<p>Insert meaningful help message here...</p>

297

{% endblock %}

, .
, ,
(
django/contrib/admin/templates/), .

JavaScript
,
JavaScript ,
- .
, .
{% block extrahead %},
<head>. ,
jQuery [http://jquery.com/] ,
:

{% extends "admin/object_history.html" %}
{% block extrahead %}
<script src="http://media.example.com/javascript/jquery.js"
type="text/javascript"></script>
<script type="text/javascript">
// code to actually use jQuery here...
</script>
{% endblock %}

jQuery ,

.
JavaScript ,
.


,
Django, . , ,
.
?
, , .
,
django.contrib.admin.views,
.

298

, ,
, ,
. , ,
,
.
,
Django .
, ,
.
, URL. :

(r'^admin/books/report/$', 'mysite.books.admin_views.report'),

, .
URL :

from django.conf.urls.defaults import *


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

URL
? , Django
URL .
, . ,
, Django URL
,
. ,
Report books, .
.

{% regroup %}. books/admin_views.py :

from
from
from
from

mysite.books.models import Book


django.template import RequestContext
django.shortcuts import render_to_response
django.contrib.admin.views.decorators import staff_member_required

def report(request):
return render_to_response(
"admin/books/report.html",
{'book_list' : Book.objects.all()},
RequestContext(request, {}),

299

)
report = staff_member_required(report)

,
. , ,
:

staff_member_required

django.contrib.admin.views.decorators. login_required,
, ,
staff ,
, .


.
admin/. ,

admin/. books
.
RequestContext (context_instance)
render_to_response().
.
RequestContext
.
.
,
:

{% extends "admin/base_site.html" %}
{% block title %}List of books by publisher{% endblock %}

{% block content %}
<div id="content-main">
<h1>List of books by publisher:</h1>
{% regroup book_list|dictsort:"publisher.name" by publisher as books_by_publis
{% for publisher in books_by_publisher %}
<h3>{{ publisher.grouper }}</h3>
<ul>
{% for book in publisher.list|dictsort:"title" %}
<li>{{ book }}</li>
{% endfor %}
</ul>
{% endfor %}
</div>
{% endblock %}

admin/base_site.html
, :

300

17.2.


, . ,
Django.
, ,
,
.

.


.

URL. .
, ,
, ISBN . ISBN
http://isbn.nu
.
, ,
URL:

(r'^admin/bookstore/book/add/$', 'mysite.books.admin_views.add_by_isbn'),

301

URL
, add_by_isbn
.
,
Django.

302

18.
.
!
<danilaru ms tusur ru>
<radz yandex ru>
Django (: , ,
65 ). ,
Django
.
,
.
, .

.
( , )
, ,
,
,
. internationalization I18N
( 18 I N).

.
L10N .
Django . ,
, ,
. Django 40 .
, , Django
.
,
, .
,
.
. Django,
, .
Django ,
.
: Django :

.

, .

Django GNU gettext (http://www.gnu.org/


software/gettext/) gettext,
Python.

303


Django ,
.
,
USE_I18N False .
Django
.
django.core.context_processors.i18n
TEMPLATE_CONTEXT_PROCESSORS.


, .
. ,
.


, _(). (,
). :

from django.utils.translation import gettext_lazy as _

, , Welcome to my site. :

def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)

django.utils.translation.gettext() _().
:

from django.utils.translation import gettext


def my_view(request):
output = gettext("Welcome to my site.")
return HttpResponse(output)

_(), .
.
:

def my_view(request):

304


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)

( ,
, ,
, make-messages.py, .
.)
, _() gettext(), ,
Python, :

def my_view(request, n):


output = _('%(name)s is my name.') % {'name': n}
return HttpResponse(output)

, ,
. , Adrian is
my name., Me llamo Adrian.,
, .
,
(%s %d). ,
.


django.utils.translation.gettext_noop() ,
, .
.
, ,

, ,
.


django.utils.translation.gettext_lazy()
, .
, help_text
:

305

from django.utils.translation import gettext_lazy


class MyThing(models.Model):
name = models.CharField(help_text=gettext_lazy('This is the help text'))

gettext_lazy()
, . ,
, Django.
, _ (
), :

from django.utils.translation import gettext_lazy as _


class MyThing(models.Model):
name = models.CharField(help_text=_('This is the help text'))

(
).
. ,
verbose_name verbose_name_plural Meta:

from django.utils.translation import gettext_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.ngettext()
,
, :

from django.utils.translation import ngettext


def hello_world(request, count):
page = ngettext(
'there is %(count)d object',
'there are %(count)d objects', count
) % {'count': count}
return HttpResponse(page)

306


ngettext() : ,
(
count.


Django
Python . ,
{% load i18n %} .
{% trans %} :

<title>{% trans "This is the title." %}</title>

, ,
noop:

<title>{% trans "value" noop %}</title>

{% trans %}
, .
( ), {% blocktrans %},
:

{% blocktrans %}This 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 %}

307

, , ,
{% plural %}, {% blocktrans %} {%
endblocktrans %}, :

{% blocktrans count list|length as counter %}


There is only one {{ name }} object.
{% plural %}
There are {{ counter }} {{ name }} objects.
{% endblocktrans %}


gettext() ngettext().
RequestContext (.
), 3 :
{{ LANGUAGES }} ,
, ( ).
{{ LANGUAGE_CODE }} , , (..,
en-us). How Django Discovers Language Preference.
{{ LANGUAGE_BIDI }} . True,
(, ). False,
(, , ).
:

{%
{%
{%
{%

load i18n %}
get_current_language as LANGUAGE_CODE %}
get_available_languages as LANGUAGES %}
get_current_language_bidi as LANGUAGE_BIDI %}


, .
_(), , :

{% some_special_tag _("Page not found") value|yesno:_("yes,no") %}

, (..,
), .


, (
) . .

308


.
,

. .po.
Django , bin/make-messages.py,
.
bin/makemessages.py -l de, de
. , . ,
pt_BR , at
.
django/conf/locale/, .
:
django ( Subversion,
$PYTHONPATH).
.
.
, ,
, . ( )
conf/locale. , : conf/
locale/de/LC_MESSAGES/django.po.
,
, : locale/LANG/LC_MESSAGES (
conf).
locale.

gettext?
gettext, bin/make-messages.py
.
(conf/locale/en/
LC_MESSAGES/django.po) .
.
.po . .po
, ,

.
, Welcome to my site.,
:
_("Welcome to my site.")
bin/make-messages.py .po ,
:

309

#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr ""

:
msgid , .
.
msgstr . .
. .

.
. msgstr ( msgid)
.
. .
,
!
, (
, Django):

msgid ""
"There's been an error. It's been reported to the site administrators via e-"
"mail and should be fixed shortly. Thanks for your patience."
msgstr ""
"Ha ocurrido un error. Se ha informado a los administradores del sitio "
"mediante correo electrnico y debera arreglarse en breve. Gracias por su "
"paciencia."


.po ,
( CHARSET)
. UTF-8
, gettext , .

, :
make-messages.py -a




gettext. bin/make-messages.py.

310


.po .mo ,
.
bin/make-messages.py :
bin/compile-messages.py
. .

Django
,
, Django,
.
Django
, : ,
.

LANGUAGE_CODE . Django ,
.
Django ,
, LANGUAGE_CODE.

, LocaleMiddleware.
LocaleMiddleware ,
. .

LocaleMiddleware

django.middleware.locale.LocaleMiddleware MIDDLEWARE_CLASSES.
,
:
, .
SessionMiddleware, LocaleMiddleware
.
CacheMiddleware, LocaleMiddleware
(
).
, MIDDLEWARE_CLASSES :
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware'
)
LocaleMiddleware
:
django_language .

311


, cookie django_language.
, HTTP Accept-Language.
,
. Django
.
,
LANGUAGE_CODE.

Django

,
. ,
pt-br. , , Django
. , de-at (
), Django ,
.
, LANGUAGES.
, ,
:
LANGUAGES = (
('de', _('German')),
('en', _('English')),
)

( , de-ch
en-us).
LANGUAGES,
. gettext(), django.utils.translation.
django.utils.translation ,
, .
-, :

_ = lambda s: s
LANGUAGES = (
('de', _('German')),
('en', _('English')),
)

bin/make-messages.py
, .
gettext() ,
LANGUAGES.
LocaleMiddleware Django
.
, Django,
. , Django

312



,
.
.po
, .
,
. ,
. ,
DATETIME_FORMAT ( DATE_FORMAT TIME_FORMAT,
, .
, {{ now }}.
, LocaleMiddleware ,
request.LANGUAGE_CODE .
. :

def hello_world(request, count):


if request.LANGUAGE_CODE == 'de-at':
return HttpResponse("You prefer to read Austrian German.")
else:
return HttpResponse("You prefer to read another language.")

, (.., )
settings.LANGUAGE_CODE,
(.., ) request.LANGUAGE_CODE.

set_language

Django

django.views.i18n.set_language,

.
URL:

(r'^i18n/', include('django.conf.urls.i18n')),

, /i18n/
setlang/.
GET1 language
. ,
. ,
cookie django_language.
Django ,
:
next .
1

Django 1.x POST.

313


, 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" />
</form>


Django :
locale
. ,
.
locale .
, .
, django/conf/locale.
,
,
.
. .

,
locale , Django
. Django

.
:
$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)
$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)
LOCALE_PATHS
<language>/LC_MESSAGES/django.(po|mo).
$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|
mo).

314


bin/makemessages.py.
conf/locale ( ) locale/
( ). compilemessages.py django.mo, gettext.
,
LocaleMiddleware. ,
Django .
, - .

,
.
make-messages.py.
, ,
,
.

( ). makemessages.py
.

JavaScript
JavaScript :
JavaScript gettext.
JavaScript .po .mo .
.
JavaScript .
Django .
JavaScript, gettext JavaScript.

javascript_catalog

javascript_catalog(), JavaScript ,
gettext, .
, Django, ,
info_dict URL.
:

js_info_dict = {
'packages': ('your.app.package',),
}
urlpatterns = patterns('',
(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
)

315


packages ,
INSTALLED_APPS, , locale.
, .
JavaScript,
.
, URL:

urlpatterns = patterns('',
(r'^jsi18n/(?P<packages>\S+?)/$, 'django.views.i18n.javascript_catalog'),
)

, ,
+ URL. ,
,
.
django.conf INSTALLED_APPS.

<script type="text/javascript" src="/path/to/jsi18n/"></script>


. JavaScript
gettext:

document.write(gettext('this is to be translated'));

ngettext :

d = {
count: 10
};
s = interpolate(ngettext('this is %(count)s object', 'this are %(count)s objects

interpolate() ,
. :

s = interpolate(ngettext('this is %s object', 'this are %s objects', 11), [11]);

316

Python.
, JavaScript,
.
Python, .



. , -d djangojs:
make-messages.py -d djangojs -l de
JavaScript
. , compile-messages.py
.

, gettext
gettext,
Django:
django djangojs.
,
( /usr/share/locale/). django
Python .
. djangojs JavaScript
.
Django gettext() gettext_noop().
Django DEFAULT_CHARSET.
ugettext(),
UTF-8 (- FIXME).
Django xgettext(). Python xgettext()
msgfmt(). .

317

19.
.
!
<radz yandex ru>
.
, high-profile security gaffes seem to crop up on a daily basis.
, ,
, ,
.
,
.
. ,

, .
Django .
,
, ( )
. , Django
, ,
.
, :
FIXME ,
, .
, Django.


, ,
, .
, HTTP .
,
, .
, ,
.
(.., ), (..,
HTTP , cookie HTTP ).
,
.
-
,
. :
?

SQL
SQL ,
( GET/POST URL)
SQL ,

318


. , , ,
.
, SQL
. ,
.
,
- :

def user_contacts(request):
user = request.GET['username']
sql = "SELECT * FROM user_contacts WHERE username = '%s';" % username
# execute the SQL here...

, ,
,
. , -
.
, .
-,
- . , ,
' 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 .

319


Django API .
SQL ,
(.., PostgreSQL MySQL).
, API:

foo.get_list(bar__exact="' OR 1=1")

Django
:

SELECT * FROM foos WHERE bar = '\' OR 1=1'

.., .
API :
where extra() (. API
). 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() SQL
(%s) ,
. SQL
.
, . ,
(..,
). ,
, , POST,
. Django , django.db.backend.quote_name(),

.

320

(XSS)
,
, , HTML
. HTML
, <script>.
XSS cookie
, (
).
,
.
:

def say_hello(request):
name = request.GET.get('name', 'world')
return render_to_response("hello.html", {"name" : name})

GET
hello.html, :

<h1>Hello, {{ name }}!</h1>

, URL http://example.com/hello/name=Jacob,
, :

<h1>Hello, Jacob!</h1>

, ,
name=<i>Jacob</i>? :

http://example.com/hello/

<h1>Hello, <i>Jacob</i>!</h1>

, <i>, HTML
, .
, ,
, .
,
. , MySpace
, .

321


JavaScript,
, - .
.
, ,
, MySpace, . ,
MySpace .
MySpace ,
, ,
- ,
.

escape
( ) ,
.

Django ?
Django ,

.
Django ,
,
. ,
. ,
Django ( Python ),
.
, , - Django
( )
.
.
, .
Django,

?. XSS
100%.

HTTP
HTTP (CSRF)
URL ,
, , .
Djagno .
.


- , ,
. :

322



.
(
) ,
.
, ,
WiFi .
,
.
cookie (
) cookie. ,
cookie,

.
, cookie
IsLoggedIn=1 LoggedInAsUser=jacob.
.
, , cookie.

.
, PHP URL (..,
http://example.com/?PHPSESSID=fa90197ca25f6ab40bb1374c510d7a32).
URL ,
, .
,
, .
.
FIXME
. ,
.
,
( ) cookie.
,
XSS .
, .

,
:
URL.
Django , ,
.
cookie . ,
, ().
(.., request.session),
. cookie,

323


,
.
, .
(XSS) ,
, ,
, .
, .
.
, , -
, Django
.
( ), ,
,
,
.
,
. .
,
HTTPS. ,
SSL, True SESSION_COOKIE_SECURE
Django cookie HTTPS.

E-mail
SQL Email ,
.
.
, ,
, .
,
. ,
, , ,
. .
,
( , ,
- ). Subject
.
,
- hello\ncc:spamvictim@example.com (
\n ).
:

To: hardcoded@example.com
Subject: hello
cc: spamvictim@example.com

SQL,
,
.

324

SQL
, .
Django (django.core.mail)
,
(from, to subject).
django.core.mail.send_mail() subject,
, Django BadHeaderError.
Django
, .
.
SafeMIMEText django.core.mail.

Directory Traversal
Directory Traversal FIXME
.
/ , .
,
:

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.
,
. ,
, .
FIXME??? ,
, URL .
Ruby on Rails. 2006
Rails URL, http://example.com/person/poke/1,
. ,
URL ,
!

,
, ,

325


,
, .

, ,
.

django.views.static. :

import os
import posixpath
# ...
path = posixpath.normpath(urllib.unquote(path))
newpath = ''
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()),
Django.
, URL , Django
, . URL,
Django - URL.



. Django
.
, ,
,
.
,
. Django ,
, .
,
, .
.

326


,
. ,
,
.

Django ,
. DEBUG True,
. , Django
500 (Internal server error),
. 500.html
.

.
,
ADMINS.
Apache mod_python
Apache:

PythonDebug Off

,
Django.


, .
, .
,
. ,
, ,
.
.
.

327

20. Django
<achepikau gmail com>
<radz yandex ru>
,
Django ,
, .
Django :
Django
.
, :

, Django
. ,
Django

,
.
Django ,
:
. ,
Django, , 10
() .
. Django
,
. Django LAMP , .

LAMP?
LAMP
,
:
Linux ( );
Apache ( );
MySQL ( );
PHP ( ).
, , -
,
. , Django Python
, LAMP
Django.
( )
, Django.
LAPD (Linux, Apache,
PostgreSQL Django), PAID (PostgreSQL, Apache, Internet Django),
Use Django and get PAID!, Django
!.

328

Django


,
, .
, - :
, , ,
(, Java).
,
:
,
. , ,
,
, .
LAMP, , ,
,
.
3 ,
(, ) , .
,
NFS .
, - ,
, .
LAMP ( Django)
!
, :
. ,

-.
.
, ,
.
.

. , Apache -
,
.
. ,
,
.
.
, Django
Django
, .

?
( ),
?
, , ,
,

329

Django
. : Amazon, Blogger,
Craigslist, Facebook, Google, LiveJournal, Slashdot, Wikipedia, Yahoo, YouTube.
:
, !

Django?
, , .
open source
; ()
(emacs vi), (Linux Windows
MacOS), (MySQL PostgreSQL) , ,
.
. .
Django
, .
,
. ,
, :
Linux (Ubuntu, );
Apache mod_python;
PostgreSQL.
Django,
, , .

Django Apache mod_python


Apache mod_python
Django .
mod_python (http://www.djangoproject.com/r/mod_python/) Apache,
Python Apache Python
.
Apache, .
Django Apache 2.x mod_python 3.x,
- Prefork, Worker.

Apache ,

. ,
. ,
:
Apache
www.djangoproject.com/r/apache/docs/;

http://

Pro Apache, Third Edition (Apress, 2004), Peter Wainwright: http://


www.djangoproject.com/r/books/pro-apache/;

330

Django
Apache: The Definitive Guide, Third Edition (OReilly, 2002), Ben
Laurie Peter Laurie: http://www.djangoproject.com/r/books/apache-pra/.


Django mod_python,
, Apache mod_python. ,
Apache
LoadModule:

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

<Location "/">
SetHandler mod_python
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug On
</Location>

mysite.settings Django
.
, Apache URL,
, mod_python Django.
DJANGO_SETTINGS_MODULE, mod_python ,
.
, <Location>, <Directory>.
, <Location>
URL . <Directory>
.
Apache ,
path sys.path.
mod_python, Django:

PythonPath "['///', '///django'] + sys.path"

, , PythonAutoReload Off,
.
mod_python.
PythonDebug (PythonDebug Off)
. ,
Python, mod_python.

331

Django
Apache ( ,
<VirtualHost>)
Django.

Django , URL,
URL URL. ,
Apache :

<Location "/mysite/">
SetHandler mod_python
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug On
</Location>

URL /mysite/.
Django
. , , URL
, URL:

urlpatterns = patterns('',
(r'^mysite/', include('normal.root.urls')),
)

Django Apache
Django Apache .
, ,
.
VirtualHost:

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

332

Django

, ,
- . PythonInterpreter,
<Location> :

<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 ,
Django Apache
, . ,
:
MaxRequestsPerChild 1 , Apache
.
, Django.
, ,
print ( ), , print
mod_python
Apache, , , - . ,
, Python logging.
: http://docs.python.org/lib/modulelogging.html.
.

Django
Apache
Django
(); .
( Django)
. .
" FIXME".
, ,
Apache, Django, mod_python
:

333

Django

<Location "/media/">
SetHandler None
</Location>

/media/ URL
.
<LocationMatch>
. ,
Django , Django media,
URL, .jpg, .gif .png:

<Location "/">
SetHandler mod_python
PythonHandler django.core.handlers.modpython
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.
Internal Server Error (
500) Python Apache.
. (,
, mod_python).

, Apache
Apache Django. ,
,
Django:
, pyexpat (
XML), ,
Apache. . Expat Apache
http://www.djangoproject.com/r/articles/expat-apache-crash/.

334

Django
, mod_python
mod_php Apache,
MySQL.
MySQL Python PHP.
mod_python FAQ http://www.djangoproject.com/r/articles/php-modpythonfaq/.
mod_python ,
mod_python
Django. ,
mod_python. mod_python
: http://www.djangoproject.com/r/articles/getting-modpython-working/.
,
Django , , URL,
RSS ..
URL. , ,
- , Django. import,
, .
, . , ,
ldconfig Linux, otool Mac OS ListDLLs ( SysInternals) Windows,
.

Django Apache mod_wsgi


: http://code.google.com/p/modwsgi/wiki/QuickInstallationGuide,
ericholscher.com/blog/2008/jul/8/setting-django-and-mod_wsgi/.

http://

mod_python mod_wsgi:
mod_python ;
mod_wsgi
.

Apache
Apache 1.3, 2.0 2.2.
Apache 1.3 . ,
Apache, mod_wsgi
.
Apache 2.0 2.2 , prefork worker
MPM.
mod_wsgi , Apache 2.0
2.2, Apache
.
Linux, Apache ,
.
Linux, Apache 2.x
apache2-dev, Apache apache2. ,
MPM,
. , apache2-worker-dev apache2prefork-dev. Apache 2.x apache-dev,
Apache 1.3.

335

Django

Python
Python 2.3-2.5. Python
.
Linux, Python ,
.
, Python .
, mod_wsgi
mod_python ( ),
Apache.


Ubuntu:

# wajig search mod_wsgi


libapache2-mod-wsgi - Python WSGI adapter module for Apache

# wajig install libapache2-mod-wsgi


...

...
:
apache2-mpm-worker apache2-mpm-event
, :
libapache2-mod-wsgi
113k .
:1 http://ru.archive.ubuntu.com intrepid/universe libapache2-mod-wsgi 2.
113k 1s (111k/c)
...
* Reloading web server config apache2
#


, django.wsgi. ,
:

$ cd ~/development/cargo
$ mkdir apache
$ emacs apache/django.wsgi

django.wsgi:

import os, sys


# ,

336

Django
sys.path.append('/home/rad/devel/django-trunk/')
# ,
sys.path.append('/home/rad/devel/')
#
os.environ['DJANGO_SETTINGS_MODULE'] = 'cargo.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Django WSGI. ,
, , -
, sys.path.


, , /etc/apache2/sitesavailable/cargo.caml.ru :

<VirtualHost *>
DocumentRoot /var/www-cargo/
ServerAdmin rusln.ppv@gmil.cm
ServerName cargo
WSGIScriptAlias / /home/rad/devel/cargo/apache/django.wsgi
WSGIDaemonProcess cargo processes=2 maximum-requests=5 threads=1
WSGIProcessGroup cargo

ErrorLog "|/usr/sbin/rotatelogs /var/log/apache2/cargo.error.%Y-%m-%d.lo


CustomLog "|/usr/sbin/rotatelogs /var/log/apache2/cargo.access.%Y-%m-%d.
ServerSignature On

Alias /css/
"/home/rad/django/cargo/css/"
Alias /js/
"/home/rad/django/cargo/js/"
Alias /pics/
"/home/rad/django/cargo/pics/"
Alias /djangobook/pics/ "/home/rad/django/cargo/djangobook/pics/"
Alias /media/
"/home/rad/django/cargo/media/"
Alias /adminmedia/ "/home/rad/devel/django-trunk/django/contrib/admin/me
</VirtualHost>

, WSGI....
WSGIScriptAlias , .
, .

, WSGIDaemonProcess
MS Windows,
Apache 1.3. ... [http://code.google.com/p/modwsgi/
wiki/ConfigurationDirectives]
, , Apache mod_wsgi:

337

Django

# ls -l /etc/apache2/mods-enabled/ | grep wsgi


lrwxrwxrwx 1 root root 27 2009-02-18 22:41 wsgi.conf -> ../mods-available/wsgi.c
lrwxrwxrwx 1 root root 27 2009-02-18 22:41 wsgi.load -> ../mods-available/wsgi.l

338

A.
.
, [http://djangobook.com/en/1.0/
appendixA/].

339

B.

.
, [http://djangobook.com/en/1.0/
appendixB/].

340

C. API

.
, [http://djangobook.com/en/1.0/
appendixC/].

341

D.

.
, [http://djangobook.com/en/1.0/
appendixD/].

342

E.

.
, [http://djangobook.com/en/1.0/
appendixE/].

343

F.

<kostik.vento gmail>
.
,

.


autoescape
1.0.

(autoescape). on off
( ).
,
HTML- (
, ), escape
.
,
,
, safe escape.

block
, -.
. .

comment
,
{% comment %} {% endcomment %}.

csrf_token
1.1.2.
1.1.X -,
. 1.2
HTTP- (.
Cross Site Request Forgeries).

cycle
1.0.

.

344

{% for o in some_list %}
<tr class="{% cycle 'row1' 'row2' %}">
...
</tr>
{% endfor %}

. ,
, rowvalue1 rowvalue2, :

{% for o in some_list %}
<tr class="{% cycle rowvalue1 rowvalue2 %}">
...
</tr>
{% endfor %}

, , :

{% for o in some_list %}
<tr class="{% cycle 'row1' rowvalue2 'row3' %}">
...
</tr>
{% endfor %}


. {%
cycle %}, as :

{% cycle 'row1' 'row2' as rowcolors %}

<tr class="{% cycle rowcolors %}">...</tr>


<tr class="{% cycle rowcolors %}">...</tr>

{% cycle %} ,
. , (') (") ,

345



,
.
, , ,
, .
(HTML Javascript), , ,
.
, :

{% filter force_escape %}
{% cycle var1 var2 var3 %}
{% endfilter %}

{% cycle %}
.
, :

{% cycle row1,row2,row3 %}


. .
. ?

debug
,
.

extends
, .
:
{% extends "base.html" %} ( ) "base.html"
.
{% extends variable %} variable.
, .
Template,
.
. .

filter
.

, .

346

{% filter force_escape|lower %}
( HTML) .
{% endfilter %}

firstof
, False.
. False, .
:

{% firstof var1 var2 var3 %}

{% if var1 %}
{{ var1|safe }}
{% else %}{% if var2 %}
{{ var2|safe }}
{% else %}{% if var3 %}
{{ var3|safe }}
{% endif %}{% endif %}{% endif %}

,
False:

{% firstof var1 var2 var3 " " %}

, , , ,
. (HTML
Javascript), , ,
.
, :

{% filter force_escape %}
{% firstof var1 var2 var3 " " %}
{% endfilter %}

347

for
(). ,
, athlete_list:

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

, {%
for obj in list reversed %}.
1.0.
,
. ,
(x,y), ,
:

{% for x, y in points %}
{{ x }},{{ y }}
{% endfor %}

, .
, data,
:

{% for key, value in data.items %}


{{ key }}: {{ value }}
{% endfor %}

for , :

F.1.

forloop.counter

( 1).

forloop.counter0

( 0).

forloop.revcounter

,
( ).

forloop.revcounter0

,
( ).

348

forloop.first

True, .

forloop.last

True, .

forloop.parentloop

for ... empty


1.1.
for {% empty %}, ,
:

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

, , ,
:

<ul>
{% if athlete_list %}
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
{% else %}
<li>, .</li>
{% endif %}
</ul>

if
{% if %} , True
(.. , false),
{% if %} {% endif %}:

{% if athlete_list %}
: {{ athlete_list|length }}
{% else %}
.
{% endif %}

349



, athlete_list , {{ athlete_list|length }}
( ).
, if {% else %},
, .


if and or not
:

{% if athlete_list and coach_list %}


, .
{% endif %}
{% if not athlete_list %}
.
{% endif %}
{% if athlete_list or coach_list %}
- .
{% endif %}
{% if not athlete_list or coach_list %}
, ( ,
,
).
{% endif %}
{% if athlete_list and not coach_list %}
.
{% endif %}

1.2.
and or,
and , or, :

{% if athlete_list and coach_list or cheerleader_list %}

:
if (athlete_list and coach_list) or cheerleader_list
if .
if.
if ==, !=, <, >, <=, >= in,
:

350

==
. :

{% if somevar == "x" %}
, somevar "x"
{% endif %}

!=
. :

{% if somevar != "x" %}
, somevar "x"
.
{% endif %}

<
. :

{% if somevar < 100 %}


, somevar 100.
{% endif %}

>
. :

{% if somevar > 0 %}
, somevar 0.
{% endif %}

<=
. :

{% if somevar <= 100 %}


, somevar 100.
{% endif %}

351

>=
. :

{% if somevar >= 1 %}
, somevar 1.
{% endif %}

in
. Python
.
x in y:

{% if "bc" in "abcdef" %}
, "bc" "abcdef"
{% endif %}
{% if "hello" in greetings %}
greetings ,
"hello", .
{% endif %}
{% if user in users %}
users QuerySet,
, user .
{% endif %}

not in
. in.
,
. , :

{% if a > b > c %}

(WRONG)

{% if a > b and b > c %}

if , :

352

Python

{% if messages|length >= 100 %}


!
{% endif %}


.
(
):
or
and
not
in
==, !=, <, >,<=, >=
( , Python). , if :

{% if a == b or c == d and e %}

... :

(a == b) or ((c == d) and e)

, .
( , ).

ifchanged
, .
ifchanged .
1.
, . , ,
:

<h1> {{ year }} </h1>


{% for date in days %}
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}

353

2. , , . ,
, ,
, :

{% for date in days %}


{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
{% ifchanged date.hour date.date %}
{{ date.hour }}
{% endifchanged %}
{% endfor %}

3. ifchanged {% else %},


, :

{% for match in matches %}


<div style="background-color:
{% ifchanged match.ballot_id %}
{% cycle "red" "blue" %}
{% else %}
grey
{% endifchanged %}
">{{ match }}</div>
{% endfor %}

ifequal
, .
:

{% ifequal user.id comment.user_id %}


...
{% endifequal %}

{% if %} , {% else %}.
, :

{% ifequal user.username "adrian" %}


...
{% endifequal %}

354




. Python-
True False. ,
if.
1.2.
ifequal if ==.

ifnotequal
, ifequal, .
1.2.
ifnotequal if !=.

include
.
.
, (
).
"foo/bar.html":

{% include "foo/bar.html" %}

,
template_name:

{% include template_name %}

,
. "Hello, John":
: person "john".
:

{% include "name_snippet.html" %}

name_snippet.html:

Hello, {{ person }}

355

. : {% ssi %}.

load
.
. .

now
, .
PHP- date() (http://php.net/
date).
:

{% now "jS F Y H:i" %}

,
, . f
,
, . o ,
:

It is the {% now "jS o\f F" %}

It is the 4th of September

regroup
.
: ,
people ,
first_name, last_name gender:

people = [
{'first_name':
{'first_name':
{'first_name':
{'first_name':

'George', 'last_name': 'Bush', 'gender': 'Male'},


'Bill', 'last_name': 'Clinton', 'gender': 'Male'},
'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},
'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},

356

{'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'},

... , , ,
:

*
*
*
*
*
*
*
*

Male:
George Bush
Bill Clinton
Female:
Margaret Thatcher
Condoleezza Rice
Unknown:
Pat Smith

{% regroup %}.
:

{% regroup people by gender as gender_list %}


<ul>
{% for gender in gender_list %}
<li>{{ gender.grouper }}
<ul>
{% for item in gender.list %}
<li>{{ item.first_name }} {{ item.last_name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>

. {% regroup %} :
, , ,
. people gender
gender_list.
{% regroup %} ( gender_list)
. :
grouper ,
(, Male Female).
list ( ,
Male).
, {% regroup %} !
, people
gender. people gender,
.

357



, people (,
):

people = [
{'first_name':
{'first_name':
{'first_name':
{'first_name':
{'first_name':
]

'Bill', 'last_name': 'Clinton', 'gender': 'Male'},


'Pat', 'last_name': 'Smith', 'gender': 'Unknown'},
'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},
'George', 'last_name': 'Bush', 'gender': 'Male'},
'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},

people,
{% regroup %} :

*
*
*
*
*
*
*
*
*
*

Male:
Bill Clinton
Unknown:
Pat Smith
Female:
Margaret Thatcher
Male:
George Bush
Female:
Condoleezza Rice

,
, .
,
, dictsort:

{% regroup people|dictsort:"gender" by gender as gender_list %}

spaceless
HTML-, ..
.
:

{% spaceless %}
<p>
<a href="foo/">Foo</a>
</p>
{% endspaceless %}

358

HTML-:

<p><a href="foo/">Foo</a></p>

,
. , Hello
:

{% spaceless %}
<strong>
Hello
</strong>
{% endspaceless %}

ssi
.
include, {% ssi %}
( ):

{% ssi /home/html/ljworld.com/includes/right_generic.html %}

parsed,
:

{% ssi /home/html/ljworld.com/includes/right_generic.html parsed %}

{% ssi %}
ALLOWED_INCLUDE_ROOTS .
. {% include %}.

templatetag
,
.
,
,
, {% templatetag %}.

359



, :

F.2.

openblock

{%

closeblock

%}

openvariable

{{

closevariable

}}

openbrace

closebrace

opencomment

{#

closecomment

#}

url
URL (.. URL ),
.
, DRY
:

{% url path.to.some_view v1 v2 %}


package.package.module.function.


URL. .
:

{% url path.to.some_view arg1=v1 arg2=v2 %}

.
, URL.
. , app_views.client,
URL ID ( , client()
app_views.py). URL
:

('^client/(\d+)/$', 'app_views.client')

URL URL
:

360



('^clients/', include('project_name.app_name.urls'))

... :

{% url app_views.client client.id %}

/clients/client/123/.
1.0.
URL-
url.
, URL, , ,
NoReverseMatch,
.
URL, , :

{% url path.to.view arg arg2 as the_url %}


<a href="{{ the_url }}"> {{ the_url }}</a>

{% url ... as var %} ,


.
:

{% url path.to.view as the_url %}


{% if the_url %}
<a href="{{ the_url }}"> - </a>
{% endif %}

1.1.
URL ,
:

{% url myapp:view-name %}

URL
, ,
.

361



1.2.
{% url %}
.
, :

{% url path.to.view arg,arg2 %}


{% url path.to.view arg, arg2 %}


. ?

widthratio
..
.
:

<img src="bar.gif" height="10" width="{% widthratio this_value max_value 100 %}"

this_value 175, max_value 200, bar.gif


88 ( 175/200 = .875; .875 * 100 = 87.5, 88).

with
1.0.
.
(
, , ).
:

{% with business.employees.count as total %}


{{ total }} employee{{ total|pluralize }}
{% endwith %}

, ( total),
{% with %} {% endwith %}.


add
.

362

{{ value|add:"2" }}

value 4, 6.
1.2.
.
, .
(, ..), .
.
, :

{{ first|add:second }}

first [1, 2, 3], second [4, 5, 6],


[1, 2, 3, 4, 5, 6].

, ,
, ,
(. ).

addslashes
. ,
CSV.
:

{{ value|addslashes }}

value I'm using Django, I\'m using Django.

capfirst
.
:

{{ value|capfirst }}

363



value django, Django.

center
.
:

"{{ value|center:"15" }}"

value "Django", " Django ".

cut
.
:

{{ value|cut:" "}}

value "String with spaces", "Stringwithspaces".

date
.
: DATE_FORMAT,
DATETIME_FORMAT, SHORT_DATE_FORMAT SHORT_DATETIME_FORMAT,
(. now ). ,
.
:

{{ value|date:"D d M Y" }}

value

datetime
(..

datetime.datetime.now()), 'Wed 09 Jan 2008'.

:
, USE_L10N True, LANGUAGE_CODE, , "es",
:

{{ value|date:"SHORT_DATE_FORMAT" }}

364

"09/01/2008" (.. "SHORT_DATE_FORMAT" es


"d/m/Y").
:

{{ value|date }}

, DATE_FORMAT,
.
1.2.
.

default
False,
. .
:

{{ value|default:"nothing" }}

value "" ( ), nothing.

default_if_none
( ) None,
. .
, .
default.
:

{{ value|default_if_none:"nothing" }}

value None, "nothing".

dictsort
, ,
.
:

365

{{ value|dictsort:"name" }}

value :

{'name': 'zed', 'age': 19},


{'name': 'amy', 'age': 22},
{'name': 'joe', 'age': 31},

{'name': 'amy', 'age': 22},


{'name': 'joe', 'age': 31},
{'name': 'zed', 'age': 19},

dictsortreversed
,
, .
, .

divisibleby
True, .
:

{{ value|divisibleby:"3" }}

value 21, True.

escape
, HTML, HTML-,
:
< &lt;;
> &gt;;

366



' ( ) &#39;;
" ( ) &quot;;
& &amp;.
,
escape : .
, force_escape.
escape ,
, .
, .
HTML-, force_escape.
1.0.

. ,
( , ).

escapejs
1.0.
JavaScript-.
HTML,
JavaScript/JSON.
:

{{ value|escapejs }}

value "testing\r\njavascript \'string" <b>escaping</b>",


"testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\
\u003Eescaping\\u003C/b\\u003E".

filesizeformat
(.. 13 KB, 4.1 MB,
102 bytes, ..).
:

{{ value|filesizeformat }}

value 123456789, 117.7 MB.

first
.

367

{{ value|first }}

value ['a', 'b', 'c'], 'a'.

fix_ampersands
1.0.
, .. . .
escape .
&amp;.
:

{{ value|fix_ampersands }}

value Tom & Jerry, Tom &amp; Jerry.

floatformat

. :

F.3.
value

34.23234

{{ value|
floatformat }}

34.2

34.00000

{{ value|
floatformat }}

34

34.26000

{{ value|
floatformat }}

34.3

, floatformat
. :

F.4.
value

34.23234

{{ value|
floatformat:3 }}

34.232

34.00000

{{ value|
floatformat:3 }}

34.000

34.26000

{{ value|
floatformat:3 }}

34.260

368



, floatformat
, . :

F.5.
value

34.23234

{{ value|
floatformat:-3 }}

34.232

34.00000

{{ value|
floatformat:-3 }}

34

34.26000

{{ value|
floatformat:-3 }}

34.260

floatformat -1.

force_escape
1.0.
HTML- ( . escape).
, ,
,
. escape.

get_digit
-, :
, 1, , 2 ..
1,
.
:

{{ value|get_digit:"2" }}

value 123456789, 8.

iriencode
IRI (Internationalized Resource Identifier) ,
URL. ,
, ASCII.
, urlencode,
.
:

{{ value|iriencode }}

369



value "?test=1&me=2", "?test=1&amp;me=2".

join
,
( Python- str.join(list)).
:

{{ value|join:" // " }}

value ['a', 'b', 'c'], "a // b // c".

last
1.0.
.
:

{{ value|last }}

value ['a', 'b', 'c', 'd'], "d".

length
. , .
:

{{ value|length }}

value ['a', 'b', 'c', 'd'], 4.

length_is
True, ,
False.
:

{{ value|length_is:"4" }}

370



value ['a', 'b', 'c', 'd'], True.

linebreaks
HTML;
<br />, </p>.
:

{{ value|linebreaks }}

value Joel\nis a slug, <p>Joel<br />is a slug</p>.

linebreaksbr
<br />.
:

{{ value|linebreaksbr }}

value Joel\nis a slug, Joel<br />is a slug.

linenumbers
.
:

{{ value|linenumbers }}

value :

one
two
three

1. one
2. two

371



3. three

ljust
. : .
:

"{{ value|ljust:"10" }}"

value Django, "Django ".

lower
.
:

{{ value|lower }}

value Still MAD At Yoko, still mad at yoko.

make_list
, .
, .
:

{{ value|make_list }}

value "Joel", [u'J', u'o', u'e', u'l'].


value 123, [1, 2, 3].

phone2numeric
( .. ) .

.
:

372



{{ value|phone2numeric }}

value 800-COLLECT, 800-2655328.

pluralize
, 1.
's'.
:

You have {{ num_messages }} message{{ num_messages|pluralize }}.

num_messages 1, You have 1 message.


num_messages 2, You have 2 messages.
( 's'),
.
:

You have {{ num_walruses }} walrus{{ num_walruses|pluralize:"es" }}.

,
(
).
:

You have {{ num_cherries }} cherr{{ num_cherries|pluralize:"y,ies" }}.

pprint
pprint.pprint .

random
.
:

373



{{ value|random }}

value ['a', 'b', 'c', 'd'], "b".

removetags
[X]HTML-, - .
:

{{ value|removetags:"b span"|safe }}

value "<b>Joel</b> <button>is</button> a <span>slug</span>",


"Joel <button>is</button> a slug".

rjust
. : .
:

"{{ value|rjust:"10" }}"

value Django, " Django".

safe
, , .
, .

safeseq
safe .
, ,
join. :

{{ some_list|safeseq|join:", " }}

safe, ..
, .

slice
.

374



Python .
http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice.
:

{{ some_list|slice:":2" }}

some_list ['a', 'b', 'c'], ['a', 'b'].

slugify
, ,
, .
.
:

{{ value|slugify }}

value "Joel is a slug", "joel-is-a-slug".

stringformat
,
. Python
, %.
Python . http://docs.python.org/
library/stdtypes.html#string-formatting-operations
:

{{ value|stringformat:"s" }}

value "Joel is a slug", "Joel is a slug".

striptags
[X]HTML-.
:

{{ value|striptags }}

375



value "<b>Joel</b> <button>is</button> a <span>slug</span>",
"Joel is a slug".

time
.
TIME_FORMAT (
) (. now).
,
, . date.
:

{{ value|time:"H:i" }}

value datetime.datetime.now(), "01:23".


:
, USE_L10N True, LANGUAGE_CODE, , "de",
:

{{ value|date:"TIME_FORMAT" }}

"01:23:00" (.. "TIME_FORMAT" de


"H:i:s").
:

{{ value|date }}

, TIME_FORMAT,
.
1.2.
.

timesince
, (, 4
days, 6 hours).
, (
). , blog_date
, 1 2006 , comment_date 08:00
1 2006 , {{ blog_date|timesince:comment_date }} 8 hours.

376



, , ,
.
.
, 0 minutes.

timeuntil
timesince, . ,
1 2006 , conference_date 29 2006 ,
{{ conference_date|timeuntil }} 4 weeks.
, (
). , from_date 22 2006, {{ conference_date|
timeuntil:from_date }} 1 week.
, , ,
.
.
, 0 minutes.

title
.
:

{{ value|title }}

value "my first post", "My First Post".

truncatewords
. :
.
:

{{ value|truncatewords:2 }}

value "Joel is a slug", "Joel is ...".

truncatewords_html
truncatewords, HTML-. ,
.
, truncatewords,
HTML-.

377

{{ value|truncatewords_html:2 }}

value "<p>Joel is a slug</p>", "<p>Joel is ...</p>".

unordered_list

<ul>).

HTML-

1.0.
.
. , var
['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']], {{ var|unordered_list }} :

<li>States
<ul>
<li>Kansas
<ul>
<li>Lawrence</li>
<li>Topeka</li>
</ul>
</li>
<li>Illinois</li>
</ul>
</li>

: ( , )
: ['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]].

upper
.
:

{{ value|upper }}

value "Joel is a slug", "JOEL IS A SLUG".

urlencode
URL.

378

{{ value|urlencode }}

value "http://www.example.org/foo?a=b&c=d",
"http%3A//www.example.org/foo%3Fa%3Db%26c%3Dd".

urlize
HTML-.
, urlize ,
HTML-, .
.
:

{{ value|urlize }}

value "Check out www.djangoproject.com",


"Check out <a href="http://www.djangoproject.com">www.djangoproject.com</
a>".

urlizetrunc
HTML-,
.
urlize_, . :
.
:

{{ value|urlizetrunc:15 }}

value "Check out www.djangoproject.com",


'Check out <a href="http://www.djangoproject.com">www.djangopr...</a>'.

wordcount
.
:

{{ value|wordcount }}

379

value "Joel is a slug", 4.

wordwrap
. : ,
.
:

{{ value|wordwrap:5 }}

value Joel is a slug, :

Joel
is a
slug

yesno
true, false () None ,
:

F.6.

True

, ,

False

, ,

None

, ,

None

( None ,
False)

.
INSTALLED_APPS
{% load %}.

django.contrib.humanize
.

380

django.contrib.markup
, :
Textile
Markdown
ReST (ReStructured Text)

django.contrib.webdesign
, -, , Lorem
Ipsum.

381

G. django-admin
.
, [http://djangobook.com/en/1.0/
appendixG/].

382

H. HttpRequest
HttpResponse
.
, [http://djangobook.com/en/1.0/
appendixH/].

383