Massive reorganization of the docs. See the new docs online at http://docs.djangoproject.com/.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@8506 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jacob Kaplan-Moss 2008-08-23 22:25:40 +00:00
parent b3688e8194
commit 97cb07c3a1
188 changed files with 19913 additions and 17059 deletions

View File

@ -67,6 +67,7 @@ answer newbie questions, and generally made Django that much better:
Jiri Barton Jiri Barton
Ned Batchelder <http://www.nedbatchelder.com/> Ned Batchelder <http://www.nedbatchelder.com/>
batiste@dosimple.ch batiste@dosimple.ch
Batman
Shannon -jj Behrens <http://jjinux.blogspot.com/> Shannon -jj Behrens <http://jjinux.blogspot.com/>
Esdras Beleza <linux@esdrasbeleza.com> Esdras Beleza <linux@esdrasbeleza.com>
Chris Bennett <chrisrbennett@yahoo.com> Chris Bennett <chrisrbennett@yahoo.com>

View File

@ -11,12 +11,12 @@ PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html web htmlhelp latex changes linkcheck .PHONY: help clean html web pickle htmlhelp latex changes linkcheck
help: help:
@echo "Please use \`make <target>' where <target> is one of" @echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files" @echo " html to make standalone HTML files"
@echo " web to make files usable by Sphinx.web" @echo " pickle to make pickle files (usable by e.g. sphinx-web)"
@echo " htmlhelp to make HTML files and a HTML help project" @echo " htmlhelp to make HTML files and a HTML help project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview over all changed/added/deprecated items" @echo " changes to make an overview over all changed/added/deprecated items"
@ -31,13 +31,15 @@ html:
@echo @echo
@echo "Build finished. The HTML pages are in _build/html." @echo "Build finished. The HTML pages are in _build/html."
web: pickle:
mkdir -p _build/web _build/doctrees mkdir -p _build/pickle _build/doctrees
$(SPHINXBUILD) -b web $(ALLSPHINXOPTS) _build/web $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
@echo @echo
@echo "Build finished; now you can run" @echo "Build finished; now you can process the pickle files or run"
@echo " python -m sphinx.web _build/web" @echo " sphinx-web _build/pickle"
@echo "to start the server." @echo "to start the sphinx-web server."
web: pickle
htmlhelp: htmlhelp:
mkdir -p _build/htmlhelp _build/doctrees mkdir -p _build/htmlhelp _build/doctrees

88
docs/_ext/applyxrefs.py Normal file
View File

@ -0,0 +1,88 @@
"""Adds xref targets to the top of files."""
import sys
import os
testing = False
DONT_TOUCH = (
'./index.txt',
)
def target_name(fn):
if fn.endswith('.txt'):
fn = fn[:-4]
return '_' + fn.lstrip('./').replace('/', '-')
def process_file(fn, lines):
lines.insert(0, '\n')
lines.insert(0, '.. %s:\n' % target_name(fn))
try:
f = open(fn, 'w')
except IOError:
print("Can't open %s for writing. Not touching it." % fn)
return
try:
f.writelines(lines)
except IOError:
print("Can't write to %s. Not touching it." % fn)
finally:
f.close()
def has_target(fn):
try:
f = open(fn, 'r')
except IOError:
print("Can't open %s. Not touching it." % fn)
return (True, None)
readok = True
try:
lines = f.readlines()
except IOError:
print("Can't read %s. Not touching it." % fn)
readok = False
finally:
f.close()
if not readok:
return (True, None)
#print fn, len(lines)
if len(lines) < 1:
print("Not touching empty file %s." % fn)
return (True, None)
if lines[0].startswith('.. _'):
return (True, None)
return (False, lines)
def main(argv=None):
if argv is None:
argv = sys.argv
if len(argv) == 1:
argv.extend('.')
files = []
for root in argv[1:]:
for (dirpath, dirnames, filenames) in os.walk(root):
files.extend([(dirpath, f) for f in filenames])
files.sort()
files = [os.path.join(p, fn) for p, fn in files if fn.endswith('.txt')]
#print files
for fn in files:
if fn in DONT_TOUCH:
print("Skipping blacklisted file %s." % fn)
continue
target_found, lines = has_target(fn)
if not target_found:
if testing:
print '%s: %s' % (fn, lines[0]),
else:
print "Adding xref to %s" % fn
process_file(fn, lines)
else:
print "Skipping %s: already has a xref" % fn
if __name__ == '__main__':
sys.exit(main())

146
docs/_ext/djangodocs.py Normal file
View File

@ -0,0 +1,146 @@
"""
Sphinx plugins for Django documentation.
"""
import docutils.nodes
import docutils.transforms
import sphinx
import sphinx.addnodes
import sphinx.builder
import sphinx.directives
import sphinx.environment
import sphinx.htmlwriter
def setup(app):
app.add_crossref_type(
directivename = "setting",
rolename = "setting",
indextemplate = "pair: %s; setting",
)
app.add_crossref_type(
directivename = "templatetag",
rolename = "ttag",
indextemplate = "pair: %s; template tag"
)
app.add_crossref_type(
directivename = "templatefilter",
rolename = "tfilter",
indextemplate = "pair: %s; template filter"
)
app.add_crossref_type(
directivename = "fieldlookup",
rolename = "lookup",
indextemplate = "pair: %s, field lookup type",
)
app.add_description_unit(
directivename = "django-admin",
rolename = "djadmin",
indextemplate = "pair: %s; django-admin command",
parse_node = parse_django_admin_node,
)
app.add_description_unit(
directivename = "django-admin-option",
rolename = "djadminopt",
indextemplate = "pair: %s; django-admin command-line option",
parse_node = lambda env, sig, signode: sphinx.directives.parse_option_desc(signode, sig),
)
app.add_transform(SuppressBlockquotes)
# Monkeypatch PickleHTMLBuilder so that it doesn't die in Sphinx 0.4.2
if sphinx.__version__ == '0.4.2':
monkeypatch_pickle_builder()
class SuppressBlockquotes(docutils.transforms.Transform):
"""
Remove the default blockquotes that encase indented list, tables, etc.
"""
default_priority = 300
suppress_blockquote_child_nodes = (
docutils.nodes.bullet_list,
docutils.nodes.enumerated_list,
docutils.nodes.definition_list,
docutils.nodes.literal_block,
docutils.nodes.doctest_block,
docutils.nodes.line_block,
docutils.nodes.table
)
def apply(self):
for node in self.document.traverse(docutils.nodes.block_quote):
if len(node.children) == 1 and isinstance(node.children[0], self.suppress_blockquote_child_nodes):
node.replace_self(node.children[0])
class DjangoHTMLTranslator(sphinx.htmlwriter.SmartyPantsHTMLTranslator):
"""
Django-specific reST to HTML tweaks.
"""
# Don't use border=1, which docutils does by default.
def visit_table(self, node):
self.body.append(self.starttag(node, 'table', CLASS='docutils'))
# Give each section a unique ID -- nice for custom CSS hooks
# This is different on docutils 0.5 vs. 0.4...
# The docutils 0.4 override.
if hasattr(sphinx.htmlwriter.SmartyPantsHTMLTranslator, 'start_tag_with_title'):
def start_tag_with_title(self, node, tagname, **atts):
node = {
'classes': node.get('classes', []),
'ids': ['s-%s' % i for i in node.get('ids', [])]
}
return self.starttag(node, tagname, **atts)
# The docutils 0.5 override.
else:
def visit_section(self, node):
old_ids = node.get('ids', [])
node['ids'] = ['s-' + i for i in old_ids]
sphinx.htmlwriter.SmartyPantsHTMLTranslator.visit_section(self, node)
node['ids'] = old_ids
def parse_django_admin_node(env, sig, signode):
command = sig.split(' ')[0]
env._django_curr_admin_command = command
title = "django-admin.py %s" % sig
signode += sphinx.addnodes.desc_name(title, title)
return sig
def monkeypatch_pickle_builder():
import shutil
from os import path
try:
import cPickle as pickle
except ImportError:
import pickle
from sphinx.util.console import bold
def handle_finish(self):
# dump the global context
outfilename = path.join(self.outdir, 'globalcontext.pickle')
f = open(outfilename, 'wb')
try:
pickle.dump(self.globalcontext, f, 2)
finally:
f.close()
self.info(bold('dumping search index...'))
self.indexer.prune(self.env.all_docs)
f = open(path.join(self.outdir, 'searchindex.pickle'), 'wb')
try:
self.indexer.dump(f, 'pickle')
finally:
f.close()
# copy the environment file from the doctree dir to the output dir
# as needed by the web app
shutil.copyfile(path.join(self.doctreedir, sphinx.builder.ENV_PICKLE_FILENAME),
path.join(self.outdir, sphinx.builder.ENV_PICKLE_FILENAME))
# touch 'last build' file, used by the web application to determine
# when to reload its environment and clear the cache
open(path.join(self.outdir, sphinx.builder.LAST_BUILD_FILENAME), 'w').close()
sphinx.builder.PickleHTMLBuilder.handle_finish = handle_finish

View File

@ -0,0 +1,171 @@
"""
Runs through a reST file looking for old-style literals, and helps replace them
with new-style references.
"""
import re
import sys
import shelve
refre = re.compile(r'``([^`\s]+?)``')
ROLES = (
'attr',
'class',
"djadmin",
'data',
'exc',
'file',
'func',
'lookup',
'meth',
'mod' ,
"djadminopt",
"ref",
"setting",
"term",
"tfilter",
"ttag",
# special
"skip"
)
ALWAYS_SKIP = [
"NULL",
"True",
"False",
]
def fixliterals(fname):
data = open(fname).read()
last = 0
new = []
storage = shelve.open("/tmp/literals_to_xref.shelve")
lastvalues = storage.get("lastvalues", {})
for m in refre.finditer(data):
new.append(data[last:m.start()])
last = m.end()
line_start = data.rfind("\n", 0, m.start())
line_end = data.find("\n", m.end())
prev_start = data.rfind("\n", 0, line_start)
next_end = data.find("\n", line_end + 1)
# Skip always-skip stuff
if m.group(1) in ALWAYS_SKIP:
new.append(m.group(0))
continue
# skip when the next line is a title
next_line = data[m.end():next_end].strip()
if next_line[0] in "!-/:-@[-`{-~" and all(c == next_line[0] for c in next_line):
new.append(m.group(0))
continue
sys.stdout.write("\n"+"-"*80+"\n")
sys.stdout.write(data[prev_start+1:m.start()])
sys.stdout.write(colorize(m.group(0), fg="red"))
sys.stdout.write(data[m.end():next_end])
sys.stdout.write("\n\n")
replace_type = None
while replace_type is None:
replace_type = raw_input(
colorize("Replace role: ", fg="yellow")
).strip().lower()
if replace_type and replace_type not in ROLES:
replace_type = None
if replace_type == "":
new.append(m.group(0))
continue
if replace_type == "skip":
new.append(m.group(0))
ALWAYS_SKIP.append(m.group(1))
continue
default = lastvalues.get(m.group(1), m.group(1))
if default.endswith("()") and replace_type in ("class", "func", "meth"):
default = default[:-2]
replace_value = raw_input(
colorize("Text <target> [", fg="yellow") + default + colorize("]: ", fg="yellow")
).strip()
if not replace_value:
replace_value = default
new.append(":%s:`%s`" % (replace_type, replace_value))
lastvalues[m.group(1)] = replace_value
new.append(data[last:])
open(fname, "w").write("".join(new))
storage["lastvalues"] = lastvalues
storage.close()
#
# The following is taken from django.utils.termcolors and is copied here to
# avoid the dependancy.
#
def colorize(text='', opts=(), **kwargs):
"""
Returns your text, enclosed in ANSI graphics codes.
Depends on the keyword arguments 'fg' and 'bg', and the contents of
the opts tuple/list.
Returns the RESET code if no parameters are given.
Valid colors:
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'
Valid options:
'bold'
'underscore'
'blink'
'reverse'
'conceal'
'noreset' - string will not be auto-terminated with the RESET code
Examples:
colorize('hello', fg='red', bg='blue', opts=('blink',))
colorize()
colorize('goodbye', opts=('underscore',))
print colorize('first line', fg='red', opts=('noreset',))
print 'this should be red too'
print colorize('and so should this')
print 'this should not be red'
"""
color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white')
foreground = dict([(color_names[x], '3%s' % x) for x in range(8)])
background = dict([(color_names[x], '4%s' % x) for x in range(8)])
RESET = '0'
opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'}
text = str(text)
code_list = []
if text == '' and len(opts) == 1 and opts[0] == 'reset':
return '\x1b[%sm' % RESET
for k, v in kwargs.iteritems():
if k == 'fg':
code_list.append(foreground[v])
elif k == 'bg':
code_list.append(background[v])
for o in opts:
if o in opt_dict:
code_list.append(opt_dict[o])
if 'noreset' not in opts:
text = text + '\x1b[%sm' % RESET
return ('\x1b[%sm' % ';'.join(code_list)) + text
if __name__ == '__main__':
try:
fixliterals(sys.argv[1])
except (KeyboardInterrupt, SystemExit):
print

3
docs/_static/default.css vendored Normal file
View File

@ -0,0 +1,3 @@
@import url(reset-fonts-grids.css);
@import url(djangodocs.css);
@import url(homepage.css);

126
docs/_static/djangodocs.css vendored Normal file
View File

@ -0,0 +1,126 @@
/*** setup ***/
html { background:#092e20;}
body { font:12px/1.5 Verdana,sans-serif; background:#092e20; color: white;}
#custom-doc { width:76.54em;*width:74.69em;min-width:995px; max-width:100em; margin:auto; text-align:left; padding-top:16px; margin-top:0;}
#hd { padding: 4px 0 12px 0; }
#bd { background:#234F32; }
#ft { color:#487858; font-size:90%; padding-bottom: 2em; }
/*** links ***/
a {text-decoration: none;}
a img {border: none;}
a:link, a:visited { color:#ffc757; }
#bd a:link, #bd a:visited { color:#ab5603; text-decoration:underline; }
#bd #sidebar a:link, #bd #sidebar a:visited { color:#ffc757; text-decoration:none; }
a:hover { color:#ffe761; }
#bd a:hover { background-color:#E0FFB8; color:#234f32; text-decoration:none; }
#bd #sidebar a:hover { color:#ffe761; background:none; }
h2 a, h3 a, h4 a { text-decoration:none !important; }
a.reference em { font-style: normal; }
/*** sidebar ***/
#sidebar div.sphinxsidebarwrapper { font-size:92%; margin-right: 14px; }
#sidebar h3, #sidebar h4 { color: white; font-size: 125%; }
#sidebar a { color: white; }
#sidebar ul ul { margin-top:0; margin-bottom:0; }
#sidebar li { margin-top: 0.2em; margin-bottom: 0.2em; }
/*** nav ***/
div.nav { margin: 0; font-size: 11px; text-align: right; color: #487858;}
#hd div.nav { margin-top: -27px; }
#ft div.nav { margin-bottom: -18px; }
#hd h1 a { color: white; }
#global-nav { position:absolute; top:5px; margin-left: -5px; padding:7px 0; color:#263E2B; }
#global-nav a:link, #global-nav a:visited {color:#487858;}
#global-nav a {padding:0 4px;}
#global-nav a.about {padding-left:0;}
#global-nav:hover {color:#fff;}
#global-nav:hover a:link, #global-nav:hover a:visited { color:#ffc757; }
/*** content ***/
#yui-main div.yui-b { position: relative; }
#yui-main div.yui-b { margin: 0 0 0 20px; background: white; color: black; padding: 0.3em 2em 1em 2em; }
/*** basic styles ***/
dd { margin-left:15px; }
h1,h2,h3,h4 { margin-top:1em; font-family:"Trebuchet MS",sans-serif; font-weight:normal; }
h1 { font-size:218%; margin-top:0.6em; margin-bottom:.4em; line-height:1.1em; }
h2 { font-size:175%; margin-bottom:.6em; line-height:1.2em; color:#092e20; }
h3 { font-size:150%; font-weight:bold; margin-bottom:.2em; color:#487858; }
h4 { font-size:125%; font-weight:bold; margin-top:1.5em; margin-bottom:3px; }
div.figure { text-align: center; }
div.figure p.caption { font-size:1em; margin-top:0; margin-bottom:1.5em; color: #555;}
hr { color:#ccc; background-color:#ccc; height:1px; border:0; }
p, ul, dl { margin-top:.6em; margin-bottom:1em; padding-bottom: 0.1em;}
#yui-main div.yui-b img { max-width: 50em; margin-left: auto; margin-right: auto; display: block; }
caption { font-size:1em; font-weight:bold; margin-top:0.5em; margin-bottom:0.5em; margin-left: 2px; text-align: center; }
blockquote { padding: 0 1em; margin: 1em 0; font:125%/1.2em "Trebuchet MS", sans-serif; color:#234f32; border-left:2px solid #94da3a; }
strong { font-weight: bold; }
em { font-style: italic; }
ins { font-weight: bold; text-decoration: none; }
/*** lists ***/
ul { padding-left:30px; }
ol { padding-left:30px; }
ol.arabic { list-style-type: decimal; }
ul li { list-style-type:square; margin-bottom:.4em; }
ol li { margin-bottom: .4em; }
ul ul { padding-left:1.2em; }
ul ul ul { padding-left:1em; }
ul.linklist, ul.toc { padding-left:0; }
ul.toc ul { margin-left:.6em; }
ul.toc ul li { list-style-type:square; }
ul.toc ul ul li { list-style-type:disc; }
ul.linklist li, ul.toc li { list-style-type:none; }
dt { font-weight:bold; margin-top:.5em; font-size:1.1em; }
dd { margin-bottom:.8em; }
ol.toc { margin-bottom: 2em; }
ol.toc li { font-size:125%; padding: .5em; line-height:1.2em; clear: right; }
ol.toc li.b { background-color: #E0FFB8; }
ol.toc li a:hover { background-color: transparent !important; text-decoration: underline !important; }
ol.toc span.release-date { color:#487858; float: right; font-size: 85%; padding-right: .5em; }
ol.toc span.comment-count { font-size: 75%; color: #999; }
/*** tables ***/
table { color:#000; margin-bottom: 1em; width: 100%; }
table.docutils td p { margin-top:0; margin-bottom:.5em; }
table.docutils td, table.docutils th { border-bottom:1px solid #dfdfdf; padding:4px 2px;}
table.docutils thead th { border-bottom:2px solid #dfdfdf; text-align:left; font-weight: bold; white-space: nowrap; }
table.docutils thead th p { margin: 0; padding: 0; }
table.docutils { border-collapse:collapse; }
/*** code blocks ***/
.literal { white-space:nowrap; }
.literal { color:#234f32; }
#sidebar .literal { color:white; background:transparent; font-size:11px; }
h4 .literal { color: #234f32; font-size: 13px; }
pre { font-size:small; background:#E0FFB8; border:1px solid #94da3a; border-width:1px 0; margin: 1em 0; padding: .3em .4em; overflow: hidden; line-height: 1.3em;}
dt .literal, table .literal { background:none; }
#bd a.reference { text-decoration: none; }
#bd a.reference tt.literal { border-bottom: 1px #234f32 dotted; }
/*** notes & admonitions ***/
.note, .admonition { padding:.8em 1em .8em; margin: 1em 0; border:1px solid #94da3a; }
.admonition-title { font-weight:bold; margin-top:0 !important; margin-bottom:0 !important;}
.admonition .last { margin-bottom:0 !important; }
.note, .admonition { padding-left:65px; background:url(docicons-note.gif) .8em .8em no-repeat;}
div.admonition-philosophy { padding-left:65px; background:url(docicons-philosophy.gif) .8em .8em no-repeat;}
div.admonition-behind-the-scenes { padding-left:65px; background:url(docicons-behindscenes.gif) .8em .8em no-repeat;}
/*** p-links ***/
a.headerlink { color: #c60f0f; font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; visibility: hidden; }
h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink { visibility: visible; }
/*** index ***/
table.indextable td { text-align: left; vertical-align: top;}
table.indextable dl, table.indextable dd { margin-top: 0; margin-bottom: 0; }
table.indextable tr.pcap { height: 10px; }
table.indextable tr.cap { margin-top: 10px; background-color: #f2f2f2;}
/*** page-specific overrides ***/
div#contents ul { margin-bottom: 0;}
div#contents ul li { margin-bottom: 0;}
div#contents ul ul li { margin-top: 0.3em;}
/*** IE hacks ***/
* pre { width: 100%; }

BIN
docs/_static/docicons-behindscenes.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
docs/_static/docicons-note.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

BIN
docs/_static/docicons-philosophy.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

22
docs/_static/homepage.css vendored Normal file
View File

@ -0,0 +1,22 @@
#index p.rubric { font-size:150%; font-weight:normal; margin-bottom:.2em; color:#487858; }
#index div.section dt { font-weight: normal; }
#index #s-getting-help { float: right; width: 35em; background: #E1ECE2; padding: 1em; margin: 2em 0 2em 2em; }
#index #s-getting-help h2 { margin: 0; }
#index #s-django-documentation div.section div.section h3 { margin: 0; }
#index #s-django-documentation div.section div.section { background: #E1ECE2; padding: 1em; margin: 2em 0 2em 40.3em; }
#index #s-django-documentation div.section div.section a.reference { white-space: nowrap; }
#index #s-using-django dl,
#index #s-add-on-contrib-applications dl,
#index #s-solving-specific-problems dl,
#index #s-reference dl
{ float: left; width: 41em; }
#index #s-add-on-contrib-applications,
#index #s-solving-specific-problems,
#index #s-reference,
#index #s-and-all-the-rest
{ clear: left; }

8
docs/_static/reset-fonts-grids.css vendored Normal file
View File

@ -0,0 +1,8 @@
/*
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.5.1
*/
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;font-variant:normal;}sup {vertical-align:text-top;}sub {vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}body {font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}table {font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
body{text-align:center;}#ft{clear:both;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;min-width:750px;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}s .yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#bd:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#bd,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}

4
docs/_templates/genindex.html vendored Normal file
View File

@ -0,0 +1,4 @@
{% extends "!genindex.html" %}
{% block bodyclass %}{% endblock %}
{% block sidebarwrapper %}{% endblock %}

87
docs/_templates/layout.html vendored Normal file
View File

@ -0,0 +1,87 @@
{% extends "!layout.html" %}
{%- macro secondnav %}
{%- if prev %}
&laquo; <a href="{{ prev.link|e }}" title="{{ prev.title|e }}">previous</a>
{{ reldelim2 }}
{%- endif %}
{%- if parents %}
<a href="{{ parents.0.link|e }}" title="{{ parents.0.title|e }}" accesskey="U">up</a>
{%- else %}
<a title="{{ docstitle }}" href="{{ pathto('index') }}" accesskey="U">up</a>
{%- endif %}
{%- if next %}
{{ reldelim2 }}
<a href="{{ next.link|e }}" title="{{ next.title|e }}">next</a> &raquo;
{%- endif %}
{%- endmacro %}
{% block document %}
<div id="custom-doc" class="{% block bodyclass %}{{ 'yui-t6' if pagename != 'index' else '' }}{% endblock %}">
<div id="hd">
<h1><a href="{{ pathto('index') }}">{{ docstitle }}</a></h1>
<div id="global-nav">
<a title="Home page" href="{{ pathto('index') }}">Home</a> {{ reldelim2 }}
<a title="Table of contents" href="{{ pathto('contents') }}">Table of contents</a> {{ reldelim2 }}
<a title="Global index" href="{{ pathto('genindex') }}">Index</a> {{ reldelim2 }}
<a title="Search" href="{{ pathto('modindex') }}">Modules</a>
</div>
<div class="nav">{{ secondnav() }}</div>
</div>
<div id="bd">
<div id="yui-main">
<div class="yui-b">
<div class="yui-g" id="{{ pagename|replace('/', '-') }}">
{% block body %}{% endblock %}
</div>
</div>
</div>
{% block sidebarwrapper %}
{% if pagename != 'index' %}
<div class="yui-b" id="sidebar">
{{ sidebar() }}
{%- if last_updated %}
<h3>Last update:</h3>
<p class="topless">{{ last_updated }}</p>
{%- endif %}
</div>
{% endif %}
{% endblock %}
</div>
<div id="ft">
<div class="nav">{{ secondnav() }}</div>
</div>
</div>
{% endblock %}
{% block sidebarrel %}
<h3>Browse</h3>
<ul>
{% if prev %}
<li>Prev: <a href="{{ prev.link }}">{{ prev.title }}</a></li>
{% endif %}
{% if next %}
<li>Next: <a href="{{ next.link }}">{{ next.title }}</a></li>
{% endif %}
</ul>
<h3>You are here:</h3>
<ul>
<li>
<a href="{{ pathto('index') }}">{{ docstitle }}</a>
{% for p in parents %}
<ul><li><a href="{{ p.link }}">{{ p.title }}</a>
{% endfor %}
<ul><li>{{ title }}</li></ul>
{% for p in parents %}</li></ul>{% endfor %}
</li>
</ul>
{% endblock %}
{# Empty some default blocks out #}
{% block relbar1 %}{% endblock %}
{% block relbar2 %}{% endblock %}
{% block sidebar1 %}{% endblock %}
{% block sidebar2 %}{% endblock %}
{% block footer %}{% endblock %}

3
docs/_templates/modindex.html vendored Normal file
View File

@ -0,0 +1,3 @@
{% extends "!modindex.html" %}
{% block bodyclass %}{% endblock %}
{% block sidebarwrapper %}{% endblock %}

3
docs/_templates/search.html vendored Normal file
View File

@ -0,0 +1,3 @@
{% extends "!search.html" %}
{% block bodyclass %}{% endblock %}
{% block sidebarwrapper %}{% endblock %}

View File

@ -1,119 +0,0 @@
=============
API stability
=============
Although Django has not reached a 1.0 release, the bulk of Django's public APIs are
stable as of the 0.95 release. This document explains which APIs will and will not
change before the 1.0 release.
What "stable" means
===================
In this context, stable means:
- All the public APIs -- everything documented in the linked documents, and
all methods that don't begin with an underscore -- will not be moved or
renamed without providing backwards-compatible aliases.
- If new features are added to these APIs -- which is quite possible --
they will not break or change the meaning of existing methods. In other
words, "stable" does not (necessarily) mean "complete."
- If, for some reason, an API declared stable must be removed or replaced, it
will be declared deprecated but will remain in the API until at least
version 1.1. Warnings will be issued when the deprecated method is
called.
- We'll only break backwards compatibility of these APIs if a bug or
security hole makes it completely unavoidable.
Stable APIs
===========
These APIs are stable:
- `Caching`_.
- `Custom template tags and libraries`_ (with the possible exception for a
small change in the way templates are registered and loaded).
- `Database lookup`_ (with the exception of validation; see below).
- `django-admin utility`_.
- `FastCGI integration`_.
- `Flatpages`_.
- `Generic views`_.
- `Internationalization`_.
- `Legacy database integration`_.
- `Model definition`_ (with the exception of generic relations; see below).
- `mod_python integration`_.
- `Redirects`_.
- `Request/response objects`_.
- `Sending e-mail`_.
- `Sessions`_.
- `Settings`_.
- `Syndication`_.
- `Template language`_ (with the exception of some possible disambiguation
of how tag arguments are passed to tags and filters).
- `Transactions`_.
- `URL dispatch`_.
You'll notice that this list comprises the bulk of Django's APIs. That's right
-- most of the changes planned between now and Django 1.0 are either under the
hood, feature additions, or changes to a few select bits. A good estimate is
that 90% of Django can be considered forwards-compatible at this point.
That said, these APIs should *not* be considered stable, and are likely to
change:
- `Serialization`_ is under heavy development; changes are likely.
- The `authentication`_ framework is changing to be far more flexible, and
API changes may be necessary.
- Generic relations will most likely be moved out of core and into the
content-types contrib package to avoid core dependencies on optional
components.
- The comments framework, which is yet undocumented, will likely get a complete
rewrite before Django 1.0. Even if the change isn't quite that drastic,
there will at least be moderate changes.
.. _caching: ../cache/
.. _custom template tags and libraries: ../templates_python/
.. _database lookup: ../db-api/
.. _django-admin utility: ../django-admin/
.. _fastcgi integration: ../fastcgi/
.. _flatpages: ../flatpages/
.. _generic views: ../generic_views/
.. _internationalization: ../i18n/
.. _legacy database integration: ../legacy_databases/
.. _model definition: ../model-api/
.. _mod_python integration: ../modpython/
.. _redirects: ../redirects/
.. _request/response objects: ../request_response/
.. _sending e-mail: ../email/
.. _sessions: ../sessions/
.. _settings: ../settings/
.. _syndication: ../syndication_feeds/
.. _template language: ../templates/
.. _transactions: ../transactions/
.. _url dispatch: ../url_dispatch/
.. _serialization: ../serialization/
.. _authentication: ../authentication/

File diff suppressed because it is too large Load Diff

View File

@ -12,35 +12,36 @@
# serve to show the default value. # serve to show the default value.
import sys import sys
import os
# If your extensions are in another directory, add it here. # If your extensions are in another directory, add it here.
#sys.path.append('some/directory') sys.path.append(os.path.join(os.path.dirname(__file__), "_ext"))
# General configuration # General configuration
# --------------------- # ---------------------
# Add any Sphinx extension module names here, as strings. They can be extensions # Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
#extensions = [] extensions = ["djangodocs"]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = [] templates_path = ["_templates"]
# The suffix of source filenames. # The suffix of source filenames.
source_suffix = '.txt' source_suffix = '.txt'
# The master toctree document. # The master toctree document.
master_doc = 'index' master_doc = 'contents'
# General substitutions. # General substitutions.
project = 'Django' project = 'Django'
copyright = '2008, Django Software Foundation' copyright = 'Django Software Foundation and contributors'
# The default replacements for |version| and |release|, also used in various # The default replacements for |version| and |release|, also used in various
# other places throughout the built documents. # other places throughout the built documents.
# #
# The short X.Y version. # The short X.Y version.
version = 'SVN' version = '1.0'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = version release = version
@ -65,7 +66,7 @@ add_module_names = False
show_authors = False show_authors = False
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx' pygments_style = 'trac'
# Options for HTML output # Options for HTML output
@ -79,7 +80,7 @@ html_style = 'default.css'
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = [] html_static_path = ["_static"]
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format. # using the given strftime format.
@ -89,6 +90,9 @@ html_last_updated_fmt = '%b %d, %Y'
# typographically correct entities. # typographically correct entities.
html_use_smartypants = True html_use_smartypants = True
# HTML translator class for the builder
html_translator_class = "djangodocs.DjangoHTMLTranslator"
# Content template for the index page. # Content template for the index page.
#html_index = '' #html_index = ''
@ -97,7 +101,7 @@ html_use_smartypants = True
# Additional templates that should be rendered to pages, maps page names to # Additional templates that should be rendered to pages, maps page names to
# template names. # template names.
#html_additional_pages = {} html_additional_pages = {}
# If false, no module index is generated. # If false, no module index is generated.
#html_use_modindex = True #html_use_modindex = True
@ -121,6 +125,9 @@ htmlhelp_basename = 'Djangodoc'
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]). # (source start file, target name, title, author, document class [howto/manual]).
#latex_documents = [] #latex_documents = []
latex_documents = [
('index', 'django.tex', 'Django Documentation', 'Django Software Foundation', 'manual'),
]
# Additional stuff for the LaTeX preamble. # Additional stuff for the LaTeX preamble.
#latex_preamble = '' #latex_preamble = ''
@ -130,3 +137,9 @@ htmlhelp_basename = 'Djangodoc'
# If false, no module index is generated. # If false, no module index is generated.
#latex_use_modindex = True #latex_use_modindex = True
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# If this isn't set to True, the LaTex writer can only handle six levels of headers.
latex_use_parts = True

36
docs/contents.txt Normal file
View File

@ -0,0 +1,36 @@
.. _contents:
=============================
Django documentation contents
=============================
.. toctree::
:maxdepth: 2
intro/index
topics/index
howto/index
faq/index
ref/index
misc/index
glossary
releases/index
internals/index
Indices, glossary and tables
============================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`glossary`
Deprecated/obsolete documentation
=================================
The following documentation covers features that have been deprecated or that
have been replaced in newer versions of Django.
.. toctree::
:maxdepth: 2
obsolete/index

View File

@ -1,297 +0,0 @@
==========================
The contenttypes framework
==========================
Django includes a "contenttypes" application that can track all of
the models installed in your Django-powered project, providing a
high-level, generic interface for working with your models.
Overview
========
At the heart of the contenttypes application is the ``ContentType``
model, which lives at
``django.contrib.contenttypes.models.ContentType``. Instances of
``ContentType`` represent and store information about the models
installed in your project, and new instances of ``ContentType`` are
automatically created whenever new models are installed.
Instances of ``ContentType`` have methods for returning the model
classes they represent and for querying objects from those models.
``ContentType`` also has a `custom manager`_ that adds methods for
working with ``ContentType`` and for obtaining instances of
``ContentType`` for a particular model.
Relations between your models and ``ContentType`` can also be used to
enable "generic" relationships between an instance of one of your
models and instances of any model you have installed.
.. _custom manager: ../model-api/#custom-managers
Installing the contenttypes framework
=====================================
The contenttypes framework is included in the default
``INSTALLED_APPS`` list created by ``django-admin.py startproject``,
but if you've removed it or if you manually set up your
``INSTALLED_APPS`` list, you can enable it by adding
``'django.contrib.contenttypes'`` to your ``INSTALLED_APPS`` setting.
It's generally a good idea to have the contenttypes framework
installed; several of Django's other bundled applications require it:
* The admin application uses it to log the history of each object
added or changed through the admin interface.
* Django's `authentication framework`_ uses it to tie user permissions
to specific models.
* Django's comments system (``django.contrib.comments``) uses it to
"attach" comments to any installed model.
.. _authentication framework: ../authentication/
The ``ContentType`` model
=========================
Each instance of ``ContentType`` has three fields which, taken
together, uniquely describe an installed model:
``app_label``
The name of the application the model is part of. This is taken from
the ``app_label`` attribute of the model, and includes only the *last*
part of the application's Python import path;
"django.contrib.contenttypes", for example, becomes an ``app_label``
of "contenttypes".
``model``
The name of the model class.
``name``
The human-readable name of the model. This is taken from
`the verbose_name attribute`_ of the model.
Let's look at an example to see how this works. If you already have
the contenttypes application installed, and then add `the sites application`_
to your ``INSTALLED_APPS`` setting and run ``manage.py syncdb`` to install it,
the model ``django.contrib.sites.models.Site`` will be installed into your
database. Along with it a new instance of ``ContentType`` will be created with
the following values:
* ``app_label`` will be set to ``'sites'`` (the last part of the Python
path "django.contrib.sites").
* ``model`` will be set to ``'site'``.
* ``name`` will be set to ``'site'``.
.. _the verbose_name attribute: ../model-api/#verbose_name
.. _the sites application: ../sites/
Methods on ``ContentType`` instances
====================================
Each ``ContentType`` instance has methods that allow you to get from a
``ContentType`` instance to the model it represents, or to retrieve objects
from that model:
``get_object_for_this_type(**kwargs)``
Takes a set of valid `lookup arguments`_ for the model the
``ContentType`` represents, and does `a get() lookup`_ on that
model, returning the corresponding object.
``model_class()``
Returns the model class represented by this ``ContentType``
instance.
For example, we could look up the ``ContentType`` for the ``User`` model::
>>> from django.contrib.contenttypes.models import ContentType
>>> user_type = ContentType.objects.get(app_label="auth", model="user")
>>> user_type
<ContentType: user>
And then use it to query for a particular ``User``, or to get access
to the ``User`` model class::
>>> user_type.model_class()
<class 'django.contrib.auth.models.User'>
>>> user_type.get_object_for_this_type(username='Guido')
<User: Guido>
Together, ``get_object_for_this_type`` and ``model_class`` enable two
extremely important use cases:
1. Using these methods, you can write high-level generic code that
performs queries on any installed model -- instead of importing and
using a single specific model class, you can pass an ``app_label``
and ``model`` into a ``ContentType`` lookup at runtime, and then
work with the model class or retrieve objects from it.
2. You can relate another model to ``ContentType`` as a way of tying
instances of it to particular model classes, and use these methods
to get access to those model classes.
Several of Django's bundled applications make use of the latter
technique. For example, `the permissions system`_ in Django's
authentication framework uses a ``Permission`` model with a foreign
key to ``ContentType``; this lets ``Permission`` represent concepts
like "can add blog entry" or "can delete news story".
.. _lookup arguments: ../db-api/#field-lookups
.. _a get() lookup: ../db-api/#get-kwargs
.. _the permissions system: ../authentication/#permissions
The ``ContentTypeManager``
--------------------------
``ContentType`` also has a custom manager, ``ContentTypeManager``,
which adds the following methods:
``clear_cache()``
Clears an internal cache used by ``ContentType`` to keep track of which
models for which it has created ``ContentType`` instances. You probably
won't ever need to call this method yourself; Django will call it
automatically when it's needed.
``get_for_model(model)``
Takes either a model class or an instance of a model, and returns the
``ContentType`` instance representing that model.
The ``get_for_model`` method is especially useful when you know you
need to work with a ``ContentType`` but don't want to go to the
trouble of obtaining the model's metadata to perform a manual lookup::
>>> from django.contrib.auth.models import User
>>> user_type = ContentType.objects.get_for_model(User)
>>> user_type
<ContentType: user>
Generic relations
=================
Adding a foreign key from one of your own models to ``ContentType``
allows your model to effectively tie itself to another model class, as
in the example of the ``Permission`` model above. But it's possible to
go one step further and use ``ContentType`` to enable truly generic
(sometimes called "polymorphic") relationships between models.
A simple example is a tagging system, which might look like this::
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
def __unicode__(self):
return self.tag
A normal ``ForeignKey`` can only "point to" one other model, which
means that if the ``TaggedItem`` model used a ``ForeignKey`` it would have to
choose one and only one model to store tags for. The contenttypes
application provides a special field type --
``django.contrib.contenttypes.generic.GenericForeignKey`` -- which
works around this and allows the relationship to be with any
model. There are three parts to setting up a ``GenericForeignKey``:
1. Give your model a ``ForeignKey`` to ``ContentType``.
2. Give your model a field that can store a primary-key value from the
models you'll be relating to. (For most models, this means an
``IntegerField`` or ``PositiveIntegerField``.)
This field must be of the same type as the primary key of the models
that will be involved in the generic relation. For example, if you use
``IntegerField``, you won't be able to form a generic relation with a
model that uses a ``CharField`` as a primary key.
3. Give your model a ``GenericForeignKey``, and pass it the names of
the two fields described above. If these fields are named
"content_type" and "object_id", you can omit this -- those are the
default field names ``GenericForeignKey`` will look for.
This will enable an API similar to the one used for a normal ``ForeignKey``;
each ``TaggedItem`` will have a ``content_object`` field that returns the
object it's related to, and you can also assign to that field or use it when
creating a ``TaggedItem``::
>>> from django.contrib.auth.models import User
>>> guido = User.objects.get(username='Guido')
>>> t = TaggedItem(content_object=guido, tag='bdfl')
>>> t.save()
>>> t.content_object
<User: Guido>
Due to the way ``GenericForeignKey`` is implemeneted, you cannot use such
fields directly with filters (``filter()`` and ``exclude()``, for example) via
the database API. They aren't normal field objects. These examples will *not*
work::
# This will fail
>>> TaggedItem.objects.filter(content_object=guido)
# This will also fail
>>> TaggedItem.objects.get(content_object=guido)
Reverse generic relations
-------------------------
If you know which models you'll be using most often, you can also add
a "reverse" generic relationship to enable an additional API. For example::
class Bookmark(models.Model):
url = models.URLField()
tags = generic.GenericRelation(TaggedItem)
``Bookmark`` instances will each have a ``tags`` attribute, which can
be used to retrieve their associated ``TaggedItems``::
>>> b = Bookmark(url='http://www.djangoproject.com/')
>>> b.save()
>>> t1 = TaggedItem(content_object=b, tag='django')
>>> t1.save()
>>> t2 = TaggedItem(content_object=b, tag='python')
>>> t2.save()
>>> b.tags.all()
[<TaggedItem: django>, <TaggedItem: python>]
If you don't add the reverse relationship, you can do the lookup manually::
>>> b = Bookmark.objects.get(url='http://www.djangoproject.com/)
>>> bookmark_type = ContentType.objects.get_for_model(b)
>>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id,
... object_id=b.id)
[<TaggedItem: django>, <TaggedItem: python>]
Note that if you delete an object that has a ``GenericRelation``, any objects
which have a ``GenericForeignKey`` pointing at it will be deleted as well. In
the example above, this means that if a ``Bookmark`` object were deleted, any
``TaggedItem`` objects pointing at it would be deleted at the same time.
Generic relations in forms and admin
------------------------------------
``django.contrib.contenttypes.generic`` provides both a ``GenericInlineFormSet``
and ``GenericInlineModelAdmin``. This enables the use of generic relations in
forms and the admin. See the `model formset`_ and `admin`_ documentation for
more information.
``GenericInlineModelAdmin`` options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``GenericInlineModelAdmin`` class inherits all properties from an
``InlineModelAdmin`` class. However, it adds a couple of its own for working
with the generic relation:
* ``ct_field`` - The name of the ``ContentType`` foreign key field on the
model. Defaults to ``content_type``.
* ``ct_fk_field`` - The name of the integer field that represents the ID
of the related object. Defaults to ``object_id``.
.. _model formset: ../modelforms/
.. _admin: ../admin/

File diff suppressed because it is too large Load Diff

View File

@ -1,138 +0,0 @@
====================================
How to read the Django documentation
====================================
We've put a lot of effort into making Django's documentation useful, easy to
read and as complete as possible. Here are a few tips on how to make the best
of it, along with some style guidelines.
(Yes, this is documentation about documentation. Rest assured we have no plans
to write a document about how to read the document about documentation.)
How documentation is updated
============================
Just as the Django code base is developed and improved on a daily basis, our
documentation is consistently improving. We improve documentation for several
reasons:
* To make content fixes, such as grammar/typo corrections.
* To add information and/or examples to existing sections that need to be
expanded.
* To document Django features that aren't yet documented. (The list of
such features is shrinking but exists nonetheless.)
* To add documentation for new features as new features get added, or as
Django APIs or behaviors change.
Django's documentation is kept in the same source control system as its code.
It lives in the `django/trunk/docs`_ directory of our Subversion repository.
Each document is a separate text file that covers a narrowly focused topic,
such as the "generic views" framework or how to construct a database model.
.. _django/trunk/docs: http://code.djangoproject.com/browser/django/trunk/docs
Where to get it
===============
You can read Django documentation in several ways. They are, in order of
preference:
On the Web
----------
The most recent version of the Django documentation lives at
http://www.djangoproject.com/documentation/ . These HTML pages are generated
automatically from the text files in source control. That means they reflect
the "latest and greatest" in Django -- they include the very latest
corrections and additions, and they discuss the latest Django features,
which may only be available to users of the Django development version. (See
"Differences between versions" below.)
We encourage you to help improve the docs by submitting changes, corrections
and suggestions in the `ticket system`_. The Django developers actively monitor
the ticket system and use your feedback to improve the documentation for
everybody.
Note, however, that tickets should explicitly relate to the documentation,
rather than asking broad tech-support questions. If you need help with your
particular Django setup, try the `django-users mailing list`_ or the
`#django IRC channel`_ instead.
.. _ticket system: http://code.djangoproject.com/simpleticket?component=Documentation
.. _django-users mailing list: http://groups.google.com/group/django-users
.. _#django IRC channel: irc://irc.freenode.net/django
In plain text
-------------
For offline reading, or just for convenience, you can read the Django
documentation in plain text.
If you're using an official release of Django, note that the zipped package
(tarball) of the code includes a ``docs/`` directory, which contains all the
documentation for that release.
If you're using the development version of Django (aka the Subversion "trunk"),
note that the ``docs/`` directory contains all of the documentation. You can
``svn update`` it, just as you ``svn update`` the Python code, in order to get
the latest changes.
You can check out the latest Django documentation from Subversion using this
shell command::
svn co http://code.djangoproject.com/svn/django/trunk/docs/ django_docs
One low-tech way of taking advantage of the text documentation is by using the
Unix ``grep`` utility to search for a phrase in all of the documentation. For
example, this will show you each mention of the phrase "edit_inline" in any
Django document::
grep edit_inline /path/to/django/docs/*.txt
Formatting
~~~~~~~~~~
The text documentation is written in ReST (ReStructured Text) format. That
means it's easy to read but is also formatted in a way that makes it easy to
convert into other formats, such as HTML. If you have the `reStructuredText`_
library installed, you can use ``rst2html`` to generate your own HTML files.
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
Differences between versions
============================
As previously mentioned, the text documentation in our Subversion repository
contains the "latest and greatest" changes and additions. These changes often
include documentation of new features added in the Django development version
-- the Subversion ("trunk") version of Django. For that reason, it's worth
pointing out our policy on keeping straight the documentation for various
versions of the framework.
We follow this policy:
* The primary documentation on djangoproject.com is an HTML version of the
latest docs in Subversion. These docs always correspond to the latest
official Django release, plus whatever features we've added/changed in
the framework *since* the latest release.
* As we add features to Django's development version, we try to update the
documentation in the same Subversion commit transaction.
* To distinguish feature changes/additions in the docs, we use the phrase
**New in Django development version**. In practice, this means that the
current documentation on djangoproject.com can be used by users of either
the latest release *or* the development version.
* Documentation for a particular Django release is frozen once the version
has been released officially. It remains a snapshot of the docs as of the
moment of the release. We will make exceptions to this rule in
the case of retroactive security updates or other such retroactive
changes. Once documentation is frozen, we add a note to the top of each
frozen document that says "These docs are frozen for Django version XXX"
and links to the current version of that document.
* The `main documentation Web page`_ includes links to documentation for
all previous versions.
.. _main documentation Web page: http://www.djangoproject.com/documentation/

View File

@ -1,744 +0,0 @@
==========
Django FAQ
==========
General questions
=================
Why does this project exist?
----------------------------
Django grew from a very practical need: World Online, a newspaper Web
operation, is responsible for building intensive Web applications on journalism
deadlines. In the fast-paced newsroom, World Online often has only a matter of
hours to take a complicated Web application from concept to public launch.
At the same time, the World Online Web developers have consistently been
perfectionists when it comes to following best practices of Web development.
In fall 2003, the World Online developers (Adrian Holovaty and Simon Willison)
ditched PHP and began using Python to develop its Web sites. As they built
intensive, richly interactive sites such as Lawrence.com, they began to extract
a generic Web development framework that let them build Web applications more
and more quickly. They tweaked this framework constantly, adding improvements
over two years.
In summer 2005, World Online decided to open-source the resulting software,
Django. Django would not be possible without a whole host of open-source
projects -- `Apache`_, `Python`_, and `PostgreSQL`_ to name a few -- and we're
thrilled to be able to give something back to the open-source community.
.. _Apache: http://httpd.apache.org/
.. _Python: http://www.python.org/
.. _PostgreSQL: http://www.postgresql.org/
What does "Django" mean, and how do you pronounce it?
-----------------------------------------------------
Django is named after `Django Reinhardt`_, a gypsy jazz guitarist from the 1930s
to early 1950s. To this day, he's considered one of the best guitarists of all time.
Listen to his music. You'll like it.
Django is pronounced **JANG**-oh. Rhymes with FANG-oh. The "D" is silent.
We've also recorded an `audio clip of the pronunciation`_.
.. _Django Reinhardt: http://en.wikipedia.org/wiki/Django_Reinhardt
.. _audio clip of the pronunciation: http://red-bean.com/~adrian/django_pronunciation.mp3
Is Django stable?
-----------------
Yes. World Online has been using Django for more than three years. Sites built
on Django have weathered traffic spikes of over one million hits an hour and a
number of Slashdottings. Yes, it's quite stable.
Does Django scale?
------------------
Yes. Compared to development time, hardware is cheap, and so Django is
designed to take advantage of as much hardware as you can throw at it.
Django uses a "shared-nothing" architecture, which means you can add hardware
at any level -- database servers, caching servers or Web/application servers.
The framework cleanly separates components such as its database layer and
application layer. And it ships with a simple-yet-powerful `cache framework`_.
.. _`cache framework`: ../cache/
Who's behind this?
------------------
Django was developed at `World Online`_, the Web department of a newspaper in
Lawrence, Kansas, USA.
`Adrian Holovaty`_
Adrian is a Web developer with a background in journalism. He was lead
developer at World Online for 2.5 years, during which time Django was
developed and implemented on World Online's sites. Now he works for
washingtonpost.com building rich, database-backed information sites, and
continues to oversee Django development. He likes playing guitar (Django
Reinhardt style) and hacking on side projects such as `chicagocrime.org`_.
He lives in Chicago.
On IRC, Adrian goes by ``adrian_h``.
`Jacob Kaplan-Moss`_
Jacob is a whipper-snapper from California who spends equal time coding and
cooking. He's lead developer at World Online and actively hacks on various
cool side projects. He's contributed to the Python-ObjC bindings and was
the first guy to figure out how to write Tivo apps in Python. Lately he's
been messing with Python on the PSP. He lives in Lawrence, Kansas.
On IRC, Jacob goes by ``jacobkm``.
`Simon Willison`_
Simon is a well-respected Web developer from England. He had a one-year
internship at World Online, during which time he and Adrian developed
Django from scratch. The most enthusiastic Brit you'll ever meet, he's
passionate about best practices in Web development and has maintained a
well-read Web-development blog for years at http://simon.incutio.com.
He works for Yahoo UK, where he managed to score the title "Hacker Liason."
He lives in London.
On IRC, Simon goes by ``SimonW``.
`Wilson Miner`_
Wilson's design-fu makes us all look like rock stars. By day, he's an
interactive designer for `Apple`_. Don't ask him what he's working on, or
he'll have to kill you. He lives in San Francisco.
On IRC, Wilson goes by ``wilsonian``.
.. _`World Online`: http://code.djangoproject.com/wiki/WorldOnline
.. _`Adrian Holovaty`: http://www.holovaty.com/
.. _`washingtonpost.com`: http://www.washingtonpost.com/
.. _`chicagocrime.org`: http://www.chicagocrime.org/
.. _`Simon Willison`: http://simon.incutio.com/
.. _`simon.incutio.com`: http://simon.incutio.com/
.. _`Jacob Kaplan-Moss`: http://www.jacobian.org/
.. _`Wilson Miner`: http://www.wilsonminer.com/
.. _`Apple`: http://www.apple.com/
Which sites use Django?
-----------------------
The Django wiki features a consistently growing `list of Django-powered sites`_.
Feel free to add your Django-powered site to the list.
.. _list of Django-powered sites: http://code.djangoproject.com/wiki/DjangoPoweredSites
Django appears to be a MVC framework, but you call the Controller the "view", and the View the "template". How come you don't use the standard names?
-----------------------------------------------------------------------------------------------------------------------------------------------------
Well, the standard names are debatable.
In our interpretation of MVC, the "view" describes the data that gets presented
to the user. It's not necessarily *how* the data *looks*, but *which* data is
presented. The view describes *which data you see*, not *how you see it.* It's
a subtle distinction.
So, in our case, a "view" is the Python callback function for a particular URL,
because that callback function describes which data is presented.
Furthermore, it's sensible to separate content from presentation -- which is
where templates come in. In Django, a "view" describes which data is presented,
but a view normally delegates to a template, which describes *how* the data is
presented.
Where does the "controller" fit in, then? In Django's case, it's probably the
framework itself: the machinery that sends a request to the appropriate view,
according to the Django URL configuration.
If you're hungry for acronyms, you might say that Django is a "MTV" framework
-- that is, "model", "template", and "view." That breakdown makes much more
sense.
At the end of the day, of course, it comes down to getting stuff done. And,
regardless of how things are named, Django gets stuff done in a way that's most
logical to us.
<Framework X> does <feature Y> -- why doesn't Django?
-----------------------------------------------------
We're well aware that there are other awesome Web frameworks out there, and
we're not averse to borrowing ideas where appropriate. However, Django was
developed precisely because we were unhappy with the status quo, so please be
aware that "because <Framework X> does it" is not going to be sufficient reason
to add a given feature to Django.
Why did you write all of Django from scratch, instead of using other Python libraries?
--------------------------------------------------------------------------------------
When Django was originally written a couple of years ago, Adrian and Simon
spent quite a bit of time exploring the various Python Web frameworks
available.
In our opinion, none of them were completely up to snuff.
We're picky. You might even call us perfectionists. (With deadlines.)
Over time, we stumbled across open-source libraries that did things we'd
already implemented. It was reassuring to see other people solving similar
problems in similar ways, but it was too late to integrate outside code: We'd
already written, tested and implemented our own framework bits in several
production settings -- and our own code met our needs delightfully.
In most cases, however, we found that existing frameworks/tools inevitably had
some sort of fundamental, fatal flaw that made us squeamish. No tool fit our
philosophies 100%.
Like we said: We're picky.
We've documented our philosophies on the `design philosophies page`_.
.. _design philosophies page: ../design_philosophies/
Do you have any of those nifty "screencast" things?
---------------------------------------------------
You can bet your bottom they're on the way. But, since we're still hammering
out a few points, we want to make sure they reflect the final state of things
at Django 1.0, not some intermediary step. In other words, we don't want to
spend a lot of energy creating screencasts yet, because Django APIs will shift.
Is Django a content-management-system (CMS)?
--------------------------------------------
No, Django is not a CMS, or any sort of "turnkey product" in and of itself.
It's a Web framework; it's a programming tool that lets you build Web sites.
For example, it doesn't make much sense to compare Django to something like
Drupal_, because Django is something you use to *create* things like Drupal.
Of course, Django's automatic admin site is fantastic and timesaving -- but
the admin site is one module of Django the framework. Furthermore, although
Django has special conveniences for building "CMS-y" apps, that doesn't mean
it's not just as appropriate for building "non-CMS-y" apps (whatever that
means!).
.. _Drupal: http://drupal.org/
When will you release Django 1.0?
---------------------------------
See our `version one roadmap`_ for the detailed timeline. We're aiming for
September 2, 2008.
.. _version one roadmap: http://code.djangoproject.com/wiki/VersionOneRoadmap
How can I download the Django documentation to read it offline?
---------------------------------------------------------------
The Django docs are available in the ``docs`` directory of each Django tarball
release. These docs are in ReST (ReStructured Text) format, and each text file
corresponds to a Web page on the official Django site.
Because the documentation is `stored in revision control`_, you can browse
documentation changes just like you can browse code changes.
Technically, the docs on Django's site are generated from the latest development
versions of those ReST documents, so the docs on the Django site may offer more
information than the docs that come with the latest Django release.
.. _stored in revision control: http://code.djangoproject.com/browser/django/trunk/docs
Where can I find Django developers for hire?
--------------------------------------------
Consult our `developers for hire page`_ for a list of Django developers who
would be happy to help you.
You might also be interested in posting a job to http://djangogigs.com/ .
If you want to find Django-capable people in your local area, try
http://djangopeople.net/ .
.. _developers for hire page: http://code.djangoproject.com/wiki/DevelopersForHire
Installation questions
======================
How do I get started?
---------------------
#. `Download the code`_.
#. Install Django (read the `installation guide`_).
#. Walk through the tutorial_.
#. Check out the rest of the documentation_, and `ask questions`_ if you
run into trouble.
.. _`Download the code`: http://www.djangoproject.com/download/
.. _`installation guide`: ../install/
.. _tutorial: ../tutorial01/
.. _documentation: ../
.. _ask questions: http://www.djangoproject.com/community/
How do I fix the "install a later version of setuptools" error?
---------------------------------------------------------------
Just run the ``ez_setup.py`` script in the Django distribution.
What are Django's prerequisites?
--------------------------------
Django requires Python_ 2.3 or later. No other Python libraries are required
for basic Django usage.
For a development environment -- if you just want to experiment with Django --
you don't need to have a separate Web server installed; Django comes with its
own lightweight development server. For a production environment, we recommend
`Apache 2`_ and mod_python_, although Django follows the WSGI_ spec, which
means it can run on a variety of server platforms.
If you want to use Django with a database, which is probably the case, you'll
also need a database engine. PostgreSQL_ is recommended, because we're
PostgreSQL fans, and MySQL_, `SQLite 3`_, and Oracle_ are also supported.
.. _Python: http://www.python.org/
.. _Apache 2: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _WSGI: http://www.python.org/peps/pep-0333.html
.. _PostgreSQL: http://www.postgresql.org/
.. _MySQL: http://www.mysql.com/
.. _`SQLite 3`: http://www.sqlite.org/
.. _Oracle: http://www.oracle.com/
Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5?
----------------------------------------------------------------------------------------
No. Django itself is guaranteed to work with any version of Python from 2.3
and higher.
If you use a Python version newer than 2.3, you will, of course, be able to
take advantage of newer Python features in your own code, along with the speed
improvements and other optimizations that have been made to the Python language
itself. But the Django framework itself should work equally well on 2.3 as it
does on 2.4 or 2.5.
Do I have to use mod_python?
----------------------------
Although we recommend mod_python for production use, you don't have to use it,
thanks to the fact that Django uses an arrangement called WSGI_. Django can
talk to any WSGI-enabled server. Other non-mod_python deployment setups are
FastCGI, SCGI or AJP. See `How to use Django with FastCGI, SCGI or AJP`_ for
full information.
Also, see the `server arrangements wiki page`_ for other deployment strategies.
If you just want to play around and develop things on your local computer, use
the development Web server that comes with Django. Things should Just Work.
.. _WSGI: http://www.python.org/peps/pep-0333.html
.. _How to use Django with FastCGI, SCGI or AJP: ../fastcgi/
.. _server arrangements wiki page: http://code.djangoproject.com/wiki/ServerArrangements
How do I install mod_python on Windows?
---------------------------------------
* For Python 2.4, grab mod_python from `win32 build of mod_python for
Python 2.4`_.
* For Python 2.4, check out this `Django on Windows howto`_.
* For Python 2.3, grab mod_python from http://www.modpython.org/ and read
`Running mod_python on Apache on Windows2000`_.
* Also, try this (not Windows-specific) `guide to getting mod_python
working`_.
.. _`win32 build of mod_python for Python 2.4`: http://www.lehuen.com/nicolas/index.php/2005/02/21/39-win32-build-of-mod_python-314-for-python-24
.. _`Django on Windows howto`: http://thinkhole.org/wp/django-on-windows/
.. _`Running mod_python on Apache on Windows2000`: http://groups-beta.google.com/group/comp.lang.python/msg/139af8c83a5a9d4f
.. _`guide to getting mod_python working`: http://www.dscpl.com.au/articles/modpython-001.html
Will Django run under shared hosting (like TextDrive or Dreamhost)?
-------------------------------------------------------------------
See our `Django-friendly Web hosts`_ page.
.. _`Django-friendly Web hosts`: http://code.djangoproject.com/wiki/DjangoFriendlyWebHosts
Should I use the official version or development version?
---------------------------------------------------------
The Django developers improve Django every day and are pretty good about not
checking in broken code. We use the development code (from the Subversion
repository) directly on our servers, so we consider it stable. With that in
mind, we recommend that you use the latest development code, because it
generally contains more features and fewer bugs than the "official" releases.
Using Django
============
Why do I get an error about importing DJANGO_SETTINGS_MODULE?
-------------------------------------------------------------
Make sure that:
* The environment variable DJANGO_SETTINGS_MODULE is set to a fully-qualified
Python module (i.e. "mysite.settings").
* Said module is on ``sys.path`` (``import mysite.settings`` should work).
* The module doesn't contain syntax errors (of course).
* If you're using mod_python but *not* using Django's request handler,
you'll need to work around a mod_python bug related to the use of
``SetEnv``; before you import anything from Django you'll need to do
the following::
os.environ.update(req.subprocess_env)
(where ``req`` is the mod_python request object).
I can't stand your template language. Do I have to use it?
----------------------------------------------------------
We happen to think our template engine is the best thing since chunky bacon,
but we recognize that choosing a template language runs close to religion.
There's nothing about Django that requires using the template language, so
if you're attached to ZPT, Cheetah, or whatever, feel free to use those.
Do I have to use your model/database layer?
-------------------------------------------
Nope. Just like the template system, the model/database layer is decoupled from
the rest of the framework.
The one exception is: If you use a different database library, you won't get to
use Django's automatically-generated admin site. That app is coupled to the
Django database layer.
How do I use image and file fields?
-----------------------------------
Using a ``FileField`` or an ``ImageField`` in a model takes a few steps:
#. In your settings file, define ``MEDIA_ROOT`` as the full path to
a directory where you'd like Django to store uploaded files. (For
performance, these files are not stored in the database.) Define
``MEDIA_URL`` as the base public URL of that directory. Make sure that
this directory is writable by the Web server's user account.
#. Add the ``FileField`` or ``ImageField`` to your model, making sure
to define the ``upload_to`` option to tell Django to which subdirectory
of ``MEDIA_ROOT`` it should upload files.
#. All that will be stored in your database is a path to the file
(relative to ``MEDIA_ROOT``). You'll most likely want to use the
convenience ``get_<fieldname>_url`` function provided by Django. For
example, if your ``ImageField`` is called ``mug_shot``, you can get the
absolute URL to your image in a template with
``{{ object.get_mug_shot_url }}``.
Databases and models
====================
How can I see the raw SQL queries Django is running?
----------------------------------------------------
Make sure your Django ``DEBUG`` setting is set to ``True``. Then, just do
this::
>>> from django.db import connection
>>> connection.queries
[{'sql': 'SELECT polls_polls.id,polls_polls.question,polls_polls.pub_date FROM polls_polls',
'time': '0.002'}]
``connection.queries`` is only available if ``DEBUG`` is ``True``. It's a list
of dictionaries in order of query execution. Each dictionary has the following::
``sql`` -- The raw SQL statement
``time`` -- How long the statement took to execute, in seconds.
``connection.queries`` includes all SQL statements -- INSERTs, UPDATES,
SELECTs, etc. Each time your app hits the database, the query will be recorded.
Can I use Django with a pre-existing database?
----------------------------------------------
Yes. See `Integrating with a legacy database`_.
.. _`Integrating with a legacy database`: ../legacy_databases/
If I make changes to a model, how do I update the database?
-----------------------------------------------------------
If you don't mind clearing data, your project's ``manage.py`` utility has an
option to reset the SQL for a particular application::
manage.py reset appname
This drops any tables associated with ``appname`` and recreates them.
If you do care about deleting data, you'll have to execute the ``ALTER TABLE``
statements manually in your database. That's the way we've always done it,
because dealing with data is a very sensitive operation that we've wanted to
avoid automating. That said, there's some work being done to add partially
automated database-upgrade functionality.
Do Django models support multiple-column primary keys?
------------------------------------------------------
No. Only single-column primary keys are supported.
But this isn't an issue in practice, because there's nothing stopping you from
adding other constraints (using the ``unique_together`` model option or
creating the constraint directly in your database), and enforcing the
uniqueness at that level. Single-column primary keys are needed for things such
as the admin interface to work; e.g., you need a simple way of being able to
specify an object to edit or delete.
How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?
------------------------------------------------------------------------------------------------------------------
We try to avoid adding special cases in the Django code to accommodate all the
database-specific options such as table type, etc. If you'd like to use any of
these options, create an `SQL initial data file`_ that contains ``ALTER TABLE``
statements that do what you want to do. The initial data files are executed in
your database after the ``CREATE TABLE`` statements.
For example, if you're using MySQL and want your tables to use the MyISAM table
type, create an initial data file and put something like this in it::
ALTER TABLE myapp_mytable ENGINE=MyISAM;
As explained in the `SQL initial data file`_ documentation, this SQL file can
contain arbitrary SQL, so you can make any sorts of changes you need to make.
.. _SQL initial data file: ../model-api/#providing-initial-sql-data
Why is Django leaking memory?
-----------------------------
Django isn't known to leak memory. If you find your Django processes are
allocating more and more memory, with no sign of releasing it, check to make
sure your ``DEBUG`` setting is set to ``True``. If ``DEBUG`` is ``True``, then
Django saves a copy of every SQL statement it has executed.
(The queries are saved in ``django.db.connection.queries``. See
`How can I see the raw SQL queries Django is running?`_.)
To fix the problem, set ``DEBUG`` to ``False``.
If you need to clear the query list manually at any point in your functions,
just call ``reset_queries()``, like this::
from django import db
db.reset_queries()
The admin site
==============
I can't log in. When I enter a valid username and password, it just brings up the login page again, with no error messages.
---------------------------------------------------------------------------------------------------------------------------
The login cookie isn't being set correctly, because the domain of the cookie
sent out by Django doesn't match the domain in your browser. Try these two
things:
* Set the ``SESSION_COOKIE_DOMAIN`` setting in your admin config file
to match your domain. For example, if you're going to
"http://www.mysite.com/admin/" in your browser, in
"myproject.settings" you should set ``SESSION_COOKIE_DOMAIN = 'www.mysite.com'``.
* Some browsers (Firefox?) don't like to accept cookies from domains that
don't have dots in them. If you're running the admin site on "localhost"
or another domain that doesn't have a dot in it, try going to
"localhost.localdomain" or "127.0.0.1". And set
``SESSION_COOKIE_DOMAIN`` accordingly.
I can't log in. When I enter a valid username and password, it brings up the login page again, with a "Please enter a correct username and password" error.
-----------------------------------------------------------------------------------------------------------------------------------------------------------
If you're sure your username and password are correct, make sure your user
account has ``is_active`` and ``is_staff`` set to True. The admin site only
allows access to users with those two fields both set to True.
How can I prevent the cache middleware from caching the admin site?
-------------------------------------------------------------------
Set the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting to ``True``. See the
`cache documentation`_ for more information.
.. _cache documentation: ../cache/#the-per-site-cache
How do I automatically set a field's value to the user who last edited the object in the admin?
-----------------------------------------------------------------------------------------------
At this point, Django doesn't have an official way to do this. But it's an oft-requested
feature, so we're discussing how it can be implemented. The problem is we don't want to couple
the model layer with the admin layer with the request layer (to get the current user). It's a
tricky problem.
One person hacked up a `solution that doesn't require patching Django`_, but note that it's an
unofficial solution, and there's no guarantee it won't break at some point.
.. _solution that doesn't require patching Django: http://lukeplant.me.uk/blog.php?id=1107301634
How do I limit admin access so that objects can only be edited by the users who created them?
---------------------------------------------------------------------------------------------
See the answer to the previous question.
My admin-site CSS and images showed up fine using the development server, but they're not displaying when using mod_python.
---------------------------------------------------------------------------------------------------------------------------
See `serving the admin files`_ in the "How to use Django with mod_python"
documentation.
.. _serving the admin files: ../modpython/#serving-the-admin-files
My "list_filter" contains a ManyToManyField, but the filter doesn't display.
----------------------------------------------------------------------------
Django won't bother displaying the filter for a ``ManyToManyField`` if there
are fewer than two related objects.
For example, if your ``list_filter`` includes ``sites``, and there's only one
site in your database, it won't display a "Site" filter. In that case,
filtering by site would be meaningless.
How can I customize the functionality of the admin interface?
-------------------------------------------------------------
You've got several options. If you want to piggyback on top of an add/change
form that Django automatically generates, you can attach arbitrary JavaScript
modules to the page via the model's ``class Admin`` ``js`` parameter. That
parameter is a list of URLs, as strings, pointing to JavaScript modules that
will be included within the admin form via a ``<script>`` tag.
If you want more flexibility than simply tweaking the auto-generated forms,
feel free to write custom views for the admin. The admin is powered by Django
itself, and you can write custom views that hook into the authentication
system, check permissions and do whatever else they need to do.
If you want to customize the look-and-feel of the admin interface, read the
next question.
The dynamically-generated admin site is ugly! How can I change it?
------------------------------------------------------------------
We like it, but if you don't agree, you can modify the admin site's
presentation by editing the CSS stylesheet and/or associated image files. The
site is built using semantic HTML and plenty of CSS hooks, so any changes you'd
like to make should be possible by editing the stylesheet. We've got a
`guide to the CSS used in the admin`_ to get you started.
.. _`guide to the CSS used in the admin`: ../admin_css/
How do I create users without having to edit password hashes?
-------------------------------------------------------------
If you'd like to use the admin site to create users, upgrade to the Django
development version, where this problem was fixed on Aug. 4, 2006.
You can also use the Python API. See `creating users`_ for full info.
.. _creating users: ../authentication/#creating-users
Getting help
============
How do I do X? Why doesn't Y work? Where can I go to get help?
--------------------------------------------------------------
If this FAQ doesn't contain an answer to your question, you might want to
try the `django-users mailing list`_. Feel free to ask any question related
to installing, using, or debugging Django.
If you prefer IRC, the `#django IRC channel`_ on the Freenode IRC network is an
active community of helpful individuals who may be able to solve your problem.
.. _`django-users mailing list`: http://groups.google.com/group/django-users
.. _`#django IRC channel`: irc://irc.freenode.net/django
Why hasn't my message appeared on django-users?
-----------------------------------------------
django-users_ has a lot of subscribers. This is good for the community, as
it means many people are available to contribute answers to questions.
Unfortunately, it also means that django-users_ is an attractive target for
spammers.
In order to combat the spam problem, when you join the django-users_ mailing
list, we manually moderate the first message you send to the list. This means
that spammers get caught, but it also means that your first question to the
list might take a little longer to get answered. We apologize for any
inconvenience that this policy may cause.
.. _django-users: http://groups.google.com/group/django-users
Nobody on django-users answered my question! What should I do?
--------------------------------------------------------------
Try making your question more specific, or provide a better example of your
problem.
As with most open-source mailing lists, the folks on django-users_ are
volunteers. If nobody has answered your question, it may be because nobody
knows the answer, it may be because nobody can understand the question, or it
may be that everybody that can help is busy. One thing you might try is to ask
the question on IRC -- visit the `#django IRC channel`_ on the Freenode IRC
network.
You might notice we have a second mailing list, called django-developers_ --
but please don't e-mail support questions to this mailing list. This list is
for discussion of the development of Django itself. Asking a tech support
question there is considered quite impolite.
.. _django-developers: http://groups.google.com/group/django-developers
I think I've found a bug! What should I do?
-------------------------------------------
Detailed instructions on how to handle a potential bug can be found in our
`Guide to contributing to Django`_.
.. _`Guide to contributing to Django`: ../contributing/#reporting-bugs
I think I've found a security problem! What should I do?
--------------------------------------------------------
If you think you've found a security problem with Django, please send a message
to security@djangoproject.com. This is a private list only open to long-time,
highly trusted Django developers, and its archives are not publicly readable.
Due to the sensitive nature of security issues, we ask that if you think you
have found a security problem, *please* don't send a message to one of the
public mailing lists. Django has a `policy for handling security issues`_;
while a defect is outstanding, we would like to minimize any damage that
could be inflicted through public knowledge of that defect.
.. _`policy for handling security issues`: ../contributing/#reporting-security-issues
Contributing code
=================
How can I get started contributing code to Django?
--------------------------------------------------
Thanks for asking! We've written an entire document devoted to this question.
It's titled `Contributing to Django`_.
.. _`Contributing to Django`: ../contributing/
I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?
--------------------------------------------------------------------------------------------
Don't worry: We're not ignoring you!
It's important to understand there is a difference between "a ticket is being
ignored" and "a ticket has not been attended to yet." Django's ticket system
contains hundreds of open tickets, of various degrees of impact on end-user
functionality, and Django's developers have to review and prioritize.
On top of that: the people who work on Django are all volunteers. As a result,
the amount of time that we have to work on the framework is limited and will
vary from week to week depending on our spare time. If we're busy, we may not
be able to spend as much time on Django as we might want.
Besides, if your feature request stands no chance of inclusion in Django, we
won't ignore it -- we'll just close the ticket. So if your ticket is still
open, it doesn't mean we're ignoring you; it just means we haven't had time to
look at it yet.

103
docs/faq/admin.txt Normal file
View File

@ -0,0 +1,103 @@
.. _faq-admin:
FAQ: The admin
==============
I can't log in. When I enter a valid username and password, it just brings up the login page again, with no error messages.
---------------------------------------------------------------------------------------------------------------------------
The login cookie isn't being set correctly, because the domain of the cookie
sent out by Django doesn't match the domain in your browser. Try these two
things:
* Set the ``SESSION_COOKIE_DOMAIN`` setting in your admin config file
to match your domain. For example, if you're going to
"http://www.example.com/admin/" in your browser, in
"myproject.settings" you should set ``SESSION_COOKIE_DOMAIN = 'www.example.com'``.
* Some browsers (Firefox?) don't like to accept cookies from domains that
don't have dots in them. If you're running the admin site on "localhost"
or another domain that doesn't have a dot in it, try going to
"localhost.localdomain" or "127.0.0.1". And set
``SESSION_COOKIE_DOMAIN`` accordingly.
I can't log in. When I enter a valid username and password, it brings up the login page again, with a "Please enter a correct username and password" error.
-----------------------------------------------------------------------------------------------------------------------------------------------------------
If you're sure your username and password are correct, make sure your user
account has ``is_active`` and ``is_staff`` set to True. The admin site only
allows access to users with those two fields both set to True.
How can I prevent the cache middleware from caching the admin site?
-------------------------------------------------------------------
Set the :setting:``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting to ``True``. See the
:ref:`cache documentation <topics-cache>` for more information.
How do I automatically set a field's value to the user who last edited the object in the admin?
-----------------------------------------------------------------------------------------------
At this point, Django doesn't have an official way to do this. But it's an oft-requested
feature, so we're discussing how it can be implemented. The problem is we don't want to couple
the model layer with the admin layer with the request layer (to get the current user). It's a
tricky problem.
One person hacked up a `solution that doesn't require patching Django`_, but note that it's an
unofficial solution, and there's no guarantee it won't break at some point.
.. _solution that doesn't require patching Django: http://lukeplant.me.uk/blog.php?id=1107301634
How do I limit admin access so that objects can only be edited by the users who created them?
---------------------------------------------------------------------------------------------
See the answer to the previous question.
My admin-site CSS and images showed up fine using the development server, but they're not displaying when using mod_python.
---------------------------------------------------------------------------------------------------------------------------
See :ref:`serving the admin files <howto-deployment-modpython-serving-the-admin-files`
in the "How to use Django with mod_python" documentation.
My "list_filter" contains a ManyToManyField, but the filter doesn't display.
----------------------------------------------------------------------------
Django won't bother displaying the filter for a ``ManyToManyField`` if there
are fewer than two related objects.
For example, if your ``list_filter`` includes ``sites``, and there's only one
site in your database, it won't display a "Site" filter. In that case,
filtering by site would be meaningless.
How can I customize the functionality of the admin interface?
-------------------------------------------------------------
You've got several options. If you want to piggyback on top of an add/change
form that Django automatically generates, you can attach arbitrary JavaScript
modules to the page via the model's ``class Admin`` ``js`` parameter. That
parameter is a list of URLs, as strings, pointing to JavaScript modules that
will be included within the admin form via a ``<script>`` tag.
If you want more flexibility than simply tweaking the auto-generated forms,
feel free to write custom views for the admin. The admin is powered by Django
itself, and you can write custom views that hook into the authentication
system, check permissions and do whatever else they need to do.
If you want to customize the look-and-feel of the admin interface, read the
next question.
The dynamically-generated admin site is ugly! How can I change it?
------------------------------------------------------------------
We like it, but if you don't agree, you can modify the admin site's
presentation by editing the CSS stylesheet and/or associated image files. The
site is built using semantic HTML and plenty of CSS hooks, so any changes you'd
like to make should be possible by editing the stylesheet. We've got a
:ref:`guide to the CSS used in the admin <obsolete-admin-css>` to get you started.
How do I create users without having to edit password hashes?
-------------------------------------------------------------
If you'd like to use the admin site to create users, upgrade to the Django
development version, where this problem was fixed on Aug. 4, 2006.
You can also use the Python API. See :ref:`creating users <topics-auth-creating-users>` for full info.

30
docs/faq/contributing.txt Normal file
View File

@ -0,0 +1,30 @@
.. _faq-contributing:
FAQ: Contributing code
======================
How can I get started contributing code to Django?
--------------------------------------------------
Thanks for asking! We've written an entire document devoted to this question.
It's titled :ref:`Contributing to Django <internals-contributing>`.
I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?
--------------------------------------------------------------------------------------------
Don't worry: We're not ignoring you!
It's important to understand there is a difference between "a ticket is being
ignored" and "a ticket has not been attended to yet." Django's ticket system
contains hundreds of open tickets, of various degrees of impact on end-user
functionality, and Django's developers have to review and prioritize.
On top of that: the people who work on Django are all volunteers. As a result,
the amount of time that we have to work on the framework is limited and will
vary from week to week depending on our spare time. If we're busy, we may not
be able to spend as much time on Django as we might want.
Besides, if your feature request stands no chance of inclusion in Django, we
won't ignore it -- we'll just close the ticket. So if your ticket is still
open, it doesn't mean we're ignoring you; it just means we haven't had time to
look at it yet.

256
docs/faq/general.txt Normal file
View File

@ -0,0 +1,256 @@
.. _faq-general:
FAQ: General
============
Why does this project exist?
----------------------------
Django grew from a very practical need: World Online, a newspaper Web
operation, is responsible for building intensive Web applications on journalism
deadlines. In the fast-paced newsroom, World Online often has only a matter of
hours to take a complicated Web application from concept to public launch.
At the same time, the World Online Web developers have consistently been
perfectionists when it comes to following best practices of Web development.
In fall 2003, the World Online developers (Adrian Holovaty and Simon Willison)
ditched PHP and began using Python to develop its Web sites. As they built
intensive, richly interactive sites such as Lawrence.com, they began to extract
a generic Web development framework that let them build Web applications more
and more quickly. They tweaked this framework constantly, adding improvements
over two years.
In summer 2005, World Online decided to open-source the resulting software,
Django. Django would not be possible without a whole host of open-source
projects -- `Apache`_, `Python`_, and `PostgreSQL`_ to name a few -- and we're
thrilled to be able to give something back to the open-source community.
.. _Apache: http://httpd.apache.org/
.. _Python: http://www.python.org/
.. _PostgreSQL: http://www.postgresql.org/
What does "Django" mean, and how do you pronounce it?
-----------------------------------------------------
Django is named after `Django Reinhardt`_, a gypsy jazz guitarist from the 1930s
to early 1950s. To this day, he's considered one of the best guitarists of all time.
Listen to his music. You'll like it.
Django is pronounced **JANG**-oh. Rhymes with FANG-oh. The "D" is silent.
We've also recorded an `audio clip of the pronunciation`_.
.. _Django Reinhardt: http://en.wikipedia.org/wiki/Django_Reinhardt
.. _audio clip of the pronunciation: http://red-bean.com/~adrian/django_pronunciation.mp3
Is Django stable?
-----------------
Yes. World Online has been using Django for more than three years. Sites built
on Django have weathered traffic spikes of over one million hits an hour and a
number of Slashdottings. Yes, it's quite stable.
Does Django scale?
------------------
Yes. Compared to development time, hardware is cheap, and so Django is
designed to take advantage of as much hardware as you can throw at it.
Django uses a "shared-nothing" architecture, which means you can add hardware
at any level -- database servers, caching servers or Web/application servers.
The framework cleanly separates components such as its database layer and
application layer. And it ships with a simple-yet-powerful
:ref:`cache framework <topics-cache>`.
Who's behind this?
------------------
Django was developed at `World Online`_, the Web department of a newspaper in
Lawrence, Kansas, USA.
`Adrian Holovaty`_
Adrian is a Web developer with a background in journalism. He was lead
developer at World Online for 2.5 years, during which time Django was
developed and implemented on World Online's sites. Now he works for
washingtonpost.com building rich, database-backed information sites, and
continues to oversee Django development. He likes playing guitar (Django
Reinhardt style) and hacking on side projects such as `chicagocrime.org`_.
He lives in Chicago.
On IRC, Adrian goes by ``adrian_h``.
`Jacob Kaplan-Moss`_
Jacob is a whipper-snapper from California who spends equal time coding and
cooking. He's lead developer at World Online and actively hacks on various
cool side projects. He's contributed to the Python-ObjC bindings and was
the first guy to figure out how to write Tivo apps in Python. Lately he's
been messing with Python on the PSP. He lives in Lawrence, Kansas.
On IRC, Jacob goes by ``jacobkm``.
`Simon Willison`_
Simon is a well-respected Web developer from England. He had a one-year
internship at World Online, during which time he and Adrian developed
Django from scratch. The most enthusiastic Brit you'll ever meet, he's
passionate about best practices in Web development and has maintained a
well-read Web-development blog for years at http://simon.incutio.com.
He works for Yahoo UK, where he managed to score the title "Hacker Liason."
He lives in London.
On IRC, Simon goes by ``SimonW``.
`Wilson Miner`_
Wilson's design-fu makes us all look like rock stars. By day, he's an
interactive designer for `Apple`_. Don't ask him what he's working on, or
he'll have to kill you. He lives in San Francisco.
On IRC, Wilson goes by ``wilsonian``.
.. _`World Online`: http://code.djangoproject.com/wiki/WorldOnline
.. _`Adrian Holovaty`: http://www.holovaty.com/
.. _`washingtonpost.com`: http://www.washingtonpost.com/
.. _`chicagocrime.org`: http://www.chicagocrime.org/
.. _`Simon Willison`: http://simon.incutio.com/
.. _`simon.incutio.com`: http://simon.incutio.com/
.. _`Jacob Kaplan-Moss`: http://www.jacobian.org/
.. _`Wilson Miner`: http://www.wilsonminer.com/
.. _`Apple`: http://www.apple.com/
Which sites use Django?
-----------------------
The Django wiki features a consistently growing `list of Django-powered sites`_.
Feel free to add your Django-powered site to the list.
.. _list of Django-powered sites: http://code.djangoproject.com/wiki/DjangoPoweredSites
.. _mtv:
Django appears to be a MVC framework, but you call the Controller the "view", and the View the "template". How come you don't use the standard names?
-----------------------------------------------------------------------------------------------------------------------------------------------------
Well, the standard names are debatable.
In our interpretation of MVC, the "view" describes the data that gets presented
to the user. It's not necessarily *how* the data *looks*, but *which* data is
presented. The view describes *which data you see*, not *how you see it.* It's
a subtle distinction.
So, in our case, a "view" is the Python callback function for a particular URL,
because that callback function describes which data is presented.
Furthermore, it's sensible to separate content from presentation -- which is
where templates come in. In Django, a "view" describes which data is presented,
but a view normally delegates to a template, which describes *how* the data is
presented.
Where does the "controller" fit in, then? In Django's case, it's probably the
framework itself: the machinery that sends a request to the appropriate view,
according to the Django URL configuration.
If you're hungry for acronyms, you might say that Django is a "MTV" framework
-- that is, "model", "template", and "view." That breakdown makes much more
sense.
At the end of the day, of course, it comes down to getting stuff done. And,
regardless of how things are named, Django gets stuff done in a way that's most
logical to us.
<Framework X> does <feature Y> -- why doesn't Django?
-----------------------------------------------------
We're well aware that there are other awesome Web frameworks out there, and
we're not averse to borrowing ideas where appropriate. However, Django was
developed precisely because we were unhappy with the status quo, so please be
aware that "because <Framework X> does it" is not going to be sufficient reason
to add a given feature to Django.
Why did you write all of Django from scratch, instead of using other Python libraries?
--------------------------------------------------------------------------------------
When Django was originally written a couple of years ago, Adrian and Simon
spent quite a bit of time exploring the various Python Web frameworks
available.
In our opinion, none of them were completely up to snuff.
We're picky. You might even call us perfectionists. (With deadlines.)
Over time, we stumbled across open-source libraries that did things we'd
already implemented. It was reassuring to see other people solving similar
problems in similar ways, but it was too late to integrate outside code: We'd
already written, tested and implemented our own framework bits in several
production settings -- and our own code met our needs delightfully.
In most cases, however, we found that existing frameworks/tools inevitably had
some sort of fundamental, fatal flaw that made us squeamish. No tool fit our
philosophies 100%.
Like we said: We're picky.
We've documented our philosophies on the
:ref:`design philosophies page <misc-design-philosophies>`.
Do you have any of those nifty "screencast" things?
---------------------------------------------------
You can bet your bottom they're on the way. But, since we're still hammering
out a few points, we want to make sure they reflect the final state of things
at Django 1.0, not some intermediary step. In other words, we don't want to
spend a lot of energy creating screencasts yet, because Django APIs will shift.
Is Django a content-management-system (CMS)?
--------------------------------------------
No, Django is not a CMS, or any sort of "turnkey product" in and of itself.
It's a Web framework; it's a programming tool that lets you build Web sites.
For example, it doesn't make much sense to compare Django to something like
Drupal_, because Django is something you use to *create* things like Drupal.
Of course, Django's automatic admin site is fantastic and timesaving -- but
the admin site is one module of Django the framework. Furthermore, although
Django has special conveniences for building "CMS-y" apps, that doesn't mean
it's not just as appropriate for building "non-CMS-y" apps (whatever that
means!).
.. _Drupal: http://drupal.org/
When will you release Django 1.0?
---------------------------------
See our `version one roadmap`_ for the detailed timeline. We're aiming for
September 2, 2008.
.. _version one roadmap: http://code.djangoproject.com/wiki/VersionOneRoadmap
How can I download the Django documentation to read it offline?
---------------------------------------------------------------
The Django docs are available in the ``docs`` directory of each Django tarball
release. These docs are in ReST (ReStructured Text) format, and each text file
corresponds to a Web page on the official Django site.
Because the documentation is `stored in revision control`_, you can browse
documentation changes just like you can browse code changes.
Technically, the docs on Django's site are generated from the latest development
versions of those ReST documents, so the docs on the Django site may offer more
information than the docs that come with the latest Django release.
.. _stored in revision control: http://code.djangoproject.com/browser/django/trunk/docs
Where can I find Django developers for hire?
--------------------------------------------
Consult our `developers for hire page`_ for a list of Django developers who
would be happy to help you.
You might also be interested in posting a job to http://djangogigs.com/ .
If you want to find Django-capable people in your local area, try
http://djangopeople.net/ .
.. _developers for hire page: http://code.djangoproject.com/wiki/DevelopersForHire

75
docs/faq/help.txt Normal file
View File

@ -0,0 +1,75 @@
.. _faq-help:
FAQ: Getting Help
=================
How do I do X? Why doesn't Y work? Where can I go to get help?
--------------------------------------------------------------
If this FAQ doesn't contain an answer to your question, you might want to
try the `django-users mailing list`_. Feel free to ask any question related
to installing, using, or debugging Django.
If you prefer IRC, the `#django IRC channel`_ on the Freenode IRC network is an
active community of helpful individuals who may be able to solve your problem.
.. _`django-users mailing list`: http://groups.google.com/group/django-users
.. _`#django IRC channel`: irc://irc.freenode.net/django
Why hasn't my message appeared on django-users?
-----------------------------------------------
django-users_ has a lot of subscribers. This is good for the community, as
it means many people are available to contribute answers to questions.
Unfortunately, it also means that django-users_ is an attractive target for
spammers.
In order to combat the spam problem, when you join the django-users_ mailing
list, we manually moderate the first message you send to the list. This means
that spammers get caught, but it also means that your first question to the
list might take a little longer to get answered. We apologize for any
inconvenience that this policy may cause.
.. _django-users: http://groups.google.com/group/django-users
Nobody on django-users answered my question! What should I do?
--------------------------------------------------------------
Try making your question more specific, or provide a better example of your
problem.
As with most open-source mailing lists, the folks on django-users_ are
volunteers. If nobody has answered your question, it may be because nobody
knows the answer, it may be because nobody can understand the question, or it
may be that everybody that can help is busy. One thing you might try is to ask
the question on IRC -- visit the `#django IRC channel`_ on the Freenode IRC
network.
You might notice we have a second mailing list, called django-developers_ --
but please don't e-mail support questions to this mailing list. This list is
for discussion of the development of Django itself. Asking a tech support
question there is considered quite impolite.
.. _django-developers: http://groups.google.com/group/django-developers
I think I've found a bug! What should I do?
-------------------------------------------
Detailed instructions on how to handle a potential bug can be found in our
:ref:`Guide to contributing to Django <reporting-bugs>`.
I think I've found a security problem! What should I do?
--------------------------------------------------------
If you think you've found a security problem with Django, please send a message
to security@djangoproject.com. This is a private list only open to long-time,
highly trusted Django developers, and its archives are not publicly readable.
Due to the sensitive nature of security issues, we ask that if you think you
have found a security problem, *please* don't send a message to one of the
public mailing lists. Django has a
:ref:`policy for handling security issues <reporting-security-issues>`;
while a defect is outstanding, we would like to minimize any damage that
could be inflicted through public knowledge of that defect.
.. _`policy for handling security issues`: ../contributing/#reporting-security-issues

16
docs/faq/index.txt Normal file
View File

@ -0,0 +1,16 @@
.. _faq-index:
==========
Django FAQ
==========
.. toctree::
:maxdepth: 2
general
install
usage
help
models
admin
contributing

108
docs/faq/install.txt Normal file
View File

@ -0,0 +1,108 @@
.. _faq-install:
FAQ: Installation
=================
How do I get started?
---------------------
#. `Download the code`_.
#. Install Django (read the :ref:`installation guide <intro-install>`).
#. Walk through the :ref:`tutorial <intro-tutorial01>`.
#. Check out the rest of the :ref:`documentation <index>`, and `ask questions`_ if you
run into trouble.
.. _`Download the code`: http://www.djangoproject.com/download/
.. _ask questions: http://www.djangoproject.com/community/
How do I fix the "install a later version of setuptools" error?
---------------------------------------------------------------
Just run the ``ez_setup.py`` script in the Django distribution.
What are Django's prerequisites?
--------------------------------
Django requires Python_ 2.3 or later. No other Python libraries are required
for basic Django usage.
For a development environment -- if you just want to experiment with Django --
you don't need to have a separate Web server installed; Django comes with its
own lightweight development server. For a production environment, we recommend
`Apache 2`_ and mod_python_, although Django follows the WSGI_ spec, which
means it can run on a variety of server platforms.
If you want to use Django with a database, which is probably the case, you'll
also need a database engine. PostgreSQL_ is recommended, because we're
PostgreSQL fans, and MySQL_, `SQLite 3`_, and Oracle_ are also supported.
.. _Python: http://www.python.org/
.. _Apache 2: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _WSGI: http://www.python.org/peps/pep-0333.html
.. _PostgreSQL: http://www.postgresql.org/
.. _MySQL: http://www.mysql.com/
.. _`SQLite 3`: http://www.sqlite.org/
.. _Oracle: http://www.oracle.com/
Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5?
----------------------------------------------------------------------------------------
No. Django itself is guaranteed to work with any version of Python from 2.3
and higher.
If you use a Python version newer than 2.3, you will, of course, be able to
take advantage of newer Python features in your own code, along with the speed
improvements and other optimizations that have been made to the Python language
itself. But the Django framework itself should work equally well on 2.3 as it
does on 2.4 or 2.5.
Do I have to use mod_python?
----------------------------
Although we recommend mod_python for production use, you don't have to use it,
thanks to the fact that Django uses an arrangement called WSGI_. Django can
talk to any WSGI-enabled server. Other non-mod_python deployment setups are
FastCGI, SCGI or AJP. See
:ref:`How to use Django with FastCGI, SCGI or AJP <howto-deployment-fastcgi>`
for full information.
Also, see the `server arrangements wiki page`_ for other deployment strategies.
If you just want to play around and develop things on your local computer, use
the development Web server that comes with Django. Things should Just Work.
.. _WSGI: http://www.python.org/peps/pep-0333.html
.. _server arrangements wiki page: http://code.djangoproject.com/wiki/ServerArrangements
How do I install mod_python on Windows?
---------------------------------------
* For Python 2.4, grab mod_python from `win32 build of mod_python for
Python 2.4`_.
* For Python 2.4, check out this `Django on Windows howto`_.
* For Python 2.3, grab mod_python from http://www.modpython.org/ and read
`Running mod_python on Apache on Windows2000`_.
* Also, try this (not Windows-specific) `guide to getting mod_python
working`_.
.. _`win32 build of mod_python for Python 2.4`: http://www.lehuen.com/nicolas/index.php/2005/02/21/39-win32-build-of-mod_python-314-for-python-24
.. _`Django on Windows howto`: http://thinkhole.org/wp/django-on-windows/
.. _`Running mod_python on Apache on Windows2000`: http://groups-beta.google.com/group/comp.lang.python/msg/139af8c83a5a9d4f
.. _`guide to getting mod_python working`: http://www.dscpl.com.au/articles/modpython-001.html
Will Django run under shared hosting (like TextDrive or Dreamhost)?
-------------------------------------------------------------------
See our `Django-friendly Web hosts`_ page.
.. _`Django-friendly Web hosts`: http://code.djangoproject.com/wiki/DjangoFriendlyWebHosts
Should I use the official version or development version?
---------------------------------------------------------
The Django developers improve Django every day and are pretty good about not
checking in broken code. We use the development code (from the Subversion
repository) directly on our servers, so we consider it stable. With that in
mind, we recommend that you use the latest development code, because it
generally contains more features and fewer bugs than the "official" releases.

94
docs/faq/models.txt Normal file
View File

@ -0,0 +1,94 @@
.. _faq-models:
FAQ: Databases and models
=========================
How can I see the raw SQL queries Django is running?
----------------------------------------------------
Make sure your Django ``DEBUG`` setting is set to ``True``. Then, just do
this::
>>> from django.db import connection
>>> connection.queries
[{'sql': 'SELECT polls_polls.id,polls_polls.question,polls_polls.pub_date FROM polls_polls',
'time': '0.002'}]
``connection.queries`` is only available if ``DEBUG`` is ``True``. It's a list
of dictionaries in order of query execution. Each dictionary has the following::
``sql`` -- The raw SQL statement
``time`` -- How long the statement took to execute, in seconds.
``connection.queries`` includes all SQL statements -- INSERTs, UPDATES,
SELECTs, etc. Each time your app hits the database, the query will be recorded.
Can I use Django with a pre-existing database?
----------------------------------------------
Yes. See :ref:`Integrating with a legacy database <howto-legacy-databases>`.
If I make changes to a model, how do I update the database?
-----------------------------------------------------------
If you don't mind clearing data, your project's ``manage.py`` utility has an
option to reset the SQL for a particular application::
manage.py reset appname
This drops any tables associated with ``appname`` and recreates them.
If you do care about deleting data, you'll have to execute the ``ALTER TABLE``
statements manually in your database. That's the way we've always done it,
because dealing with data is a very sensitive operation that we've wanted to
avoid automating. That said, there's some work being done to add partially
automated database-upgrade functionality.
Do Django models support multiple-column primary keys?
------------------------------------------------------
No. Only single-column primary keys are supported.
But this isn't an issue in practice, because there's nothing stopping you from
adding other constraints (using the ``unique_together`` model option or
creating the constraint directly in your database), and enforcing the
uniqueness at that level. Single-column primary keys are needed for things such
as the admin interface to work; e.g., you need a simple way of being able to
specify an object to edit or delete.
How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type?
------------------------------------------------------------------------------------------------------------------
We try to avoid adding special cases in the Django code to accommodate all the
database-specific options such as table type, etc. If you'd like to use any of
these options, create an :ref:`SQL initial data file <initial-sql>` that
contains ``ALTER TABLE`` statements that do what you want to do. The initial
data files are executed in your database after the ``CREATE TABLE`` statements.
For example, if you're using MySQL and want your tables to use the MyISAM table
type, create an initial data file and put something like this in it::
ALTER TABLE myapp_mytable ENGINE=MyISAM;
As explained in the :ref:`SQL initial data file <initial-sql>` documentation,
this SQL file can contain arbitrary SQL, so you can make any sorts of changes
you need to make.
Why is Django leaking memory?
-----------------------------
Django isn't known to leak memory. If you find your Django processes are
allocating more and more memory, with no sign of releasing it, check to make
sure your ``DEBUG`` setting is set to ``True``. If ``DEBUG`` is ``True``, then
Django saves a copy of every SQL statement it has executed.
(The queries are saved in ``django.db.connection.queries``. See
`How can I see the raw SQL queries Django is running?`_.)
To fix the problem, set ``DEBUG`` to ``False``.
If you need to clear the query list manually at any point in your functions,
just call ``reset_queries()``, like this::
from django import db
db.reset_queries()

65
docs/faq/usage.txt Normal file
View File

@ -0,0 +1,65 @@
.. _faq-usage:
FAQ: Using Django
=================
Why do I get an error about importing DJANGO_SETTINGS_MODULE?
-------------------------------------------------------------
Make sure that:
* The environment variable DJANGO_SETTINGS_MODULE is set to a fully-qualified
Python module (i.e. "mysite.settings").
* Said module is on ``sys.path`` (``import mysite.settings`` should work).
* The module doesn't contain syntax errors (of course).
* If you're using mod_python but *not* using Django's request handler,
you'll need to work around a mod_python bug related to the use of
``SetEnv``; before you import anything from Django you'll need to do
the following::
os.environ.update(req.subprocess_env)
(where ``req`` is the mod_python request object).
I can't stand your template language. Do I have to use it?
----------------------------------------------------------
We happen to think our template engine is the best thing since chunky bacon,
but we recognize that choosing a template language runs close to religion.
There's nothing about Django that requires using the template language, so
if you're attached to ZPT, Cheetah, or whatever, feel free to use those.
Do I have to use your model/database layer?
-------------------------------------------
Nope. Just like the template system, the model/database layer is decoupled from
the rest of the framework.
The one exception is: If you use a different database library, you won't get to
use Django's automatically-generated admin site. That app is coupled to the
Django database layer.
How do I use image and file fields?
-----------------------------------
Using a ``FileField`` or an ``ImageField`` in a model takes a few steps:
#. In your settings file, define ``MEDIA_ROOT`` as the full path to
a directory where you'd like Django to store uploaded files. (For
performance, these files are not stored in the database.) Define
``MEDIA_URL`` as the base public URL of that directory. Make sure that
this directory is writable by the Web server's user account.
#. Add the ``FileField`` or ``ImageField`` to your model, making sure
to define the ``upload_to`` option to tell Django to which subdirectory
of ``MEDIA_ROOT`` it should upload files.
#. All that will be stored in your database is a path to the file
(relative to ``MEDIA_ROOT``). You'll most likely want to use the
convenience ``get_<fieldname>_url`` function provided by Django. For
example, if your ``ImageField`` is called ``mug_shot``, you can get the
absolute URL to your image in a template with
``{{ object.get_mug_shot_url }}``.

View File

@ -1,388 +0,0 @@
==============
Managing files
==============
**New in Django development version**
This document describes Django's file access APIs.
By default, Django stores files locally, using the ``MEDIA_ROOT`` and
``MEDIA_URL`` settings_. The examples below assume that you're using
these defaults.
However, Django provides ways to write custom `file storage systems`_ that
allow you to completely customize where and how Django stores files. The
second half of this document describes how these storage systems work.
.. _file storage systems: `File storage`_
.. _settings: ../settings/
Using files in models
=====================
When you use a `FileField`_ or `ImageField`_, Django provides a set of APIs you can use to deal with that file.
.. _filefield: ../model-api/#filefield
.. _imagefield: ../model-api/#imagefield
Consider the following model, using a ``FileField`` to store a photo::
class Car(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=5, decimal_places=2)
photo = models.ImageField(upload_to='cars')
Any ``Car`` instance will have a ``photo`` attribute that you can use to get at
the details of the attached photo::
>>> car = Car.object.get(name="57 Chevy")
>>> car.photo
<ImageFieldFile: chevy.jpg>
>>> car.photo.name
u'chevy.jpg'
>>> car.photo.path
u'/media/cars/chevy.jpg'
>>> car.photo.url
u'http://media.example.com/cars/chevy.jpg'
This object -- ``car.photo`` in the example -- is a ``File`` object, which means
it has all the methods and attributes described below.
The ``File`` object
===================
Internally, Django uses a ``django.core.files.File`` any time it needs to
represent a file. This object is a thin wrapper around Python's `built-in file
object`_ with some Django-specific additions.
.. _built-in file object: http://docs.python.org/lib/bltin-file-objects.html
Creating ``File`` instances
---------------------------
Most of the time you'll simply use a ``File`` that Django's given you (i.e. a
file attached to a model as above, or perhaps an `uploaded file`_).
.. _uploaded file: ../upload_handling/
If you need to construct a ``File`` yourself, the easiest way is to create one
using a Python built-in ``file`` object::
>>> from django.core.files import File
# Create a Python file object using open()
>>> f = open('/tmp/hello.world', 'w')
>>> myfile = File(f)
Now you can use any of the ``File`` attributes and methods defined below.
``File`` attributes and methods
-------------------------------
Django's ``File`` has the following attributes and methods:
``File.path``
~~~~~~~~~~~~~
The absolute path to the file's location on a local filesystem.
Custom `file storage systems`_ may not store files locally; files stored on
these systems will have a ``path`` of ``None``.
``File.url``
~~~~~~~~~~~~
The URL where the file can be retrieved. This is often useful in templates_; for
example, a bit of a template for displaying a ``Car`` (see above) might look
like::
<img src='{{ car.photo.url }}' alt='{{ car.name }}' />
.. _templates: ../templates/
``File.size``
~~~~~~~~~~~~~
The size of the file in bytes.
``File.open(mode=None)``
~~~~~~~~~~~~~~~~~~~~~~~~
Open or reopen the file (which by definition also does ``File.seek(0)``). The
``mode`` argument allows the same values as Python's standard ``open()``.
When reopening a file, ``mode`` will override whatever mode the file was
originally opened with; ``None`` means to reopen with the original mode.
``File.read(num_bytes=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Read content from the file. The optional ``size`` is the number of bytes to
read; if not specified, the file will be read to the end.
``File.__iter__()``
~~~~~~~~~~~~~~~~~~~
Iterate over the file yielding one line at a time.
``File.chunks(chunk_size=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Iterate over the file yielding "chunks" of a given size. ``chunk_size`` defaults
to 64 KB.
This is especially useful with very large files since it allows them to be
streamed off disk and avoids storing the whole file in memory.
``File.multiple_chunks(chunk_size=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Returns ``True`` if the file is large enough to require multiple chunks to
access all of its content give some ``chunk_size``.
``File.write(content)``
~~~~~~~~~~~~~~~~~~~~~~~
Writes the specified content string to the file. Depending on the storage system
behind the scenes, this content might not be fully committed until ``close()``
is called on the file.
``File.close()``
~~~~~~~~~~~~~~~~
Close the file.
.. TODO: document the rest of the File methods.
Additional ``ImageField`` attributes
------------------------------------
``File.width`` and ``File.height``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These attributes provide the dimensions of the image.
Additional methods on files attached to objects
-----------------------------------------------
Any ``File`` that's associated with an object (as with ``Car.photo``, above)
will also have a couple of extra methods:
``File.save(name, content, save=True)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Saves a new file with the file name and contents provided. This will not replace
the existing file, but will create a new file and update the object to point to
it. If ``save`` is ``True``, the model's ``save()`` method will be called once
the file is saved. That is, these two lines::
>>> car.photo.save('myphoto.jpg', contents, save=False)
>>> car.save()
are the same as this one line::
>>> car.photo.save('myphoto.jpg', contents, save=True)
``File.delete(save=True)``
~~~~~~~~~~~~~~~~~~~~~~~~~~
Remove the file from the model instance and delete the underlying file. The
``save`` argument works as above.
File storage
============
Behind the scenes, Django delegates decisions about how and where to store files
to a file storage system. This is the object that actually understands things
like file systems, opening and reading files, etc.
Django's default file storage is given by the `DEFAULT_FILE_STORAGE setting`_;
if you don't explicitly provide a storage system, this is the one that will be
used.
.. _default_file_storage setting: ../settings/#default-file-storage
The built-in filesystem storage class
-------------------------------------
Django ships with a built-in ``FileSystemStorage`` class (defined in
``django.core.files.storage``) which implements basic local filesystem file
storage. Its initializer takes two arguments:
====================== ===================================================
Argument Description
====================== ===================================================
``location`` Optional. Absolute path to the directory that will
hold the files. If omitted, it will be set to the
value of your ``MEDIA_ROOT`` setting.
``base_url`` Optional. URL that serves the files stored at this
location. If omitted, it will default to the value
of your ``MEDIA_URL`` setting.
====================== ===================================================
For example, the following code will store uploaded files under
``/media/photos`` regardless of what your ``MEDIA_ROOT`` setting is::
from django.db import models
from django.core.files.storage import FileSystemStorage
fs = FileSystemStorage(location='/media/photos')
class Car(models.Model):
...
photo = models.ImageField(storage=fs)
`Custom storage systems`_ work the same way: you can pass them in as the
``storage`` argument to a ``FileField``.
.. _custom storage systems: `writing a custom storage system`_
Storage objects
---------------
Though most of the time you'll want to use a ``File`` object (which delegates to
the proper storage for that file), you can use file storage systems directly.
You can create an instance of some custom file storage class, or -- often more
useful -- you can use the global default storage system::
>>> from django.core.files.storage import default_storage
>>> path = default_storage.save('/path/to/file', 'new content')
>>> path
u'/path/to/file'
>>> default_storage.filesize(path)
11
>>> default_storage.open(path).read()
'new content'
>>> default_storage.delete(path)
>>> default_storage.exists(path)
False
Storage objects define the following methods:
``Storage.exists(name)``
~~~~~~~~~~~~~~~~~~~~~~~~
``True`` if a file exists given some ``name``.
``Storage.path(name)``
~~~~~~~~~~~~~~~~~~~~~~
The local filesystem path where the file can be opened using Python's standard
``open()``. For storage systems that aren't accessible from the local
filesystem, this will raise ``NotImplementedError`` instead.
``Storage.size(name)``
~~~~~~~~~~~~~~~~~~~~~~
Returns the total size, in bytes, of the file referenced by ``name``.
``Storage.url(name)``
~~~~~~~~~~~~~~~~~~~~~
Returns the URL where the contents of the file referenced by ``name`` can be
accessed.
``Storage.open(name, mode='rb')``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Opens the file given by ``name``. Note that although the returned file is
guaranteed to be a ``File`` object, it might actually be some subclass. In the
case of remote file storage this means that reading/writing could be quite slow,
so be warned.
``Storage.save(name, content)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Saves a new file using the storage system, preferably with the name specified.
If there already exists a file with this name ``name``, the storage system may
modify the filename as necessary to get a unique name. The actual name of the
stored file will be returned.
``Storage.delete(name)``
~~~~~~~~~~~~~~~~~~~~~~~~
Deletes the file referenced by ``name``. This method won't raise an exception if
the file doesn't exist.
Writing a custom storage system
===============================
If you need to provide custom file storage -- a common example is storing files
on some remote system -- you can do so by defining a custom storage class.
You'll need to follow these steps:
#. Your custom storage system must be a subclass of
``django.core.files.storage.Storage``::
from django.core.files.storage import Storage
class MyStorage(Storage):
...
#. Django must be able to instantiate your storage system without any arguments.
This means that any settings should be taken from ``django.conf.settings``::
from django.conf import settings
from django.core.files.storage import Storage
class MyStorage(Storage):
def __init__(self, option=None):
if not option:
option = settings.CUSTOM_STORAGE_OPTIONS
...
#. Your storage class must implement the ``_open()`` and ``_save()`` methods,
along with any other methods appropriate to your storage class. See below for
more on these methods.
In addition, if your class provides local file storage, it must override
the ``path()`` method.
Custom storage system methods
-----------------------------
Your custom storage system may override any of the storage methods explained
above in `storage objects`_. However, it's usually better to use the hooks
specifically designed for custom storage objects. These are:
``_open(name, mode='rb')``
~~~~~~~~~~~~~~~~~~~~~~~~~~
**Required**.
Called by ``Storage.open()``, this is the actual mechanism the storage class
uses to open the file. This must return a ``File`` object, though in most cases,
you'll want to return some subclass here that implements logic specific to the
backend storage system.
``_save(name, content)``
~~~~~~~~~~~~~~~~~~~~~~~~
Called by ``Storage.save()``. The ``name`` will already have gone through
``get_valid_name()`` and ``get_available_name()``, and the ``content`` will be a
``File`` object itself. No return value is expected.
``get_valid_name(name)``
------------------------
Returns a filename suitable for use with the underlying storage system. The
``name`` argument passed to this method is the original filename sent to the
server, after having any path information removed. Override this to customize
how non-standard characters are converted to safe filenames.
The code provided on ``Storage`` retains only alpha-numeric characters, periods
and underscores from the original filename, removing everything else.
``get_available_name(name)``
----------------------------
Returns a filename that is available in the storage mechanism, possibly taking
the provided filename into account. The ``name`` argument passed to this method
will have already cleaned to a filename valid for the storage system, according
to the ``get_valid_name()`` method described above.
The code provided on ``Storage`` simply appends underscores to the filename
until it finds one that's available in the destination directory.

View File

@ -1,95 +0,0 @@
============
Form preview
============
Django comes with an optional "form preview" application that helps automate
the following workflow:
"Display an HTML form, force a preview, then do something with the submission."
To force a preview of a form submission, all you have to do is write a short
Python class.
Overview
=========
Given a ``django.forms.Form`` subclass that you define, this application
takes care of the following workflow:
1. Displays the form as HTML on a Web page.
2. Validates the form data when it's submitted via POST.
a. If it's valid, displays a preview page.
b. If it's not valid, redisplays the form with error messages.
3. When the "confirmation" form is submitted from the preview page, calls
a hook that you define -- a ``done()`` method that gets passed the valid
data.
The framework enforces the required preview by passing a shared-secret hash to
the preview page via hidden form fields. If somebody tweaks the form parameters
on the preview page, the form submission will fail the hash-comparison test.
How to use ``FormPreview``
==========================
1. Point Django at the default FormPreview templates. There are two ways to
do this:
* Add ``'django.contrib.formtools'`` to your ``INSTALLED_APPS``
setting. This will work if your ``TEMPLATE_LOADERS`` setting includes
the ``app_directories`` template loader (which is the case by
default). See the `template loader docs`_ for more.
* Otherwise, determine the full filesystem path to the
``django/contrib/formtools/templates`` directory, and add that
directory to your ``TEMPLATE_DIRS`` setting.
2. Create a ``FormPreview`` subclass that overrides the ``done()`` method::
from django.contrib.formtools.preview import FormPreview
from myapp.models import SomeModel
class SomeModelFormPreview(FormPreview):
def done(self, request, cleaned_data):
# Do something with the cleaned_data, then redirect
# to a "success" page.
return HttpResponseRedirect('/form/success')
This method takes an ``HttpRequest`` object and a dictionary of the form
data after it has been validated and cleaned. It should return an
``HttpResponseRedirect`` that is the end result of the form being
submitted.
3. Change your URLconf to point to an instance of your ``FormPreview``
subclass::
from myapp.preview import SomeModelFormPreview
from myapp.models import SomeModel
from django import forms
...and add the following line to the appropriate model in your URLconf::
(r'^post/$', SomeModelFormPreview(SomeModelForm)),
where ``SomeModelForm`` is a Form or ModelForm class for the model.
4. Run the Django server and visit ``/post/`` in your browser.
.. _template loader docs: ../templates_python/#loader-types
``FormPreview`` classes
=======================
A ``FormPreview`` class is a simple Python class that represents the preview
workflow. ``FormPreview`` classes must subclass
``django.contrib.formtools.preview.FormPreview`` and override the ``done()``
method. They can live anywhere in your codebase.
``FormPreview`` templates
=========================
By default, the form is rendered via the template ``formtools/form.html``, and
the preview page is rendered via the template ``formtools.preview.html``.
These values can be overridden for a particular form preview by setting
``preview_template`` and ``form_template`` attributes on the FormPreview
subclass. See ``django/contrib/formtools/templates`` for the default templates.

View File

@ -1,304 +0,0 @@
===========
Form wizard
===========
**New in Django development version.**
Django comes with an optional "form wizard" application that splits forms_
across multiple Web pages. It maintains state in hashed HTML
``<input type="hidden">`` fields, and the data isn't processed server-side
until the final form is submitted.
You might want to use this if you have a lengthy form that would be too
unwieldy for display on a single page. The first page might ask the user for
core information, the second page might ask for less important information,
etc.
The term "wizard," in this context, is `explained on Wikipedia`_.
.. _explained on Wikipedia: http://en.wikipedia.org/wiki/Wizard_%28software%29
.. _forms: ../forms/
How it works
============
Here's the basic workflow for how a user would use a wizard:
1. The user visits the first page of the wizard, fills in the form and
submits it.
2. The server validates the data. If it's invalid, the form is displayed
again, with error messages. If it's valid, the server calculates a
secure hash of the data and presents the user with the next form,
saving the validated data and hash in ``<input type="hidden">`` fields.
3. Step 1 and 2 repeat, for every subsequent form in the wizard.
4. Once the user has submitted all the forms and all the data has been
validated, the wizard processes the data -- saving it to the database,
sending an e-mail, or whatever the application needs to do.
Usage
=====
This application handles as much machinery for you as possible. Generally, you
just have to do these things:
1. Define a number of ``django.forms`` ``Form`` classes -- one per wizard
page.
2. Create a ``FormWizard`` class that specifies what to do once all of your
forms have been submitted and validated. This also lets you override some
of the wizard's behavior.
3. Create some templates that render the forms. You can define a single,
generic template to handle every one of the forms, or you can define a
specific template for each form.
4. Point your URLconf at your ``FormWizard`` class.
Defining ``Form`` classes
=========================
The first step in creating a form wizard is to create the ``Form`` classes.
These should be standard ``django.forms`` ``Form`` classes, covered in the
`forms documentation`_.
These classes can live anywhere in your codebase, but convention is to put them
in a file called ``forms.py`` in your application.
For example, let's write a "contact form" wizard, where the first page's form
collects the sender's e-mail address and subject, and the second page collects
the message itself. Here's what the ``forms.py`` might look like::
from django import forms
class ContactForm1(forms.Form):
subject = forms.CharField(max_length=100)
sender = forms.EmailField()
class ContactForm2(forms.Form):
message = forms.CharField(widget=forms.Textarea)
**Important limitation:** Because the wizard uses HTML hidden fields to store
data between pages, you may not include a ``FileField`` in any form except the
last one.
.. _forms documentation: ../forms/
Creating a ``FormWizard`` class
===============================
The next step is to create a ``FormWizard`` class, which should be a subclass
of ``django.contrib.formtools.wizard.FormWizard``.
As your ``Form`` classes, this ``FormWizard`` class can live anywhere in your
codebase, but convention is to put it in ``forms.py``.
The only requirement on this subclass is that it implement a ``done()`` method,
which specifies what should happen when the data for *every* form is submitted
and validated. This method is passed two arguments:
* ``request`` -- an HttpRequest_ object
* ``form_list`` -- a list of ``django.forms`` ``Form`` classes
In this simplistic example, rather than perform any database operation, the
method simply renders a template of the validated data::
from django.shortcuts import render_to_response
from django.contrib.formtools.wizard import FormWizard
class ContactWizard(FormWizard):
def done(self, request, form_list):
return render_to_response('done.html', {
'form_data': [form.cleaned_data for form in form_list],
})
Note that this method will be called via ``POST``, so it really ought to be a
good Web citizen and redirect after processing the data. Here's another
example::
from django.http import HttpResponseRedirect
from django.contrib.formtools.wizard import FormWizard
class ContactWizard(FormWizard):
def done(self, request, form_list):
do_something_with_the_form_data(form_list)
return HttpResponseRedirect('/page-to-redirect-to-when-done/')
See the section "Advanced ``FormWizard`` methods" below to learn about more
``FormWizard`` hooks.
.. _HttpRequest: request_response/#httprequest-objects
Creating templates for the forms
================================
Next, you'll need to create a template that renders the wizard's forms. By
default, every form uses a template called ``forms/wizard.html``. (You can
change this template name by overriding ``FormWizard.get_template()``, which is
documented below. This hook also allows you to use a different template for
each form.)
This template expects the following context:
* ``step_field`` -- The name of the hidden field containing the step.
* ``step0`` -- The current step (zero-based).
* ``step`` -- The current step (one-based).
* ``step_count`` -- The total number of steps.
* ``form`` -- The ``Form`` instance for the current step (either empty or
with errors).
* ``previous_fields`` -- A string representing every previous data field,
plus hashes for completed forms, all in the form of hidden fields. Note
that you'll need to run this through the ``safe`` template filter, to
prevent auto-escaping, because it's raw HTML.
It will also be passed any objects in ``extra_context``, which is a dictionary
you can specify that contains extra values to add to the context. You can
specify it in two ways:
* Set the ``extra_context`` attribute on your ``FormWizard`` subclass to a
dictionary.
* Pass ``extra_context`` as extra parameters in the URLconf.
Here's a full example template::
{% extends "base.html" %}
{% block content %}
<p>Step {{ step }} of {{ step_count }}</p>
<form action="." method="post">
<table>
{{ form }}
</table>
<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" />
{{ previous_fields|safe }}
<input type="submit">
</form>
{% endblock %}
Note that ``previous_fields``, ``step_field`` and ``step0`` are all required
for the wizard to work properly.
Hooking the wizard into a URLconf
=================================
Finally, give your new ``FormWizard`` object a URL in ``urls.py``. The wizard
takes a list of your form objects as arguments::
from django.conf.urls.defaults import *
from mysite.testapp.forms import ContactForm1, ContactForm2, ContactWizard
urlpatterns = patterns('',
(r'^contact/$', ContactWizard([ContactForm1, ContactForm2])),
)
Advanced ``FormWizard`` methods
===============================
Aside from the ``done()`` method, ``FormWizard`` offers a few advanced method
hooks that let you customize how your wizard works.
Some of these methods take an argument ``step``, which is a zero-based counter
representing the current step of the wizard. (E.g., the first form is ``0`` and
the second form is ``1``.)
``prefix_for_step``
~~~~~~~~~~~~~~~~~~~
Given the step, returns a ``Form`` prefix to use. By default, this simply uses
the step itself. For more, see the `form prefix documentation`_.
Default implementation::
def prefix_for_step(self, step):
return str(step)
.. _form prefix documentation: ../forms/#prefixes-for-forms
``render_hash_failure``
~~~~~~~~~~~~~~~~~~~~~~~
Renders a template if the hash check fails. It's rare that you'd need to
override this.
Default implementation::
def render_hash_failure(self, request, step):
return self.render(self.get_form(step), request, step,
context={'wizard_error': 'We apologize, but your form has expired. Please continue filling out the form from this page.'})
``security_hash``
~~~~~~~~~~~~~~~~~
Calculates the security hash for the given request object and ``Form`` instance.
By default, this uses an MD5 hash of the form data and your
`SECRET_KEY setting`_. It's rare that somebody would need to override this.
Example::
def security_hash(self, request, form):
return my_hash_function(request, form)
.. _SECRET_KEY setting: ../settings/#secret-key
``parse_params``
~~~~~~~~~~~~~~~~
A hook for saving state from the request object and ``args`` / ``kwargs`` that
were captured from the URL by your URLconf.
By default, this does nothing.
Example::
def parse_params(self, request, *args, **kwargs):
self.my_state = args[0]
``get_template``
~~~~~~~~~~~~~~~~
Returns the name of the template that should be used for the given step.
By default, this returns ``'forms/wizard.html'``, regardless of step.
Example::
def get_template(self, step):
return 'myapp/wizard_%s.html' % step
If ``get_template`` returns a list of strings, then the wizard will use the
template system's ``select_template()`` function, `explained in the template docs`_.
This means the system will use the first template that exists on the filesystem.
For example::
def get_template(self, step):
return ['myapp/wizard_%s.html' % step, 'myapp/wizard.html']
.. _explained in the template docs: ../templates_python/#the-python-api
``render_template``
~~~~~~~~~~~~~~~~~~~
Renders the template for the given step, returning an ``HttpResponse`` object.
Override this method if you want to add a custom context, return a different
MIME type, etc. If you only need to override the template name, use
``get_template()`` instead.
The template will be rendered with the context documented in the
"Creating templates for the forms" section above.
``process_step``
~~~~~~~~~~~~~~~~
Hook for modifying the wizard's internal state, given a fully validated ``Form``
object. The Form is guaranteed to have clean, valid data.
This method should *not* modify any of that data. Rather, it might want to set
``self.extra_context`` or dynamically alter ``self.form_list``, based on
previously submitted forms.
Note that this method is called every time a page is rendered for *all*
submitted steps.
The function signature::
def process_step(self, request, form, step):
# ...

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

80
docs/glossary.txt Normal file
View File

@ -0,0 +1,80 @@
.. _glossary:
========
Glossary
========
.. glossary::
field
An attribute on a :term:`model`; a given field usually maps directly to
a single database column.
See :ref:`topics-db-models`.
generic view
A higher-order :term:`view` function that abstracts common idioms and patterns
found in view development and abstracts them.
See :ref:`ref-generic-views`.
model
Models store your application's data.
See :ref:`topics-db-models`.
MTV
See :ref:`mtv`.
MVC
`Model-view-controller`__; a software pattern. Django :ref:`follows MVC
to some extent <mtv>`.
__ http://en.wikipedia.org/wiki/Model-view-controller
project
A Python package -- i.e. a directory of code -- that contains all the
settings for an instance of Django. This would include database
configuration, Django-specific options and application-specific
settings.
property
Also known as "managed attributes", and a feature of Python since
version 2.2. From `the property documentation`__:
Properties are a neat way to implement attributes whose usage
resembles attribute access, but whose implementation uses method
calls. [...] You
could only do this by overriding ``__getattr__`` and
``__setattr__``; but overriding ``__setattr__`` slows down all
attribute assignments considerably, and overriding ``__getattr__``
is always a bit tricky to get right. Properties let you do this
painlessly, without having to override ``__getattr__`` or
``__setattr__``.
__ http://www.python.org/download/releases/2.2/descrintro/#property
queryset
An object representing some set of rows to be fetched from the database.
See :ref:`topics-db-queries`.
slug
A short label for something, containing only letters, numbers,
underscores or hyphens. They're generally used in URLs. For
example, in a typical blog entry URL:
.. parsed-literal::
http://www.djangoproject.com/weblog/2008/apr/12/**spring**/
the last bit (``spring``) is the slug.
template
A chunk of text that separates the presentation of a document from its
data.
See :ref:`topics-templates`.
view
A function responsible for rending a page.

View File

@ -1,10 +1,13 @@
.. _howto-apache-auth:
========================================================= =========================================================
Authenticating against Django's user database from Apache Authenticating against Django's user database from Apache
========================================================= =========================================================
Since keeping multiple authentication databases in sync is a common problem when Since keeping multiple authentication databases in sync is a common problem when
dealing with Apache, you can configuring Apache to authenticate against Django's dealing with Apache, you can configuring Apache to authenticate against Django's
`authentication system`_ directly. For example, you could: :ref:`authentication system <topics-auth>` directly. For example, you
could:
* Serve static/media files directly from Apache only to authenticated users. * Serve static/media files directly from Apache only to authenticated users.
@ -13,12 +16,17 @@ dealing with Apache, you can configuring Apache to authenticate against Django's
* Allow certain users to connect to a WebDAV share created with mod_dav_. * Allow certain users to connect to a WebDAV share created with mod_dav_.
.. _Subversion: http://subversion.tigris.org/
.. _mod_dav: http://httpd.apache.org/docs/2.0/mod/mod_dav.html
Configuring Apache Configuring Apache
================== ==================
To check against Django's authorization database from a Apache configuration To check against Django's authorization database from a Apache configuration
file, you'll need to use mod_python's ``PythonAuthenHandler`` directive along file, you'll need to use mod_python's ``PythonAuthenHandler`` directive along
with the standard ``Auth*`` and ``Require`` directives:: with the standard ``Auth*`` and ``Require`` directives:
.. code-block:: apache
<Location /example/> <Location /example/>
AuthType Basic AuthType Basic
@ -44,6 +52,8 @@ with the standard ``Auth*`` and ``Require`` directives::
on which other authentication modules you have loaded, you might need one on which other authentication modules you have loaded, you might need one
or more of the following directives:: or more of the following directives::
.. code-block:: apache
AuthBasicAuthoritative Off AuthBasicAuthoritative Off
AuthDefaultAuthoritative Off AuthDefaultAuthoritative Off
AuthzLDAPAuthoritative Off AuthzLDAPAuthoritative Off
@ -94,8 +104,9 @@ location to users marked as staff members. You can use a set of
Defaults to ``off``. Defaults to ``off``.
``DjangoPermissionName`` The name of a permission to require for ``DjangoPermissionName`` The name of a permission to require for
access. See `custom permissions`_ for access. See :ref:`custom permissions
more information. <custom-permissions>` for more
information.
By default no specific permission will be By default no specific permission will be
required. required.
@ -109,8 +120,3 @@ are equivalent::
SetEnv DJANGO_SETTINGS_MODULE mysite.settings SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption DJANGO_SETTINGS_MODULE mysite.settings PythonOption DJANGO_SETTINGS_MODULE mysite.settings
.. _authentication system: ../authentication/
.. _Subversion: http://subversion.tigris.org/
.. _mod_dav: http://httpd.apache.org/docs/2.0/mod/mod_dav.html
.. _custom permissions: ../authentication/#custom-permissions

View File

@ -0,0 +1,78 @@
.. _howto-custom-file-storage:
Writing a custom storage system
===============================
If you need to provide custom file storage -- a common example is storing files
on some remote system -- you can do so by defining a custom storage class.
You'll need to follow these steps:
#. Your custom storage system must be a subclass of
``django.core.files.storage.Storage``::
from django.core.files.storage import Storage
class MyStorage(Storage):
...
#. Django must be able to instantiate your storage system without any arguments.
This means that any settings should be taken from ``django.conf.settings``::
from django.conf import settings
from django.core.files.storage import Storage
class MyStorage(Storage):
def __init__(self, option=None):
if not option:
option = settings.CUSTOM_STORAGE_OPTIONS
...
#. Your storage class must implement the ``_open()`` and ``_save()`` methods,
along with any other methods appropriate to your storage class. See below for
more on these methods.
In addition, if your class provides local file storage, it must override
the ``path()`` method.
Your custom storage system may override any of the storage methods explained in
:ref:`ref-files-storage`. However, it's usually better to use the hooks
specifically designed for custom storage objects. These are:
``_open(name, mode='rb')``
~~~~~~~~~~~~~~~~~~~~~~~~~~
**Required**.
Called by ``Storage.open()``, this is the actual mechanism the storage class
uses to open the file. This must return a ``File`` object, though in most cases,
you'll want to return some subclass here that implements logic specific to the
backend storage system.
``_save(name, content)``
~~~~~~~~~~~~~~~~~~~~~~~~
Called by ``Storage.save()``. The ``name`` will already have gone through
``get_valid_name()`` and ``get_available_name()``, and the ``content`` will be a
``File`` object itself. No return value is expected.
``get_valid_name(name)``
------------------------
Returns a filename suitable for use with the underlying storage system. The
``name`` argument passed to this method is the original filename sent to the
server, after having any path information removed. Override this to customize
how non-standard characters are converted to safe filenames.
The code provided on ``Storage`` retains only alpha-numeric characters, periods
and underscores from the original filename, removing everything else.
``get_available_name(name)``
----------------------------
Returns a filename that is available in the storage mechanism, possibly taking
the provided filename into account. The ``name`` argument passed to this method
will have already cleaned to a filename valid for the storage system, according
to the ``get_valid_name()`` method described above.
The code provided on ``Storage`` simply appends underscores to the filename
until it finds one that's available in the destination directory.

View File

@ -0,0 +1,33 @@
.. _howto-custom-management-commands:
Writing custom django-admin commands
====================================
**New in Django development version**
Applications can register their own actions with ``manage.py``. For example,
you might want to add a ``manage.py`` action for a Django app that you're
distributing.
To do this, just add a ``management/commands`` directory to your application.
Each Python module in that directory will be auto-discovered and registered as
a command that can be executed as an action when you run ``manage.py``::
blog/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
explode.py
views.py
In this example, the ``explode`` command will be made available to any project
that includes the ``blog`` application in ``settings.INSTALLED_APPS``.
The ``explode.py`` module has only one requirement -- it must define a class
called ``Command`` that extends ``django.core.management.base.BaseCommand``.
For more details on how to define your own commands, look at the code for the
existing ``django-admin.py`` commands, in ``/django/core/management/commands``.

View File

@ -1,23 +1,28 @@
=================== .. _howto-custom-model-fields:
Custom model fields
=================== ===========================
Writing custom model fields
===========================
**New in Django development version** **New in Django development version**
Introduction Introduction
============ ============
The `model reference`_ documentation explains how to use Django's standard The :ref:`model reference <topics-db-models>` documentation explains how to use
field classes -- ``CharField``, ``DateField``, etc. For many purposes, those Django's standard field classes -- :class:`~django.db.models.CharField`,
classes are all you'll need. Sometimes, though, the Django version won't meet :class:`~django.db.models.DateField`, etc. For many purposes, those classes are
your precise requirements, or you'll want to use a field that is entirely all you'll need. Sometimes, though, the Django version won't meet your precise
different from those shipped with Django. requirements, or you'll want to use a field that is entirely different from
those shipped with Django.
Django's built-in field types don't cover every possible database column type -- Django's built-in field types don't cover every possible database column type --
only the common types, such as ``VARCHAR`` and ``INTEGER``. For more obscure only the common types, such as ``VARCHAR`` and ``INTEGER``. For more obscure
column types, such as geographic polygons or even user-created types such as column types, such as geographic polygons or even user-created types such as
`PostgreSQL custom types`_, you can define your own Django ``Field`` subclasses. `PostgreSQL custom types`_, you can define your own Django ``Field`` subclasses.
.. _PostgreSQL custom types: http://www.postgresql.org/docs/8.2/interactive/sql-createtype.html
Alternatively, you may have a complex Python object that can somehow be Alternatively, you may have a complex Python object that can somehow be
serialized to fit into a standard database column type. This is another case serialized to fit into a standard database column type. This is another case
where a ``Field`` subclass will help you use your object with your models. where a ``Field`` subclass will help you use your object with your models.
@ -43,6 +48,8 @@ Our class looks something like this::
# ... (other possibly useful methods omitted) ... # ... (other possibly useful methods omitted) ...
.. _Bridge: http://en.wikipedia.org/wiki/Contract_bridge
This is just an ordinary Python class, with nothing Django-specific about it. This is just an ordinary Python class, with nothing Django-specific about it.
We'd like to be able to do things like this in our models (we assume the We'd like to be able to do things like this in our models (we assume the
``hand`` attribute on the model is an instance of ``Hand``):: ``hand`` attribute on the model is an instance of ``Hand``)::
@ -68,10 +75,6 @@ model support for existing classes where you cannot change the source code.
strings, or floats, for example. This case is similar to our ``Hand`` strings, or floats, for example. This case is similar to our ``Hand``
example and we'll note any differences as we go along. example and we'll note any differences as we go along.
.. _model reference: ../model_api/
.. _PostgreSQL custom types: http://www.postgresql.org/docs/8.2/interactive/sql-createtype.html
.. _Bridge: http://en.wikipedia.org/wiki/Contract_bridge
Background theory Background theory
================= =================
@ -103,15 +106,13 @@ What does a field class do?
--------------------------- ---------------------------
All of Django's fields (and when we say *fields* in this document, we always All of Django's fields (and when we say *fields* in this document, we always
mean model fields and not `form fields`_) are subclasses of mean model fields and not :ref:`form fields <ref-forms-fields>`) are subclasses
``django.db.models.Field``. Most of the information that Django records about a of :class:`django.db.models.Field`. Most of the information that Django records
field is common to all fields -- name, help text, validator lists, uniqueness about a field is common to all fields -- name, help text, validator lists,
and so forth. Storing all that information is handled by ``Field``. We'll get uniqueness and so forth. Storing all that information is handled by ``Field``.
into the precise details of what ``Field`` can do later on; for now, suffice it We'll get into the precise details of what ``Field`` can do later on; for now,
to say that everything descends from ``Field`` and then customizes key pieces suffice it to say that everything descends from ``Field`` and then customizes
of the class behavior. key pieces of the class behavior.
.. _form fields: ../forms/#fields
It's important to realize that a Django field class is not what is stored in It's important to realize that a Django field class is not what is stored in
your model attributes. The model attributes contain normal Python objects. The your model attributes. The model attributes contain normal Python objects. The
@ -120,7 +121,7 @@ when the model class is created (the precise details of how this is done are
unimportant here). This is because the field classes aren't necessary when unimportant here). This is because the field classes aren't necessary when
you're just creating and modifying attributes. Instead, they provide the you're just creating and modifying attributes. Instead, they provide the
machinery for converting between the attribute value and what is stored in the machinery for converting between the attribute value and what is stored in the
database or sent to the serializer. database or sent to the :ref:`serializer <topics-serialization>`.
Keep this in mind when creating your own custom fields. The Django ``Field`` Keep this in mind when creating your own custom fields. The Django ``Field``
subclass you write provides the machinery for converting between your Python subclass you write provides the machinery for converting between your Python
@ -139,22 +140,25 @@ classes when you want a custom field:
how to convert your first class back and forth between its permanent how to convert your first class back and forth between its permanent
storage form and the Python form. storage form and the Python form.
Writing a ``Field`` subclass Writing a field subclass
============================= ========================
When planning your ``Field`` subclass, first give some thought to which When planning your :class:`~django.db.models.Field` subclass, first give some
existing ``Field`` class your new field is most similar to. Can you subclass an thought to which existing :class:`~django.db.models.Field` class your new field
existing Django field and save yourself some work? If not, you should subclass is most similar to. Can you subclass an existing Django field and save yourself
the ``Field`` class, from which everything is descended. some work? If not, you should subclass the :class:`~django.db.models.Field`
class, from which everything is descended.
Initializing your new field is a matter of separating out any arguments that Initializing your new field is a matter of separating out any arguments that are
are specific to your case from the common arguments and passing the latter to specific to your case from the common arguments and passing the latter to the
the ``__init__()`` method of ``Field`` (or your parent class). :meth:`~django.db.models.Field.__init__` method of
:class:`~django.db.models.Field` (or your parent class).
In our example, we'll call our field ``HandField``. (It's a good idea to call In our example, we'll call our field ``HandField``. (It's a good idea to call
your ``Field`` subclass ``(Something)Field``, so it's easily identifiable as a your :class:`~django.db.models.Field` subclass ``<Something>Field``, so it's
``Field`` subclass.) It doesn't behave like any existing field, so we'll easily identifiable as a :class:`~django.db.models.Field` subclass.) It doesn't
subclass directly from ``Field``:: behave like any existing field, so we'll subclass directly from
:class:`~django.db.models.Field`::
from django.db import models from django.db import models
@ -169,10 +173,13 @@ card values plus their suits; 104 characters in total.
.. note:: .. note::
Many of Django's model fields accept options that they don't do anything Many of Django's model fields accept options that they don't do anything
with. For example, you can pass both ``editable`` and ``auto_now`` to a with. For example, you can pass both
``DateField`` and it will simply ignore the ``editable`` parameter :attr:`~django.db.models.Field.editable` and
(``auto_now`` being set implies ``editable=False``). No error is raised in :attr:`~django.db.models.Field.auto_now` to a
this case. :class:`django.db.models.DateField` and it will simply ignore the
:attr:`~django.db.models.Field.editable` parameter
(:attr:`~django.db.models.Field.auto_now` being set implies
``editable=False``). No error is raised in this case.
This behavior simplifies the field classes, because they don't need to This behavior simplifies the field classes, because they don't need to
check for options that aren't necessary. They just pass all the options to check for options that aren't necessary. They just pass all the options to
@ -180,41 +187,42 @@ card values plus their suits; 104 characters in total.
you want your fields to be more strict about the options they select, or you want your fields to be more strict about the options they select, or
to use the simpler, more permissive behavior of the current fields. to use the simpler, more permissive behavior of the current fields.
The ``Field.__init__()`` method takes the following parameters, in this The :meth:`~django.db.models.Field.__init__` method takes the following
order: parameters:
* ``verbose_name`` * :attr:`~django.db.models.Field.verbose_name`
* ``name`` * :attr:`~django.db.models.Field.name`
* ``primary_key`` * :attr:`~django.db.models.Field.primary_key`
* ``max_length`` * :attr:`~django.db.models.Field.max_length`
* ``unique`` * :attr:`~django.db.models.Field.unique`
* ``blank`` * :attr:`~django.db.models.Field.blank`
* ``null`` * :attr:`~django.db.models.Field.null`
* ``db_index`` * :attr:`~django.db.models.Field.db_index`
* ``core`` * :attr:`~django.db.models.Field.core`
* ``rel``: Used for related fields (like ``ForeignKey``). For advanced use * :attr:`~django.db.models.Field.rel`: Used for related fields (like
only. :attr:`~django.db.models.Field.ForeignKey`). For advanced use only.
* ``default`` * :attr:`~django.db.models.Field.default`
* ``editable`` * :attr:`~django.db.models.Field.editable`
* ``serialize``: If ``False``, the field will not be serialized when the * :attr:`~django.db.models.Field.serialize`: If
model is passed to Django's serializers_. Defaults to ``True``. :attr:`~django.db.models.Field.False`, the field will not be serialized
* ``prepopulate_from`` when the model is passed to Django's :ref:`serializers
* ``unique_for_date`` <topics-serialization>`. Defaults to
* ``unique_for_month`` :attr:`~django.db.models.Field.True`.
* ``unique_for_year`` * :attr:`~django.db.models.Field.prepopulate_from`
* ``validator_list`` * :attr:`~django.db.models.Field.unique_for_date`
* ``choices`` * :attr:`~django.db.models.Field.unique_for_month`
* ``help_text`` * :attr:`~django.db.models.Field.unique_for_year`
* ``db_column`` * :attr:`~django.db.models.Field.validator_list`
* ``db_tablespace``: Currently only used with the Oracle backend and only * :attr:`~django.db.models.Field.choices`
for index creation. You can usually ignore this option. * :attr:`~django.db.models.Field.help_text`
* :attr:`~django.db.models.Field.db_column`
* :attr:`~django.db.models.Field.db_tablespace`: Currently only used with
the Oracle backend and only for index creation. You can usually ignore
this option.
All of the options without an explanation in the above list have the same All of the options without an explanation in the above list have the same
meaning they do for normal Django fields. See the `model documentation`_ for meaning they do for normal Django fields. See the :ref:`field documentation
examples and details. <ref-models-fields>` for examples and details.
.. _serializers: ../serialization/
.. _model documentation: ../model-api/
The ``SubfieldBase`` metaclass The ``SubfieldBase`` metaclass
------------------------------ ------------------------------
@ -226,13 +234,16 @@ possible. If you're only working with custom database column types and your
model fields appear in Python as standard Python types direct from the model fields appear in Python as standard Python types direct from the
database backend, you don't need to worry about this section. database backend, you don't need to worry about this section.
If you're handling custom Python types, such as our ``Hand`` class, we need If you're handling custom Python types, such as our ``Hand`` class, we need to
to make sure that when Django initializes an instance of our model and assigns make sure that when Django initializes an instance of our model and assigns a
a database value to our custom field attribute, we convert that value into the database value to our custom field attribute, we convert that value into the
appropriate Python object. The details of how this happens internally are a appropriate Python object. The details of how this happens internally are a
little complex, but the code you need to write in your ``Field`` class is little complex, but the code you need to write in your ``Field`` class is
simple: make sure your field subclass uses ``django.db.models.SubfieldBase`` as simple: make sure your field subclass uses a special metaclass:
its metaclass::
.. class:: django.db.models.SubfieldBase
For example::
class HandField(models.Field): class HandField(models.Field):
__metaclass__ = models.SubfieldBase __metaclass__ = models.SubfieldBase
@ -240,27 +251,27 @@ its metaclass::
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
# ... # ...
This ensures that the ``to_python()`` method, documented below_, will always be This ensures that the :meth:`to_python` method, documented below, will always be
called when the attribute is initialized. called when the attribute is initialized.
.. _below: #to-python-self-value
Useful methods Useful methods
-------------- --------------
Once you've created your ``Field`` subclass and set up up the Once you've created your :class:`~django.db.models.Field` subclass and set up up
``__metaclass__``, you might consider overriding a few standard methods, the ``__metaclass__``, you might consider overriding a few standard methods,
depending on your field's behavior. The list of methods below is in depending on your field's behavior. The list of methods below is in
approximately decreasing order of importance, so start from the top. approximately decreasing order of importance, so start from the top.
``db_type(self)`` Custom database types
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
Returns the database column data type for the ``Field``, taking into account .. method:: db_type(self)
the current ``DATABASE_ENGINE`` setting.
Returns the database column data type for the :class:`~django.db.models.Field`,
taking into account the current :setting:`DATABASE_ENGINE` setting.
Say you've created a PostgreSQL custom type called ``mytype``. You can use this Say you've created a PostgreSQL custom type called ``mytype``. You can use this
field with Django by subclassing ``Field`` and implementing the ``db_type()`` field with Django by subclassing ``Field`` and implementing the :meth:`db_type`
method, like so:: method, like so::
from django.db import models from django.db import models
@ -281,7 +292,7 @@ If you aim to build a database-agnostic application, you should account for
differences in database column types. For example, the date/time column type differences in database column types. For example, the date/time column type
in PostgreSQL is called ``timestamp``, while the same column in MySQL is called in PostgreSQL is called ``timestamp``, while the same column in MySQL is called
``datetime``. The simplest way to handle this in a ``db_type()`` method is to ``datetime``. The simplest way to handle this in a ``db_type()`` method is to
import the Django settings module and check the ``DATABASE_ENGINE`` setting. import the Django settings module and check the :setting:`DATABASE_ENGINE` setting.
For example:: For example::
class MyDateField(models.Field): class MyDateField(models.Field):
@ -292,11 +303,11 @@ For example::
else: else:
return 'timestamp' return 'timestamp'
The ``db_type()`` method is only called by Django when the framework constructs The :meth:`db_type` method is only called by Django when the framework
the ``CREATE TABLE`` statements for your application -- that is, when you first constructs the ``CREATE TABLE`` statements for your application -- that is, when
create your tables. It's not called at any other time, so it can afford to you first create your tables. It's not called at any other time, so it can
execute slightly complex code, such as the ``DATABASE_ENGINE`` check in the afford to execute slightly complex code, such as the :setting:`DATABASE_ENGINE`
above example. check in the above example.
Some database column types accept parameters, such as ``CHAR(25)``, where the Some database column types accept parameters, such as ``CHAR(25)``, where the
parameter ``25`` represents the maximum column length. In cases like these, parameter ``25`` represents the maximum column length. In cases like these,
@ -316,7 +327,7 @@ sense to have a ``CharMaxlength25Field``, shown here::
The better way of doing this would be to make the parameter specifiable at run The better way of doing this would be to make the parameter specifiable at run
time -- i.e., when the class is instantiated. To do that, just implement time -- i.e., when the class is instantiated. To do that, just implement
``__init__()``, like so:: :meth:`django.db.models.Field.__init__`, like so::
# This is a much more flexible example. # This is a much more flexible example.
class BetterCharField(models.Field): class BetterCharField(models.Field):
@ -333,13 +344,15 @@ time -- i.e., when the class is instantiated. To do that, just implement
my_field = BetterCharField(25) my_field = BetterCharField(25)
Finally, if your column requires truly complex SQL setup, return ``None`` from Finally, if your column requires truly complex SQL setup, return ``None`` from
``db_type()``. This will cause Django's SQL creation code to skip over this :meth:`db_type`. This will cause Django's SQL creation code to skip over this
field. You are then responsible for creating the column in the right table in field. You are then responsible for creating the column in the right table in
some other way, of course, but this gives you a way to tell Django to get out some other way, of course, but this gives you a way to tell Django to get out of
of the way. the way.
``to_python(self, value)`` Converting database values to Python objects
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: to_python(self, value)
Converts a value as returned by your database (or a serializer) to a Python Converts a value as returned by your database (or a serializer) to a Python
object. object.
@ -348,10 +361,10 @@ The default implementation simply returns ``value``, for the common case in
which the database backend already returns data in the correct format (as a which the database backend already returns data in the correct format (as a
Python string, for example). Python string, for example).
If your custom ``Field`` class deals with data structures that are more complex If your custom :class:`~django.db.models.Field` class deals with data structures
than strings, dates, integers or floats, then you'll need to override this that are more complex than strings, dates, integers or floats, then you'll need
method. As a general rule, the method should deal gracefully with any of the to override this method. As a general rule, the method should deal gracefully
following arguments: with any of the following arguments:
* An instance of the correct type (e.g., ``Hand`` in our ongoing example). * An instance of the correct type (e.g., ``Hand`` in our ongoing example).
@ -361,7 +374,7 @@ following arguments:
In our ``HandField`` class, we're storing the data as a VARCHAR field in the In our ``HandField`` class, we're storing the data as a VARCHAR field in the
database, so we need to be able to process strings and ``Hand`` instances in database, so we need to be able to process strings and ``Hand`` instances in
``to_python()``:: :meth:`to_python`::
import re import re
@ -381,18 +394,20 @@ database, so we need to be able to process strings and ``Hand`` instances in
Notice that we always return a ``Hand`` instance from this method. That's the Notice that we always return a ``Hand`` instance from this method. That's the
Python object type we want to store in the model's attribute. Python object type we want to store in the model's attribute.
**Remember:** If your custom field needs the ``to_python()`` method to be **Remember:** If your custom field needs the :meth:`to_python` method to be
called when it is created, you should be using `The SubfieldBase metaclass`_ called when it is created, you should be using `The SubfieldBase metaclass`_
mentioned earlier. Otherwise ``to_python()`` won't be called automatically. mentioned earlier. Otherwise :meth:`to_python` won't be called automatically.
``get_db_prep_value(self, value)`` Converting Python objects to database values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is the reverse of ``to_python()`` when working with the database backends .. method:: get_db_prep_value(self, value)
This is the reverse of :meth:`to_python` when working with the database backends
(as opposed to serialization). The ``value`` parameter is the current value of (as opposed to serialization). The ``value`` parameter is the current value of
the model's attribute (a field has no reference to its containing model, so it the model's attribute (a field has no reference to its containing model, so it
cannot retrieve the value itself), and the method should return data in a cannot retrieve the value itself), and the method should return data in a format
format that can be used as a parameter in a query for the database backend. that can be used as a parameter in a query for the database backend.
For example:: For example::
@ -403,8 +418,7 @@ For example::
return ''.join([''.join(l) for l in (value.north, return ''.join([''.join(l) for l in (value.north,
value.east, value.south, value.west)]) value.east, value.south, value.west)])
``get_db_prep_save(self, value)`` .. method:: get_db_prep_save(self, value)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Same as the above, but called when the Field value must be *saved* to the Same as the above, but called when the Field value must be *saved* to the
database. As the default implementation just calls ``get_db_prep_value``, you database. As the default implementation just calls ``get_db_prep_value``, you
@ -412,28 +426,33 @@ shouldn't need to implement this method unless your custom field need a special
conversion when being saved that is not the same as the used for normal query conversion when being saved that is not the same as the used for normal query
parameters (which is implemented by ``get_db_prep_value``). parameters (which is implemented by ``get_db_prep_value``).
Preprocessing values before saving
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``pre_save(self, model_instance, add)`` .. method:: pre_save(self, model_instance, add)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method is called just prior to ``get_db_prep_save()`` and should return This method is called just prior to :meth:`get_db_prep_save` and should return
the value of the appropriate attribute from ``model_instance`` for this field. the value of the appropriate attribute from ``model_instance`` for this field.
The attribute name is in ``self.attname`` (this is set up by ``Field``). If The attribute name is in ``self.attname`` (this is set up by
the model is being saved to the database for the first time, the ``add`` :class:`~django.db.models.Field`). If the model is being saved to the database
parameter will be ``True``, otherwise it will be ``False``. for the first time, the ``add`` parameter will be ``True``, otherwise it will be
``False``.
You only need to override this method if you want to preprocess the value You only need to override this method if you want to preprocess the value
somehow, just before saving. For example, Django's ``DateTimeField`` uses this somehow, just before saving. For example, Django's
method to set the attribute correctly in the case of ``auto_now`` or `:class:`~django.db.models.DateTimeField` uses this method to set the attribute
``auto_now_add``. correctly in the case of :attr:`~django.db.models.Field.auto_now` or
:attr:`~django.db.models.Field.auto_now_add`.
If you do override this method, you must return the value of the attribute at If you do override this method, you must return the value of the attribute at
the end. You should also update the model's attribute if you make any changes the end. You should also update the model's attribute if you make any changes
to the value so that code holding references to the model will always see the to the value so that code holding references to the model will always see the
correct value. correct value.
``get_db_prep_lookup(self, lookup_type, value)`` Preparing values for use in database lookups
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. method:: get_db_prep_lookup(self, lookup_type, value)
Prepares the ``value`` for passing to the database when used in a lookup (a Prepares the ``value`` for passing to the database when used in a lookup (a
``WHERE`` constraint in SQL). The ``lookup_type`` will be one of the valid ``WHERE`` constraint in SQL). The ``lookup_type`` will be one of the valid
@ -447,7 +466,7 @@ should raise either a ``ValueError`` if the ``value`` is of the wrong sort (a
list when you were expecting an object, for example) or a ``TypeError`` if list when you were expecting an object, for example) or a ``TypeError`` if
your field does not support that type of lookup. For many fields, you can get your field does not support that type of lookup. For many fields, you can get
by with handling the lookup types that need special handling for your field by with handling the lookup types that need special handling for your field
and pass the rest of the ``get_db_prep_lookup()`` method of the parent class. and pass the rest of the :meth:`get_db_prep_lookup` method of the parent class.
If you needed to implement ``get_db_prep_save()``, you will usually need to If you needed to implement ``get_db_prep_save()``, you will usually need to
implement ``get_db_prep_lookup()``. If you don't, ``get_db_prep_value`` will be implement ``get_db_prep_lookup()``. If you don't, ``get_db_prep_value`` will be
@ -478,22 +497,23 @@ accepted lookup types to ``exact`` and ``in``::
else: else:
raise TypeError('Lookup type %r not supported.' % lookup_type) raise TypeError('Lookup type %r not supported.' % lookup_type)
Specifying the form field for a model field
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``formfield(self, form_class=forms.CharField, **kwargs)`` .. method:: formfield(self, form_class=forms.CharField, **kwargs)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Returns the default form field to use when this field is displayed Returns the default form field to use when this field is displayed in a model.
in a model. This method is called by the :class:`~django.forms.ModelForm` helper.
All of the ``kwargs`` dictionary is passed directly to the form field's All of the ``kwargs`` dictionary is passed directly to the form field's
``__init__()`` method. Normally, all you need to do is set up a good default :meth:`~django.forms.Field__init__` method. Normally, all you need to do is
for the ``form_class`` argument and then delegate further handling to the set up a good default for the ``form_class`` argument and then delegate further
parent class. This might require you to write a custom form field (and even a handling to the parent class. This might require you to write a custom form
form widget). See the `forms documentation`_ for information about this, and field (and even a form widget). See the :ref:`forms documentation
take a look at the code in ``django.contrib.localflavor`` for some examples of <topics-forms-index>` for information about this, and take a look at the code in
custom widgets. :mod:`django.contrib.localflavor` for some examples of custom widgets.
Continuing our ongoing example, we can write the ``formfield()`` method as:: Continuing our ongoing example, we can write the :meth:`formfield` method as::
class HandField(models.Field): class HandField(models.Field):
# ... # ...
@ -512,15 +532,17 @@ fields.
.. _helper functions: ../forms/#generating-forms-for-models .. _helper functions: ../forms/#generating-forms-for-models
.. _forms documentation: ../forms/ .. _forms documentation: ../forms/
``get_internal_type(self)`` Emulating built-in field types
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Returns a string giving the name of the ``Field`` subclass we are emulating at .. method:: get_internal_type(self)
the database level. This is used to determine the type of database column for
simple cases.
If you have created a ``db_type()`` method, you don't need to worry about Returns a string giving the name of the :class:`~django.db.models.Field`
``get_internal_type()`` -- it won't be used much. Sometimes, though, your subclass we are emulating at the database level. This is used to determine the
type of database column for simple cases.
If you have created a :meth:`db_type` method, you don't need to worry about
:meth:`get_internal_type` -- it won't be used much. Sometimes, though, your
database storage is similar in type to some other field, so you can use that database storage is similar in type to some other field, so you can use that
other field's logic to create the right column. other field's logic to create the right column.
@ -535,35 +557,35 @@ For example::
No matter which database backend we are using, this will mean that ``syncdb`` No matter which database backend we are using, this will mean that ``syncdb``
and other SQL commands create the right column type for storing a string. and other SQL commands create the right column type for storing a string.
If ``get_internal_type()`` returns a string that is not known to Django for If :meth:`get_internal_type` returns a string that is not known to Django for
the database backend you are using -- that is, it doesn't appear in the database backend you are using -- that is, it doesn't appear in
``django.db.backends.<db_name>.creation.DATA_TYPES`` -- the string will still ``django.db.backends.<db_name>.creation.DATA_TYPES`` -- the string will still be
be used by the serializer, but the default ``db_type()`` method will return used by the serializer, but the default :meth:`db_type` method will return
``None``. See the documentation of ``db_type()`` above_ for reasons why this ``None``. See the documentation of :meth:`db_type` for reasons why this might be
might be useful. Putting a descriptive string in as the type of the field for useful. Putting a descriptive string in as the type of the field for the
the serializer is a useful idea if you're ever going to be using the serializer is a useful idea if you're ever going to be using the serializer
serializer output in some other place, outside of Django. output in some other place, outside of Django.
.. _above: #db-type-self Converting field data for serialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``flatten_data(self, follow, obj=None)`` .. method:: flatten_data(self, follow, obj=None)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. admonition:: Subject to change .. admonition:: Subject to change
Although implementing this method is necessary to allow field Although implementing this method is necessary to allow field
serialization, the API might change in the future. serialization, the API might change in the future.
Returns a dictionary, mapping the field's attribute name to a Returns a dictionary, mapping the field's attribute name to a flattened string
flattened string version of the data. This method has some internal version of the data. This method has some internal uses that aren't of interest
uses that aren't of interest to use here (mostly having to do with to use here (mostly having to do with forms). For our purposes, it's sufficient
forms). For our purposes, it's sufficient to return a one item to return a one item dictionary that maps the attribute name to a string.
dictionary that maps the attribute name to a string.
This method is used by the serializers to convert the field into a string for This method is used by the serializers to convert the field into a string for
output. You can ignore the input parameters for serialization purposes, output. You can ignore the input parameters for serialization purposes, although
although calling ``Field._get_val_from_obj(obj)`` is the best way to get the calling :meth:`Field._get_val_from_obj(obj)
value to serialize. <django.db.models.Field._get_val_from_obj>` is the best way to get the value to
serialize.
For example, since our ``HandField`` uses strings for its data storage anyway, For example, since our ``HandField`` uses strings for its data storage anyway,
we can reuse some existing conversion code:: we can reuse some existing conversion code::
@ -584,17 +606,19 @@ serialization formats. Here are a couple of tips to make things go more
smoothly: smoothly:
1. Look at the existing Django fields (in 1. Look at the existing Django fields (in
``django/db/models/fields/__init__.py``) for inspiration. Try to find a :file:`django/db/models/fields/__init__.py`) for inspiration. Try to find
field that's similar to what you want and extend it a little bit, a field that's similar to what you want and extend it a little bit,
instead of creating an entirely new field from scratch. instead of creating an entirely new field from scratch.
2. Put a ``__str__()`` or ``__unicode__()`` method on the class you're 2. Put a :meth:`__str__` or :meth:`__unicode__` method on the class you're
wrapping up as a field. There are a lot of places where the default wrapping up as a field. There are a lot of places where the default
behavior of the field code is to call ``force_unicode()`` on the value. behavior of the field code is to call
(In our examples in this document, ``value`` would be a ``Hand`` :func:`~django.utils.encoding.force_unicode` on the value. (In our
instance, not a ``HandField``). So if your ``__unicode__()`` method examples in this document, ``value`` would be a ``Hand`` instance, not a
automatically converts to the string form of your Python object, you can ``HandField``). So if your :meth:`__unicode__` method automatically
save yourself a lot of work. converts to the string form of your Python object, you can save yourself
a lot of work.
Writing a ``FileField`` subclass Writing a ``FileField`` subclass
================================= =================================
@ -606,17 +630,15 @@ retrieval, can remain unchanged, leaving subclasses to deal with the challenge
of supporting a particular type of file. of supporting a particular type of file.
Django provides a ``File`` class, which is used as a proxy to the file's Django provides a ``File`` class, which is used as a proxy to the file's
contents and operations. This can be subclassed to customzie hwo the file is contents and operations. This can be subclassed to customize how the file is
accessed, and what methods are available. It lives at accessed, and what methods are available. It lives at
``django.db.models.fields.files``, and its default behavior is explained in the ``django.db.models.fields.files``, and its default behavior is explained in the
`file documentation`_. :ref:`file documentation <ref-files-file>`.
Once a subclass of ``File`` is created, the new ``FileField`` subclass must be Once a subclass of ``File`` is created, the new ``FileField`` subclass must be
told to use it. To do so, simply assign the new ``File`` subclass to the special told to use it. To do so, simply assign the new ``File`` subclass to the special
``attr_class`` attribute of the ``FileField`` subclass. ``attr_class`` attribute of the ``FileField`` subclass.
.. _file documentation: ../files/
A few suggestions A few suggestions
------------------ ------------------

View File

@ -1,634 +1,61 @@
==================================================== .. _howto-custom-template-tags:
The Django template language: For Python programmers
====================================================
This document explains the Django template system from a technical ================================
perspective -- how it works and how to extend it. If you're just looking for Custom template tags and filters
reference on the language syntax, see ================================
`The Django template language: For template authors`_.
If you're looking to use the Django template system as part of another Introduction
application -- i.e., without the rest of the framework -- make sure to read ============
the `configuration`_ section later in this document.
.. _`The Django template language: For template authors`: ../templates/ Django's template system comes a wide variety of :ref:`built-in tags and filters
<ref-templates-builtins>` designed to address the presentation logic needs of
your application. Nevertheless, you may find yourself needing functionality that
is not covered by the core set of template primitives. You can extend the
template engine by defining custom tags and filters using Python, and then make
them available to your templates using the ``{% load %}`` tag.
Basics Code layout
====== -----------
A **template** is a text document, or a normal Python string, that is marked-up Custom template tags and filters must live inside a Django app. If they relate
using the Django template language. A template can contain **block tags** or to an existing app it makes sense to bundle them there; otherwise, you should
**variables**. create a new app to hold them.
A **block tag** is a symbol within a template that does something. The app should contain a ``templatetags`` directory, at the same level as
``models.py``, ``views.py``, etc. If this doesn't already exist, create it -
don't forget the ``__init__.py`` file to ensure the directory is treated as a
Python package.
This definition is deliberately vague. For example, a block tag can output Your custom tags and filters will live in a module inside the ``templatetags``
content, serve as a control structure (an "if" statement or "for" loop), grab directory. The name of the module file is the name you'll use to load the tags
content from a database or enable access to other template tags. later, so be careful to pick a name that won't clash with custom tags and
filters in another app.
Block tags are surrounded by ``"{%"`` and ``"%}"``. For example, if your custom tags/filters are in a file called
``poll_extras.py``, your app layout might look like this::
Example template with block tags::
{% if is_logged_in %}Thanks for logging in!{% else %}Please log in.{% endif %}
A **variable** is a symbol within a template that outputs a value.
Variable tags are surrounded by ``"{{"`` and ``"}}"``.
Example template with variables::
My first name is {{ first_name }}. My last name is {{ last_name }}.
A **context** is a "variable name" -> "variable value" mapping that is passed
to a template.
A template **renders** a context by replacing the variable "holes" with values
from the context and executing all block tags.
Using the template system
=========================
Using the template system in Python is a two-step process:
* First, you compile the raw template code into a ``Template`` object.
* Then, you call the ``render()`` method of the ``Template`` object with a
given context.
Compiling a string
------------------
The easiest way to create a ``Template`` object is by instantiating it
directly. The class lives at ``django.template.Template``. The constructor
takes one argument -- the raw template code::
>>> from django.template import Template
>>> t = Template("My name is {{ my_name }}.")
>>> print t
<django.template.Template instance>
.. admonition:: Behind the scenes
The system only parses your raw template code once -- when you create the
``Template`` object. From then on, it's stored internally as a "node"
structure for performance.
Even the parsing itself is quite fast. Most of the parsing happens via a
single call to a single, short, regular expression.
Rendering a context
-------------------
Once you have a compiled ``Template`` object, you can render a context -- or
multiple contexts -- with it. The ``Context`` class lives at
``django.template.Context``, and the constructor takes one (optional)
argument: a dictionary mapping variable names to variable values. Call the
``Template`` object's ``render()`` method with the context to "fill" the
template::
>>> from django.template import Context, Template
>>> t = Template("My name is {{ my_name }}.")
>>> c = Context({"my_name": "Adrian"})
>>> t.render(c)
"My name is Adrian."
>>> c = Context({"my_name": "Dolores"})
>>> t.render(c)
"My name is Dolores."
Variable names must consist of any letter (A-Z), any digit (0-9), an underscore
or a dot.
Dots have a special meaning in template rendering. A dot in a variable name
signifies **lookup**. Specifically, when the template system encounters a dot
in a variable name, it tries the following lookups, in this order:
* Dictionary lookup. Example: ``foo["bar"]``
* Attribute lookup. Example: ``foo.bar``
* Method call. Example: ``foo.bar()``
* List-index lookup. Example: ``foo[bar]``
The template system uses the first lookup type that works. It's short-circuit
logic.
Here are a few examples::
>>> from django.template import Context, Template
>>> t = Template("My name is {{ person.first_name }}.")
>>> d = {"person": {"first_name": "Joe", "last_name": "Johnson"}}
>>> t.render(Context(d))
"My name is Joe."
>>> class PersonClass: pass
>>> p = PersonClass()
>>> p.first_name = "Ron"
>>> p.last_name = "Nasty"
>>> t.render(Context({"person": p}))
"My name is Ron."
>>> class PersonClass2:
... def first_name(self):
... return "Samantha"
>>> p = PersonClass2()
>>> t.render(Context({"person": p}))
"My name is Samantha."
>>> t = Template("The first stooge in the list is {{ stooges.0 }}.")
>>> c = Context({"stooges": ["Larry", "Curly", "Moe"]})
>>> t.render(c)
"The first stooge in the list is Larry."
Method lookups are slightly more complex than the other lookup types. Here are
some things to keep in mind:
* If, during the method lookup, a method raises an exception, the exception
will be propagated, unless the exception has an attribute
``silent_variable_failure`` whose value is ``True``. If the exception
*does* have a ``silent_variable_failure`` attribute, the variable will
render as an empty string. Example::
>>> t = Template("My name is {{ person.first_name }}.")
>>> class PersonClass3:
... def first_name(self):
... raise AssertionError, "foo"
>>> p = PersonClass3()
>>> t.render(Context({"person": p}))
Traceback (most recent call last):
...
AssertionError: foo
>>> class SilentAssertionError(Exception):
... silent_variable_failure = True
>>> class PersonClass4:
... def first_name(self):
... raise SilentAssertionError
>>> p = PersonClass4()
>>> t.render(Context({"person": p}))
"My name is ."
Note that ``django.core.exceptions.ObjectDoesNotExist``, which is the
base class for all Django database API ``DoesNotExist`` exceptions, has
``silent_variable_failure = True``. So if you're using Django templates
with Django model objects, any ``DoesNotExist`` exception will fail
silently.
* A method call will only work if the method has no required arguments.
Otherwise, the system will move to the next lookup type (list-index
lookup).
* Obviously, some methods have side effects, and it'd be either foolish or
a security hole to allow the template system to access them.
A good example is the ``delete()`` method on each Django model object.
The template system shouldn't be allowed to do something like this::
I will now delete this valuable data. {{ data.delete }}
To prevent this, set a function attribute ``alters_data`` on the method.
The template system won't execute a method if the method has
``alters_data=True`` set. The dynamically-generated ``delete()`` and
``save()`` methods on Django model objects get ``alters_data=True``
automatically. Example::
def sensitive_function(self):
self.database_record.delete()
sensitive_function.alters_data = True
How invalid variables are handled
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Generally, if a variable doesn't exist, the template system inserts the
value of the ``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''``
(the empty string) by default.
Filters that are applied to an invalid variable will only be applied if
``TEMPLATE_STRING_IF_INVALID`` is set to ``''`` (the empty string). If
``TEMPLATE_STRING_IF_INVALID`` is set to any other value, variable
filters will be ignored.
This behavior is slightly different for the ``if``, ``for`` and ``regroup``
template tags. If an invalid variable is provided to one of these template
tags, the variable will be interpreted as ``None``. Filters are always
applied to invalid variables within these template tags.
If ``TEMPLATE_STRING_IF_INVALID`` contains a ``'%s'``, the format marker will
be replaced with the name of the invalid variable.
.. admonition:: For debug purposes only!
While ``TEMPLATE_STRING_IF_INVALID`` can be a useful debugging tool,
it is a bad idea to turn it on as a 'development default'.
Many templates, including those in the Admin site, rely upon the
silence of the template system when a non-existent variable is
encountered. If you assign a value other than ``''`` to
``TEMPLATE_STRING_IF_INVALID``, you will experience rendering
problems with these templates and sites.
Generally, ``TEMPLATE_STRING_IF_INVALID`` should only be enabled
in order to debug a specific template problem, then cleared
once debugging is complete.
Playing with Context objects
----------------------------
Most of the time, you'll instantiate ``Context`` objects by passing in a
fully-populated dictionary to ``Context()``. But you can add and delete items
from a ``Context`` object once it's been instantiated, too, using standard
dictionary syntax::
>>> c = Context({"foo": "bar"})
>>> c['foo']
'bar'
>>> del c['foo']
>>> c['foo']
''
>>> c['newvariable'] = 'hello'
>>> c['newvariable']
'hello'
A ``Context`` object is a stack. That is, you can ``push()`` and ``pop()`` it.
If you ``pop()`` too much, it'll raise
``django.template.ContextPopException``::
>>> c = Context()
>>> c['foo'] = 'first level'
>>> c.push()
>>> c['foo'] = 'second level'
>>> c['foo']
'second level'
>>> c.pop()
>>> c['foo']
'first level'
>>> c['foo'] = 'overwritten'
>>> c['foo']
'overwritten'
>>> c.pop()
Traceback (most recent call last):
...
django.template.ContextPopException
Using a ``Context`` as a stack comes in handy in some custom template tags, as
you'll see below.
Subclassing Context: RequestContext
-----------------------------------
Django comes with a special ``Context`` class,
``django.template.RequestContext``, that acts slightly differently than
the normal ``django.template.Context``. The first difference is that it takes
an `HttpRequest object`_ as its first argument. For example::
c = RequestContext(request, {
'foo': 'bar',
}
The second difference is that it automatically populates the context with a few
variables, according to your `TEMPLATE_CONTEXT_PROCESSORS setting`_.
The ``TEMPLATE_CONTEXT_PROCESSORS`` setting is a tuple of callables -- called
**context processors** -- that take a request object as their argument and
return a dictionary of items to be merged into the context. By default,
``TEMPLATE_CONTEXT_PROCESSORS`` is set to::
("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media")
Each processor is applied in order. That means, if one processor adds a
variable to the context and a second processor adds a variable with the same
name, the second will override the first. The default processors are explained
below.
Also, you can give ``RequestContext`` a list of additional processors, using the
optional, third positional argument, ``processors``. In this example, the
``RequestContext`` instance gets a ``ip_address`` variable::
def ip_address_processor(request):
return {'ip_address': request.META['REMOTE_ADDR']}
def some_view(request):
# ...
c = RequestContext(request, {
'foo': 'bar',
}, [ip_address_processor])
return t.render(c)
.. note::
If you're using Django's ``render_to_response()`` shortcut to populate a
template with the contents of a dictionary, your template will be passed a
``Context`` instance by default (not a ``RequestContext``). To use a
``RequestContext`` in your template rendering, pass an optional third
argument to ``render_to_response()``: a ``RequestContext``
instance. Your code might look like this::
def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
Here's what each of the default processors does:
.. _HttpRequest object: ../request_response/#httprequest-objects
.. _TEMPLATE_CONTEXT_PROCESSORS setting: ../settings/#template-context-processors
django.core.context_processors.auth
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
``RequestContext`` will contain these three variables:
* ``user`` -- An ``auth.User`` instance representing the currently
logged-in user (or an ``AnonymousUser`` instance, if the client isn't
logged in). See the `user authentication docs`_.
* ``messages`` -- A list of messages (as strings) for the currently
logged-in user. Behind the scenes, this calls
``request.user.get_and_delete_messages()`` for every request. That method
collects the user's messages and deletes them from the database.
Note that messages are set with ``user.message_set.create``. See the
`message docs`_ for more.
* ``perms`` -- An instance of
``django.core.context_processors.PermWrapper``, representing the
permissions that the currently logged-in user has. See the `permissions
docs`_.
.. _user authentication docs: ../authentication/#users
.. _message docs: ../authentication/#messages
.. _permissions docs: ../authentication/#permissions
django.core.context_processors.debug
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
``RequestContext`` will contain these two variables -- but only if your
``DEBUG`` setting is set to ``True`` and the request's IP address
(``request.META['REMOTE_ADDR']``) is in the ``INTERNAL_IPS`` setting:
* ``debug`` -- ``True``. You can use this in templates to test whether
you're in ``DEBUG`` mode.
* ``sql_queries`` -- A list of ``{'sql': ..., 'time': ...}`` dictionaries,
representing every SQL query that has happened so far during the request
and how long it took. The list is in order by query.
django.core.context_processors.i18n
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
``RequestContext`` will contain these two variables:
* ``LANGUAGES`` -- The value of the `LANGUAGES setting`_.
* ``LANGUAGE_CODE`` -- ``request.LANGUAGE_CODE``, if it exists. Otherwise,
the value of the `LANGUAGE_CODE setting`_.
See the `internationalization docs`_ for more.
.. _LANGUAGES setting: ../settings/#languages
.. _LANGUAGE_CODE setting: ../settings/#language-code
.. _internationalization docs: ../i18n/
django.core.context_processors.media
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version**
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
``RequestContext`` will contain a variable ``MEDIA_URL``, providing the
value of the `MEDIA_URL setting`_.
.. _MEDIA_URL setting: ../settings/#media-url
django.core.context_processors.request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
``RequestContext`` will contain a variable ``request``, which is the current
`HttpRequest object`_. Note that this processor is not enabled by default;
you'll have to activate it.
Writing your own context processors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A context processor has a very simple interface: It's just a Python function
that takes one argument, an ``HttpRequest`` object, and returns a dictionary
that gets added to the template context. Each context processor *must* return
a dictionary.
Custom context processors can live anywhere in your code base. All Django cares
about is that your custom context processors are pointed-to by your
``TEMPLATE_CONTEXT_PROCESSORS`` setting.
Loading templates
-----------------
Generally, you'll store templates in files on your filesystem rather than using
the low-level ``Template`` API yourself. Save templates in a directory
specified as a **template directory**.
Django searches for template directories in a number of places, depending on
your template-loader settings (see "Loader types" below), but the most basic
way of specifying template directories is by using the ``TEMPLATE_DIRS``
setting.
The TEMPLATE_DIRS setting
~~~~~~~~~~~~~~~~~~~~~~~~~
Tell Django what your template directories are by using the ``TEMPLATE_DIRS``
setting in your settings file. This should be set to a list or tuple of strings
that contain full paths to your template directory(ies). Example::
TEMPLATE_DIRS = (
"/home/html/templates/lawrence.com",
"/home/html/templates/default",
)
Your templates can go anywhere you want, as long as the directories and
templates are readable by the Web server. They can have any extension you want,
such as ``.html`` or ``.txt``, or they can have no extension at all.
Note that these paths should use Unix-style forward slashes, even on Windows.
The Python API
~~~~~~~~~~~~~~
Django has two ways to load templates from files:
``django.template.loader.get_template(template_name)``
``get_template`` returns the compiled template (a ``Template`` object) for
the template with the given name. If the template doesn't exist, it raises
``django.template.TemplateDoesNotExist``.
``django.template.loader.select_template(template_name_list)``
``select_template`` is just like ``get_template``, except it takes a list
of template names. Of the list, it returns the first template that exists.
For example, if you call ``get_template('story_detail.html')`` and have the
above ``TEMPLATE_DIRS`` setting, here are the files Django will look for, in
order:
* ``/home/html/templates/lawrence.com/story_detail.html``
* ``/home/html/templates/default/story_detail.html``
If you call ``select_template(['story_253_detail.html', 'story_detail.html'])``,
here's what Django will look for:
* ``/home/html/templates/lawrence.com/story_253_detail.html``
* ``/home/html/templates/default/story_253_detail.html``
* ``/home/html/templates/lawrence.com/story_detail.html``
* ``/home/html/templates/default/story_detail.html``
When Django finds a template that exists, it stops looking.
.. admonition:: Tip
You can use ``select_template()`` for super-flexible "templatability." For
example, if you've written a news story and want some stories to have
custom templates, use something like
``select_template(['story_%s_detail.html' % story.id, 'story_detail.html'])``.
That'll allow you to use a custom template for an individual story, with a
fallback template for stories that don't have custom templates.
Using subdirectories
~~~~~~~~~~~~~~~~~~~~
It's possible -- and preferable -- to organize templates in subdirectories of
the template directory. The convention is to make a subdirectory for each
Django app, with subdirectories within those subdirectories as needed.
Do this for your own sanity. Storing all templates in the root level of a
single directory gets messy.
To load a template that's within a subdirectory, just use a slash, like so::
get_template('news/story_detail.html')
Using the same ``TEMPLATE_DIRS`` setting from above, this example
``get_template()`` call will attempt to load the following templates:
* ``/home/html/templates/lawrence.com/news/story_detail.html``
* ``/home/html/templates/default/news/story_detail.html``
Loader types
~~~~~~~~~~~~
By default, Django uses a filesystem-based template loader, but Django comes
with a few other template loaders, which know how to load templates from other
sources.
These other loaders are disabled by default, but you can activate them by
editing your ``TEMPLATE_LOADERS`` setting. ``TEMPLATE_LOADERS`` should be a
tuple of strings, where each string represents a template loader. Here are the
template loaders that come with Django:
``django.template.loaders.filesystem.load_template_source``
Loads templates from the filesystem, according to ``TEMPLATE_DIRS``.
``django.template.loaders.app_directories.load_template_source``
Loads templates from Django apps on the filesystem. For each app in
``INSTALLED_APPS``, the loader looks for a ``templates`` subdirectory. If
the directory exists, Django looks for templates in there.
This means you can store templates with your individual apps. This also
makes it easy to distribute Django apps with default templates.
For example, for this setting::
INSTALLED_APPS = ('myproject.polls', 'myproject.music')
...then ``get_template('foo.html')`` will look for templates in these
directories, in this order:
* ``/path/to/myproject/polls/templates/foo.html``
* ``/path/to/myproject/music/templates/foo.html``
Note that the loader performs an optimization when it is first imported:
It caches a list of which ``INSTALLED_APPS`` packages have a ``templates``
subdirectory.
``django.template.loaders.eggs.load_template_source``
Just like ``app_directories`` above, but it loads templates from Python
eggs rather than from the filesystem.
Django uses the template loaders in order according to the ``TEMPLATE_LOADERS``
setting. It uses each loader until a loader finds a match.
The ``render_to_string()`` shortcut
===================================
To cut down on the repetitive nature of loading and rendering
templates, Django provides a shortcut function which largely
automates the process: ``render_to_string()`` in
``django.template.loader``, which loads a template, renders it and
returns the resulting string::
from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', { 'foo': 'bar' })
The ``render_to_string`` shortcut takes one required argument --
``template_name``, which should be the name of the template to load
and render -- and two optional arguments::
dictionary
A dictionary to be used as variables and values for the
template's context. This can also be passed as the second
positional argument.
context_instance
An instance of ``Context`` or a subclass (e.g., an instance of
``RequestContext``) to use as the template's context. This can
also be passed as the third positional argument.
See also the `render_to_response()`_ shortcut, which calls
``render_to_string`` and feeds the result into an ``HttpResponse``
suitable for returning directly from a view.
.. _render_to_response(): ../shortcuts/#render-to-response
Extending the template system
=============================
Although the Django template language comes with several default tags and
filters, you might want to write your own. It's easy to do.
First, create a ``templatetags`` package in the appropriate Django app's
package. It should be on the same level as ``models.py``, ``views.py``, etc. For
example::
polls/ polls/
models.py models.py
templatetags/ templatetags/
__init__.py
poll_extras.py
views.py views.py
Add two files to the ``templatetags`` package: an ``__init__.py`` file and a And in your template you would use the following:
file that will contain your custom tag/filter definitions. The name of the
latter file is the name you'll use to load the tags later. For example, if your .. code-block:: html+django
custom tags/filters are in a file called ``poll_extras.py``, you'd do the
following in a template::
{% load poll_extras %} {% load poll_extras %}
The ``{% load %}`` tag looks at your ``INSTALLED_APPS`` setting and only allows The app that contains the custom tags must be in :setting:`INSTALLED_APPS` in
the loading of template libraries within installed Django apps. This is a order for the ``{% load %}`` tag to work. This is a security feature: It allows
security feature: It allows you to host Python code for many template libraries you to host Python code for many template libraries on a single host machine
on a single computer without enabling access to all of them for every Django without enabling access to all of them for every Django installation.
installation.
If you write a template library that isn't tied to any particular models/views,
it's perfectly OK to have a Django app package that only contains a
``templatetags`` package.
There's no limit on how many modules you put in the ``templatetags`` package. There's no limit on how many modules you put in the ``templatetags`` package.
Just keep in mind that a ``{% load %}`` statement will load tags/filters for Just keep in mind that a ``{% load %}`` statement will load tags/filters for
the given Python module name, not the name of the app. the given Python module name, not the name of the app.
Once you've created that Python module, you'll just have to write a bit of
Python code, depending on whether you're writing filters or tags.
To be a valid tag library, the module must contain a module-level variable To be a valid tag library, the module must contain a module-level variable
named ``register`` that is a ``template.Library`` instance, in which all the named ``register`` that is a ``template.Library`` instance, in which all the
tags and filters are registered. So, near the top of your module, put the tags and filters are registered. So, near the top of your module, put the
@ -666,7 +93,9 @@ Here's an example filter definition::
"Removes all values of arg from the given string" "Removes all values of arg from the given string"
return value.replace(arg, '') return value.replace(arg, '')
And here's an example of how that filter would be used:: And here's an example of how that filter would be used:
.. code-block:: html+django
{{ somevariable|cut:"0" }} {{ somevariable|cut:"0" }}
@ -818,7 +247,8 @@ Template filter code falls into one of two situations:
escaping so that your HTML markup isn't escaped further, so you'll need escaping so that your HTML markup isn't escaped further, so you'll need
to handle the input yourself. to handle the input yourself.
To mark the output as a safe string, use ``django.utils.safestring.mark_safe()``. To mark the output as a safe string, use
:func:`django.utils.safestring.mark_safe`.
Be careful, though. You need to do more than just mark the output as Be careful, though. You need to do more than just mark the output as
safe. You need to ensure it really *is* safe, and what you do depends on safe. You need to ensure it really *is* safe, and what you do depends on
@ -852,9 +282,9 @@ Template filter code falls into one of two situations:
The ``needs_autoescape`` attribute on the filter function and the The ``needs_autoescape`` attribute on the filter function and the
``autoescape`` keyword argument mean that our function will know whether ``autoescape`` keyword argument mean that our function will know whether
automatic escaping is in effect when the filter is called. We use automatic escaping is in effect when the filter is called. We use
``autoescape`` to decide whether the input data needs to be passed through ``autoescape`` to decide whether the input data needs to be passed
``django.utils.html.conditional_escape`` or not. (In the latter case, we through ``django.utils.html.conditional_escape`` or not. (In the latter
just use the identity function as the "escape" function.) The case, we just use the identity function as the "escape" function.) The
``conditional_escape()`` function is like ``escape()`` except it only ``conditional_escape()`` function is like ``escape()`` except it only
escapes input that is **not** a ``SafeData`` instance. If a ``SafeData`` escapes input that is **not** a ``SafeData`` instance. If a ``SafeData``
instance is passed to ``conditional_escape()``, the data is returned instance is passed to ``conditional_escape()``, the data is returned
@ -902,7 +332,9 @@ responsible for returning a ``Node`` instance based on the contents of the tag.
For example, let's write a template tag, ``{% current_time %}``, that displays For example, let's write a template tag, ``{% current_time %}``, that displays
the current date/time, formatted according to a parameter given in the tag, in the current date/time, formatted according to a parameter given in the tag, in
`strftime syntax`_. It's a good idea to decide the tag syntax before anything `strftime syntax`_. It's a good idea to decide the tag syntax before anything
else. In our case, let's say the tag should be used like this:: else. In our case, let's say the tag should be used like this:
.. code-block:: html+django
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p> <p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
@ -1064,7 +496,9 @@ content (a template variable) to a template tag as an argument.
While the previous examples have formatted the current time into a string and While the previous examples have formatted the current time into a string and
returned the string, suppose you wanted to pass in a ``DateTimeField`` from an returned the string, suppose you wanted to pass in a ``DateTimeField`` from an
object and have the template tag format that date-time:: object and have the template tag format that date-time:
.. code-block:: html+django
<p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p> <p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p>
@ -1174,7 +608,7 @@ In Python 2.4, the decorator syntax also works::
A couple of things to note about the ``simple_tag`` helper function: A couple of things to note about the ``simple_tag`` helper function:
* Checking for the required number of arguments, etc, has already been * Checking for the required number of arguments, etc., has already been
done by the time our function is called, so we don't need to do that. done by the time our function is called, so we don't need to do that.
* The quotes around the argument (if any) have already been stripped away, * The quotes around the argument (if any) have already been stripped away,
so we just receive a plain string. so we just receive a plain string.
@ -1200,11 +634,15 @@ These sorts of tags are called "inclusion tags".
Writing inclusion tags is probably best demonstrated by example. Let's write a Writing inclusion tags is probably best demonstrated by example. Let's write a
tag that outputs a list of choices for a given ``Poll`` object, such as was tag that outputs a list of choices for a given ``Poll`` object, such as was
created in the tutorials_. We'll use the tag like this:: created in the :ref:`tutorials <creating-models>`. We'll use the tag like this:
.. code-block:: html+django
{% show_results poll %} {% show_results poll %}
...and the output will be something like this:: ...and the output will be something like this:
.. code-block:: html
<ul> <ul>
<li>First choice</li> <li>First choice</li>
@ -1223,7 +661,9 @@ for the template fragment. Example::
Next, create the template used to render the tag's output. This template is a Next, create the template used to render the tag's output. This template is a
fixed feature of the tag: the tag writer specifies it, not the template fixed feature of the tag: the tag writer specifies it, not the template
designer. Following our example, the template is very simple:: designer. Following our example, the template is very simple:
.. code-block:: html+django
<ul> <ul>
{% for choice in choices %} {% for choice in choices %}
@ -1272,13 +712,17 @@ back to the main page. Here's what the Python function would look like::
In that ``register.inclusion_tag()`` line, we specified ``takes_context=True`` In that ``register.inclusion_tag()`` line, we specified ``takes_context=True``
and the name of the template. Here's what the template ``link.html`` might look and the name of the template. Here's what the template ``link.html`` might look
like:: like:
.. code-block:: html+django
Jump directly to <a href="{{ link }}">{{ title }}</a>. Jump directly to <a href="{{ link }}">{{ title }}</a>.
Then, any time you want to use that custom tag, load its library and call it Then, any time you want to use that custom tag, load its library and call it
without any arguments, like so:: without any arguments, like so::
.. code-block:: html+django
{% jump_link %} {% jump_link %}
Note that when you're using ``takes_context=True``, there's no need to pass Note that when you're using ``takes_context=True``, there's no need to pass
@ -1288,8 +732,6 @@ The ``takes_context`` parameter defaults to ``False``. When it's set to *True*,
the tag is passed the context object, as in this example. That's the only the tag is passed the context object, as in this example. That's the only
difference between this case and the previous ``inclusion_tag`` example. difference between this case and the previous ``inclusion_tag`` example.
.. _tutorials: ../tutorial01/#creating-models
Setting a variable in the context Setting a variable in the context
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1313,7 +755,9 @@ Note that ``render()`` returns the empty string. ``render()`` should always
return string output. If all the template tag does is set a variable, return string output. If all the template tag does is set a variable,
``render()`` should return the empty string. ``render()`` should return the empty string.
Here's how you'd use this new version of the tag:: Here's how you'd use this new version of the tag:
.. code-block:: html+django
{% current_time "%Y-%M-%d %I:%M %p" %}<p>The time is {{ current_time }}.</p> {% current_time "%Y-%M-%d %I:%M %p" %}<p>The time is {{ current_time }}.</p>
@ -1322,7 +766,9 @@ But, there's a problem with ``CurrentTimeNode2``: The variable name
template doesn't use ``{{ current_time }}`` anywhere else, because the template doesn't use ``{{ current_time }}`` anywhere else, because the
``{% current_time %}`` will blindly overwrite that variable's value. A cleaner ``{% current_time %}`` will blindly overwrite that variable's value. A cleaner
solution is to make the template tag specify the name of the output variable, solution is to make the template tag specify the name of the output variable,
like so:: like so:
.. code-block:: html+django
{% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %} {% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
<p>The current time is {{ my_current_time }}.</p> <p>The current time is {{ my_current_time }}.</p>
@ -1402,7 +848,9 @@ possible to do something with the code between block tags.
For example, here's a custom template tag, ``{% upper %}``, that capitalizes For example, here's a custom template tag, ``{% upper %}``, that capitalizes
everything between itself and ``{% endupper %}``. everything between itself and ``{% endupper %}``.
Usage:: Usage:
.. code-block:: html+django
{% upper %}This will appear in uppercase, {{ your_name }}.{% endupper %} {% upper %}This will appear in uppercase, {{ your_name }}.{% endupper %}
@ -1427,37 +875,3 @@ The only new concept here is the ``self.nodelist.render(context)`` in
For more examples of complex rendering, see the source code for ``{% if %}``, For more examples of complex rendering, see the source code for ``{% if %}``,
``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in ``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in
``django/template/defaulttags.py``. ``django/template/defaulttags.py``.
.. _configuration:
Configuring the template system in standalone mode
==================================================
.. note::
This section is only of interest to people trying to use the template
system as an output component in another application. If you're using the
template system as part of a Django application, nothing here applies to
you.
Normally, Django will load all the configuration information it needs from its
own default configuration file, combined with the settings in the module given
in the ``DJANGO_SETTINGS_MODULE`` environment variable. But if you're using the
template system independently of the rest of Django, the environment variable
approach isn't very convenient, because you probably want to configure the
template system in line with the rest of your application rather than dealing
with settings files and pointing to them via environment variables.
To solve this problem, you need to use the manual configuration option
described in the `settings file`_ documentation. Simply import the appropriate
pieces of the templating system and then, *before* you call any of the
templating functions, call ``django.conf.settings.configure()`` with any
settings you wish to specify. You might want to consider setting at least
``TEMPLATE_DIRS`` (if you're going to use template loaders),
``DEFAULT_CHARSET`` (although the default of ``utf-8`` is probably fine) and
``TEMPLATE_DEBUG``. All available settings are described in the
`settings documentation`_, and any setting starting with *TEMPLATE_*
is of obvious interest.
.. _settings file: ../settings/#using-settings-without-the-django-settings-module-environment-variable
.. _settings documentation: ../settings/

View File

@ -1,17 +1,22 @@
.. _howto-deployment-fastcgi:
=========================================== ===========================================
How to use Django with FastCGI, SCGI or AJP How to use Django with FastCGI, SCGI or AJP
=========================================== ===========================================
Although the `current preferred setup`_ for running Django is Apache_ with .. highlight:: bash
`mod_python`_, many people use shared hosting, on which protocols such as
FastCGI, SCGI or AJP are the only viable options. In some setups, these protocols Although the current preferred setup for running Django is :ref:`Apache with
also allow better security -- and, possibly, better performance -- than mod_python. mod_python <howto-deployment-modpython>`, many people use shared hosting, on
which protocols such as FastCGI, SCGI or AJP are the only viable options. In
some setups, these protocols also allow better security -- and, possibly, better
performance -- than mod_python_.
.. admonition:: Note .. admonition:: Note
This document primarily focuses on FastCGI. Other protocols, such as SCGI This document primarily focuses on FastCGI. Other protocols, such as SCGI
and AJP, are also supported, through the ``flup`` Python package. See the and AJP, are also supported, through the ``flup`` Python package. See the
"Protocols" section below for specifics about SCGI and AJP. Protocols_ section below for specifics about SCGI and AJP.
Essentially, FastCGI is an efficient way of letting an external application Essentially, FastCGI is an efficient way of letting an external application
serve pages to a Web server. The Web server delegates the incoming Web requests serve pages to a Web server. The Web server delegates the incoming Web requests
@ -19,12 +24,10 @@ serve pages to a Web server. The Web server delegates the incoming Web requests
to the Web server, which, in turn, passes it back to the client's Web browser. to the Web server, which, in turn, passes it back to the client's Web browser.
Like mod_python, FastCGI allows code to stay in memory, allowing requests to be Like mod_python, FastCGI allows code to stay in memory, allowing requests to be
served with no startup time. Unlike mod_python (or `mod_perl`_), a FastCGI served with no startup time. Unlike mod_python_ (or `mod_perl`_), a FastCGI
process doesn't run inside the Web server process, but in a separate, process doesn't run inside the Web server process, but in a separate,
persistent process. persistent process.
.. _current preferred setup: ../modpython/
.. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/ .. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/ .. _mod_perl: http://perl.apache.org/
@ -45,9 +48,8 @@ persistent process.
Prerequisite: flup Prerequisite: flup
================== ==================
Before you can start using FastCGI with Django, you'll need to install flup_, Before you can start using FastCGI with Django, you'll need to install flup_, a
which is a Python library for dealing with FastCGI. Version 0.5 or newer should Python library for dealing with FastCGI. Version 0.5 or newer should work fine.
work fine.
.. _flup: http://www.saddi.com/software/flup/ .. _flup: http://www.saddi.com/software/flup/
@ -72,25 +74,27 @@ TCP socket. What you choose is a manner of preference; a TCP socket is usually
easier due to permissions issues. easier due to permissions issues.
To start your server, first change into the directory of your project (wherever To start your server, first change into the directory of your project (wherever
your ``manage.py`` is), and then run ``manage.py`` with the ``runfcgi`` option:: your :ref:`manage.py <ref-django-admin>` is), and then run the
:djadmin:`runfcgi` command::
./manage.py runfcgi [options] ./manage.py runfcgi [options]
If you specify ``help`` as the only option after ``runfcgi``, it'll display a If you specify ``help`` as the only option after :djadmin:`runfcgi`, it'll
list of all the available options. display a list of all the available options.
You'll need to specify either a ``socket``, ``protocol`` or both ``host`` and You'll need to specify either a ``socket``, a ``protocol`` or both ``host`` and
``port``. Then, when you set up your Web server, you'll just need to point it ``port``. Then, when you set up your Web server, you'll just need to point it at
at the host/port or socket you specified when starting the FastCGI server. the host/port or socket you specified when starting the FastCGI server. See the
examples_, below.
Protocols Protocols
--------- ---------
Django supports all the protocols that flup_ does, namely fastcgi_, `SCGI`_ and Django supports all the protocols that flup_ does, namely fastcgi_, `SCGI`_ and
`AJP1.3`_ (the Apache JServ Protocol, version 1.3). Select your preferred `AJP1.3`_ (the Apache JServ Protocol, version 1.3). Select your preferred
protocol by using the ``protocol=<protocol_name>`` option with protocol by using the ``protocol=<protocol_name>`` option with ``./manage.py
``./manage.py runfcgi`` -- where ``<protocol_name>`` may be one of: ``fcgi`` runfcgi`` -- where ``<protocol_name>`` may be one of: ``fcgi`` (the default),
(the default), ``scgi`` or ``ajp``. For example:: ``scgi`` or ``ajp``. For example::
./manage.py runfcgi protocol=scgi ./manage.py runfcgi protocol=scgi
@ -122,8 +126,8 @@ Simply hitting ``Ctrl-C`` will stop and quit the FastCGI server. However, when
you're dealing with background processes, you'll need to resort to the Unix you're dealing with background processes, you'll need to resort to the Unix
``kill`` command. ``kill`` command.
If you specify the ``pidfile`` option to your ``manage.py runfcgi``, you can If you specify the ``pidfile`` option to :djadmin:`runfcgi`, you can kill the
kill the running FastCGI daemon like this:: running FastCGI daemon like this::
kill `cat $PIDFILE` kill `cat $PIDFILE`
@ -170,7 +174,9 @@ Specifying the location of the FastCGI server
The ``FastCGIExternalServer`` directive tells Apache how to find your FastCGI The ``FastCGIExternalServer`` directive tells Apache how to find your FastCGI
server. As the `FastCGIExternalServer docs`_ explain, you can specify either a server. As the `FastCGIExternalServer docs`_ explain, you can specify either a
``socket`` or a ``host``. Here are examples of both:: ``socket`` or a ``host``. Here are examples of both:
.. code-block:: apache
# Connect to FastCGI via a socket / named pipe. # Connect to FastCGI via a socket / named pipe.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock
@ -195,7 +201,9 @@ directive, as explained in the previous section).
In this example, we tell Apache to use FastCGI to handle any request that In this example, we tell Apache to use FastCGI to handle any request that
doesn't represent a file on the filesystem and doesn't start with ``/media/``. doesn't represent a file on the filesystem and doesn't start with ``/media/``.
This is probably the most common case, if you're using Django's admin site:: This is probably the most common case, if you're using Django's admin site:
.. code-block:: apache
<VirtualHost 12.34.56.78> <VirtualHost 12.34.56.78>
ServerName example.com ServerName example.com
@ -215,15 +223,19 @@ constructing URLs with the ``{% url %}`` template tag (and similar methods).
lighttpd setup lighttpd setup
============== ==============
lighttpd is a lightweight Web server commonly used for serving static files. It lighttpd_ is a lightweight Web server commonly used for serving static files. It
supports FastCGI natively and, thus, is a good choice for serving both static supports FastCGI natively and, thus, is a good choice for serving both static
and dynamic pages, if your site doesn't have any Apache-specific needs. and dynamic pages, if your site doesn't have any Apache-specific needs.
.. _lighttpd: http://www.lighttpd.net/
Make sure ``mod_fastcgi`` is in your modules list, somewhere after Make sure ``mod_fastcgi`` is in your modules list, somewhere after
``mod_rewrite`` and ``mod_access``, but not after ``mod_accesslog``. You'll ``mod_rewrite`` and ``mod_access``, but not after ``mod_accesslog``. You'll
probably want ``mod_alias`` as well, for serving admin media. probably want ``mod_alias`` as well, for serving admin media.
Add the following to your lighttpd config file:: Add the following to your lighttpd config file:
.. code-block:: lua
server.document-root = "/home/user/public_html" server.document-root = "/home/user/public_html"
fastcgi.server = ( fastcgi.server = (
@ -289,7 +301,9 @@ using Web server-spawned processes.
there's no need for you to start the FastCGI server on your own. Apache there's no need for you to start the FastCGI server on your own. Apache
will spawn a number of processes, scaling as it needs to. will spawn a number of processes, scaling as it needs to.
In your Web root directory, add this to a file named ``.htaccess`` :: In your Web root directory, add this to a file named ``.htaccess``:
.. code-block:: apache
AddHandler fastcgi-script .fcgi AddHandler fastcgi-script .fcgi
RewriteEngine On RewriteEngine On
@ -298,7 +312,9 @@ In your Web root directory, add this to a file named ``.htaccess`` ::
Then, create a small script that tells Apache how to spawn your FastCGI Then, create a small script that tells Apache how to spawn your FastCGI
program. Create a file ``mysite.fcgi`` and place it in your Web directory, and program. Create a file ``mysite.fcgi`` and place it in your Web directory, and
be sure to make it executable:: be sure to make it executable:
.. code-block:: python
#!/usr/bin/python #!/usr/bin/python
import sys, os import sys, os
@ -332,12 +348,10 @@ easily by using the ``touch`` command::
Serving admin media files Serving admin media files
========================= =========================
Regardless of the server and configuration you eventually decide to use, you will Regardless of the server and configuration you eventually decide to use, you
also need to give some thought to how to serve the admin media files. The will also need to give some thought to how to serve the admin media files. The
advice given in the modpython_ documentation is also applicable in the setups advice given in the :ref:`modpython <serving-the-admin-files>` documentation
detailed above. is also applicable in the setups detailed above.
.. _modpython: ../modpython/#serving-the-admin-files
Forcing the URL prefix to a particular value Forcing the URL prefix to a particular value
============================================ ============================================
@ -366,3 +380,4 @@ As an example of how to use it, if your Django configuration is serving all of
the URLs under ``'/'`` and you wanted to use this setting, you would set the URLs under ``'/'`` and you wanted to use this setting, you would set
``FORCE_SCRIPT_NAME = ''`` in your settings file. ``FORCE_SCRIPT_NAME = ''`` in your settings file.

View File

@ -0,0 +1,33 @@
.. _howto-deployment-index:
Deploying Django
================
Django's chock-full of shortcuts to make web developer's lives easier, but all
those tools are of no use if you can't easily deploy your sites. Since Django's
inception, ease of deployment has been a major goal. There's a number of good
ways to easily deploy Django:
.. toctree::
:maxdepth: 1
modpython
fastcgi
:ref:`Deploying under mod_python <howto-deployment-modpython>` is the
recommended deployment method; start there if you're not sure which path you'd
like to go down.
.. seealso::
* `Chapter 20 of The Django Book`_ discusses deployment and especially
scaling in more detail.
* `mod_wsgi`_ is a newcomer to the Python deployment world, but it's rapidly
gaining traction. Currently there's a few hoops you have to jump through to
`use mod_wsgi with Django`_, but mod_wsgi tends to get rave reviews from
those who use it.
.. _chapter 20 of the django book: http://djangobook.com/en/1.0/chapter20/
.. _mod_wsgi: http://code.google.com/p/modwsgi/
.. _use mod_wsgi with Django: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango

View File

@ -1,27 +1,30 @@
================================= .. _howto-deployment-modpython:
How to use Django with mod_python
================================= ============================================
How to use Django with Apache and mod_python
============================================
.. highlight:: apache
Apache_ with `mod_python`_ currently is the preferred setup for using Django Apache_ with `mod_python`_ currently is the preferred setup for using Django
on a production server. on a production server.
mod_python is similar to `mod_perl`_ : It embeds Python within Apache and loads mod_python is similar to (and inspired by) `mod_perl`_ : It embeds Python within
Python code into memory when the server starts. Code stays in memory throughout Apache and loads Python code into memory when the server starts. Code stays in
the life of an Apache process, which leads to significant performance gains over memory throughout the life of an Apache process, which leads to significant
other server arrangements. performance gains over other server arrangements.
Django requires Apache 2.x and mod_python 3.x, and you should use Apache's Django requires Apache 2.x and mod_python 3.x, and you should use Apache's
`prefork MPM`_, as opposed to the `worker MPM`_. `prefork MPM`_, as opposed to the `worker MPM`_.
You may also be interested in `How to use Django with FastCGI, SCGI or AJP`_ You may also be interested in :ref:`How to use Django with FastCGI, SCGI or AJP
(which also covers SCGI and AJP). <howto-deployment-fastcgi>` (which also covers SCGI and AJP).
.. _Apache: http://httpd.apache.org/ .. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/ .. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/ .. _mod_perl: http://perl.apache.org/
.. _prefork MPM: http://httpd.apache.org/docs/2.2/mod/prefork.html .. _prefork MPM: http://httpd.apache.org/docs/2.2/mod/prefork.html
.. _worker MPM: http://httpd.apache.org/docs/2.2/mod/worker.html .. _worker MPM: http://httpd.apache.org/docs/2.2/mod/worker.html
.. _How to use Django with FastCGI, SCGI or AJP: ../fastcgi/
Basic configuration Basic configuration
=================== ===================
@ -43,8 +46,8 @@ Then edit your ``httpd.conf`` file and add the following::
project's settings file. project's settings file.
This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
Django mod_python handler." It passes the value of ``DJANGO_SETTINGS_MODULE`` Django mod_python handler." It passes the value of :ref:`DJANGO_SETTINGS_MODULE
so mod_python knows which settings to use. <django-settings-module>` so mod_python knows which settings to use.
**New in Django development version:** Because mod_python does not know we are **New in Django development version:** Because mod_python does not know we are
serving this site from underneath the ``/mysite/`` prefix, this value needs to serving this site from underneath the ``/mysite/`` prefix, this value needs to
@ -85,18 +88,18 @@ computer, you'll have to tell mod_python where your project can be found:
The value you use for ``PythonPath`` should include the parent directories of The value you use for ``PythonPath`` should include the parent directories of
all the modules you are going to import in your application. It should also all the modules you are going to import in your application. It should also
include the parent directory of the ``DJANGO_SETTINGS_MODULE`` location. This include the parent directory of the :ref:`DJANGO_SETTINGS_MODULE
is exactly the same situation as setting the Python path for interactive <django-settings-module>` location. This is exactly the same situation as
usage. Whenever you try to import something, Python will run through all the setting the Python path for interactive usage. Whenever you try to import
directories in ``sys.path`` in turn, from first to last, and try to import something, Python will run through all the directories in ``sys.path`` in turn,
from each directory until one succeeds. from first to last, and try to import from each directory until one succeeds.
An example might make this clearer. Suppose An example might make this clearer. Suppose you have some applications under
you have some applications under ``/usr/local/django-apps/`` (for example, ``/usr/local/django-apps/`` (for example, ``/usr/local/django-apps/weblog/`` and
``/usr/local/django-apps/weblog/`` and so forth), your settings file is at so forth), your settings file is at ``/var/www/mysite/settings.py`` and you have
``/var/www/mysite/settings.py`` and you have specified specified :ref:`DJANGO_SETTINGS_MODULE <django-settings-module>` as in the above
``DJANGO_SETTINGS_MODULE`` as in the above example. In this case, you would example. In this case, you would need to write your ``PythonPath`` directive
need to write your ``PythonPath`` directive as:: as::
PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path" PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path"
@ -127,9 +130,9 @@ Note that you should set ``PythonDebug Off`` on a production server. If you
leave ``PythonDebug On``, your users would see ugly (and revealing) Python leave ``PythonDebug On``, your users would see ugly (and revealing) Python
tracebacks if something goes wrong within mod_python. tracebacks if something goes wrong within mod_python.
Restart Apache, and any request to /mysite/ or below will be served by Django. Restart Apache, and any request to ``/mysite/`` or below will be served by
Note that Django's URLconfs won't trim the "/mysite/" -- they get passed the Django. Note that Django's URLconfs won't trim the "/mysite/" -- they get passed
full URL. the full URL.
When deploying Django sites on mod_python, you'll need to restart Apache each When deploying Django sites on mod_python, you'll need to restart Apache each
time you make changes to your Python code. time you make changes to your Python code.
@ -196,6 +199,8 @@ Or add the debugging information to the template of your page.
.. _mod_python documentation: http://modpython.org/live/current/doc-html/directives.html .. _mod_python documentation: http://modpython.org/live/current/doc-html/directives.html
.. _serving-media-files:
Serving media files Serving media files
=================== ===================
@ -205,9 +210,9 @@ server you choose.
We recommend using a separate Web server -- i.e., one that's not also running We recommend using a separate Web server -- i.e., one that's not also running
Django -- for serving media. Here are some good choices: Django -- for serving media. Here are some good choices:
* lighttpd_ * lighttpd_
* TUX_ * TUX_
* A stripped-down version of Apache_ * A stripped-down version of Apache_
If, however, you have no option but to serve media files on the same Apache If, however, you have no option but to serve media files on the same Apache
``VirtualHost`` as Django, here's how you can turn off mod_python for a ``VirtualHost`` as Django, here's how you can turn off mod_python for a
@ -243,6 +248,10 @@ the ``media`` subdirectory and any URL that ends with ``.jpg``, ``.gif`` or
.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server .. _TUX: http://en.wikipedia.org/wiki/TUX_web_server
.. _Apache: http://httpd.apache.org/ .. _Apache: http://httpd.apache.org/
.. _howto-deployment-modpython-serving-the-admin-files:
.. _serving-the-admin-files:
Serving the admin files Serving the admin files
======================= =======================
@ -251,25 +260,27 @@ but this is not the case when you use any other server arrangement. You're
responsible for setting up Apache, or whichever media server you're using, to responsible for setting up Apache, or whichever media server you're using, to
serve the admin files. serve the admin files.
The admin files live in (``django/contrib/admin/media``) of the Django The admin files live in (:file:`django/contrib/admin/media`) of the Django
distribution. distribution.
Here are two recommended approaches: Here are two recommended approaches:
1. Create a symbolic link to the admin media files from within your 1. Create a symbolic link to the admin media files from within your
document root. This way, all of your Django-related files -- code document root. This way, all of your Django-related files -- code **and**
**and** templates -- stay in one place, and you'll still be able to templates -- stay in one place, and you'll still be able to ``svn
``svn update`` your code to get the latest admin templates, if they update`` your code to get the latest admin templates, if they change.
change.
2. Or, copy the admin media files so that they live within your Apache 2. Or, copy the admin media files so that they live within your Apache
document root. document root.
Using eggs with mod_python Using "eggs" with mod_python
========================== ============================
If you installed Django from a Python egg_ or are using eggs in your Django If you installed Django from a Python egg_ or are using eggs in your Django
project, some extra configuration is required. Create an extra file in your project, some extra configuration is required. Create an extra file in your
project (or somewhere else) that contains something like the following:: project (or somewhere else) that contains something like the following:
.. code-block:: python
import os import os
os.environ['PYTHON_EGG_CACHE'] = '/some/directory' os.environ['PYTHON_EGG_CACHE'] = '/some/directory'
@ -322,6 +333,7 @@ of which has to do with Django itself.
1. It may be because your Python code is importing the "pyexpat" module, 1. It may be because your Python code is importing the "pyexpat" module,
which may conflict with the version embedded in Apache. For full which may conflict with the version embedded in Apache. For full
information, see `Expat Causing Apache Crash`_. information, see `Expat Causing Apache Crash`_.
2. It may be because you're running mod_python and mod_php in the same 2. It may be because you're running mod_python and mod_php in the same
Apache instance, with MySQL as your database backend. In some cases, Apache instance, with MySQL as your database backend. In some cases,
this causes a known mod_python issue due to version conflicts in PHP and this causes a known mod_python issue due to version conflicts in PHP and

View File

@ -0,0 +1,65 @@
.. _howto-error-reporting:
Error reporting via e-mail
==========================
When you're running a public site you should always turn off the
:setting:`DEBUG` setting. That will make your server run much faster, and will
also prevent malicious users from seeing details of your application that can be
revealed by the error pages.
However, running with :setting:`DEBUG` set to ``False`` means you'll never see
errors generated by your site -- everyone will just see your public error pages.
You need to keep track of errors that occur in deployed sites, so Django can be
configured to email you details of those errors.
Server errors
-------------
When :setting:`DEBUG` is ``False``, Django will e-mail the users listed in the
:setting:`ADMIN` setting whenever your code raises an unhandled exception and
results in an internal server error (HTTP status code 500). This gives the
administrators immediate notification of any errors. The :setting:`ADMINS` will
get a description of the error, a complete Python traceback, and details about
the HTTP request that caused the error.
To disable this behavior, just remove all entries from the :setting:`ADMINS`
setting.
404 errors
----------
Django can also be configured to email errors about broken links (404 "page
not found" errors). Django sends emails about 404 errors when:
* :setting:`DEBUG` is ``False``
* :setting:`SEND_BROKEN_LINK_EMAILS` is ``True``
* Your :setting:`MIDDLEWARE_CLASSES` setting includes ``CommonMiddleware``
(which it does by default).
If those conditions are met, Django will e-mail the users listed in the
:setting:`MANAGERS` setting whenever your code raises a 404 and the request has
a referer. (It doesn't bother to e-mail for 404s that don't have a referer --
those are usually just people typing in broken URLs or broken web 'bots).
You can tell Django to stop reporting particular 404s by tweaking the
:setting:`IGNORABLE_404_ENDS` and :setting:`IGNORABLE_404_STARTS` settings. Both
should be a tuple of strings. For example::
IGNORABLE_404_ENDS = ('.php', '.cgi')
IGNORABLE_404_STARTS = ('/phpmyadmin/',)
In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not* be
reported. Neither will any URL starting with ``/phpmyadmin/``.
The best way to disable this behavior is to set
:setting:`SEND_BROKEN_LINK_EMAILS` to ``False``.
.. seealso::
You can also set up custom error reporting by writing a custom piece of
:ref:`exception middleware <exception-middleware>`. If you do write custom
error handling, it's a good idea to emulate Django's built-in error handling
and only report/log errors if :setting:`DEBUG` is ``False``.

33
docs/howto/index.txt Normal file
View File

@ -0,0 +1,33 @@
.. _howto-index:
"How-to" guides
===============
Here you'll find short answers to "How do I....?" types of questions. These
how-to guides don't cover topics in depth -- you'll find that material in the
:ref:`topics-index` and the :ref:`ref-index`. However, these guides will help
you quickly accomplish common tasks.
.. toctree::
:maxdepth: 1
apache-auth
custom-management-commands
custom-model-fields
custom-template-tags
custom-file-storage
deployment/index
error-reporting
initial-data
legacy-databases
outputting-csv
outputting-pdf
static-files
.. seealso::
The `Django community aggregator`_, where we aggregate content from the
global Django community. Many writers in the aggregator write this sort of
how-to material.
.. _django community aggregator: http://www.djangoproject.com/community/

140
docs/howto/initial-data.txt Normal file
View File

@ -0,0 +1,140 @@
.. _howto-initial-data:
=================================
Providing initial data for models
=================================
It's sometimes useful to pre-populate your database with hard-coded data when
you're first setting up an app. There's a couple of ways you can have Django
automatically create this data: you can provide `initial data via fixtures`_, or
you can provide `initial data as SQL`_.
In general, using a fixture is a cleaner method since it's database-agnostic,
but initial SQL is also quite a bit more flexible.
.. _initial data as sql: `providing initial sql data`_
.. _initial data via fixtures: `providing initial data with fixtures`_
Providing initial data with fixtures
====================================
A fixture is a collection of data that Django knows how to import into a
database. The most straightforward way of creating a fixture if you've already
got some data is to use the :djadmin:`manage.py dumpdata` command. Or, you can
write fixtures by hand; fixtures can be written as XML, YAML, or JSON documents.
The :ref:`serialization documentation <topics-serialization>` has more details
about each of these supported :ref:`serialization formats
<serialization-formats>`.
As an example, though, here's what a fixture for a simple ``Person`` model might
look like in JSON:
.. code-block:: js
[
{
"model": "myapp.person",
"pk": 1,
"fields": {
"first_name": "John",
"last_name": "Lennon",
}
},
{
"model": "myapp.person",
"pk": 2,
"fields": {
"first_name": "Paul",
"last_name": "McCartney",
}
},
]
And here's that same fixture as YAML:
.. code-block:: none
- model: myapp.person
pk: 1
fields:
first_name: John
last_name: Lennon
- model: myapp.person
pk: 1
fields:
first_name: Paul
last_name: McCartney
You'll store this data in a ``fixtures`` directory inside you app.
Loading data is easy: just call :djadmin:`manage.py loaddata fixturename
<loaddata>`, where *fixturename* is the name of the fixture file you've created.
Every time you run :djadmin:`loaddata` the data will be read from the fixture
and re-loaded into the database. Note that this means that if you change one of
the rows created by a fixture and the run :djadmin:`loaddata` again you'll wipe
out any changes you've made.
Automatically loading initial data fixtures
-------------------------------------------
If you create a fixture named ``initial_data.[xml/yml/json]``, that fixture will
be loaded every time you run :djadmin:`syncdb`. This is extremely convenient,
but be careful: remember that the data will be refreshed *every time* you run
:djadmin:`syncdb`. So don't use ``initial_data`` for data you'll want to edit.
.. seealso::
Fixtures are also used by the :ref:`testing framework
<topics-testing-fixtures>` to help set up a consistent test environment.
.. _initial-sql:
Providing initial SQL data
==========================
Django provides a hook for passing the database arbitrary SQL that's executed
just after the CREATE TABLE statements when you run :djadmin:`syncdb`. You can
use this hook to populate default records, or you could also create SQL
functions, views, triggers, etc.
The hook is simple: Django just looks for a file called ``sql/<modelname>.sql``,
in your app directory, where ``<modelname>`` is the model's name in lowercase.
So, if you had a ``Person`` model in an app called ``myapp``, you could add
arbitrary SQL to the file ``sql/person.sql`` inside your ``myapp`` directory.
Here's an example of what the file might contain:
.. code-block:: sql
INSERT INTO myapp_person (first_name, last_name) VALUES ('John', 'Lennon');
INSERT INTO myapp_person (first_name, last_name) VALUES ('Paul', 'McCartney');
Each SQL file, if given, is expected to contain valid SQL statements
which will insert the desired data (e.g., properly-formatted
``INSERT`` statements separated by semicolons).
The SQL files are read by the :djadmin:`sqlcustom`, :djadmin:`sqlreset`,
:djadmin:`sqlall` and :djadmin:`reset` commands in :ref:`manage.py
<ref-django-admin>`. Refer to the :ref:`manage.py documentation
<ref-django-admin>` for more information.
Note that if you have multiple SQL data files, there's no guarantee of the order
in which they're executed. The only thing you can assume is that, by the time
your custom data files are executed, all the database tables already will have
been created.
Database-backend-specific SQL data
----------------------------------
There's also a hook for backend-specific SQL data. For example, you can have
separate initial-data files for PostgreSQL and MySQL. For each app, Django
looks for a file called ``<appname>/sql/<modelname>.<backend>.sql``, where
``<appname>`` is your app directory, ``<modelname>`` is the model's name in
lowercase and ``<backend>`` is the value of :setting:`DATABASE_ENGINE` in your
settings file (e.g., ``postgresql``, ``mysql``).
Backend-specific SQL data is executed before non-backend-specific SQL data. For
example, if your app contains the files ``sql/person.sql`` and
``sql/person.postgresql.sql`` and you're installing the app on PostgreSQL,
Django will execute the contents of ``sql/person.postgresql.sql`` first, then
``sql/person.sql``.

View File

@ -0,0 +1,67 @@
.. _howto-legacy-databases:
=========================================
Integrating Django with a legacy database
=========================================
While Django is best suited for developing new applications, it's quite
possible to integrate it into legacy databases. Django includes a couple of
utilities to automate as much of this process as possible.
This document assumes you know the Django basics, as covered in the
:ref:`tutorial <intro-tutorial01>`.
Once you've got Django set up, you'll follow this general process to integrate
with an existing database.
Give Django your database parameters
====================================
You'll need to tell Django what your database connection parameters are, and
what the name of the database is. Do that by editing these settings in your
:ref:`settings file <topics-settings>`:
* :setting:`DATABASE_NAME`
* :setting:`DATABASE_ENGINE`
* :setting:`DATABASE_USER`
* :setting:`DATABASE_PASSWORD`
* :setting:`DATABASE_HOST`
* :setting:`DATABASE_PORT`
Auto-generate the models
========================
.. highlight:: bash
Django comes with a utility called :djadmin:`inspectdb` that can create models
by introspecting an existing database. You can view the output by running this
command::
python manage.py inspectdb
Save this as a file by using standard Unix output redirection::
python manage.py inspectdb > models.py
This feature is meant as a shortcut, not as definitive model generation. See the
:djadmin:`documentation of inspectdb <inspectdb>` for more information.
Once you've cleaned up your models, name the file ``models.py`` and put it in
the Python package that holds your app. Then add the app to your
:setting:`INSTALLED_APPS` setting.
Install the core Django tables
==============================
Next, run the :djadmin:`syncdb` command to install any extra needed database
records such as admin permissions and content types::
python manage.py syncdb
Test and tweak
==============
Those are the basic steps -- from here you'll want to tweak the models Django
generated until they work the way you'd like. Try accessing your data via the
Django database API, and try editing objects via Django's admin site, and edit
the models file accordingly.

View File

@ -1,12 +1,12 @@
.. _howto-outputting-csv:
========================== ==========================
Outputting CSV with Django Outputting CSV with Django
========================== ==========================
This document explains how to output CSV (Comma Separated Values) dynamically This document explains how to output CSV (Comma Separated Values) dynamically
using Django views. using Django views. To do this, you can either use the `Python CSV library`_ or
the Django template system.
To do this, you can either use the `Python CSV library`_ or the Django template
system.
.. _Python CSV library: http://www.python.org/doc/current/lib/module-csv.html .. _Python CSV library: http://www.python.org/doc/current/lib/module-csv.html
@ -14,18 +14,8 @@ Using the Python CSV library
============================ ============================
Python comes with a CSV library, ``csv``. The key to using it with Django is Python comes with a CSV library, ``csv``. The key to using it with Django is
that the ``csv`` module's CSV-creation capability acts on file-like objects, that the ``csv`` module's CSV-creation capability acts on file-like objects, and
and Django's ``HttpResponse`` objects are file-like objects. Django's :class:`~django.http.HttpResponse` objects are file-like objects.
.. admonition:: Note
For more information on ``HttpResponse`` objects, see
`Request and response objects`_.
For more information on the CSV library, see the `CSV library docs`_.
.. _Request and response objects: ../request_response/
.. _CSV library docs: http://www.python.org/doc/current/lib/module-csv.html
Here's an example:: Here's an example::
@ -46,7 +36,7 @@ Here's an example::
The code and comments should be self-explanatory, but a few things deserve a The code and comments should be self-explanatory, but a few things deserve a
mention: mention:
* The response gets a special mimetype, ``text/csv``. This tells * The response gets a special MIME type, ``text/csv``. This tells
browsers that the document is a CSV file, rather than an HTML file. If browsers that the document is a CSV file, rather than an HTML file. If
you leave this off, browsers will probably interpret the output as HTML, you leave this off, browsers will probably interpret the output as HTML,
which will result in ugly, scary gobbledygook in the browser window. which will result in ugly, scary gobbledygook in the browser window.
@ -56,9 +46,10 @@ mention:
whatever you want. It'll be used by browsers in the "Save as..." whatever you want. It'll be used by browsers in the "Save as..."
dialogue, etc. dialogue, etc.
* Hooking into the CSV-generation API is easy: Just pass ``response`` as * Hooking into the CSV-generation API is easy: Just pass ``response`` as the
the first argument to ``csv.writer``. The ``csv.writer`` function expects first argument to ``csv.writer``. The ``csv.writer`` function expects a
a file-like object, and ``HttpResponse`` objects fit the bill. file-like object, and :class:`~django.http.HttpResponse` objects fit the
bill.
* For each row in your CSV file, call ``writer.writerow``, passing it an * For each row in your CSV file, call ``writer.writerow``, passing it an
iterable object such as a list or tuple. iterable object such as a list or tuple.
@ -70,12 +61,12 @@ mention:
Using the template system Using the template system
========================= =========================
Alternatively, you can use the `Django template system`_ to generate CSV. This Alternatively, you can use the :ref:`Django template system <topics-templates>`
is lower-level than using the convenient CSV, but the solution is presented to generate CSV. This is lower-level than using the convenient CSV, but the
here for completeness. solution is presented here for completeness.
The idea here is to pass a list of items to your template, and have the The idea here is to pass a list of items to your template, and have the
template output the commas in a ``{% for %}`` loop. template output the commas in a :ttag:`for` loop.
Here's an example, which generates the same CSV file as above:: Here's an example, which generates the same CSV file as above::
@ -105,15 +96,21 @@ The only difference between this example and the previous example is that this
one uses template loading instead of the CSV module. The rest of the code -- one uses template loading instead of the CSV module. The rest of the code --
such as the ``mimetype='text/csv'`` -- is the same. such as the ``mimetype='text/csv'`` -- is the same.
Then, create the template ``my_template_name.txt``, with this template code:: Then, create the template ``my_template_name.txt``, with this template code:
.. code-block:: html+django
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}" {% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %} {% endfor %}
This template is quite basic. It just iterates over the given data and displays This template is quite basic. It just iterates over the given data and displays
a line of CSV for each row. It uses the `addslashes template filter`_ to ensure a line of CSV for each row. It uses the :tfilter:`addslashes` template filter to
there aren't any problems with quotes. If you can be certain your data doesn't ensure there aren't any problems with quotes.
have single or double quotes in it, you can remove the ``addslashes`` filters.
.. _Django template system: ../templates/ Other text-based formats
.. _addslashes template filter: ../templates/#addslashes ========================
Notice that there isn't very much specific to CSV here -- just the specific
output format. You can use either of these techniques to output any text-based
format you can dream of. You can also use a similar technique to generate
arbitrary binary data; see :ref:`howto-outputting-pdf` for an example.

View File

@ -1,3 +1,5 @@
.. _howto-outputting-pdf:
=========================== ===========================
Outputting PDFs with Django Outputting PDFs with Django
=========================== ===========================
@ -35,15 +37,8 @@ Write your view
=============== ===============
The key to generating PDFs dynamically with Django is that the ReportLab API The key to generating PDFs dynamically with Django is that the ReportLab API
acts on file-like objects, and Django's ``HttpResponse`` objects are file-like acts on file-like objects, and Django's :class:`~django.http.HttpResponse`
objects. objects are file-like objects.
.. admonition:: Note
For more information on ``HttpResponse`` objects, see
`Request and response objects`_.
.. _Request and response objects: ../request_response/
Here's a "Hello World" example:: Here's a "Hello World" example::
@ -70,7 +65,7 @@ Here's a "Hello World" example::
The code and comments should be self-explanatory, but a few things deserve a The code and comments should be self-explanatory, but a few things deserve a
mention: mention:
* The response gets a special mimetype, ``application/pdf``. This tells * The response gets a special MIME type, ``application/pdf``. This tells
browsers that the document is a PDF file, rather than an HTML file. If browsers that the document is a PDF file, rather than an HTML file. If
you leave this off, browsers will probably interpret the output as HTML, you leave this off, browsers will probably interpret the output as HTML,
which would result in ugly, scary gobbledygook in the browser window. which would result in ugly, scary gobbledygook in the browser window.
@ -91,7 +86,8 @@ mention:
* Hooking into the ReportLab API is easy: Just pass ``response`` as the * Hooking into the ReportLab API is easy: Just pass ``response`` as the
first argument to ``canvas.Canvas``. The ``Canvas`` class expects a first argument to ``canvas.Canvas``. The ``Canvas`` class expects a
file-like object, and ``HttpResponse`` objects fit the bill. file-like object, and :class:`~django.http.HttpResponse` objects fit the
bill.
* Note that all subsequent PDF-generation methods are called on the PDF * Note that all subsequent PDF-generation methods are called on the PDF
object (in this case, ``p``) -- not on ``response``. object (in this case, ``p``) -- not on ``response``.
@ -103,10 +99,9 @@ Complex PDFs
============ ============
If you're creating a complex PDF document with ReportLab, consider using the If you're creating a complex PDF document with ReportLab, consider using the
cStringIO_ library as a temporary holding place for your PDF file. The cStringIO_ library as a temporary holding place for your PDF file. The cStringIO
cStringIO library provides a file-like object interface that is particularly library provides a file-like object interface that is particularly efficient.
efficient. Here's the above "Hello World" example rewritten to use Here's the above "Hello World" example rewritten to use ``cStringIO``::
``cStringIO``::
from cStringIO import StringIO from cStringIO import StringIO
from reportlab.pdfgen import canvas from reportlab.pdfgen import canvas
@ -154,3 +149,12 @@ Further resources
.. _`Pisa HTML2PDF`: http://www.htmltopdf.org/ .. _`Pisa HTML2PDF`: http://www.htmltopdf.org/
.. _HTMLdoc: http://www.htmldoc.org/ .. _HTMLdoc: http://www.htmldoc.org/
.. _forge_fdf in Python: http://www.accesspdf.com/article.php/20050421092951834 .. _forge_fdf in Python: http://www.accesspdf.com/article.php/20050421092951834
Other formats
=============
Notice that there isn't a lot in these examples that's PDF-specific -- just the
bits using ``reportlab``. You can use a similar technique to generate any
arbitrary format that you can find a Python library for. Also see
:ref:`howto-outputting-csv` for another example and some techniques you can use
when generated text-based formats.

View File

@ -1,7 +1,12 @@
.. _howto-static-files:
========================= =========================
How to serve static files How to serve static files
========================= =========================
.. module:: django.views.static
:synopsis: Serving of static files during development.
Django itself doesn't serve static (media) files, such as images, style sheets, Django itself doesn't serve static (media) files, such as images, style sheets,
or video. It leaves that job to whichever Web server you choose. or video. It leaves that job to whichever Web server you choose.
@ -9,8 +14,8 @@ The reasoning here is that standard Web servers, such as Apache_ and lighttpd_,
are much more fine-tuned at serving static files than a Web application are much more fine-tuned at serving static files than a Web application
framework. framework.
With that said, Django does support static files **during development**. Use With that said, Django does support static files **during development**. You can
the view ``django.views.static.serve`` to serve media files. use the :func:`django.views.static.serve` view to serve media files.
.. _Apache: http://httpd.apache.org/ .. _Apache: http://httpd.apache.org/
.. _lighttpd: http://www.lighttpd.net/ .. _lighttpd: http://www.lighttpd.net/
@ -22,23 +27,25 @@ Using this method is **inefficient** and **insecure**. Do not use this in a
production setting. Use this only for development. production setting. Use this only for development.
For information on serving static files in an Apache production environment, For information on serving static files in an Apache production environment,
see the `Django mod_python documentation`_. see the :ref:`Django mod_python documentation <serving-media-files>`.
.. _Django mod_python documentation: ../modpython/#serving-media-files
How to do it How to do it
============ ============
Just put this in your URLconf_:: Here's the formal definition of the :func:`~django.views.static.serve` view:
.. function:: def serve(request, path, document_root, show_indexes=False):
To use it, just put this in your :ref:`URLconf <topics-http-urls>`::
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}), (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
...where ``site_media`` is the URL where your media will be rooted, and ...where ``site_media`` is the URL where your media will be rooted, and
``/path/to/media`` is the filesystem root for your media. ``/path/to/media`` is the filesystem root for your media. This will call the
:func:`~django.views.static.serve` view, passing in the path from the URLconf
and the (required) ``document_root`` parameter.
You must pass a ``document_root`` parameter to indicate the filesystem root. Given the above URLconf:
Examples:
* The file ``/path/to/media/foo.jpg`` will be made available at the URL * The file ``/path/to/media/foo.jpg`` will be made available at the URL
``/site_media/foo.jpg``. ``/site_media/foo.jpg``.
@ -49,26 +56,27 @@ Examples:
* The file ``/path/bar.jpg`` will not be accessible, because it doesn't * The file ``/path/bar.jpg`` will not be accessible, because it doesn't
fall under the document root. fall under the document root.
.. _URLconf: ../url_dispatch/
Directory listings Directory listings
================== ==================
Optionally, you can pass a ``show_indexes`` parameter to the ``static.serve`` Optionally, you can pass the ``show_indexes`` parameter to the
view. This is ``False`` by default. If it's ``True``, Django will display file :func:`~django.views.static.serve` view. This is ``False`` by default. If it's
listings for directories. ``True``, Django will display file listings for directories.
Example:: For example::
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}), (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
You can customize the index view by creating a template called You can customize the index view by creating a template called
``static/directory_index``. That template gets two objects in its context: ``static/directory_index.html``. That template gets two objects in its context:
* ``directory`` -- the directory name (a string) * ``directory`` -- the directory name (a string)
* ``file_list`` -- a list of file names (as strings) in the directory * ``file_list`` -- a list of file names (as strings) in the directory
Here's the default ``static/directory_index`` template:: Here's the default ``static/directory_index`` template:
.. code-block:: html+django
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
@ -97,7 +105,7 @@ trick to make sure the static-serving view doesn't slip into a production
setting by mistake. setting by mistake.
Do this by wrapping an ``if DEBUG`` statement around the Do this by wrapping an ``if DEBUG`` statement around the
``django.views.static.serve`` inclusion. Here's a full example URLconf:: :func:`django.views.static.serve` inclusion. Here's a full example URLconf::
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
from django.conf import settings from django.conf import settings
@ -115,11 +123,9 @@ Do this by wrapping an ``if DEBUG`` statement around the
) )
This code is straightforward. It imports the settings and checks the value of This code is straightforward. It imports the settings and checks the value of
the ``DEBUG`` setting. If it evaluates to ``True``, then ``site_media`` will be the :setting:`DEBUG` setting. If it evaluates to ``True``, then ``site_media``
associated with the ``django.views.static.serve`` view. If not will be associated with the ``django.views.static.serve`` view. If not, then the
(``DEBUG == False``), then the view won't be made available. view won't be made available.
Of course, the catch here is that you'll have to remember to set ``DEBUG=False`` Of course, the catch here is that you'll have to remember to set ``DEBUG=False``
in your production settings file. But you should be doing that anyway. in your production settings file. But you should be doing that anyway.
.. _DEBUG setting: ../settings/#debug

View File

@ -1,134 +1,162 @@
.. _index:
==================== ====================
Django Documentation Django documentation
==================== ====================
The essential documentation .. rubric:: Everything you need to know about Django (and then some).
===========================
If you're new to Django, make sure to read the following documentation in Getting help
order.. The rest (in the "reference" section below) can be ready in any order as ============
you need various functionality.
.. toctree:: Having trouble? We'd like to help!
:maxdepth: 1
overview * Try the :ref:`FAQ <faq-index>` -- it's got answers to many common questions.
install
tutorial01 * Looking for specific information? Try the :ref:`genindex`, :ref:`modindex` or
tutorial02 the :ref:`detailed table of contents <contents>`.
tutorial03
tutorial04 * Search for information in the `archives of the django-users mailing list`_, or
faq `post a question`_
documentation
* Ask a question in the `#django IRC channel`_, or search the `IRC logs`_ to see
if its been asked before
* Report bugs with Django in our `ticket tracker`_.
.. _archives of the django-users mailing list: http://groups.google.com/group/django-users/
.. _post a question: http://groups.google.com/group/django-users/
.. _#django IRC channel: irc://irc.freenode.net/django
.. _IRC logs: http://oebfare.com/logger/django/
.. _ticket tracker: http://code.djangoproject.com/
First steps
===========
:ref:`Overview <intro-overview>`
See what writing a database-driven application with Django looks like.
:ref:`Installation <intro-install>`
Get Django installed on your computer.
Tutorial: Writing your first Django application
===============================================
:ref:`Part 1 <intro-tutorial01>`
Get set up, create models, and play with the database API.
:ref:`Part 2 <intro-tutorial02>`
Explore the automatically-generated admin site.
:ref:`Part 3 <intro-tutorial03>`
Write the public interface views.
:ref:`Part 4 <intro-tutorial04>`
Learn how to process forms.
Using Django
============
:ref:`Models <topics-db-index>`
Design a single, definitive source of data about your data.
:ref:`Handling web requests <topics-http-index>`
Handle web requests, map them to views, and return pages.
:ref:`Forms <topics-forms-index>`
Build and handle HTML forms.
:ref:`Templates <topics-templates>`
Develop the visual design of your site.
And more:
---------
:ref:`topics-auth` ... :ref:`topics-cache` ... :ref:`topics-email` ...
:ref:`topics-files` ... :ref:`topics-i18n` ... :ref:`topics-install` ...
:ref:`topics-pagination` ... :ref:`topics-serialization` ...
:ref:`topics-settings` ... :ref:`topics-testing`
Add-on ("contrib") applications
===============================
:ref:`Django's automatic admin site <ref-contrib-admin>`
Get a clean interface to your data with no effort at all.
:ref:`Form tools <ref-contrib-formtools-index>`
Easily handle complex form workflows.
:ref:`Syndication feeds <ref-contrib-syndication>`
Generate RSS and Atom feeds of your data.
:ref:`"Local flavor" <ref-contrib-localflavor>`
Give your site that special local touch.
And more:
---------
:ref:`ref-contrib-contenttypes` ... :ref:`ref-contrib-csrf` ...
:ref:`ref-contrib-databrowse` ... :ref:`ref-contrib-flatpages` ...
:ref:`ref-contrib-humanize` ... :ref:`ref-contrib-redirects` ...
:ref:`ref-contrib-sitemaps` ... :ref:`ref-contrib-sites` ...
:ref:`ref-contrib-webdesign`
Solving specific problems
=========================
:ref:`Deployment <howto-deployment-index>`
Release your project to the world.
:ref:`Importing data from legacy databases <howto-legacy-databases>`
Use Django with an existing database or alongside other web development
toolkits.
:ref:`Custom template tags <howto-custom-template-tags>`
Add your own extensions to Django's template language.
:ref:`Generating CSV <howto-outputting-csv>` & :ref:`PDF <howto-outputting-PDF>`
Produce non-HTML content with Django.
And more:
---------
:ref:`Authenticating in Apache <howto-apache-auth>` ...
:ref:`howto-custom-file-storage` ... :ref:`howto-custom-management-commands` ...
:ref:`howto-custom-model-fields` ... :ref:`howto-error-reporting` ...
:ref:`howto-initial-data` ... :ref:`howto-static-files`
Reference Reference
========= =========
.. toctree:: :ref:`Settings <ref-settings>`
:maxdepth: 1 See all of Django's settings and what they do.
django-admin :ref:`Request & response objects <ref-request-response>`
model-api Understand the classes Django uses to represent HTTP requests and responses.
db-api
transactions
templates
templates_python
forms
modelforms
files
upload_handling
testing
sessions
cache
settings
url_dispatch
request_response
generic_views
authentication
shortcuts
unicode
pagination
serialization
i18n
middleware
custom_model_fields
databases
``django.contrib`` add-ons :ref:`Model API reference <ref-models-index>`
-------------------------- Revel in the gory details of Django's model system.
.. toctree:: :ref:`Form API reference <ref-forms-index>`
:maxdepth: 1 Learn the details of forms, fields, and widgets.
admin And more:
add_ons
contenttypes
csrf
databrowse
flatpages
form_preview
form_wizard
localflavor
redirects
sites
sitemaps
syndication_feeds
webdesign
Deployment
----------
.. toctree::
:maxdepth: 1
modpython
fastcgi
Solving specific problems
-------------------------
.. toctree::
:maxdepth: 1
apache_auth
static_files
email
legacy_databases
outputting_pdf
outputting_csv
Et cetera
--------- ---------
.. toctree:: :ref:`ref-databases` ... :ref:`ref-django-admin` ... :ref:`ref-files-index` ...
:maxdepth: 1 :ref:`ref-generic-views` ... :ref:`ref-middleware` ...
:ref:`ref-templates-index` ... :ref:`ref-unicode`
design_philosophies And all the rest
contributing ================
admin_css
api_stability
distributions
Release notes :ref:`Internals <internals-index>`
------------- Learn how Django works under the hood, and how you can contribute to the
project.
.. toctree:: :ref:`Release notes <releases-index>`
:maxdepth: 1 See what is and was new in each release of Django.
release_notes_0.96
release_notes_0.95
release_notes_1.0_alpha
release_notes_1.0_alpha_2
Also see the list of `backwards-incompatible changes`__ for changes made between
releases.
__ http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
:ref:`Miscellany <misc-index>`
Stuff we can't find a more organized place for. Like that drawer in your
kitchen with the scissors, batteries, and duct tape.

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -1,3 +1,5 @@
.. _internals-contributing:
====================== ======================
Contributing to Django Contributing to Django
====================== ======================
@ -30,6 +32,8 @@ community. The rest of this document describes the details of how our community
works and how it handles bugs, mailing lists, and all the other minutiae of works and how it handles bugs, mailing lists, and all the other minutiae of
Django development. Django development.
.. _reporting-bugs:
Reporting bugs Reporting bugs
============== ==============
@ -38,7 +42,7 @@ amount of overhead involved in working with any bug tracking system, so your
help in keeping our ticket tracker as useful as possible is appreciated. In help in keeping our ticket tracker as useful as possible is appreciated. In
particular: particular:
* **Do** read the FAQ_ to see if your issue might be a well-known question. * **Do** read the :ref:`FAQ <faq-index>` to see if your issue might be a well-known question.
* **Do** `search the tracker`_ to see if your issue has already been filed. * **Do** `search the tracker`_ to see if your issue has already been filed.
@ -74,6 +78,8 @@ particular:
.. _django-updates: http://groups.google.com/group/django-updates .. _django-updates: http://groups.google.com/group/django-updates
.. _reporting-security-issues:
Reporting security issues Reporting security issues
========================= =========================
@ -231,7 +237,7 @@ ticket is waiting on.
Since a picture is worth a thousand words, let's start there: Since a picture is worth a thousand words, let's start there:
.. image:: http://media.djangoproject.com/img/doc/djangotickets.png .. image:: _images/djangotickets.png
:height: 451 :height: 451
:width: 590 :width: 590
:alt: Django's ticket workflow :alt: Django's ticket workflow
@ -377,6 +383,8 @@ the ticket database:
be making a change, don't make the change -- leave a comment with your be making a change, don't make the change -- leave a comment with your
concerns on the ticket, or post a message to `django-developers`_. concerns on the ticket, or post a message to `django-developers`_.
.. _contributing-translations:
Submitting and maintaining translations Submitting and maintaining translations
======================================= =======================================
@ -390,21 +398,20 @@ translated, here's what to do:
* Join the `Django i18n mailing list`_ and introduce yourself. * Join the `Django i18n mailing list`_ and introduce yourself.
* Create translations using the methods described in the * Create translations using the methods described in the
`i18n documentation`_. :ref:`i18n documentation <topics-i18n>`.
* Create a diff of the ``.po`` file against the current Subversion trunk. * Create a diff of the ``.po`` file against the current Subversion trunk.
* Make sure that `` django-admin.py compilemessages -l <lang>`` runs without * Make sure that `` django-admin.py compilemessages -l <lang>`` runs without
producing any warnings. producing any warnings.
* Attach the patch to a ticket in Django's ticket system. * Attach the patch to a ticket in Django's ticket system.
.. _Django i18n mailing list: http://groups.google.com/group/django-i18n/ .. _Django i18n mailing list: http://groups.google.com/group/django-i18n/
.. _i18n documentation: ../i18n/
Coding style Coding style
============ ============
Please follow these coding standards when writing code for inclusion in Django: Please follow these coding standards when writing code for inclusion in Django:
* Unless otherwise specified, follow `PEP 8`_. * Unless otherwise specified, follow :pep:8.
You could use a tool like `pep8.py`_ to check for some problems in this You could use a tool like `pep8.py`_ to check for some problems in this
area, but remember that PEP 8 is only a guide, so respect the style of area, but remember that PEP 8 is only a guide, so respect the style of
@ -418,8 +425,8 @@ Please follow these coding standards when writing code for inclusion in Django:
* Use ``InitialCaps`` for class names (or for factory functions that * Use ``InitialCaps`` for class names (or for factory functions that
return classes). return classes).
* Mark all strings for internationalization; see the `i18n documentation`_ * Mark all strings for internationalization; see the :ref:`i18n
for details. documentation <topics-i18n>` for details.
* In docstrings, use "action words" such as:: * In docstrings, use "action words" such as::
@ -449,11 +456,15 @@ Template style
* In Django template code, put one (and only one) space between the curly * In Django template code, put one (and only one) space between the curly
brackets and the tag contents. brackets and the tag contents.
Do this:: Do this:
.. code-block:: html+django
{{ foo }} {{ foo }}
Don't do this:: Don't do this:
.. code-block:: html+django
{{foo}} {{foo}}
@ -706,15 +717,15 @@ The tests cover:
We appreciate any and all contributions to the test suite! We appreciate any and all contributions to the test suite!
The Django tests all use the testing infrastructure that ships with Django for The Django tests all use the testing infrastructure that ships with Django for
testing applications. See `Testing Django applications`_ for an explanation of testing applications. See :ref:`Testing Django applications <topics-testing>`
how to write new tests. for an explanation of how to write new tests.
.. _Testing Django applications: ../testing/
Running the unit tests Running the unit tests
---------------------- ----------------------
To run the tests, ``cd`` to the ``tests/`` directory and type:: To run the tests, ``cd`` to the ``tests/`` directory and type:
.. code-block:: bash
./runtests.py --settings=path.to.django.settings ./runtests.py --settings=path.to.django.settings
@ -727,13 +738,13 @@ needed. A temporary database will be created in memory when running the tests.
If you're using another backend: If you're using another backend:
* Your ``DATABASE_USER`` setting needs to specify an existing user account * Your :setting:`DATABASE_USER` setting needs to specify an existing user account
for the database engine. for the database engine.
* The ``DATABASE_NAME`` setting must be the name of an existing database to * The :setting:`DATABASE_NAME` setting must be the name of an existing database to
which the given user has permission to connect. The unit tests will not which the given user has permission to connect. The unit tests will not
touch this database; the test runner creates a new database whose name is touch this database; the test runner creates a new database whose name is
``DATABASE_NAME`` prefixed with ``test_``, and this test database is :setting:`DATABASE_NAME` prefixed with ``test_``, and this test database is
deleted when the tests are finished. This means your user account needs deleted when the tests are finished. This means your user account needs
permission to execute ``CREATE DATABASE``. permission to execute ``CREATE DATABASE``.
@ -766,7 +777,9 @@ To run a subset of the unit tests, append the names of the test modules to the
As an example, if Django is not in your ``PYTHONPATH``, you placed As an example, if Django is not in your ``PYTHONPATH``, you placed
``settings.py`` in the ``tests/`` directory, and you'd like to only run tests ``settings.py`` in the ``tests/`` directory, and you'd like to only run tests
for generic relations and internationalization, type:: for generic relations and internationalization, type:
.. code-block:: bash
PYTHONPATH=.. PYTHONPATH=..
./runtests.py --settings=settings generic_relations i18n ./runtests.py --settings=settings generic_relations i18n
@ -787,6 +800,7 @@ method as above::
./runtests.py --settings=settings markup ./runtests.py --settings=settings markup
Requesting features Requesting features
=================== ===================
@ -854,7 +868,9 @@ To use a branch, you'll need to do two things:
Getting the code from Subversion Getting the code from Subversion
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To get the latest version of a branch's code, check it out using Subversion:: To get the latest version of a branch's code, check it out using Subversion:
.. code-block:: bash
svn co http://code.djangoproject.com/svn/django/branches/<branch>/ svn co http://code.djangoproject.com/svn/django/branches/<branch>/
@ -862,7 +878,9 @@ To get the latest version of a branch's code, check it out using Subversion::
Alternatively, you can automatically convert an existing directory of the Alternatively, you can automatically convert an existing directory of the
Django source code as long as you've checked it out via Subversion. To do the Django source code as long as you've checked it out via Subversion. To do the
conversion, execute this command from within your ``django`` directory:: conversion, execute this command from within your ``django`` directory:
.. code-block:: bash
svn switch http://code.djangoproject.com/svn/django/branches/<branch>/ svn switch http://code.djangoproject.com/svn/django/branches/<branch>/
@ -1025,12 +1043,10 @@ requests for commit access are potential flame-war starters, and will be ignored
.. _community page: http://www.djangoproject.com/community/ .. _community page: http://www.djangoproject.com/community/
.. _ticket tracker: http://code.djangoproject.com/newticket .. _ticket tracker: http://code.djangoproject.com/newticket
.. _django-developers: http://groups.google.com/group/django-developers .. _django-developers: http://groups.google.com/group/django-developers
.. _FAQ: http://www.djangoproject.com/documentation/faq/
.. _search the tracker: http://code.djangoproject.com/search .. _search the tracker: http://code.djangoproject.com/search
.. _django-users: http://groups.google.com/group/django-users .. _django-users: http://groups.google.com/group/django-users
.. _`#django`: irc://irc.freenode.net/django .. _`#django`: irc://irc.freenode.net/django
.. _list of tickets with patches: http://code.djangoproject.com/query?status=new&status=assigned&status=reopened&has_patch=1&order=priority .. _list of tickets with patches: http://code.djangoproject.com/query?status=new&status=assigned&status=reopened&has_patch=1&order=priority
.. _PEP 8: http://www.python.org/peps/pep-0008.html
.. _pep8.py: http://svn.browsershots.org/trunk/devtools/pep8/pep8.py .. _pep8.py: http://svn.browsershots.org/trunk/devtools/pep8/pep8.py
.. _i18n branch: http://code.djangoproject.com/browser/django/branches/i18n .. _i18n branch: http://code.djangoproject.com/browser/django/branches/i18n
.. _`tags/releases`: http://code.djangoproject.com/browser/django/tags/releases .. _`tags/releases`: http://code.djangoproject.com/browser/django/tags/releases

View File

@ -0,0 +1,204 @@
.. _internals-documentation:
How the Django documentation works
==================================
\... and how to contribute.
Django's documentation uses the Sphinx__ documentation system, which in turn is
based on docutils__. The basic idea is that lightly-formatted plain-text
documentation is transformed into HTML, PDF, and any other output format.
__ http://sphinx.pocoo.org/
__ http://docutils.sf.net/
To actually build the documentation locally, you'll currently need to install
Sphinx -- ``easy_install Sphinx`` should do the trick.
Then, building the html is easy; just ``make html`` from the ``docs`` directory.
To get started contributing, you'll want to read the `ReStructuredText
Primer`__. After that, you'll want to read about the `Sphinx-specific markup`__
that's used to manage metadata, indexing, and cross-references.
__ http://sphinx.pocoo.org/rest.html
__ http://sphinx.pocoo.org/markup/
The main thing to keep in mind as you write and edit docs is that the more
semantic markup you can add the better. So::
Add ``django.contrib.auth`` to your ``INSTALLED_APPS``...
Isn't nearly as helpful as::
Add :mod:`django.contrib.auth` to your :setting:`INSTALLED_APPS`...
This is because Sphinx will generate proper links for the later, which greatly
helps readers. There's basically no limit to the amount of useful markup you can
add.
Django-specific markup
----------------------
Besides the `Sphinx built-in markup`__, Django's docs defines some extra description units:
__ http://sphinx.pocoo.org/markup/desc.html
* Settings::
.. setting:: INSTALLED_APPS
To link to a setting, use ``:setting:`INSTALLED_APPS```.
* Template tags::
.. templatetag:: regroup
To link, use ``:ttag:`regroup```.
* Template filters::
.. templatefilter:: linebreaksbr
To link, use ``:tfilter:`linebreaksbr```.
* Field lookups (i.e. ``Foo.objects.filter(bar__exact=whatever)``)::
.. fieldlookup:: exact
To link, use ``:lookup:`exact```.
* ``django-admin`` commands::
.. django-admin:: syncdb
To link, use ``:djadmin:`syncdb```.
* ``django-admin`` command-line options::
.. django-admin-option:: --traceback
To link, use ``:djadminopt:`--traceback```.
An example
----------
For a quick example of how it all fits together, check this out:
* First, the ``ref/settings.txt`` document starts out like this::
.. _ref-settings:
Available settings
==================
...
* Next, if you look at the ``topics/settings.txt`` document, you can see how
a link to ``ref/settings`` works::
Available settings
==================
For a full list of available settings, see the :ref:`settings reference
<ref-settings>`.
* Next, notice how the settings (right now just the top few) are annotated::
.. setting:: ADMIN_FOR
ADMIN_FOR
---------
Default: ``()`` (Empty tuple)
Used for admin-site settings modules, this should be a tuple of settings
modules (in the format ``'foo.bar.baz'``) for which this site is an
admin.
The admin site uses this in its automatically-introspected
documentation of models, views and template tags.
This marks up the following header as the "canonical" target for the
setting ``ADMIN_FOR`` This means any time I talk about ``ADMIN_FOR``, I
can reference it using ``:setting:`ADMIN_FOR```.
That's basically how everything fits together.
TODO
----
The work is mostly done, but here's what's left, in rough order of priority.
* Fix up generic view docs: adapt Chapter 9 of the Django Book (consider
this TODO item my permission and license) into
``topics/generic-views.txt``; remove the intro material from
``ref/generic-views.txt`` and just leave the function reference.
* Change the "Added/changed in development version" callouts to proper
Sphinx ``.. versionadded::`` or ``.. versionchanged::`` directives.
* Check for and fix malformed links. Do this by running ``make linkcheck``
and fix all of the 300+ errors/warnings.
In particular, look at all the relative links; these need to be
changed to proper references.
* Most of the various ``index.txt`` documents have *very* short or even
non-existent intro text. Each of those documents needs a good short intro
the content below that point.
* The glossary is very perfunctory. It needs to be filled out.
* Add more metadata targets: there's lots of places that look like::
``File.close()``
~~~~~~~~~~~~~~~~
\... these should be::
.. method:: File.close()
That is, use metadata instead of titles.
* Add more links -- nearly everything that's an inline code literal
right now can probably be turned into a xref.
See the ``literals_to_xrefs.py`` file in ``_ext`` -- it's a shell script
to help do this work.
This will probably be a continuing, never-ending project.
* Add `info field lists`__ where appropriate.
__ http://sphinx.pocoo.org/markup/desc.html#info-field-lists
* Add ``.. code-block:: <lang>`` to literal blocks so that they get
highlighted.
Hints
-----
Some hints for making things look/read better:
* Whenever possible, use links. So, use ``:setting:`ADMIN_FOR``` instead of
````ADMIN_FOR````.
* Some directives (``.. setting::``, for one) are prefix-style directives;
they go *before* the unit they're describing. These are known as
"crossref" directives. Others (``.. class::``, e.g.) generate their own
markup; these should go inside the section they're describing. These are
called "description units".
You can tell which are which by looking at in :file:`_ext/djangodocs.py`;
it registers roles as one of the other.
* When referring to classes/functions/modules, etc., you'll want to use the
fully-qualified name of the target
(``:class:`django.contrib.contenttypes.models.ContentType```).
Since this doesn't look all that awesome in the output -- it shows the
entire path to the object -- you can prefix the target with a ``~``
(that's a tilde) to get just the "last bit" of that path. So
``:class:`~django.contrib.contenttypes.models.ContentType``` will just
display a link with the title "ContentType".

22
docs/internals/index.txt Normal file
View File

@ -0,0 +1,22 @@
.. _internals-index:
Django internals
================
Documentation for people hacking on Django itself. This is the place to go if
you'd like to help improve Django, learn or learn about how Django works "under
the hood".
.. warning::
Elsewhere in the Django documentation, coverage of a feature is a sort of a
contract: once an API is in the official documentation, we consider it
"stable" and don't change it without a good reason. APIs covered here,
however, are considered "internal-only": we reserve the right to change
these internals if we must.
.. toctree::
:maxdepth: 1
contributing
documentation

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

38
docs/intro/index.txt Normal file
View File

@ -0,0 +1,38 @@
.. _intro-index:
Getting started
===============
New to Django? Or to web development in general? Well, you came to the right
place: read this material to quickly get up and running.
.. toctree::
:maxdepth: 1
overview
install
tutorial01
tutorial02
tutorial03
tutorial04
whatsnext
.. seealso::
If you're new to Python_, you might want to start by getting an idea of what
the language is like. Django is 100% Python, so if you've got minimal
comfort with Python you'll probably get a lot more out of Django.
If you're new to programming entirely, you might want to start with this
`list of Python resources for non-programmers`_
If you already know a few other languages and want to get up to speed with
Python quickly, we recommend `Dive Into Python`_ (also available in a
`dead-tree version`_). If that's not quite your style, there are quite
a few other `books about Python`_.
.. _python: http://python.org/
.. _list of Python resources for non-programmers: http://wiki.python.org/moin/BeginnersGuide/NonProgrammers
.. _dive into python: http://diveintopython.org/
.. _dead-tree version: http://www.amazon.com/exec/obidos/ASIN/1590593561/ref=nosim/jacobian20
.. _books about Python: http://wiki.python.org/moin/PythonBooks

75
docs/intro/install.txt Normal file
View File

@ -0,0 +1,75 @@
.. _intro-install:
Quick install guide
===================
Before you can use Django, you'll need to get it installed. We have a
:ref:`complete installation guide <topics-install>` that covers all the
possibilities; this guide will guide you to a simple, minimal installation
that'll work while you walk through the introduction.
Install Python
--------------
Being a Python Web framework, Django requires Python. It works with any Python
version 2.3 and higher, but we recommend installing Python 2.5 or later. If you do so, you won't need to set up a database just yet: Python 2.5 or later includes a lightweight database called SQLite_.
.. _sqlite: http://sqlite.org/
Get Python at http://www.python.org. If you're running Linux or Mac OS X, you
probably already have it installed.
You can verify that Python's installed py typing ``python`` from your shell; you should see something like::
Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
Set up a database
-----------------
If you installed Python 2.5 or later, you can skip this step for now.
If not, or if you'd like to work with a "large" database engine like PostgreSQL,
MySQL, or Oracle, consult the :ref:`database installation information
<database-installation>`.
Remove any old versions of Django
---------------------------------
If you are upgrading your installation of Django from a previous version, you
will need to :ref:`uninstall the old Django version before installing the new
version <removing-old-versions-of-django>`.
Install Django
--------------
You've got three easy options to install Django:
* Install a version of Django :ref:`provided by your operating system
distribution <misc-distributions>`. This is the quickest option for those
who have operating systems that distribute Django.
* :ref:`Install an official release <installing-official-release>`. This
is the best approach for users who want a stable version number and aren't
concerned about running a slightly older version of Django.
* :ref:`Install the latest development version
<installing-development-version>`. This is best for users who want the
latest-and-greatest features and aren't afraid of running brand-new code.
.. warning::
If do either of the first two steps, keep an eye out for parts of the
documentation marked **new in development version**. That phrase flags
features that are only available in development versions of Django; if you
try to use them with an official release they won't work.
That's it!
----------
That's it -- you can now :ref:`move onto the tutorial <intro-tutorial01>`.

View File

@ -1,3 +1,5 @@
.. _intro-overview:
================== ==================
Django at a glance Django at a glance
================== ==================
@ -8,10 +10,9 @@ overview of how to write a database-driven Web app with Django.
The goal of this document is to give you enough technical specifics to The goal of this document is to give you enough technical specifics to
understand how Django works, but this isn't intended to be a tutorial or understand how Django works, but this isn't intended to be a tutorial or
reference. Please see our more-detailed Django documentation_ when you're ready reference -- but we've got both! When you're ready to start a project, you can
to start a project. :ref:`start with the tutorial <intro-tutorial01>` or :ref:`dive right into more
detailed documentation <topics-index>`.
.. _documentation: ../
Design your model Design your model
================= =================
@ -20,9 +21,9 @@ Although you can use Django without a database, it comes with an
object-relational mapper in which you describe your database layout in Python object-relational mapper in which you describe your database layout in Python
code. code.
The data-model syntax offers many rich ways of representing your models -- so The :ref:`data-model syntax <topics-db-models>` offers many rich ways of
far, it's been solving two years' worth of database-schema problems. Here's a representing your models -- so far, it's been solving two years' worth of
quick example:: database-schema problems. Here's a quick example::
class Reporter(models.Model): class Reporter(models.Model):
full_name = models.CharField(max_length=70) full_name = models.CharField(max_length=70)
@ -43,18 +44,20 @@ Install it
========== ==========
Next, run the Django command-line utility to create the database tables Next, run the Django command-line utility to create the database tables
automatically:: automatically:
.. code-block:: bash
manage.py syncdb manage.py syncdb
The ``syncdb`` command looks at all your available models and creates tables The :djadmin:`syncdb` command looks at all your available models and creates
in your database for whichever tables don't already exist. tables in your database for whichever tables don't already exist.
Enjoy the free API Enjoy the free API
================== ==================
With that, you've got a free, and rich, Python API to access your data. The API With that, you've got a free, and rich, :ref:`Python API <topics-db-queries>` to
is created on the fly, no code generation necessary:: access your data. The API is created on the fly, no code generation necessary::
>>> from mysite.models import Reporter, Article >>> from mysite.models import Reporter, Article
@ -128,15 +131,16 @@ A dynamic admin interface: it's not just scaffolding -- it's the whole house
============================================================================ ============================================================================
Once your models are defined, Django can automatically create a professional, Once your models are defined, Django can automatically create a professional,
production ready administrative interface -- a Web site that lets authenticated production ready :ref:`administrative interface <ref-contrib-admin>` -- a Web
users add, change and delete objects. It's as easy as adding a line of code to site that lets authenticated users add, change and delete objects. It's as easy
your model classes:: as adding a line of code to your model classes::
class Article(models.Model): class Article(models.Model):
pub_date = models.DateTimeField() pub_date = models.DateTimeField()
headline = models.CharField(max_length=200) headline = models.CharField(max_length=200)
content = models.TextField() content = models.TextField()
reporter = models.ForeignKey(Reporter) reporter = models.ForeignKey(Reporter)
class Admin: pass class Admin: pass
The philosophy here is that your site is edited by a staff, or a client, or The philosophy here is that your site is edited by a staff, or a client, or
@ -154,10 +158,10 @@ A clean, elegant URL scheme is an important detail in a high-quality Web
application. Django encourages beautiful URL design and doesn't put any cruft application. Django encourages beautiful URL design and doesn't put any cruft
in URLs, like ``.php`` or ``.asp``. in URLs, like ``.php`` or ``.asp``.
To design URLs for an app, you create a Python module called a URLconf. A table To design URLs for an app, you create a Python module called a :ref:`URLconf
of contents for your app, it contains a simple mapping between URL patterns and <topics-http-urls>`. A table of contents for your app, it contains a simple mapping
Python callback functions. URLconfs also serve to decouple URLs from Python between URL patterns and Python callback functions. URLconfs also serve to
code. decouple URLs from Python code.
Here's what a URLconf might look like for the ``Reporter``/``Article`` Here's what a URLconf might look like for the ``Reporter``/``Article``
example above:: example above::
@ -190,8 +194,9 @@ Write your views
================ ================
Each view is responsible for doing one of two things: Returning an Each view is responsible for doing one of two things: Returning an
``HttpResponse`` object containing the content for the requested page, or :class:`~django.http.HttpResponse` object containing the content for the
raising an exception such as ``Http404``. The rest is up to you. requested page, or raising an exception such as :class:`~django.http.Http404`.
The rest is up to you.
Generally, a view retrieves data according to the parameters, loads a template Generally, a view retrieves data according to the parameters, loads a template
and renders the template with the retrieved data. Here's an example view for and renders the template with the retrieved data. Here's an example view for
@ -201,8 +206,9 @@ and renders the template with the retrieved data. Here's an example view for
a_list = Article.objects.filter(pub_date__year=year) a_list = Article.objects.filter(pub_date__year=year)
return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list}) return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list})
This example uses Django's template system, which has several powerful This example uses Django's :ref:`template system <topics-templates>`, which has
features but strives to stay simple enough for non-programmers to use. several powerful features but strives to stay simple enough for non-programmers
to use.
Design your templates Design your templates
===================== =====================
@ -215,7 +221,9 @@ for templates. If a template doesn't exist in the first directory, it checks the
second, and so on. second, and so on.
Let's say the ``news/article_detail.html`` template was found. Here's what that Let's say the ``news/article_detail.html`` template was found. Here's what that
might look like:: might look like:
.. code-block:: html+django
{% extends "base.html" %} {% extends "base.html" %}
@ -252,7 +260,9 @@ Finally, Django uses the concept of "template inheritance": That's what the
following blocks." In short, that lets you dramatically cut down on redundancy following blocks." In short, that lets you dramatically cut down on redundancy
in templates: each template has to define only what's unique to that template. in templates: each template has to define only what's unique to that template.
Here's what the "base.html" template might look like:: Here's what the "base.html" template might look like:
.. code-block:: html+django
<html> <html>
<head> <head>
@ -287,17 +297,18 @@ This is just the surface
This has been only a quick overview of Django's functionality. Some more useful This has been only a quick overview of Django's functionality. Some more useful
features: features:
* A caching framework that integrates with memcached or other backends. * A :ref:`caching framework <topics-cache>` that integrates with memcached
* A `syndication framework`_ that makes creating RSS and Atom feeds as easy as or other backends.
writing a small Python class.
* A :ref:`syndication framework <ref-contrib-syndication>` that makes
creating RSS and Atom feeds as easy as writing a small Python class.
* More sexy automatically-generated admin features -- this overview barely * More sexy automatically-generated admin features -- this overview barely
scratched the surface. scratched the surface.
.. _syndication framework: ../syndication_feeds/ The next obvious steps are for you to `download Django`_, read :ref:`the
tutorial <intro-tutorial01>` and join `the community`_. Thanks for your
The next obvious steps are for you to `download Django`_, read `the tutorial`_ interest!
and join `the community`_. Thanks for your interest!
.. _download Django: http://www.djangoproject.com/download/ .. _download Django: http://www.djangoproject.com/download/
.. _the tutorial: ../tutorial01/
.. _the community: http://www.djangoproject.com/community/ .. _the community: http://www.djangoproject.com/community/

View File

@ -1,3 +1,5 @@
.. _intro-tutorial01:
===================================== =====================================
Writing your first Django app, part 1 Writing your first Django app, part 1
===================================== =====================================
@ -12,71 +14,70 @@ It'll consist of two parts:
* A public site that lets people view polls and vote in them. * A public site that lets people view polls and vote in them.
* An admin site that lets you add, change and delete polls. * An admin site that lets you add, change and delete polls.
We'll assume you have `Django installed`_ already. You can tell Django is We'll assume you have :ref:`Django installed <intro-install>` already. You can
installed by running the Python interactive interpreter and typing tell Django is installed by running the Python interactive interpreter and
``import django``. If that command runs successfully, with no errors, Django is typing ``import django``. If that command runs successfully, with no errors,
installed. Django is installed.
.. _`Django installed`: ../install/
.. admonition:: Where to get help: .. admonition:: Where to get help:
If you're having trouble going through this tutorial, please post a message If you're having trouble going through this tutorial, please post a message
to `django-users`_ or drop by `#django`_ on ``irc.freenode.net`` to chat to `django-users`__ or drop by `#django on irc.freenode.net`__ to chat
with other Django users who might be able to help. with other Django users who might be able to help.
.. _django-users: http://groups.google.com/group/django-users __ http://groups.google.com/group/django-users
.. _#django: irc://irc.freenode.net/django __ irc://irc.freenode.net/django
Creating a project Creating a project
================== ==================
If this is your first time using Django, you'll have to take care of some If this is your first time using Django, you'll have to take care of some
initial setup. Namely, you'll need to auto-generate some code that establishes initial setup. Namely, you'll need to auto-generate some code that establishes a
a Django *project* -- a collection of settings for an instance of Django, Django :term:`project` -- a collection of settings for an instance of Django,
including database configuration, Django-specific options and including database configuration, Django-specific options and
application-specific settings. application-specific settings.
From the command line, ``cd`` into a directory where you'd like to store your From the command line, ``cd`` into a directory where you'd like to store your
code, then run the command ``django-admin.py startproject mysite``. This code, then run the command ``django-admin.py startproject mysite``. This will
will create a ``mysite`` directory in your current directory. create a ``mysite`` directory in your current directory.
.. admonition:: Mac OS X permissions .. admonition:: Mac OS X permissions
If you're using Mac OS X, you may see the message "permission If you're using Mac OS X, you may see the message "permission denied" when
denied" when you try to run ``django-admin.py startproject``. This you try to run ``django-admin.py startproject``. This is because, on
is because, on Unix-based systems like OS X, a file must be marked Unix-based systems like OS X, a file must be marked as "executable" before it
as "executable" before it can be run as a program. To do this, open can be run as a program. To do this, open Terminal.app and navigate (using
Terminal.app and navigate (using the ``cd`` command) to the directory the ``cd`` command) to the directory where :ref:`django-admin.py
where ``django-admin.py`` is installed, then run the command <ref-django-admin>` is installed, then run the command
``chmod +x django-admin.py``. ``chmod +x django-admin.py``.
.. note:: .. note::
You'll need to avoid naming projects after built-in Python or Django You'll need to avoid naming projects after built-in Python or Django
components. In particular, this means you should avoid using names like components. In particular, this means you should avoid using names like
``django`` (which will conflict with Django itself) or ``site`` (which ``django`` (which will conflict with Django itself) or ``test`` (which
conflicts with a built-in Python package). conflicts with a built-in Python package).
(``django-admin.py`` should be on your system path if you installed Django via :ref:`django-admin.py <ref-django-admin>` should be on your system path if you
``python setup.py``. If it's not on your path, you can find it in installed Django via ``python setup.py``. If it's not on your path, you can find
``site-packages/django/bin``, where ``site-packages`` is a directory within it in ``site-packages/django/bin``, where ```site-packages``` is a directory
your Python installation. Consider symlinking to ``django-admin.py`` from some within your Python installation. Consider symlinking to :ref:`django-admin.py
place on your path, such as ``/usr/local/bin``.) <ref-django-admin>` from some place on your path, such as
:file:`/usr/local/bin`.
.. admonition:: Where should this code live? .. admonition:: Where should this code live?
If your background is in PHP, you're probably used to putting code under the If your background is in PHP, you're probably used to putting code under the
Web server's document root (in a place such as ``/var/www``). With Django, Web server's document root (in a place such as ``/var/www``). With Django,
you don't do that. It's not a good idea to put any of this Python code within you don't do that. It's not a good idea to put any of this Python code
your Web server's document root, because it risks the possibility that within your Web server's document root, because it risks the possibility
people may be able to view your code over the Web. That's not good for that people may be able to view your code over the Web. That's not good for
security. security.
Put your code in some directory **outside** of the document root, such as Put your code in some directory **outside** of the document root, such as
``/home/mycode``. :file:`/home/mycode`.
Let's look at what ``startproject`` created:: Let's look at what :djadmin:`startproject` created::
mysite/ mysite/
__init__.py __init__.py
@ -86,28 +87,34 @@ Let's look at what ``startproject`` created::
These files are: These files are:
* ``__init__.py``: An empty file that tells Python that this directory * :file:`__init__.py`: An empty file that tells Python that this directory
should be considered a Python package. (Read `more about packages`_ in the should be considered a Python package. (Read `more about packages`_ in the
official Python docs if you're a Python beginner.) official Python docs if you're a Python beginner.)
* ``manage.py``: A command-line utility that lets you interact with this
Django project in various ways. * :file:`manage.py`: A command-line utility that lets you interact with this
* ``settings.py``: Settings/configuration for this Django project. Django project in various ways. You can read all the details about
* ``urls.py``: The URL declarations for this Django project; a "table of :file:`manage.py` in :ref:`ref-django-admin`.
contents" of your Django-powered site.
* :file:`settings.py`: Settings/configuration for this Django project.
:ref:`topics-settings` will tell you all about how settings work.
* :file:`urls.py`: The URL declarations for this Django project; a "table of
contents" of your Django-powered site. You can read more about URLs in
:ref:`topics-http-urls`.
.. _more about packages: http://docs.python.org/tut/node8.html#packages .. _more about packages: http://docs.python.org/tut/node8.html#packages
The development server The development server
---------------------- ----------------------
Let's verify this worked. Change into the ``mysite`` directory, if you Let's verify this worked. Change into the :file:`mysite` directory, if you
haven't already, and run the command ``python manage.py runserver``. You'll see haven't already, and run the command ``python manage.py runserver``. You'll see
the following output on the command line:: the following output on the command line::
Validating models... Validating models...
0 errors found. 0 errors found.
Django version 0.95, using settings 'mysite.settings' Django version 0.96, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/ Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows). Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
@ -126,40 +133,49 @@ It worked!
.. admonition:: Changing the port .. admonition:: Changing the port
By default, the ``runserver`` command starts the development server on port By default, the :djadmin:`runserver` command starts the development server
8000. If you want to change the server's port, pass it as a command-line on port 8000. If you want to change the server's port, pass it as a
argument. For instance, this command starts the server on port 8080:: command-line argument. For instance, this command starts the server on port
8080:
.. code-block:: bash
python manage.py runserver 8080 python manage.py runserver 8080
Full docs for the development server are at `django-admin documentation`_. Full docs for the development server can be found in the
:djadmin:`runserver` reference.
.. _django-admin documentation: ../django-admin/
Database setup Database setup
-------------- --------------
Now, edit ``settings.py``. It's a normal Python module with module-level Now, edit :file:`settings.py`. It's a normal Python module with module-level
variables representing Django settings. Change these settings to match your variables representing Django settings. Change these settings to match your
database's connection parameters: database's connection parameters:
* ``DATABASE_ENGINE`` -- Either 'postgresql_psycopg2', 'mysql' or 'sqlite3'. * :setting:`DATABASE_ENGINE` -- Either 'postgresql_psycopg2', 'mysql' or
Other backends are `also available`_. 'sqlite3'. Other backends are :setting:`also available <DATABASE_ENGINE>`.
* ``DATABASE_NAME`` -- The name of your database. If you're using
SQLite, the database will be a file on your computer; in that
case, ``DATABASE_NAME`` should be the full absolute path,
including filename, of that file. If the file doesn't exist, it
will automatically be created when you synchronize the database
for the first time (see below).
* ``DATABASE_USER`` -- Your database username (not used for SQLite).
* ``DATABASE_PASSWORD`` -- Your database password (not used for SQLite).
* ``DATABASE_HOST`` -- The host your database is on. Leave this as an
empty string if your database server is on the same physical machine
(not used for SQLite).
.. _also available: ../settings/ * :setting:`DATABASE_NAME` -- The name of your database. If you're using
SQLite, the database will be a file on your computer; in that case,
``DATABASE_NAME`` should be the full absolute path, including filename, of
that file. If the file doesn't exist, it will automatically be created
when you synchronize the database for the first time (see below).
.. admonition:: Note * :setting:`DATABASE_USER` -- Your database username (not used for SQLite).
* :setting:`DATABASE_PASSWORD` -- Your database password (not used for
SQLite).
* :setting:`DATABASE_HOST` -- The host your database is on. Leave this as an
empty string if your database server is on the same physical machine (not
used for SQLite).
If you're new to databases, we recommend simply using SQLite (by setting
:setting:`DATABASE_ENGINE` to ``'sqlite3'``). SQLite is included as part of
Python 2.5 and later, so you won't need to install anything else.
.. note::
If you're using PostgreSQL or MySQL, make sure you've created a database by If you're using PostgreSQL or MySQL, make sure you've created a database by
this point. Do that with "``CREATE DATABASE database_name;``" within your this point. Do that with "``CREATE DATABASE database_name;``" within your
@ -168,35 +184,39 @@ database's connection parameters:
If you're using SQLite, you don't need to create anything beforehand - the If you're using SQLite, you don't need to create anything beforehand - the
database file will be created automatically when it is needed. database file will be created automatically when it is needed.
While you're editing ``settings.py``, take note of the ``INSTALLED_APPS`` While you're editing :file:`settings.py`, take note of the
setting towards the bottom of the file. That variable holds the names of all :setting:`INSTALLED_APPS` setting towards the bottom of the file. That variable
Django applications that are activated in this Django instance. Apps can be holds the names of all Django applications that are activated in this Django
used in multiple projects, and you can package and distribute them for use instance. Apps can be used in multiple projects, and you can package and
by others in their projects. distribute them for use by others in their projects.
By default, ``INSTALLED_APPS`` contains the following apps, all of which come By default, :setting:`INSTALLED_APPS` contains the following apps, all of which
with Django: come with Django:
* ``django.contrib.auth`` -- An authentication system. * :mod:`django.contrib.auth` -- An authentication system.
* ``django.contrib.contenttypes`` -- A framework for content types.
* ``django.contrib.sessions`` -- A session framework. * :mod:`django.contrib.contenttypes` -- A framework for content types.
* ``django.contrib.sites`` -- A framework for managing multiple sites
* :mod:`django.contrib.sessions` -- A session framework.
* :mod:`django.contrib.sites` -- A framework for managing multiple sites
with one Django installation. with one Django installation.
These applications are included by default as a convenience for the common These applications are included by default as a convenience for the common case.
case.
Each of these applications makes use of at least one database table, though, Each of these applications makes use of at least one database table, though,
so we need to create the tables in the database before we can use them. To do so we need to create the tables in the database before we can use them. To do
that, run the following command:: that, run the following command:
.. code-block:: bash
python manage.py syncdb python manage.py syncdb
The ``syncdb`` command looks at the ``INSTALLED_APPS`` setting and creates any The :djadmin:`syncdb` command looks at the :setting:`INSTALLED_APPS` setting and
necessary database tables according to the database settings in your creates any necessary database tables according to the database settings in your
``settings.py`` file. You'll see a message for each database table it creates, :file:`settings.py` file. You'll see a message for each database table it
and you'll get a prompt asking you if you'd like to create a superuser account creates, and you'll get a prompt asking you if you'd like to create a superuser
for the authentication system. Go ahead and do that. account for the authentication system. Go ahead and do that.
If you're interested, run the command-line client for your database and type If you're interested, run the command-line client for your database and type
``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to ``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to
@ -207,8 +227,11 @@ display the tables Django created.
Like we said above, the default applications are included for the common Like we said above, the default applications are included for the common
case, but not everybody needs them. If you don't need any or all of them, case, but not everybody needs them. If you don't need any or all of them,
feel free to comment-out or delete the appropriate line(s) from feel free to comment-out or delete the appropriate line(s) from
``INSTALLED_APPS`` before running ``syncdb``. The ``syncdb`` command will :setting:`INSTALLED_APPS` before running :djadmin:`syncdb`. The
only create tables for apps in ``INSTALLED_APPS``. :djadmin:`syncdb` command will only create tables for apps in
:setting:`INSTALLED_APPS`.
.. _creating-models:
Creating models Creating models
=============== ===============
@ -229,17 +252,19 @@ so you can focus on writing code rather than creating directories.
configuration and apps for a particular Web site. A project can contain configuration and apps for a particular Web site. A project can contain
multiple apps. An app can be in multiple projects. multiple apps. An app can be in multiple projects.
In this tutorial, we'll create our poll app in the ``mysite`` directory, In this tutorial, we'll create our poll app in the :file:`mysite` directory,
for simplicity. As a consequence, the app will be coupled to the project -- for simplicity. As a consequence, the app will be coupled to the project --
that is, Python code within the poll app will refer to ``mysite.polls``. that is, Python code within the poll app will refer to ``mysite.polls``.
Later in this tutorial, we'll discuss decoupling your apps for distribution. Later in this tutorial, we'll discuss decoupling your apps for distribution.
To create your app, make sure you're in the ``mysite`` directory and type To create your app, make sure you're in the :file:`mysite` directory and type
this command:: this command:
.. code-block:: bash
python manage.py startapp polls python manage.py startapp polls
That'll create a directory ``polls``, which is laid out like this:: That'll create a directory :file:`polls`, which is laid out like this::
polls/ polls/
__init__.py __init__.py
@ -253,17 +278,17 @@ The first step in writing a database Web app in Django is to define your models
.. admonition:: Philosophy .. admonition:: Philosophy
A model is the single, definitive source of data about your A model is the single, definitive source of data about your data. It contains
data. It contains the essential fields and behaviors of the data you're the essential fields and behaviors of the data you're storing. Django follows
storing. Django follows the `DRY Principle`_. The goal is to define your the :ref:`DRY Principle <dry>`. The goal is to define your data model in one
data model in one place and automatically derive things from it. place and automatically derive things from it.
In our simple poll app, we'll create two models: polls and choices. A poll has In our simple poll app, we'll create two models: polls and choices. A poll has
a question and a publication date. A choice has two fields: the text of the a question and a publication date. A choice has two fields: the text of the
choice and a vote tally. Each choice is associated with a poll. choice and a vote tally. Each choice is associated with a poll.
These concepts are represented by simple Python classes. Edit the These concepts are represented by simple Python classes. Edit the
``polls/models.py`` file so it looks like this:: :file:`polls/models.py` file so it looks like this::
from django.db import models from django.db import models
@ -276,51 +301,54 @@ These concepts are represented by simple Python classes. Edit the
choice = models.CharField(max_length=200) choice = models.CharField(max_length=200)
votes = models.IntegerField() votes = models.IntegerField()
.. admonition:: Errors about ``max_length`` .. admonition:: Errors about :attr:`~django.db.models.Field.max_length`
If Django gives you an error message saying that ``max_length`` is If Django gives you an error message saying that
not a valid argument, you're most likely using an old version of :attr:`~django.db.models.Field.max_length` is not a valid argument, you're
Django. (This version of the tutorial is written for the latest most likely using an old version of Django. (This version of the tutorial is
development version of Django.) If you're using a Subversion checkout written for the latest development version of Django.) If you're using a
of Django's development version (see `the installation docs`_ for Subversion checkout of Django's development version (see :ref:`the
more information), you shouldn't have any problems. installation docs <topics-install>` for more information), you shouldn't have
any problems.
If you want to stick with an older version of Django, you'll want to If you want to stick with an older version of Django, you'll want to switch
switch to `the Django 0.96 tutorial`_, because this tutorial covers to `the Django 0.96 tutorial`_, because this tutorial covers several features
several features that only exist in the Django development version. that only exist in the Django development version.
.. _the installation docs: ../install/ .. _the Django 0.96 tutorial: http://www.djangoproject.com/documentation/0.96/tutorial01/
.. _the Django 0.96 tutorial: ../0.96/tutorial01/
The code is straightforward. Each model is represented by a class that The code is straightforward. Each model is represented by a class that
subclasses ``django.db.models.Model``. Each model has a number of class subclasses :class:`django.db.models.Model`. Each model has a number of class
variables, each of which represents a database field in the model. variables, each of which represents a database field in the model.
Each field is represented by an instance of a ``models.*Field`` class -- e.g., Each field is represented by an instance of a :class:`~django.db.models.Field`
``models.CharField`` for character fields and ``models.DateTimeField`` for class -- e.g., :class:`~django.db.models.CharField` for character fields and
datetimes. This tells Django what type of data each field holds. :class:`~django.db.models.DateTimeField` for datetimes. This tells Django what
type of data each field holds.
The name of each ``models.*Field`` instance (e.g. ``question`` or ``pub_date`` ) The name of each :class:`~django.db.models.Field` instance (e.g. ``question`` or
is the field's name, in machine-friendly format. You'll use this value in your ``pub_date`` ) is the field's name, in machine-friendly format. You'll use this
Python code, and your database will use it as the column name. value in your Python code, and your database will use it as the column name.
You can use an optional first positional argument to a ``Field`` to designate a You can use an optional first positional argument to a
human-readable name. That's used in a couple of introspective parts of Django, :class:`~django.db.models.Field` to designate a human-readable name. That's used
and it doubles as documentation. If this field isn't provided, Django will use in a couple of introspective parts of Django, and it doubles as documentation.
the machine-readable name. In this example, we've only defined a human-readable If this field isn't provided, Django will use the machine-readable name. In this
name for ``Poll.pub_date``. For all other fields in this model, the field's example, we've only defined a human-readable name for ``Poll.pub_date``. For all
machine-readable name will suffice as its human-readable name. other fields in this model, the field's machine-readable name will suffice as
its human-readable name.
Some ``Field`` classes have required elements. ``CharField``, for example, Some :class:`~django.db.models.Field` classes have required elements.
requires that you give it a ``max_length``. That's used not only in the database :class:`~django.db.models.CharField`, for example, requires that you give it a
:attr:`~django.db.models.Field.max_length`. That's used not only in the database
schema, but in validation, as we'll soon see. schema, but in validation, as we'll soon see.
Finally, note a relationship is defined, using ``models.ForeignKey``. That tells Finally, note a relationship is defined, using
Django each Choice is related to a single Poll. Django supports all the common :class:`~django.db.models.ForeignKey`. That tells Django each Choice is related
database relationships: many-to-ones, many-to-manys and one-to-ones. to a single Poll. Django supports all the common database relationships:
many-to-ones, many-to-manys and one-to-ones.
.. _`Python path`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000 .. _`Python path`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000
.. _DRY Principle: http://c2.com/cgi/wiki?DontRepeatYourself
Activating models Activating models
================= =================
@ -339,8 +367,9 @@ But first we need to tell our project that the ``polls`` app is installed.
you can distribute apps, because they don't have to be tied to a given you can distribute apps, because they don't have to be tied to a given
Django installation. Django installation.
Edit the ``settings.py`` file again, and change the ``INSTALLED_APPS`` setting Edit the :file:`settings.py` file again, and change the
to include the string ``'mysite.polls'``. So it'll look like this:: :setting:`INSTALLED_APPS` setting to include the string ``'mysite.polls'``. So
it'll look like this::
INSTALLED_APPS = ( INSTALLED_APPS = (
'django.contrib.auth', 'django.contrib.auth',
@ -350,12 +379,17 @@ to include the string ``'mysite.polls'``. So it'll look like this::
'mysite.polls' 'mysite.polls'
) )
Now Django knows ``mysite`` includes the ``polls`` app. Let's run another command:: Now Django knows ``mysite`` includes the ``polls`` app. Let's run another
command:
.. code-block:: bash
python manage.py sql polls python manage.py sql polls
You should see something similar to the following (the CREATE TABLE SQL statements You should see something similar to the following (the ``CREATE TABLE`` SQL
for the polls app):: statements for the polls app):
.. code-block:: sql
BEGIN; BEGIN;
CREATE TABLE "polls_poll" ( CREATE TABLE "polls_poll" (
@ -384,7 +418,8 @@ Note the following:
* By convention, Django appends ``"_id"`` to the foreign key field name. * By convention, Django appends ``"_id"`` to the foreign key field name.
Yes, you can override this, as well. Yes, you can override this, as well.
* The foreign key relationship is made explicit by a ``REFERENCES`` statement. * The foreign key relationship is made explicit by a ``REFERENCES``
statement.
* It's tailored to the database you're using, so database-specific field * It's tailored to the database you're using, so database-specific field
types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or
@ -393,53 +428,58 @@ Note the following:
quotes. The author of this tutorial runs PostgreSQL, so the example quotes. The author of this tutorial runs PostgreSQL, so the example
output is in PostgreSQL syntax. output is in PostgreSQL syntax.
* The ``sql`` command doesn't actually run the SQL in your database - it just * The :djadmin:`sql` command doesn't actually run the SQL in your database -
prints it to the screen so that you can see what SQL Django thinks is required. it just prints it to the screen so that you can see what SQL Django thinks
If you wanted to, you could copy and paste this SQL into your database prompt. is required. If you wanted to, you could copy and paste this SQL into your
However, as we will see shortly, Django provides an easier way of committing database prompt. However, as we will see shortly, Django provides an
the SQL to the database. easier way of committing the SQL to the database.
If you're interested, also run the following commands: If you're interested, also run the following commands:
* ``python manage.py validate`` -- Checks for any errors in the
construction of your models.
* ``python manage.py sqlcustom polls`` -- Outputs any custom SQL statements * :djadmin:`python manage.py validate <validate>` -- Checks for any errors
(such as table modifications or constraints) that are defined for the in the construction of your models.
application.
* ``python manage.py sqlclear polls`` -- Outputs the necessary ``DROP * :djadmin:`python manage.py sqlcustom polls <sqlcustom>` -- Outputs any
TABLE`` statements for this app, according to which tables already exist :ref:`custom SQL statements <initial-sql>` (such as table modifications or
in your database (if any). constraints) that are defined for the application.
* ``python manage.py sqlindexes polls`` -- Outputs the ``CREATE INDEX`` * :djadmin:`python manage.py sqlclear polls <sqlclear>` -- Outputs the
statements for this app. necessary ``DROP TABLE`` statements for this app, according to which
tables already exist in your database (if any).
* ``python manage.py sqlall polls`` -- A combination of all the SQL from * :djadmin:`python manage.py sqlindexes polls <sqlindexes>` -- Outputs the
the 'sql', 'sqlcustom', and 'sqlindexes' commands. ``CREATE INDEX`` statements for this app.
* :djadmin:`python manage.py sqlall polls <sqlall>` -- A combination of all
the SQL from the :djadmin:`sql`, :djadmin:`sqlcustom`, and
:djadmin:`sqlindexes` commands.
Looking at the output of those commands can help you understand what's actually Looking at the output of those commands can help you understand what's actually
happening under the hood. happening under the hood.
Now, run ``syncdb`` again to create those model tables in your database:: Now, run :djadmin:`syncdb` again to create those model tables in your database:
.. code-block:: bash
python manage.py syncdb python manage.py syncdb
The ``syncdb`` command runs the sql from 'sqlall' on your database for all apps The :djadmin:`syncdb` command runs the sql from 'sqlall' on your database for
in ``INSTALLED_APPS`` that don't already exist in your database. This creates all apps in :setting:`INSTALLED_APPS` that don't already exist in your database.
all the tables, initial data and indexes for any apps you have added to your This creates all the tables, initial data and indexes for any apps you have
project since the last time you ran syncdb. ``syncdb`` can be called as often added to your project since the last time you ran syncdb. :djadmin:`syncdb` can
as you like, and it will only ever create the tables that don't exist. be called as often as you like, and it will only ever create the tables that
don't exist.
Read the `django-admin.py documentation`_ for full information on what the Read the :ref:`django-admin.py documentation <ref-django-admin>` for full
``manage.py`` utility can do. information on what the ``manage.py`` utility can do.
.. _django-admin.py documentation: ../django-admin/
Playing with the API Playing with the API
==================== ====================
Now, let's hop into the interactive Python shell and play around with the free Now, let's hop into the interactive Python shell and play around with the free
API Django gives you. To invoke the Python shell, use this command:: API Django gives you. To invoke the Python shell, use this command:
.. code-block:: bash
python manage.py shell python manage.py shell
@ -449,28 +489,28 @@ things:
* Putting ``mysite`` on ``sys.path``. For flexibility, several pieces of * Putting ``mysite`` on ``sys.path``. For flexibility, several pieces of
Django refer to projects in Python dotted-path notation (e.g. Django refer to projects in Python dotted-path notation (e.g.
``'mysite.polls.models'``). In order for this to work, the ``'mysite.polls.models'``). In order for this to work, the ``mysite``
``mysite`` package has to be on ``sys.path``. package has to be on ``sys.path``.
We've already seen one example of this: the ``INSTALLED_APPS`` setting is We've already seen one example of this: the :setting:`INSTALLED_APPS`
a list of packages in dotted-path notation. setting is a list of packages in dotted-path notation.
* Setting the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives * Setting the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives
Django the path to your ``settings.py`` file. Django the path to your ``settings.py`` file.
.. admonition:: Bypassing manage.py .. admonition:: Bypassing manage.py
If you'd rather not use ``manage.py``, no problem. Just make sure If you'd rather not use ``manage.py``, no problem. Just make sure ``mysite``
``mysite`` is at the root level on the Python path (i.e., is at the root level on the Python path (i.e., ``import mysite`` works) and
``import mysite`` works) and set the ``DJANGO_SETTINGS_MODULE`` set the ``DJANGO_SETTINGS_MODULE`` environment variable to
environment variable to ``mysite.settings``. ``mysite.settings``.
For more information on all of this, see the `django-admin.py documentation`_. For more information on all of this, see the :ref:`django-admin.py
documentation <ref-django-admin>`.
Once you're in the shell, explore the database API:: Once you're in the shell, explore the :ref:`database API <topics-db-queries>`::
# Import the model classes we just wrote. >>> from mysite.polls.models import Poll, Choice # Import the model classes we just wrote.
>>> from mysite.polls.models import Poll, Choice
# No polls are in the system yet. # No polls are in the system yet.
>>> Poll.objects.all() >>> Poll.objects.all()
@ -505,10 +545,11 @@ Once you're in the shell, explore the database API::
[<Poll: Poll object>] [<Poll: Poll object>]
Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful representation
representation of this object. Let's fix that by editing the polls model (in of this object. Let's fix that by editing the polls model (in the
the ``polls/models.py`` file) and adding a ``__unicode__()`` method to both ``polls/models.py`` file) and adding a
``Poll`` and ``Choice``:: :meth:`~django.db.models.Model.__unicode__` method to both ``Poll`` and
``Choice``::
class Poll(models.Model): class Poll(models.Model):
# ... # ...
@ -520,43 +561,46 @@ the ``polls/models.py`` file) and adding a ``__unicode__()`` method to both
def __unicode__(self): def __unicode__(self):
return self.choice return self.choice
.. admonition:: If ``__unicode__()`` doesn't seem to work .. admonition:: If :meth:`~django.db.models.Model.__unicode__` doesn't seem to work
If you add the ``__unicode__()`` method to your models and don't If you add the :meth:`~django.db.models.Model.__unicode__` method to your
see any change in how they're represented, you're most likely using models and don't see any change in how they're represented, you're most
an old version of Django. (This version of the tutorial is written likely using an old version of Django. (This version of the tutorial is
for the latest development version of Django.) If you're using a written for the latest development version of Django.) If you're using a
Subversion checkout of of Django's development version (see `the Subversion checkout of of Django's development version (see :ref:`the
installation docs`_ for more information), you shouldn't have any installation docs <topics-install>` for more information), you shouldn't have
problems. any problems.
If you want to stick with an older version of Django, you'll want to If you want to stick with an older version of Django, you'll want to switch
switch to `the Django 0.96 tutorial`_, because this tutorial covers to `the Django 0.96 tutorial`_, because this tutorial covers several features
several features that only exist in the Django development version. that only exist in the Django development version.
.. _the installation docs: ../install/ .. _the Django 0.96 tutorial: http://www.djangoproject.com/documentation/0.96/tutorial01/
.. _the Django 0.96 tutorial: ../0.96/tutorial01/
It's important to add ``__unicode__()`` methods to your models, not only for It's important to add :meth:`~django.db.models.Model.__unicode__` methods to
your own sanity when dealing with the interactive prompt, but also because your models, not only for your own sanity when dealing with the interactive
objects' representations are used throughout Django's automatically-generated prompt, but also because objects' representations are used throughout Django's
admin. automatically-generated admin.
.. admonition:: Why ``__unicode__()`` and not ``__str__()``? .. admonition:: Why :meth:`~django.db.models.Model.__unicode__` and not
:meth:`django.db.models.Model.__str__`?
If you're familiar with Python, you might be in the habit of adding If you're familiar with Python, you might be in the habit of adding
``__str__()`` methods to your classes, not ``__unicode__()`` methods. :meth:`django.db.models.Model.__str__` methods to your classes, not
We use ``__unicode__()`` here because Django models deal with Unicode by :meth:`~django.db.models.Model.__unicode__` methods. We use
default. All data stored in your database is converted to Unicode when it's :meth:`~django.db.models.Model.__unicode__` here because Django models deal
returned. with Unicode by default. All data stored in your database is converted to
Unicode when it's returned.
Django models have a default ``__str__()`` method that calls Django models have a default :meth:`django.db.models.Model.__str__` method
``__unicode__()`` and converts the result to a UTF-8 bytestring. This means that calls :meth:`~django.db.models.Model.__unicode__` and converts the
that ``unicode(p)`` will return a Unicode string, and ``str(p)`` will return result to a UTF-8 bytestring. This means that ``unicode(p)`` will return a
a normal string, with characters encoded as UTF-8. Unicode string, and ``str(p)`` will return a normal string, with characters
encoded as UTF-8.
If all of this is jibberish to you, just remember to add ``__unicode__()`` If all of this is jibberish to you, just remember to add
methods to your models. With any luck, things should Just Work for you. :meth:`~django.db.models.Model.__unicode__` methods to your models. With any
luck, things should Just Work for you.
Note these are normal Python methods. Let's add a custom method, just for Note these are normal Python methods. Let's add a custom method, just for
demonstration:: demonstration::
@ -639,10 +683,8 @@ Let's jump back into the Python interactive shell by running
>>> c = p.choice_set.filter(choice__startswith='Just hacking') >>> c = p.choice_set.filter(choice__startswith='Just hacking')
>>> c.delete() >>> c.delete()
For full details on the database API, see our `Database API reference`_. For full details on the database API, see our :ref:`Database API reference
<topics-db-queries>`.
When you're comfortable with the API, read `part 2 of this tutorial`_ to get When you're comfortable with the API, read :ref:`part 2 of this tutorial
Django's automatic admin working. <intro-tutorial02>` to get Django's automatic admin working.
.. _Database API reference: ../db-api/
.. _part 2 of this tutorial: ../tutorial02/

View File

@ -1,26 +1,27 @@
.. _intro-tutorial02:
===================================== =====================================
Writing your first Django app, part 2 Writing your first Django app, part 2
===================================== =====================================
This tutorial begins where `Tutorial 1`_ left off. We're continuing the Web-poll This tutorial begins where :ref:`Tutorial 1 <intro-tutorial01>` left off. We're
application and will focus on Django's automatically-generated admin site. continuing the Web-poll application and will focus on Django's
automatically-generated admin site.
.. _Tutorial 1: ../tutorial01/
.. admonition:: Philosophy .. admonition:: Philosophy
Generating admin sites for your staff or clients to add, change and delete Generating admin sites for your staff or clients to add, change and delete
content is tedious work that doesn't require much creativity. For that reason, content is tedious work that doesn't require much creativity. For that
Django entirely automates creation of admin interfaces for models. reason, Django entirely automates creation of admin interfaces for models.
Django was written in a newsroom environment, with a very clear separation Django was written in a newsroom environment, with a very clear separation
between "content publishers" and the "public" site. Site managers use the between "content publishers" and the "public" site. Site managers use the
system to add news stories, events, sports scores, etc., and that content is system to add news stories, events, sports scores, etc., and that content is
displayed on the public site. Django solves the problem of creating a unified displayed on the public site. Django solves the problem of creating a
interface for site administrators to edit content. unified interface for site administrators to edit content.
The admin isn't necessarily intended to be used by site visitors; it's for site The admin isn't necessarily intended to be used by site visitors; it's for
managers. site managers.
Activate the admin site Activate the admin site
======================= =======================
@ -28,10 +29,10 @@ Activate the admin site
The Django admin site is not activated by default -- it's an opt-in thing. To The Django admin site is not activated by default -- it's an opt-in thing. To
activate the admin site for your installation, do these three things: activate the admin site for your installation, do these three things:
* Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting. * Add ``"django.contrib.admin"`` to your :setting:`INSTALLED_APPS` setting.
* Run ``python manage.py syncdb``. Since you have added a new application * Run ``python manage.py syncdb``. Since you have added a new application
to ``INSTALLED_APPS``, the database tables need to be updated. to :setting:`INSTALLED_APPS`, the database tables need to be updated.
* Edit your ``mysite/urls.py`` file and uncomment the lines below the * Edit your ``mysite/urls.py`` file and uncomment the lines below the
"Uncomment this for admin:" comments. This file is a URLconf; we'll dig "Uncomment this for admin:" comments. This file is a URLconf; we'll dig
@ -65,14 +66,16 @@ Start the development server
Let's start the development server and explore the admin site. Let's start the development server and explore the admin site.
Recall from Tutorial 1 that you start the development server like so:: Recall from Tutorial 1 that you start the development server like so:
.. code-block:: bash
python manage.py runserver python manage.py runserver
Now, open a Web browser and go to "/admin/" on your local domain -- e.g., Now, open a Web browser and go to "/admin/" on your local domain -- e.g.,
http://127.0.0.1:8000/admin/. You should see the admin's login screen: http://127.0.0.1:8000/admin/. You should see the admin's login screen:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin01.png .. image:: _images/admin01.png
:alt: Django admin login screen :alt: Django admin login screen
Enter the admin site Enter the admin site
@ -81,24 +84,22 @@ Enter the admin site
Now, try logging in. (You created a superuser account in the first part of this Now, try logging in. (You created a superuser account in the first part of this
tutorial, remember?) You should see the Django admin index page: tutorial, remember?) You should see the Django admin index page:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin02t.png .. image:: _images/admin02t.png
:alt: Django admin index page :alt: Django admin index page
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin02.png
You should see a few other types of editable content, including groups, users You should see a few other types of editable content, including groups, users
and sites. These are core features Django ships with by default. and sites. These are core features Django ships with by default.
.. _"I can't log in" questions: ../faq/#the-admin-site
Make the poll app modifiable in the admin Make the poll app modifiable in the admin
========================================= =========================================
But where's our poll app? It's not displayed on the admin index page. But where's our poll app? It's not displayed on the admin index page.
Just one thing to do: We need to tell the admin that ``Poll`` Just one thing to do: We need to tell the admin that ``Poll``
objects have an admin interface. Edit the ``mysite/polls/models.py`` file and objects have an admin interface. Edit the ``mysite/polls/admin.py`` file and
add the following to the bottom of the file:: add the following to the bottom of the file::
from mysite.polls.models import Poll
from django.contrib import admin from django.contrib import admin
admin.site.register(Poll) admin.site.register(Poll)
@ -113,52 +114,54 @@ Explore the free admin functionality
Now that we've registered ``Poll``, Django knows that it should be displayed on Now that we've registered ``Poll``, Django knows that it should be displayed on
the admin index page: the admin index page:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin03t.png .. image:: _images/admin03t.png
:alt: Django admin index page, now with polls displayed :alt: Django admin index page, now with polls displayed
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin03.png
Click "Polls." Now you're at the "change list" page for polls. This page Click "Polls." Now you're at the "change list" page for polls. This page
displays all the polls in the database and lets you choose one to change it. displays all the polls in the database and lets you choose one to change it.
There's the "What's up?" poll we created in the first tutorial: There's the "What's up?" poll we created in the first tutorial:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin04t.png .. image:: _images/admin04t.png
:alt: Polls change list page :alt: Polls change list page
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin04.png
Click the "What's up?" poll to edit it: Click the "What's up?" poll to edit it:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin05t.png .. image:: _images/admin05t.png
:alt: Editing form for poll object :alt: Editing form for poll object
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin05.png
Things to note here: Things to note here:
* The form is automatically generated from the Poll model. * The form is automatically generated from the Poll model.
* The different model field types (``models.DateTimeField``, ``models.CharField``)
correspond to the appropriate HTML input widget. Each type of field knows * The different model field types (:class:`~django.db.models.DateTimeField`,
how to display itself in the Django admin. :class:`~django.db.models.CharField`) correspond to the appropriate HTML
* Each ``DateTimeField`` gets free JavaScript shortcuts. Dates get a "Today" input widget. Each type of field knows how to display itself in the Django
shortcut and calendar popup, and times get a "Now" shortcut and a convenient admin.
popup that lists commonly entered times.
* Each :class:`~django.db.models.DateTimeField` gets free JavaScript
shortcuts. Dates get a "Today" shortcut and calendar popup, and times get
a "Now" shortcut and a convenient popup that lists commonly entered times.
The bottom part of the page gives you a couple of options: The bottom part of the page gives you a couple of options:
* Save -- Saves changes and returns to the change-list page for this type of * Save -- Saves changes and returns to the change-list page for this type of
object. object.
* Save and continue editing -- Saves changes and reloads the admin page for
* Save and continue editing -- Saves changes and reloads the admin page for
this object. this object.
* Save and add another -- Saves changes and loads a new, blank form for this
* Save and add another -- Saves changes and loads a new, blank form for this
type of object. type of object.
* Delete -- Displays a delete confirmation page.
* Delete -- Displays a delete confirmation page.
Change the "Date published" by clicking the "Today" and "Now" shortcuts. Then Change the "Date published" by clicking the "Today" and "Now" shortcuts. Then
click "Save and continue editing." Then click "History" in the upper right. click "Save and continue editing." Then click "History" in the upper right.
You'll see a page listing all changes made to this object via the Django admin, You'll see a page listing all changes made to this object via the Django admin,
with the timestamp and username of the person who made the change: with the timestamp and username of the person who made the change:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin06t.png .. image:: _images/admin06t.png
:alt: History page for poll object :alt: History page for poll object
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin06.png
Customize the admin form Customize the admin form
======================== ========================
@ -184,7 +187,7 @@ admin options for an object.
This particular change above makes the "Publication date" come before the This particular change above makes the "Publication date" come before the
"Question" field: "Question" field:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin07.png .. image:: _images/admin07.png
:alt: Fields have been reordered :alt: Fields have been reordered
This isn't impressive with only two fields, but for admin forms with dozens This isn't impressive with only two fields, but for admin forms with dozens
@ -204,9 +207,8 @@ up into fieldsets::
The first element of each tuple in ``fieldsets`` is the title of the fieldset. The first element of each tuple in ``fieldsets`` is the title of the fieldset.
Here's what our form looks like now: Here's what our form looks like now:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin08t.png .. image:: _images/admin08t.png
:alt: Form has fieldsets now :alt: Form has fieldsets now
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin08.png
You can assign arbitrary HTML classes to each fieldset. Django provides a You can assign arbitrary HTML classes to each fieldset. Django provides a
``"collapse"`` class that displays a particular fieldset initially collapsed. ``"collapse"`` class that displays a particular fieldset initially collapsed.
@ -219,7 +221,7 @@ aren't commonly used::
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
] ]
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin09.png .. image:: _images/admin09.png
:alt: Fieldset is initially collapsed :alt: Fieldset is initially collapsed
Adding related objects Adding related objects
@ -233,17 +235,20 @@ Yet.
There are two ways to solve this problem. The first register ``Choice`` with the There are two ways to solve this problem. The first register ``Choice`` with the
admin just as we did with ``Poll``. That's easy:: admin just as we did with ``Poll``. That's easy::
from mysite.polls.models import Choice
admin.site.register(Choice) admin.site.register(Choice)
Now "Choices" is an available option in the Django admin. The "Add choice" form Now "Choices" is an available option in the Django admin. The "Add choice" form
looks like this: looks like this:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin10.png .. image:: _images/admin10.png
:alt: Choice admin page :alt: Choice admin page
In that form, the "Poll" field is a select box containing every poll in the In that form, the "Poll" field is a select box containing every poll in the
database. Django knows that a ``ForeignKey`` should be represented in the admin database. Django knows that a :class:`~django.db.models.ForeignKey` should be
as a ``<select>`` box. In our case, only one poll exists at this point. represented in the admin as a ``<select>`` box. In our case, only one poll
exists at this point.
Also note the "Add Another" link next to "Poll." Every object with a Also note the "Add Another" link next to "Poll." Every object with a
``ForeignKey`` relationship to another gets this for free. When you click "Add ``ForeignKey`` relationship to another gets this for free. When you click "Add
@ -259,6 +264,7 @@ Poll object. Let's make that happen.
Remove the ``register()`` call for the Choice model. Then, edit the ``Poll`` Remove the ``register()`` call for the Choice model. Then, edit the ``Poll``
registration code to read:: registration code to read::
poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3)
class ChoiceInline(admin.StackedInline): class ChoiceInline(admin.StackedInline):
model = Choice model = Choice
extra = 3 extra = 3
@ -277,16 +283,15 @@ default, provide enough fields for 3 choices."
Load the "Add poll" page to see how that looks: Load the "Add poll" page to see how that looks:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin11t.png .. image:: _images/admin11t.png
:alt: Add poll page now has choices on it :alt: Add poll page now has choices on it
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin11.png
It works like this: There are three slots for related Choices -- as specified It works like this: There are three slots for related Choices -- as specified
by ``extra`` -- and each time you come back to the "Change" page for an by ``extra`` -- and each time you come back to the "Change" page for an
already-created object, you get another three extra slots. already-created object, you get another three extra slots.
One small problem, though. It takes a lot of screen space to display all the One small problem, though. It takes a lot of screen space to display all the
fields for entering related Choice objects. For that reason, Django offers an fields for entering related Choice objects. For that reason, Django offers a
tabular way of displaying inline related objects; you just need to change tabular way of displaying inline related objects; you just need to change
the ``ChoiceInline`` declaration to read:: the ``ChoiceInline`` declaration to read::
@ -296,7 +301,7 @@ the ``ChoiceInline`` declaration to read::
With that ``TabularInline`` (instead of ``StackedInline``), the With that ``TabularInline`` (instead of ``StackedInline``), the
related objects are displayed in a more compact, table-based format: related objects are displayed in a more compact, table-based format:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin12.png .. image:: _images/admin12.png
:alt: Add poll page now has more compact choices :alt: Add poll page now has more compact choices
Customize the admin change list Customize the admin change list
@ -307,9 +312,8 @@ Now that the Poll admin page is looking good, let's make some tweaks to the
Here's what it looks like at this point: Here's what it looks like at this point:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin04t.png .. image:: _images/admin04t.png
:alt: Polls change list page :alt: Polls change list page
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin04.png
By default, Django displays the ``str()`` of each object. But sometimes it'd be By default, Django displays the ``str()`` of each object. But sometimes it'd be
more helpful if we could display individual fields. To do that, use the more helpful if we could display individual fields. To do that, use the
@ -329,9 +333,8 @@ method from Tutorial 1::
Now the poll change list page looks like this: Now the poll change list page looks like this:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin13t.png .. image:: _images/admin13t.png
:alt: Polls change list page, updated :alt: Polls change list page, updated
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin13.png
You can click on the column headers to sort by those values -- except in the You can click on the column headers to sort by those values -- except in the
case of the ``was_published_today`` header, because sorting by the output of case of the ``was_published_today`` header, because sorting by the output of
@ -352,9 +355,8 @@ following line to ``PollAdmin``::
That adds a "Filter" sidebar that lets people filter the change list by the That adds a "Filter" sidebar that lets people filter the change list by the
``pub_date`` field: ``pub_date`` field:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin14t.png .. image:: _images/admin14t.png
:alt: Polls change list page, updated :alt: Polls change list page, updated
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin14.png
The type of filter displayed depends on the type of field you're filtering on. The type of filter displayed depends on the type of field you're filtering on.
Because ``pub_date`` is a DateTimeField, Django knows to give the default Because ``pub_date`` is a DateTimeField, Django knows to give the default
@ -395,11 +397,12 @@ is powered by Django itself, and its interfaces use Django's own template
system. (How meta!) system. (How meta!)
Open your settings file (``mysite/settings.py``, remember) and look at the Open your settings file (``mysite/settings.py``, remember) and look at the
``TEMPLATE_DIRS`` setting. ``TEMPLATE_DIRS`` is a tuple of filesystem :setting:`TEMPLATE_DIRS` setting. :setting:`TEMPLATE_DIRS` is a tuple of
directories to check when loading Django templates. It's a search path. filesystem directories to check when loading Django templates. It's a search
path.
By default, ``TEMPLATE_DIRS`` is empty. So, let's add a line to it, to tell By default, :setting:`TEMPLATE_DIRS` is empty. So, let's add a line to it, to
Django where our templates live:: tell Django where our templates live::
TEMPLATE_DIRS = ( TEMPLATE_DIRS = (
"/home/my_username/mytemplates", # Change this to your own directory. "/home/my_username/mytemplates", # Change this to your own directory.
@ -407,9 +410,10 @@ Django where our templates live::
Now copy the template ``admin/base_site.html`` from within the default Django Now copy the template ``admin/base_site.html`` from within the default Django
admin template directory (``django/contrib/admin/templates``) into an ``admin`` admin template directory (``django/contrib/admin/templates``) into an ``admin``
subdirectory of whichever directory you're using in ``TEMPLATE_DIRS``. For subdirectory of whichever directory you're using in :setting:`TEMPLATE_DIRS`.
example, if your ``TEMPLATE_DIRS`` includes ``"/home/my_username/mytemplates"``, For example, if your :setting:`TEMPLATE_DIRS` includes
as above, then copy ``django/contrib/admin/templates/admin/base_site.html`` to ``"/home/my_username/mytemplates"``, as above, then copy
``django/contrib/admin/templates/admin/base_site.html`` to
``/home/my_username/mytemplates/admin/base_site.html``. Don't forget that ``/home/my_username/mytemplates/admin/base_site.html``. Don't forget that
``admin`` subdirectory. ``admin`` subdirectory.
@ -421,13 +425,11 @@ override a template, just do the same thing you did with ``base_site.html`` --
copy it from the default directory into your custom directory, and make copy it from the default directory into your custom directory, and make
changes. changes.
Astute readers will ask: But if ``TEMPLATE_DIRS`` was empty by default, how was Astute readers will ask: But if :setting:`TEMPLATE_DIRS` was empty by default,
Django finding the default admin templates? The answer is that, by default, how was Django finding the default admin templates? The answer is that, by
Django automatically looks for a ``templates/`` subdirectory within each app default, Django automatically looks for a ``templates/`` subdirectory within
package, for use as a fallback. See the `loader types documentation`_ for full each app package, for use as a fallback. See the :ref:`template loader
information. documentation <template-loaders>` for full information.
.. _loader types documentation: ../templates_python/#loader-types
Customize the admin index page Customize the admin index page
============================== ==============================
@ -435,10 +437,10 @@ Customize the admin index page
On a similar note, you might want to customize the look and feel of the Django On a similar note, you might want to customize the look and feel of the Django
admin index page. admin index page.
By default, it displays all the apps in your ``INSTALLED_APPS`` setting that By default, it displays all the apps in :setting:`INSTALLED_APPS` that have been
have been registered with the admin application, in alphabetical order. You registered with the admin application, in alphabetical order. You may want to
may want to make significant changes to the layout. After all, the index is make significant changes to the layout. After all, the index is probably the
probably the most important page of the admin, and it should be easy to use. most important page of the admin, and it should be easy to use.
The template to customize is ``admin/index.html``. (Do the same as with The template to customize is ``admin/index.html``. (Do the same as with
``admin/base_site.html`` in the previous section -- copy it from the default ``admin/base_site.html`` in the previous section -- copy it from the default
@ -447,15 +449,9 @@ uses a template variable called ``app_list``. That variable contains every
installed Django app. Instead of using that, you can hard-code links to installed Django app. Instead of using that, you can hard-code links to
object-specific admin pages in whatever way you think is best. object-specific admin pages in whatever way you think is best.
Django offers another shortcut in this department. Run the command Django offers another shortcut in this department. Run the command ``python
``python manage.py adminindex polls`` to get a chunk of template code for manage.py adminindex polls`` to get a chunk of template code for inclusion in
inclusion in the admin index template. It's a useful starting point. the admin index template. It's a useful starting point.
For full details on customizing the look and feel of the Django admin site in When you're comfortable with the admin site, read :ref:`part 3 of this tutorial
general, see the `Django admin CSS guide`_. <intro-tutorial03>` to start working on public poll views.
When you're comfortable with the admin site, read `part 3 of this tutorial`_ to
start working on public poll views.
.. _Django admin CSS guide: ../admin_css/
.. _part 3 of this tutorial: ../tutorial03/

View File

@ -1,11 +1,12 @@
.. _intro-tutorial03:
===================================== =====================================
Writing your first Django app, part 3 Writing your first Django app, part 3
===================================== =====================================
This tutorial begins where `Tutorial 2`_ left off. We're continuing the Web-poll This tutorial begins where :ref:`Tutorial 2 <intro-tutorial02>` left off. We're
application and will focus on creating the public interface -- "views." continuing the Web-poll application and will focus on creating the public
interface -- "views."
.. _Tutorial 2: ../tutorial02/
Philosophy Philosophy
========== ==========
@ -15,20 +16,28 @@ a specific function and has a specific template. For example, in a weblog
application, you might have the following views: application, you might have the following views:
* Blog homepage -- displays the latest few entries. * Blog homepage -- displays the latest few entries.
* Entry "detail" page -- permalink page for a single entry. * Entry "detail" page -- permalink page for a single entry.
* Year-based archive page -- displays all months with entries in the * Year-based archive page -- displays all months with entries in the
given year. given year.
* Month-based archive page -- displays all days with entries in the * Month-based archive page -- displays all days with entries in the
given month. given month.
* Day-based archive page -- displays all entries in the given day. * Day-based archive page -- displays all entries in the given day.
* Comment action -- handles posting comments to a given entry. * Comment action -- handles posting comments to a given entry.
In our poll application, we'll have the following four views: In our poll application, we'll have the following four views:
* Poll "archive" page -- displays the latest few polls. * Poll "archive" page -- displays the latest few polls.
* Poll "detail" page -- displays a poll question, with no results but * Poll "detail" page -- displays a poll question, with no results but
with a form to vote. with a form to vote.
* Poll "results" page -- displays results for a particular poll. * Poll "results" page -- displays results for a particular poll.
* Vote action -- handles voting for a particular choice in a particular * Vote action -- handles voting for a particular choice in a particular
poll. poll.
@ -42,8 +51,8 @@ creating a Python module, called a URLconf. URLconfs are how Django associates
a given URL with given Python code. a given URL with given Python code.
When a user requests a Django-powered page, the system looks at the When a user requests a Django-powered page, the system looks at the
``ROOT_URLCONF`` setting, which contains a string in Python dotted syntax. :setting:`ROOT_URLCONF` setting, which contains a string in Python dotted
Django loads that module and looks for a module-level variable called syntax. Django loads that module and looks for a module-level variable called
``urlpatterns``, which is a sequence of tuples in the following format:: ``urlpatterns``, which is a sequence of tuples in the following format::
(regular expression, Python callback function [, optional dictionary]) (regular expression, Python callback function [, optional dictionary])
@ -53,17 +62,19 @@ comparing the requested URL against each regular expression until it finds one
that matches. that matches.
When it finds a match, Django calls the Python callback function, with an When it finds a match, Django calls the Python callback function, with an
``HTTPRequest`` object as the first argument, any "captured" values from the :class:`~django.http.HttpRequest` object as the first argument, any "captured"
regular expression as keyword arguments, and, optionally, arbitrary keyword values from the regular expression as keyword arguments, and, optionally,
arguments from the dictionary (an optional third item in the tuple). arbitrary keyword arguments from the dictionary (an optional third item in the
tuple).
For more on ``HTTPRequest`` objects, see the `request and response documentation`_. For more on :class:`~django.http.HttpRequest` objects, see the
For more details on URLconfs, see the `URLconf documentation`_. :ref:`ref-request-response`. For more details on URLconfs, see the
:ref:`topics-http-urls`.
When you ran ``python django-admin.py startproject mysite`` at the beginning of When you ran ``python django-admin.py startproject mysite`` at the beginning of
Tutorial 1, it created a default URLconf in ``mysite/urls.py``. It also Tutorial 1, it created a default URLconf in ``mysite/urls.py``. It also
automatically set your ``ROOT_URLCONF`` setting (in ``settings.py``) to point automatically set your :setting:`ROOT_URLCONF` setting (in ``settings.py``) to
at that file:: point at that file::
ROOT_URLCONF = 'mysite.urls' ROOT_URLCONF = 'mysite.urls'
@ -78,27 +89,27 @@ Time for an example. Edit ``mysite/urls.py`` so it looks like this::
(r'^polls/(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'), (r'^polls/(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
) )
This is worth a review. When somebody requests a page from your Web site -- This is worth a review. When somebody requests a page from your Web site -- say,
say, "/polls/23/", Django will load this Python module, because it's pointed to "/polls/23/", Django will load this Python module, because it's pointed to by
by the ``ROOT_URLCONF`` setting. It finds the variable named ``urlpatterns`` the :setting:`ROOT_URLCONF` setting. It finds the variable named ``urlpatterns``
and traverses the regular expressions in order. When it finds a regular and traverses the regular expressions in order. When it finds a regular
expression that matches -- ``r'^polls/(?P<poll_id>\d+)/$'`` -- it loads the expression that matches -- ``r'^polls/(?P<poll_id>\d+)/$'`` -- it loads the
associated Python package/module: ``mysite.polls.views.detail``. That associated Python package/module: ``mysite.polls.views.detail``. That
corresponds to the function ``detail()`` in ``mysite/polls/views.py``. corresponds to the function ``detail()`` in ``mysite/polls/views.py``. Finally,
Finally, it calls that ``detail()`` function like so:: it calls that ``detail()`` function like so::
detail(request=<HttpRequest object>, poll_id='23') detail(request=<HttpRequest object>, poll_id='23')
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parenthesis around a The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parenthesis
pattern "captures" the text matched by that pattern and sends it as an argument around a pattern "captures" the text matched by that pattern and sends it as an
to the view function; the ``?P<poll_id>`` defines the name that will be used to argument to the view function; the ``?P<poll_id>`` defines the name that will be
identify the matched pattern; and ``\d+`` is a regular expression to match a sequence of used to identify the matched pattern; and ``\d+`` is a regular expression to
digits (i.e., a number). match a sequence of digits (i.e., a number).
Because the URL patterns are regular expressions, there really is no limit on Because the URL patterns are regular expressions, there really is no limit on
what you can do with them. And there's no need to add URL cruft such as what you can do with them. And there's no need to add URL cruft such as ``.php``
``.php`` -- unless you have a sick sense of humor, in which case you can do -- unless you have a sick sense of humor, in which case you can do something
something like this:: like this::
(r'^polls/latest\.php$', 'mysite.polls.views.index'), (r'^polls/latest\.php$', 'mysite.polls.views.index'),
@ -110,16 +121,14 @@ the URLconf will look for ``/myapp/``. In a request to
``http://www.example.com/myapp/?page=3``, the URLconf will look for ``/myapp/``. ``http://www.example.com/myapp/?page=3``, the URLconf will look for ``/myapp/``.
If you need help with regular expressions, see `Wikipedia's entry`_ and the If you need help with regular expressions, see `Wikipedia's entry`_ and the
`Python documentation`_. Also, the O'Reilly book "Mastering Regular `Python documentation`_. Also, the O'Reilly book "Mastering Regular Expressions"
Expressions" by Jeffrey Friedl is fantastic. by Jeffrey Friedl is fantastic.
Finally, a performance note: these regular expressions are compiled the first Finally, a performance note: these regular expressions are compiled the first
time the URLconf module is loaded. They're super fast. time the URLconf module is loaded. They're super fast.
.. _Wikipedia's entry: http://en.wikipedia.org/wiki/Regular_expression .. _Wikipedia's entry: http://en.wikipedia.org/wiki/Regular_expression
.. _Python documentation: http://www.python.org/doc/current/lib/module-re.html .. _Python documentation: http://www.python.org/doc/current/lib/module-re.html
.. _request and response documentation: ../request_response/
.. _URLconf documentation: ../url_dispatch/
Write your first view Write your first view
===================== =====================
@ -127,7 +136,9 @@ Write your first view
Well, we haven't created any views yet -- we just have the URLconf. But let's Well, we haven't created any views yet -- we just have the URLconf. But let's
make sure Django is following the URLconf properly. make sure Django is following the URLconf properly.
Fire up the Django development Web server:: Fire up the Django development Web server:
.. code-block:: bash
python manage.py runserver python manage.py runserver
@ -170,21 +181,22 @@ provide in the URL.
Write views that actually do something Write views that actually do something
====================================== ======================================
Each view is responsible for doing one of two things: Returning an ``HttpResponse`` Each view is responsible for doing one of two things: Returning an
object containing the content for the requested page, or raising an exception :class:`~django.http.HttpResponse` object containing the content for the
such as ``Http404``. The rest is up to you. requested page, or raising an exception such as :exc:`~django.http.Http404`. The
rest is up to you.
Your view can read records from a database, or not. It can use a template Your view can read records from a database, or not. It can use a template
system such as Django's -- or a third-party Python template system -- or not. system such as Django's -- or a third-party Python template system -- or not.
It can generate a PDF file, output XML, create a ZIP file on the fly, anything It can generate a PDF file, output XML, create a ZIP file on the fly, anything
you want, using whatever Python libraries you want. you want, using whatever Python libraries you want.
All Django wants is that ``HttpResponse``. Or an exception. All Django wants is that :class:`~django.http.HttpResponse`. Or an exception.
Because it's convenient, let's use Django's own database API, which we covered Because it's convenient, let's use Django's own database API, which we covered
in Tutorial 1. Here's one stab at the ``index()`` view, which displays the in :ref:`Tutorial 1 <intro-tutorial01>`. Here's one stab at the ``index()``
latest 5 poll questions in the system, separated by commas, according to view, which displays the latest 5 poll questions in the system, separated by
publication date:: commas, according to publication date::
from mysite.polls.models import Poll from mysite.polls.models import Poll
from django.http import HttpResponse from django.http import HttpResponse
@ -210,8 +222,8 @@ So let's use Django's template system to separate the design from Python::
}) })
return HttpResponse(t.render(c)) return HttpResponse(t.render(c))
That code loads the template called "polls/index.html" and passes it a context. The That code loads the template called "polls/index.html" and passes it a context.
context is a dictionary mapping template variable names to Python objects. The context is a dictionary mapping template variable names to Python objects.
Reload the page. Now you'll see an error:: Reload the page. Now you'll see an error::
@ -219,20 +231,21 @@ Reload the page. Now you'll see an error::
polls/index.html polls/index.html
Ah. There's no template yet. First, create a directory, somewhere on your Ah. There's no template yet. First, create a directory, somewhere on your
filesystem, whose contents Django can access. (Django runs as whatever user filesystem, whose contents Django can access. (Django runs as whatever user your
your server runs.) Don't put them under your document root, though. You server runs.) Don't put them under your document root, though. You probably
probably shouldn't make them public, just for security's sake. shouldn't make them public, just for security's sake.
Then edit :setting:`TEMPLATE_DIRS` in your ``settings.py`` to tell Django where
Then edit ``TEMPLATE_DIRS`` in your ``settings.py`` to tell Django where it can it can find templates -- just as you did in the "Customize the admin look and
find templates -- just as you did in the "Customize the admin look and feel" feel" section of Tutorial 2.
section of Tutorial 2.
When you've done that, create a directory ``polls`` in your template directory. When you've done that, create a directory ``polls`` in your template directory.
Within that, create a file called ``index.html``. Note that our Within that, create a file called ``index.html``. Note that our
``loader.get_template('polls/index.html')`` code from above maps to ``loader.get_template('polls/index.html')`` code from above maps to
"[template_directory]/polls/index.html" on the filesystem. "[template_directory]/polls/index.html" on the filesystem.
Put the following code in that template:: Put the following code in that template:
.. code-block:: html+django
{% if latest_poll_list %} {% if latest_poll_list %}
<ul> <ul>
@ -251,8 +264,9 @@ A shortcut: render_to_response()
-------------------------------- --------------------------------
It's a very common idiom to load a template, fill a context and return an It's a very common idiom to load a template, fill a context and return an
``HttpResponse`` object with the result of the rendered template. Django :class:`~django.http.HttpResponse` object with the result of the rendered
provides a shortcut. Here's the full ``index()`` view, rewritten:: template. Django provides a shortcut. Here's the full ``index()`` view,
rewritten::
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from mysite.polls.models import Poll from mysite.polls.models import Poll
@ -261,11 +275,14 @@ provides a shortcut. Here's the full ``index()`` view, rewritten::
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5] latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list}) return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})
Note that once we've done this in all these views, we no longer need to import ``loader``, ``Context`` and ``HttpResponse``. Note that once we've done this in all these views, we no longer need to import
:mod:`~django.template.loader`, :class:`~django.template.Context` and
:class:`~django.http.HttpResponse`.
The ``render_to_response()`` function takes a template name as its first The :func:`~django.shortcuts.render_to_response` function takes a template name
argument and a dictionary as its optional second argument. It returns an as its first argument and a dictionary as its optional second argument. It
``HttpResponse`` object of the given template rendered with the given context. returns an :class:`~django.http.HttpResponse` object of the given template
rendered with the given context.
Raising 404 Raising 404
=========== ===========
@ -282,15 +299,15 @@ for a given poll. Here's the view::
raise Http404 raise Http404
return render_to_response('polls/detail.html', {'poll': p}) return render_to_response('polls/detail.html', {'poll': p})
The new concept here: The view raises the ``django.http.Http404`` The new concept here: The view raises the :exc:`~django.http.Http404` exception
exception if a poll with the requested ID doesn't exist. if a poll with the requested ID doesn't exist.
A shortcut: get_object_or_404() A shortcut: get_object_or_404()
------------------------------- -------------------------------
It's a very common idiom to use ``get()`` and raise ``Http404`` if the It's a very common idiom to use :meth:`~django.db.models.QuerySet.get` and raise
object doesn't exist. Django provides a shortcut. Here's the ``detail()`` view, :exc:`~django.http.Http404` if the object doesn't exist. Django provides a
rewritten:: shortcut. Here's the ``detail()`` view, rewritten::
from django.shortcuts import render_to_response, get_object_or_404 from django.shortcuts import render_to_response, get_object_or_404
# ... # ...
@ -298,32 +315,36 @@ rewritten::
p = get_object_or_404(Poll, pk=poll_id) p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('polls/detail.html', {'poll': p}) return render_to_response('polls/detail.html', {'poll': p})
The ``get_object_or_404()`` function takes a Django model module as its first The :func:`~django.shortcuts.get_object_or_404` function takes a Django model
argument and an arbitrary number of keyword arguments, which it passes to the module as its first argument and an arbitrary number of keyword arguments, which
module's ``get()`` function. It raises ``Http404`` if the object doesn't it passes to the module's :meth:`~django.db.models.QuerySet.get` function. It
exist. raises :exc:`~django.http.Http404` if the object doesn't exist.
.. admonition:: Philosophy .. admonition:: Philosophy
Why do we use a helper function ``get_object_or_404()`` instead of Why do we use a helper function :func:`~django.shortcuts.get_object_or_404`
automatically catching the ``DoesNotExist`` exceptions at a higher level, instead of automatically catching the
or having the model API raise ``Http404`` instead of ``DoesNotExist``? :exc:`~django.core.exceptions.ObjectDoesNotExist` exceptions at a higher
level, or having the model API raise :exc:`~django.http.Http404` instead of
:exc:`~django.core.exceptions.ObjectDoesNotExist`?
Because that would couple the model layer to the view layer. One of the Because that would couple the model layer to the view layer. One of the
foremost design goals of Django is to maintain loose coupling. foremost design goals of Django is to maintain loose coupling.
There's also a ``get_list_or_404()`` function, which works just as There's also a :func:`~django.shortcuts.get_list_or_404` function, which works
``get_object_or_404()`` -- except using ``filter()`` instead of just as :func:`~django.shortcuts.get_object_or_404` -- except using
``get()``. It raises ``Http404`` if the list is empty. :meth:`~django.db.models.QuerySet.filter` instead of
:meth:`~django.db.models.QuerySet.get`. It raises :exc:`~django.http.Http404` if
the list is empty.
Write a 404 (page not found) view Write a 404 (page not found) view
================================= =================================
When you raise ``Http404`` from within a view, Django will load a special view When you raise :exc:`~django.http.Http404` from within a view, Django will load
devoted to handling 404 errors. It finds it by looking for the variable a special view devoted to handling 404 errors. It finds it by looking for the
``handler404``, which is a string in Python dotted syntax -- the same format variable ``handler404``, which is a string in Python dotted syntax -- the same
the normal URLconf callbacks use. A 404 view itself has nothing special: It's format the normal URLconf callbacks use. A 404 view itself has nothing special:
just a normal view. It's just a normal view.
You normally won't have to bother with writing 404 views. By default, URLconfs You normally won't have to bother with writing 404 views. By default, URLconfs
have the following line up top:: have the following line up top::
@ -332,18 +353,20 @@ have the following line up top::
That takes care of setting ``handler404`` in the current module. As you can see That takes care of setting ``handler404`` in the current module. As you can see
in ``django/conf/urls/defaults.py``, ``handler404`` is set to in ``django/conf/urls/defaults.py``, ``handler404`` is set to
``'django.views.defaults.page_not_found'`` by default. :func:`django.views.defaults.page_not_found` by default.
Three more things to note about 404 views: Three more things to note about 404 views:
* The 404 view is also called if Django doesn't find a match after checking * The 404 view is also called if Django doesn't find a match after checking
every regular expression in the URLconf. every regular expression in the URLconf.
* If you don't define your own 404 view -- and simply use the default,
which is recommended -- you still have one obligation: To create a * If you don't define your own 404 view -- and simply use the default, which
``404.html`` template in the root of your template directory. The default is recommended -- you still have one obligation: To create a ``404.html``
404 view will use that template for all 404 errors. template in the root of your template directory. The default 404 view will
* If ``DEBUG`` is set to ``True`` (in your settings module) then your 404 use that template for all 404 errors.
view will never be used, and the traceback will be displayed instead.
* If :setting:`DEBUG` is set to ``True`` (in your settings module) then your
404 view will never be used, and the traceback will be displayed instead.
Write a 500 (server error) view Write a 500 (server error) view
=============================== ===============================
@ -357,7 +380,9 @@ Use the template system
Back to the ``detail()`` view for our poll application. Given the context Back to the ``detail()`` view for our poll application. Given the context
variable ``poll``, here's what the "polls/detail.html" template might look variable ``poll``, here's what the "polls/detail.html" template might look
like:: like:
.. code-block:: html+django
<h1>{{ poll.question }}</h1> <h1>{{ poll.question }}</h1>
<ul> <ul>
@ -376,9 +401,7 @@ Method-calling happens in the ``{% for %}`` loop: ``poll.choice_set.all`` is
interpreted as the Python code ``poll.choice_set.all()``, which returns an interpreted as the Python code ``poll.choice_set.all()``, which returns an
iterable of Choice objects and is suitable for use in the ``{% for %}`` tag. iterable of Choice objects and is suitable for use in the ``{% for %}`` tag.
See the `template guide`_ for full details on how templates work. See the :ref:`template guide <topics-templates>` for more about templates.
.. _template guide: ../templates/
Simplifying the URLconfs Simplifying the URLconfs
======================== ========================
@ -397,7 +420,7 @@ Namely, ``mysite.polls.views`` is in every callback.
Because this is a common case, the URLconf framework provides a shortcut for Because this is a common case, the URLconf framework provides a shortcut for
common prefixes. You can factor out the common prefixes and add them as the common prefixes. You can factor out the common prefixes and add them as the
first argument to ``patterns()``, like so:: first argument to :func:`~django.conf.urls.defaults.patterns`, like so::
urlpatterns = patterns('mysite.polls.views', urlpatterns = patterns('mysite.polls.views',
(r'^polls/$', 'index'), (r'^polls/$', 'index'),
@ -414,7 +437,7 @@ Decoupling the URLconfs
While we're at it, we should take the time to decouple our poll-app URLs from While we're at it, we should take the time to decouple our poll-app URLs from
our Django project configuration. Django apps are meant to be pluggable -- that our Django project configuration. Django apps are meant to be pluggable -- that
is, each particular app should be transferrable to another Django installation is, each particular app should be transferable to another Django installation
with minimal fuss. with minimal fuss.
Our poll app is pretty decoupled at this point, thanks to the strict directory Our poll app is pretty decoupled at this point, thanks to the strict directory
@ -425,28 +448,29 @@ We've been editing the URLs in ``mysite/urls.py``, but the URL design of an
app is specific to the app, not to the Django installation -- so let's move the app is specific to the app, not to the Django installation -- so let's move the
URLs within the app directory. URLs within the app directory.
Copy the file ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then, Copy the file ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then, change
change ``mysite/urls.py`` to remove the poll-specific URLs and insert an ``mysite/urls.py`` to remove the poll-specific URLs and insert an
``include()``:: :func:`~django.conf.urls.defaults.include`::
(r'^polls/', include('mysite.polls.urls')), (r'^polls/', include('mysite.polls.urls')),
``include()``, simply, references another URLconf. Note that the regular :func:`~django.conf.urls.defaults.include`, simply, references another URLconf.
expression doesn't have a ``$`` (end-of-string match character) but has the Note that the regular expression doesn't have a ``$`` (end-of-string match
trailing slash. Whenever Django encounters ``include()``, it chops off whatever character) but has the trailing slash. Whenever Django encounters
part of the URL matched up to that point and sends the remaining string to the :func:`~django.conf.urls.defaults.include`, it chops off whatever part of the
included URLconf for further processing. URL matched up to that point and sends the remaining string to the included
URLconf for further processing.
Here's what happens if a user goes to "/polls/34/" in this system: Here's what happens if a user goes to "/polls/34/" in this system:
* Django will find the match at ``'^polls/'`` * Django will find the match at ``'^polls/'``
* It will strip off the matching text (``"polls/"``) and send the remaining
text -- ``"34/"`` -- to the 'mysite.polls.urls' URLconf for * Then, Django will strip off the matching text (``"polls/"``) and send the
remaining text -- ``"34/"`` -- to the 'mysite.polls.urls' URLconf for
further processing. further processing.
Now that we've decoupled that, we need to decouple the Now that we've decoupled that, we need to decouple the 'mysite.polls.urls'
'mysite.polls.urls' URLconf by removing the leading "polls/" from each URLconf by removing the leading "polls/" from each line::
line::
urlpatterns = patterns('mysite.polls.views', urlpatterns = patterns('mysite.polls.views',
(r'^$', 'index'), (r'^$', 'index'),
@ -455,14 +479,12 @@ line::
(r'^(?P<poll_id>\d+)/vote/$', 'vote'), (r'^(?P<poll_id>\d+)/vote/$', 'vote'),
) )
The idea behind ``include()`` and URLconf decoupling is to make it easy to The idea behind :func:`~django.conf.urls.defaults.include` and URLconf
plug-and-play URLs. Now that polls are in their own URLconf, they can be placed decoupling is to make it easy to plug-and-play URLs. Now that polls are in their
under "/polls/", or under "/fun_polls/", or under "/content/polls/", or any own URLconf, they can be placed under "/polls/", or under "/fun_polls/", or
other URL root, and the app will still work. under "/content/polls/", or any other URL root, and the app will still work.
All the poll app cares about is its relative URLs, not its absolute URLs. All the poll app cares about is its relative URLs, not its absolute URLs.
When you're comfortable with writing views, read `part 4 of this tutorial`_ to When you're comfortable with writing views, read :ref:`part 4 of this tutorial
learn about simple form processing and generic views. <intro-tutorial04>` to learn about simple form processing and generic views.
.. _part 4 of this tutorial: ../tutorial04/

View File

@ -1,15 +1,20 @@
.. _intro-tutorial04:
===================================== =====================================
Writing your first Django app, part 4 Writing your first Django app, part 4
===================================== =====================================
This tutorial begins where `Tutorial 3`_ left off. We're continuing the Web-poll This tutorial begins where :ref:`Tutorial 3 <intro-tutorial03>` left off. We're
application and will focus on simple form processing and cutting down our code. continuing the Web-poll application and will focus on simple form processing and
cutting down our code.
Write a simple form Write a simple form
=================== ===================
Let's update our poll detail template ("polls/detail.html") from the last Let's update our poll detail template ("polls/detail.html") from the last
tutorial, so that the template contains an HTML ``<form>`` element:: tutorial, so that the template contains an HTML ``<form>`` element:
.. code-block:: html+django
<h1>{{ poll.question }}</h1> <h1>{{ poll.question }}</h1>
@ -38,15 +43,12 @@ A quick rundown:
data server-side, use ``method="post"``. This tip isn't specific to data server-side, use ``method="post"``. This tip isn't specific to
Django; it's just good Web development practice. Django; it's just good Web development practice.
* ``forloop.counter`` indicates how many times the ``for`` tag has * ``forloop.counter`` indicates how many times the ;ttag:`for` tag has gone
gone through its loop. For more information, see `the through its loop
documentation for the "for" tag`_.
.. _the documentation for the "for" tag: ../templates/#for
Now, let's create a Django view that handles the submitted data and does Now, let's create a Django view that handles the submitted data and does
something with it. Remember, in `Tutorial 3`_, we created a URLconf for the something with it. Remember, in :ref:`Tutorial 3 <intro-tutorial03>`, we created
polls application that includes this line:: a URLconf for the polls application that includes this line::
(r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'), (r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
@ -77,47 +79,52 @@ So let's create a ``vote()`` function in ``mysite/polls/views.py``::
This code includes a few things we haven't covered yet in this tutorial: This code includes a few things we haven't covered yet in this tutorial:
* ``request.POST`` is a dictionary-like object that lets you access * :attr:`request.POST <django.http.HttpRequest.POST>` is a dictionary-like
submitted data by key name. In this case, ``request.POST['choice']`` object that lets you access submitted data by key name. In this case,
returns the ID of the selected choice, as a string. ``request.POST`` ``request.POST['choice']`` returns the ID of the selected choice, as a
values are always strings. string. :attr:`request.POST <django.http.HttpRequest.POST>` values are
always strings.
Note that Django also provides ``request.GET`` for accessing GET data Note that Django also provides :attr:`request.GET
in the same way -- but we're explicitly using ``request.POST`` in our <django.http.HttpRequest.GET>` for accessing GET data in the same way --
code, to ensure that data is only altered via a POST call. but we're explicitly using :attr:`request.POST
<django.http.HttpRequest.POST>` in our code, to ensure that data is only
altered via a POST call.
* ``request.POST['choice']`` will raise ``KeyError`` if ``choice`` wasn't * ``request.POST['choice']`` will raise :exc:`KeyError` if ``choice`` wasn't
provided in POST data. The above code checks for ``KeyError`` and provided in POST data. The above code checks for :exc:`KeyError` and
redisplays the poll form with an error message if ``choice`` isn't given. redisplays the poll form with an error message if ``choice`` isn't given.
* After incrementing the choice count, the code returns an * After incrementing the choice count, the code returns an
``HttpResponseRedirect`` rather than a normal ``HttpResponse``. :class:`~django.http.HttpResponseRedirect` rather than a normal
``HttpResponseRedirect`` takes a single argument: the URL to which the :class:`~django.http.HttpResponse`.
user will be redirected (see the following point for how we construct :class:`~django.http.HttpResponseRedirect` takes a single argument: the
the URL in this case). URL to which the user will be redirected (see the following point for how
we construct the URL in this case).
As the Python comment above points out, you should always return an As the Python comment above points out, you should always return an
``HttpResponseRedirect`` after successfully dealing with POST data. This :class:`~django.http.HttpResponseRedirect` after successfully dealing with
tip isn't specific to Django; it's just good Web development practice. POST data. This tip isn't specific to Django; it's just good Web
development practice.
* We are using the ``reverse()`` function in the ``HttpResponseRedirect`` * We are using the :func:`~django.core.urlresolvers.reverse` function in the
constructor in this example. This function helps avoid having to :class:`~django.http.HttpResponseRedirect` constructor in this example.
hardcode a URL in the view function. It is given the name of the view This function helps avoid having to hardcode a URL in the view function.
that we want to pass control to and the variable portion of the URL It is given the name of the view that we want to pass control to and the
pattern that points to that view. In this case, using the URLConf we set variable portion of the URL pattern that points to that view. In this
up in Tutorial 3, this ``reverse()`` call will return a string like :: case, using the URLConf we set up in Tutorial 3, this
:func:`~django.core.urlresolvers.reverse` call will return a string like
::
'/polls/3/results/' '/polls/3/results/'
... where the ``3`` is the value of ``p.id``. This redirected URL will ... where the ``3`` is the value of ``p.id``. This redirected URL will
then call the ``'results'`` view to display the final page. Note that then call the ``'results'`` view to display the final page. Note that you
you need to use the full name of the view here (including the prefix). need to use the full name of the view here (including the prefix).
For more information about ``reverse()``, see the `URL dispatcher`_ As mentioned in Tutorial 3, ``request`` is a :class:`~django.http.HttpRequest`
documentation. object. For more on :class:`~django.http.HttpRequest` objects, see the
:ref:`request and response documentation <ref-request-response>`.
As mentioned in Tutorial 3, ``request`` is a ``HTTPRequest`` object. For more
on ``HTTPRequest`` objects, see the `request and response documentation`_.
After somebody votes in a poll, the ``vote()`` view redirects to the results After somebody votes in a poll, the ``vote()`` view redirects to the results
page for the poll. Let's write that view:: page for the poll. Let's write that view::
@ -126,10 +133,13 @@ page for the poll. Let's write that view::
p = get_object_or_404(Poll, pk=poll_id) p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('polls/results.html', {'poll': p}) return render_to_response('polls/results.html', {'poll': p})
This is almost exactly the same as the ``detail()`` view from `Tutorial 3`_. This is almost exactly the same as the ``detail()`` view from :ref:`Tutorial 3
The only difference is the template name. We'll fix this redundancy later. <intro-tutorial03>`. The only difference is the template name. We'll fix this
redundancy later.
Now, create a ``results.html`` template:: Now, create a ``results.html`` template:
.. code-block:: html+django
<h1>{{ poll.question }}</h1> <h1>{{ poll.question }}</h1>
@ -143,15 +153,12 @@ Now, go to ``/polls/1/`` in your browser and vote in the poll. You should see a
results page that gets updated each time you vote. If you submit the form results page that gets updated each time you vote. If you submit the form
without having chosen a choice, you should see the error message. without having chosen a choice, you should see the error message.
.. _request and response documentation: ../request_response/
.. _URL dispatcher: ../url_dispatch#reverse
Use generic views: Less code is better Use generic views: Less code is better
====================================== ======================================
The ``detail()`` (from `Tutorial 3`_) and ``results()`` views are stupidly The ``detail()`` (from :ref:`Tutorial 3 <intro-tutorial03>`) and ``results()``
simple -- and, as mentioned above, redundant. The ``index()`` view (also from views are stupidly simple -- and, as mentioned above, redundant. The ``index()``
Tutorial 3), which displays a list of polls, is similar. view (also from Tutorial 3), which displays a list of polls, is similar.
These views represent a common case of basic Web development: getting data from These views represent a common case of basic Web development: getting data from
the database according to a parameter passed in the URL, loading a template and the database according to a parameter passed in the URL, loading a template and
@ -175,7 +182,7 @@ conversion.
You should know basic math before you start using a calculator. You should know basic math before you start using a calculator.
First, open the polls/urls.py URLconf. It looks like this, according to the First, open the ``polls/urls.py`` URLconf. It looks like this, according to the
tutorial so far:: tutorial so far::
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
@ -203,92 +210,95 @@ Change it like so::
(r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'), (r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
) )
We're using two generic views here: ``object_list`` and ``object_detail``. We're using two generic views here:
Respectively, those two views abstract the concepts of "display a list of :func:`~django.views.generic.list_detail.object_list` and
objects" and "display a detail page for a particular type of object." :func:`~django.views.generic.list_detail.object_detail`. Respectively, those two
views abstract the concepts of "display a list of objects" and "display a detail
page for a particular type of object."
* Each generic view needs to know what data it will be acting upon. This * Each generic view needs to know what data it will be acting upon. This
data is provided in a dictionary. The ``queryset`` key in this dictionary data is provided in a dictionary. The ``queryset`` key in this dictionary
points to the list of objects to be manipulated by the generic view. points to the list of objects to be manipulated by the generic view.
* The ``object_detail`` generic view expects the ID value captured * The :func:`~django.views.generic.list_detail.object_detail` generic view
from the URL to be called ``"object_id"``, so we've changed ``poll_id`` to expects the ID value captured from the URL to be called ``"object_id"``,
``object_id`` for the generic views. so we've changed ``poll_id`` to ``object_id`` for the generic views.
* We've added a name, ``poll_results``, to the results view so that we * We've added a name, ``poll_results``, to the results view so that we have
have a way to refer to its URL later on (see the documentation about a way to refer to its URL later on (see the documentation about
`naming URL patterns`_ for information). We're also using the `url()`_ :ref:`naming URL patterns <naming-url-patterns>` for information). We're
function from ``django.conf.urls.defaults`` here. It's a good habit to also using the :func:`~django.conf.urls.default.url` function from
use ``url()`` when you are providing a pattern name like this. :mod:`django.conf.urls.defaults` here. It's a good habit to use
:func:`~django.conf.urls.defaults.url` when you are providing a pattern
name like this.
.. _naming URL patterns: ../url_dispatch/#naming-url-patterns By default, the :func:`~django.views.generic.list_detail.object_detail` generic
.. _url(): ../url_dispatch/#url view uses a template called ``<app name>/<model name>_detail.html``. In our
case, it'll use the template ``"polls/poll_detail.html"``. Thus, rename your
``polls/detail.html`` template to ``polls/poll_detail.html``, and change the
:func:`~django.shortcuts.render_to_response` line in ``vote()``.
By default, the ``object_detail`` generic view uses a template called Similarly, the :func:`~django.views.generic.list_detail.object_list` generic
``<app name>/<model name>_detail.html``. In our case, it'll use the template view uses a template called ``<app name>/<model name>_list.html``. Thus, rename
``"polls/poll_detail.html"``. Thus, rename your ``polls/detail.html`` template to ``polls/index.html`` to ``polls/poll_list.html``.
``polls/poll_detail.html``, and change the ``render_to_response()`` line in
``vote()``.
Similarly, the ``object_list`` generic view uses a template called Because we have more than one entry in the URLconf that uses
``<app name>/<model name>_list.html``. Thus, rename ``polls/index.html`` to :func:`~django.views.generic.list_detail.object_detail` for the polls app, we
``polls/poll_list.html``. manually specify a template name for the results view:
Because we have more than one entry in the URLconf that uses ``object_detail``
for the polls app, we manually specify a template name for the results view:
``template_name='polls/results.html'``. Otherwise, both views would use the same ``template_name='polls/results.html'``. Otherwise, both views would use the same
template. Note that we use ``dict()`` to return an altered dictionary in place. template. Note that we use ``dict()`` to return an altered dictionary in place.
.. note:: ``all()`` is lazy .. note:: :meth:`django.db.models.QuerySet.all` is lazy
It might look a little frightening to see ``Poll.objects.all()`` being used It might look a little frightening to see ``Poll.objects.all()`` being used
in a detail view which only needs one ``Poll`` object, but don't worry; in a detail view which only needs one ``Poll`` object, but don't worry;
``Poll.objects.all()`` is actually a special object called a ``QuerySet``, ``Poll.objects.all()`` is actually a special object called a
which is "lazy" and doesn't hit your database until it absolutely has to. By :class:`~django.db.models.QuerySet`, which is "lazy" and doesn't hit your
the time the database query happens, the ``object_detail`` generic view will database until it absolutely has to. By the time the database query happens,
have narrowed its scope down to a single object, so the eventual query will the :func:`~django.views.generic.list_detail.object_detail` generic view
only select one row from the database. will have narrowed its scope down to a single object, so the eventual query
will only select one row from the database.
If you'd like to know more about how that works, The Django database API If you'd like to know more about how that works, The Django database API
documentation `explains the lazy nature of QuerySet objects`_. documentation :ref:`explains the lazy nature of QuerySet objects
<querysets-are-lazy>`.
.. _explains the lazy nature of QuerySet objects: ../db-api/#querysets-are-lazy In previous parts of the tutorial, the templates have been provided with a
context that contains the ``poll`` and ``latest_poll_list`` context variables.
In previous parts of the tutorial, the templates have been provided with a context However, the generic views provide the variables ``object`` and ``object_list``
that contains the ``poll`` and ``latest_poll_list`` context variables. However, as context. Therefore, you need to change your templates to match the new
the generic views provide the variables ``object`` and ``object_list`` as context. context variables. Go through your templates, and modify any reference to
Therefore, you need to change your templates to match the new context variables. ``latest_poll_list`` to :func:`~django.views.generic.list_detail.object_list`,
Go through your templates, and modify any reference to ``latest_poll_list`` to and change any reference to ``poll`` to ``object``.
``object_list``, and change any reference to ``poll`` to ``object``.
You can now delete the ``index()``, ``detail()`` and ``results()`` views You can now delete the ``index()``, ``detail()`` and ``results()`` views
from ``polls/views.py``. We don't need them anymore -- they have been replaced from ``polls/views.py``. We don't need them anymore -- they have been replaced
by generic views. by generic views.
The ``vote()`` view is still required. However, it must be modified to match The ``vote()`` view is still required. However, it must be modified to match the
the new context variables. In the ``render_to_response()`` call, rename the new context variables. In the :func:`~django.shortcuts.render_to_response` call,
``poll`` context variable to ``object``. rename the ``poll`` context variable to ``object``.
The last thing to do is fix the URL handling to account for the use of generic The last thing to do is fix the URL handling to account for the use of generic
views. In the vote view above, we used the ``reverse()`` function to avoid views. In the vote view above, we used the
hard-coding our URLs. Now that we've switched to a generic view, we'll need to :func:`~django.core.urlresolvers.reverse` function to avoid hard-coding our
change the ``reverse()`` call to point back to our new generic view. We can't URLs. Now that we've switched to a generic view, we'll need to change the
simply use the view function anymore -- generic views can be (and are) used :func:`~django.core.urlresolvers.reverse` call to point back to our new generic
multiple times -- but we can use the name we've given:: view. We can't simply use the view function anymore -- generic views can be (and
are) used multiple times -- but we can use the name we've given::
return HttpResponseRedirect(reverse('poll_results', args=(p.id,))) return HttpResponseRedirect(reverse('poll_results', args=(p.id,)))
Run the server, and use your new polling app based on generic views. Run the server, and use your new polling app based on generic views.
For full details on generic views, see the `generic views documentation`_. For full details on generic views, see the :ref:`generic views documentation
<topics-http-generic-views>`.
.. _generic views documentation: ../generic_views/
Coming soon Coming soon
=========== ===========
The tutorial ends here for the time being. But check back soon for the next The tutorial ends here for the time being. Future installments of the tutorial
installments: will cover:
* Advanced form processing * Advanced form processing
* Using the RSS framework * Using the RSS framework
@ -297,8 +307,5 @@ installments:
* Advanced admin features: Permissions * Advanced admin features: Permissions
* Advanced admin features: Custom JavaScript * Advanced admin features: Custom JavaScript
In the meantime, you can read through the rest of the `Django documentation`_ In the meantime, you might want to check out some pointers on :ref:`where to go
and start writing your own applications. from here <intro-whatsnext>`
.. _Tutorial 3: ../tutorial03/
.. _Django documentation: http://www.djangoproject.com/documentation/

235
docs/intro/whatsnext.txt Normal file
View File

@ -0,0 +1,235 @@
.. _intro-whatsnext:
=================
What to read next
=================
So you've read all the :ref:`introductory material <intro-index>` and have
decided you'd like to keep using Django. We've only just scratched the surface
with this intro (in fact, if you've read every single word you've still read
less than 10% of the overall documentation).
So what's next?
Well, we've always been big fans of learning by doing. At this point you should
know enough to start a project of your own and start fooling around. As you need
to learn new tricks, come back to the documentation.
We've put a lot of effort into making Django's documentation useful, easy to
read and as complete as possible. The rest of this document explains more about
how the documentation works so that you can get the most out of it.
(Yes, this is documentation about documentation. Rest assured we have no plans
to write a document about how to read the document about documentation.)
Finding documentation
=====================
Django's got a *lot* of documentation -- almost 200,000 words -- so finding what
you need can sometimes be tricky. A few good places to start the :ref:`search`
and the :ref:`genindex`.
Or you can just browse around!
How the documentation is organized
==================================
Django's main documentation is broken up into "chunks" designed to fill
different needs:
* The :ref:`introductory material <intro-index>` is designed for people new
to Django -- or to web development in general. It doesn't cover anything
in depth, but instead gives a high-level overview of how developing in
Django "feels".
* The :ref:`topic guides <topics-index>`, on the other hand, dive deep into
individual parts of Django. There are complete guides to Django's
:ref:`model system <topics-db-index>`, :ref:`template engine
<topics-templates>`, :ref:`forms framework <topics-forms-index>`, and much
more.`
This is probably where you'll want to spent most of your time; if you work
your way through these guides you should come out knowing pretty much
everything there is to know about Django.
* Web development is often broad, not deep -- problems span many domains.
We've written a set of :ref:`how-to guides <howto-index>` that answer
common "How do I ...?" questions. Here you'll find information about
:ref:`generating PDFs with Django <howto-outputting-pdf>`, :ref:`writing
custom template tags <howto-custom-template-tags>`, and more.
Answers to really common questions can also be found in the :ref:`FAQ
<faq-index>`.
* The guides and how-to's don't cover every single class, function, and
method available in Django -- that would be overwhelming when you're
trying to learn. Instead, details about individual classes, functions,
methods, and modules are kept in the :ref:`reference <ref-index>`. This is
where you'll turn to find the details of a particular function or
whathaveyou.
* Finally, there's some "specialized" documentation not usually relevant to
most developers. This includes the :ref:`release notes <releases-index>`,
:ref:`documentation of obsolete features <obsolete-index>`,
:ref:`internals documentation <internals-index>` for those who want to add
code to Django itself, and a :ref:`few other things that simply don't fit
elsewhere <misc-index>`.
How documentation is updated
============================
Just as the Django code base is developed and improved on a daily basis, our
documentation is consistently improving. We improve documentation for several
reasons:
* To make content fixes, such as grammar/typo corrections.
* To add information and/or examples to existing sections that need to be
expanded.
* To document Django features that aren't yet documented. (The list of
such features is shrinking but exists nonetheless.)
* To add documentation for new features as new features get added, or as
Django APIs or behaviors change.
Django's documentation is kept in the same source control system as its code. It
lives in the `django/trunk/docs`_ directory of our Subversion repository. Each
document online is a separate text file in the repository.
.. _django/trunk/docs: http://code.djangoproject.com/browser/django/trunk/docs
Where to get it
===============
You can read Django documentation in several ways. They are, in order of
preference:
On the Web
----------
The most recent version of the Django documentation lives at
http://www.djangoproject.com/documentation/ . These HTML pages are generated
automatically from the text files in source control. That means they reflect the
"latest and greatest" in Django -- they include the very latest corrections and
additions, and they discuss the latest Django features, which may only be
available to users of the Django development version. (See "Differences between
versions" below.)
We encourage you to help improve the docs by submitting changes, corrections and
suggestions in the `ticket system`_. The Django developers actively monitor the
ticket system and use your feedback to improve the documentation for everybody.
Note, however, that tickets should explicitly relate to the documentation,
rather than asking broad tech-support questions. If you need help with your
particular Django setup, try the `django-users mailing list`_ or the `#django
IRC channel`_ instead.
.. _ticket system: http://code.djangoproject.com/simpleticket?component=Documentation
.. _django-users mailing list: http://groups.google.com/group/django-users
.. _#django IRC channel: irc://irc.freenode.net/django
In plain text
-------------
For offline reading, or just for convenience, you can read the Django
documentation in plain text.
If you're using an official release of Django, note that the zipped package
(tarball) of the code includes a ``docs/`` directory, which contains all the
documentation for that release.
If you're using the development version of Django (aka the Subversion "trunk"),
note that the ``docs/`` directory contains all of the documentation. You can
``svn update`` it, just as you ``svn update`` the Python code, in order to get
the latest changes.
You can check out the latest Django documentation from Subversion using this
shell command:
.. code-block:: bash
$ svn co http://code.djangoproject.com/svn/django/trunk/docs/ django_docs
One low-tech way of taking advantage of the text documentation is by using the
Unix ``grep`` utility to search for a phrase in all of the documentation. For
example, this will show you each mention of the phrase "edit_inline" in any
Django document:
.. code-block:: bash
$ grep edit_inline /path/to/django/docs/*.txt
As HTML, locally
----------------
You can get a local copy of the HTML documentation following a few easy steps:
* Django's documentation uses a system called Sphinx__ to convert from
plain text to HTML. You'll need to install Sphinx by either downloading
and installing the package from the Sphinx website, or by Python's
``easy_install``:
.. code-block:: bash
$ easy_install Sphinx
* Then, just use the included ``Makefile`` to turn the documentation into
HTML:
.. code-block:: bash
$ cd path/to/django/docs
$ make html
You'll need `GNU Make`__ installed for this.
* The HTML documentation will be placed in ``docs/_build/html``.
.. warning::
At the time of this writing, Django's using a version of Sphinx not
yet released, so you'll currently need to install Sphinx from the
source. We'll fix this shortly.
__ http://sphinx.pocoo.org/
__ http://www.gnu.org/software/make/
Differences between versions
============================
As previously mentioned, the text documentation in our Subversion repository
contains the "latest and greatest" changes and additions. These changes often
include documentation of new features added in the Django development version
-- the Subversion ("trunk") version of Django. For that reason, it's worth
pointing out our policy on keeping straight the documentation for various
versions of the framework.
We follow this policy:
* The primary documentation on djangoproject.com is an HTML version of the
latest docs in Subversion. These docs always correspond to the latest
official Django release, plus whatever features we've added/changed in
the framework *since* the latest release.
* As we add features to Django's development version, we try to update the
documentation in the same Subversion commit transaction.
* To distinguish feature changes/additions in the docs, we use the phrase
**New in Django development version**. In practice, this means that the
current documentation on djangoproject.com can be used by users of either
the latest release *or* the development version.
* Documentation for a particular Django release is frozen once the version
has been released officially. It remains a snapshot of the docs as of the
moment of the release. We will make exceptions to this rule in
the case of retroactive security updates or other such retroactive
changes. Once documentation is frozen, we add a note to the top of each
frozen document that says "These docs are frozen for Django version XXX"
and links to the current version of that document.
* The `main documentation Web page`_ includes links to documentation for
all previous versions.
.. _main documentation Web page: http://www.djangoproject.com/documentation/

View File

@ -1,69 +0,0 @@
==================================
Integrating with a legacy database
==================================
While Django is best suited for developing new applications, it's quite
possible to integrate it into legacy databases. Django includes a couple of
utilities to automate as much of this process as possible.
This document assumes you know the Django basics, as covered in the
`official tutorial`_.
.. _official tutorial: ../tutorial01/
Give Django your database parameters
====================================
You'll need to tell Django what your database connection parameters are, and
what the name of the database is. Do that by editing these settings in your
`settings file`_:
* `DATABASE_NAME`_
* `DATABASE_ENGINE`_
* `DATABASE_USER`_
* `DATABASE_PASSWORD`_
* `DATABASE_HOST`_
* `DATABASE_PORT`_
.. _settings file: ../settings/
.. _DATABASE_NAME: ../settings/#database-name
.. _DATABASE_ENGINE: ../settings/#database-engine
.. _DATABASE_USER: ../settings/#database-user
.. _DATABASE_PASSWORD: ../settings/#database-password
.. _DATABASE_HOST: ../settings/#database-host
.. _DATABASE_PORT: ../settings/#database-port
Auto-generate the models
========================
Django comes with a utility that can create models by introspecting an existing
database. You can view the output by running this command::
python manage.py inspectdb
Save this as a file by using standard Unix output redirection::
python manage.py inspectdb > models.py
This feature is meant as a shortcut, not as definitive model generation. See
the `django-admin.py documentation`_ for more information.
Once you've cleaned up your models, name the file ``models.py`` and put it in
the Python package that holds your app. Then add the app to your
``INSTALLED_APPS`` setting.
.. _django-admin.py documentation: ../django-admin/
Install the core Django tables
==============================
Next, run the ``manage.py syncdb`` command to install any extra needed database
records such as admin permissions and content types::
python manage.py syncdb
See whether it worked
=====================
That's it. Try accessing your data via the Django database API, and try editing
objects via Django's admin site.

View File

@ -1,733 +0,0 @@
==========================
The "local flavor" add-ons
==========================
Following its "batteries included" philosophy, Django comes with assorted
pieces of code that are useful for particular countries or cultures. These are
called the "local flavor" add-ons and live in the ``django.contrib.localflavor``
package.
Inside that package, country- or culture-specific code is organized into
subpackages, named using `ISO 3166 country codes`_.
Most of the ``localflavor`` add-ons are localized form components deriving from
the forms_ framework -- for example, a ``USStateField`` that knows how to
validate U.S. state abbreviations, and a ``FISocialSecurityNumber`` that knows
how to validate Finnish social security numbers.
To use one of these localized components, just import the relevant subpackage.
For example, here's how you can create a form with a field representing a
French telephone number::
from django import forms
from django.contrib.localflavor import fr
class MyForm(forms.Form):
my_french_phone_no = fr.forms.FRPhoneNumberField()
Supported countries
===================
Countries currently supported by ``localflavor`` are:
* Argentina_
* Australia_
* Austria_
* Brazil_
* Canada_
* Chile_
* Finland_
* France_
* Germany_
* Holland_
* Iceland_
* India_
* Italy_
* Japan_
* Mexico_
* Norway_
* Peru_
* Poland_
* Romania_
* Slovakia_
* `South Africa`_
* Spain_
* Switzerland_
* `United Kingdom`_
* `United States of America`_
The ``localflavor`` package also includes a ``generic`` subpackage, containing
useful code that is not specific to one particular country or culture.
Currently, it defines date and datetime input fields based on those from
forms_, but with non-US default formats. Here's an example of how to use
them::
from django import forms
from django.contrib.localflavor import generic
class MyForm(forms.Form):
my_date_field = generic.forms.DateField()
.. _ISO 3166 country codes: http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
.. _Argentina: `Argentina (django.contrib.localflavor.ar)`_
.. _Australia: `Australia (django.contrib.localflavor.au)`_
.. _Austria: `Austria (django.contrib.localflavor.at)`_
.. _Brazil: `Brazil (django.contrib.localflavor.br)`_
.. _Canada: `Canada (django.contrib.localflavor.ca)`_
.. _Chile: `Chile (django.contrib.localflavor.cl)`_
.. _Finland: `Finland (django.contrib.localflavor.fi)`_
.. _France: `France (django.contrib.localflavor.fr)`_
.. _Germany: `Germany (django.contrib.localflavor.de)`_
.. _Holland: `Holland (django.contrib.localflavor.nl)`_
.. _Iceland: `Iceland (django.contrib.localflavor.is\_)`_
.. _India: `India (django.contrib.localflavor.in\_)`_
.. _Italy: `Italy (django.contrib.localflavor.it)`_
.. _Japan: `Japan (django.contrib.localflavor.jp)`_
.. _Mexico: `Mexico (django.contrib.localflavor.mx)`_
.. _Norway: `Norway (django.contrib.localflavor.no)`_
.. _Peru: `Peru (django.contrib.localflavor.pe)`_
.. _Poland: `Poland (django.contrib.localflavor.pl)`_
.. _Romania: `Romania (django.contrib.localflavor.ro)`_
.. _Slovakia: `Slovakia (django.contrib.localflavor.sk)`_
.. _South Africa: `South Africa (django.contrib.localflavor.za)`_
.. _Spain: `Spain (django.contrib.localflavor.es)`_
.. _Switzerland: `Switzerland (django.contrib.localflavor.ch)`_
.. _United Kingdom: `United Kingdom (django.contrib.localflavor.uk)`_
.. _United States of America: `United States of America (django.contrib.localflavor.us)`_
.. _forms: ../forms/
Adding flavors
==============
We'd love to add more of these to Django, so please `create a ticket`_ with
any code you'd like to contribute. One thing we ask is that you please use
Unicode objects (``u'mystring'``) for strings, rather than setting the encoding
in the file. See any of the existing flavors for examples.
.. _create a ticket: http://code.djangoproject.com/simpleticket
Argentina (``django.contrib.localflavor.ar``)
=============================================
ARPostalCodeField
-----------------
A form field that validates input as either a classic four-digit Argentinian
postal code or a CPA_.
.. _CPA: http://www.correoargentino.com.ar/consulta_cpa/home.php
ARDNIField
----------
A form field that validates input as a Documento Nacional de Identidad (DNI)
number.
ARCUITField
-----------
A form field that validates input as a Código Único de Identificación
Tributaria (CUIT) number.
ARProvinceSelect
----------------
A ``Select`` widget that uses a list of Argentina's provinces and autonomous
cities as its choices.
Australia (``django.contrib.localflavor.au``)
=============================================
AUPostCodeField
---------------
A form field that validates input as an Australian postcode.
AUPhoneNumberField
------------------
A form field that validates input as an Australian phone number. Valid numbers
have ten digits.
AUStateSelect
-------------
A ``Select`` widget that uses a list of Australian states/territories as its
choices.
Austria (``django.contrib.localflavor.at``)
=============================================
ATZipCodeField
---------------
A form field that validates its input as an Austrian zip code.
ATStateSelect
-------------
A ``Select`` widget that uses a list of Austrian states as its choices.
ATSocialSecurityNumberField
---------------------------
A form field that validates its input as an Austrian social security number.
Brazil (``django.contrib.localflavor.br``)
==========================================
BRPhoneNumberField
------------------
A form field that validates input as a Brazilian phone number, with the format
XX-XXXX-XXXX.
BRZipCodeField
--------------
A form field that validates input as a Brazilian zip code, with the format
XXXXX-XXX.
BRStateSelect
-------------
A ``Select`` widget that uses a list of Brazilian states/territories as its
choices.
Canada (``django.contrib.localflavor.ca``)
==========================================
CAPhoneNumberField
------------------
A form field that validates input as a Canadian phone number, with the format
XXX-XXX-XXXX.
CAPostalCodeField
-----------------
A form field that validates input as a Canadian postal code, with the format
XXX XXX.
CAProvinceField
---------------
A form field that validates input as a Canadian province name or abbreviation.
CASocialInsuranceNumberField
----------------------------
A form field that validates input as a Canadian Social Insurance Number (SIN).
A valid number must have the format XXX-XXX-XXX and pass a `Luhn mod-10
checksum`_.
.. _Luhn mod-10 checksum: http://en.wikipedia.org/wiki/Luhn_algorithm
CAProvinceSelect
----------------
A ``Select`` widget that uses a list of Canadian provinces and territories as
its choices.
Chile (``django.contrib.localflavor.cl``)
=========================================
CLRutField
----------
A form field that validates input as a Chilean national identification number
('Rol Unico Tributario' or RUT). The valid format is XX.XXX.XXX-X.
CLRegionSelect
--------------
A ``Select`` widget that uses a list of Chilean regions (Regiones) as its
choices.
Finland (``django.contrib.localflavor.fi``)
===========================================
FISocialSecurityNumber
----------------------
A form field that validates input as a Finnish social security number.
FIZipCodeField
--------------
A form field that validates input as a Finnish zip code. Valid codes
consist of five digits.
FIMunicipalitySelect
--------------------
A ``Select`` widget that uses a list of Finnish municipalities as its
choices.
France (``django.contrib.localflavor.fr``)
==========================================
FRPhoneNumberField
------------------
A form field that validates input as a French local phone number. The
correct format is 0X XX XX XX XX. 0X.XX.XX.XX.XX and 0XXXXXXXXX validate
but are corrected to 0X XX XX XX XX.
FRZipCodeField
--------------
A form field that validates input as a French zip code. Valid codes
consist of five digits.
FRDepartmentSelect
------------------
A ``Select`` widget that uses a list of French departments as its choices.
Germany (``django.contrib.localflavor.de``)
===========================================
DEIdentityCardNumberField
-------------------------
A form field that validates input as a German identity card number
(Personalausweis_). Valid numbers have the format
XXXXXXXXXXX-XXXXXXX-XXXXXXX-X, with no group consisting entirely of zeroes.
.. _Personalausweis: http://de.wikipedia.org/wiki/Personalausweis
DEZipCodeField
--------------
A form field that validates input as a German zip code. Valid codes
consist of five digits.
DEStateSelect
-------------
A ``Select`` widget that uses a list of German states as its choices.
Holland (``django.contrib.localflavor.nl``)
===========================================
NLPhoneNumberField
------------------
A form field that validates input as a Dutch telephone number.
NLSofiNumberField
-----------------
A form field that validates input as a Dutch social security number
(SoFI/BSN).
NLZipCodeField
--------------
A form field that validates input as a Dutch zip code.
NLProvinceSelect
----------------
A ``Select`` widget that uses a list of Dutch provinces as its list of
choices.
Iceland (``django.contrib.localflavor.is_``)
============================================
ISIdNumberField
---------------
A form field that validates input as an Icelandic identification number
(kennitala). The format is XXXXXX-XXXX.
ISPhoneNumberField
------------------
A form field that validates input as an Icelandtic phone number (seven
digits with an optional hyphen or space after the first three digits).
ISPostalCodeSelect
------------------
A ``Select`` widget that uses a list of Icelandic postal codes as its
choices.
India (``django.contrib.localflavor.in_``)
==========================================
INStateField
------------
A form field that validates input as an Indian state/territory name or
abbreviation. Input is normalized to the standard two-letter vehicle
registration abbreviation for the given state or territory.
INZipCodeField
--------------
A form field that validates input as an Indian zip code, with the
format XXXXXXX.
INStateSelect
-------------
A ``Select`` widget that uses a list of Indian states/territories as its
choices.
Italy (``django.contrib.localflavor.it``)
=========================================
ITSocialSecurityNumberField
---------------------------
A form field that validates input as an Italian social security number
(`codice fiscale`_).
.. _codice fiscale: http://www.agenziaentrate.it/ilwwcm/connect/Nsi/Servizi/Codice+fiscale+-+tessera+sanitaria/Codice+fiscale/NSI+Informazioni+sulla+codificazione+delle+persone+fisiche
ITVatNumberField
----------------
A form field that validates Italian VAT numbers (partita IVA).
ITZipCodeField
--------------
A form field that validates input as an Italian zip code. Valid codes
must have five digits.
ITProvinceSelect
----------------
A ``Select`` widget that uses a list of Italian provinces as its choices.
ITRegionSelect
--------------
A ``Select`` widget that uses a list of Italian regions as its choices.
Japan (``django.contrib.localflavor.jp``)
=========================================
JPPostalCodeField
-----------------
A form field that validates input as a Japanese postcode. It accepts seven
digits, with or without a hyphen.
JPPrefectureSelect
------------------
A ``Select`` widget that uses a list of Japanese prefectures as its choices.
Mexico (``django.contrib.localflavor.mx``)
==========================================
MXStateSelect
-------------
A ``Select`` widget that uses a list of Mexican states as its choices.
Norway (``django.contrib.localflavor.no``)
==========================================
NOSocialSecurityNumber
----------------------
A form field that validates input as a Norwegian social security number
(personnummer_).
.. _personnummer: http://no.wikipedia.org/wiki/Personnummer
NOZipCodeField
--------------
A form field that validates input as a Norwegian zip code. Valid codes
have four digits.
NOMunicipalitySelect
--------------------
A ``Select`` widget that uses a list of Norwegian municipalities (fylker) as
its choices.
Peru (``django.contrib.localflavor.pe``)
========================================
PEDNIField
----------
A form field that validates input as a DNI (Peruvian national identity)
number.
PERUCField
----------
A form field that validates input as an RUC (Registro Unico de
Contribuyentes) number. Valid RUC numbers have 11 digits.
PEDepartmentSelect
------------------
A ``Select`` widget that uses a list of Peruvian Departments as its choices.
Poland (``django.contrib.localflavor.pl``)
==========================================
PLNationalIdentificationNumberField
-----------------------------------
A form field that validates input as a Polish national identification number
(PESEL_).
.. _PESEL: http://en.wikipedia.org/wiki/PESEL
PLNationalBusinessRegisterField
-------------------------------
A form field that validates input as a Polish National Official Business
Register Number (REGON_), having either seven or nine digits. The checksum
algorithm used for REGONs is documented at
http://wipos.p.lodz.pl/zylla/ut/nip-rego.html.
.. _REGON: http://www.stat.gov.pl/bip/regon_ENG_HTML.htm
PLPostalCodeField
-----------------
A form field that validates input as a Polish postal code. The valid format
is XX-XXX, where X is a digit.
PLTaxNumberField
----------------
A form field that validates input as a Polish Tax Number (NIP). Valid
formats are XXX-XXX-XX-XX or XX-XX-XXX-XXX. The checksum algorithm used
for NIPs is documented at http://wipos.p.lodz.pl/zylla/ut/nip-rego.html.
PLAdministrativeUnitSelect
--------------------------
A ``Select`` widget that uses a list of Polish administrative units as its
choices.
PLVoivodeshipSelect
-------------------
A ``Select`` widget that uses a list of Polish voivodeships (administrative
provinces) as its choices.
Romania (``django.contrib.localflavor.ro``)
============================================
ROCIFField
----------
A form field that validates Romanian fiscal identification codes (CIF). The
return value strips the leading RO, if given.
ROCNPField
----------
A form field that validates Romanian personal numeric codes (CNP).
ROCountyField
-------------
A form field that validates its input as a Romanian county (judet) name or
abbreviation. It normalizes the input to the standard vehicle registration
abbreviation for the given county. This field will only accept names written
with diacritics; consider using ROCountySelect as an alternative.
ROCountySelect
--------------
A ``Select`` widget that uses a list of Romanian counties (judete) as its
choices.
ROIBANField
-----------
A form field that validates its input as a Romanian International Bank
Account Number (IBAN). The valid format is ROXX-XXXX-XXXX-XXXX-XXXX-XXXX,
with or without hyphens.
ROPhoneNumberField
------------------
A form field that validates Romanian phone numbers, short special numbers
excluded.
ROPostalCodeField
-----------------
A form field that validates Romanian postal codes.
Slovakia (``django.contrib.localflavor.sk``)
============================================
SKPostalCodeField
-----------------
A form field that validates input as a Slovak postal code. Valid formats
are XXXXX or XXX XX, where X is a digit.
SKDistrictSelect
----------------
A ``Select`` widget that uses a list of Slovak districts as its choices.
SKRegionSelect
--------------
A ``Select`` widget that uses a list of Slovak regions as its choices.
South Africa (``django.contrib.localflavor.za``)
================================================
ZAIDField
---------
A form field that validates input as a South African ID number. Validation
uses the Luhn checksum and a simplistic (i.e., not entirely accurate) check
for birth date.
ZAPostCodeField
---------------
A form field that validates input as a South African postcode. Valid
postcodes must have four digits.
Spain (``django.contrib.localflavor.es``)
=========================================
ESIdentityCardNumberField
-------------------------
A form field that validates input as a Spanish NIF/NIE/CIF (Fiscal
Identification Number) code.
ESCCCField
----------
A form field that validates input as a Spanish bank account number (Codigo
Cuenta Cliente or CCC). A valid CCC number has the format
EEEE-OOOO-CC-AAAAAAAAAA, where the E, O, C and A digits denote the entity,
office, checksum and account, respectively. The first checksum digit
validates the entity and office. The second checksum digit validates the
account. It is also valid to use a space as a delimiter, or to use no
delimiter.
ESPhoneNumberField
------------------
A form field that validates input as a Spanish phone number. Valid numbers
have nine digits, the first of which is 6, 8 or 9.
ESPostalCodeField
-----------------
A form field that validates input as a Spanish postal code. Valid codes
have five digits, the first two being in the range 01 to 52, representing
the province.
ESProvinceSelect
----------------
A ``Select`` widget that uses a list of Spanish provinces as its choices.
ESRegionSelect
--------------
A ``Select`` widget that uses a list of Spanish regions as its choices.
Switzerland (``django.contrib.localflavor.ch``)
===============================================
CHIdentityCardNumberField
-------------------------
A form field that validates input as a Swiss identity card number.
A valid number must confirm to the X1234567<0 or 1234567890 format and
have the correct checksums -- see http://adi.kousz.ch/artikel/IDCHE.htm.
CHPhoneNumberField
------------------
A form field that validates input as a Swiss phone number. The correct
format is 0XX XXX XX XX. 0XX.XXX.XX.XX and 0XXXXXXXXX validate but are
corrected to 0XX XXX XX XX.
CHZipCodeField
--------------
A form field that validates input as a Swiss zip code. Valid codes
consist of four digits.
CHStateSelect
-------------
A ``Select`` widget that uses a list of Swiss states as its choices.
United Kingdom (``django.contrib.localflavor.uk``)
==================================================
UKPostcodeField
---------------
A form field that validates input as a UK postcode. The regular
expression used is sourced from the schema for British Standard BS7666
address types at http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd.
UKCountySelect
--------------
A ``Select`` widget that uses a list of UK counties/regions as its choices.
UKNationSelect
--------------
A ``Select`` widget that uses a list of UK nations as its choices.
United States of America (``django.contrib.localflavor.us``)
============================================================
USPhoneNumberField
------------------
A form field that validates input as a U.S. phone number.
USSocialSecurityNumberField
---------------------------
A form field that validates input as a U.S. Social Security Number (SSN).
A valid SSN must obey the following rules:
* Format of XXX-XX-XXXX
* No group of digits consisting entirely of zeroes
* Leading group of digits cannot be 666
* Number not in promotional block 987-65-4320 through 987-65-4329
* Number not one known to be invalid due to widespread promotional
use or distribution (e.g., the Woolworth's number or the 1962
promotional number)
USStateField
------------
A form field that validates input as a U.S. state name or abbreviation. It
normalizes the input to the standard two-letter postal service abbreviation
for the given state.
USZipCodeField
--------------
A form field that validates input as a U.S. ZIP code. Valid formats are
XXXXX or XXXXX-XXXX.
USStateSelect
-------------
A form ``Select`` widget that uses a list of U.S. states/territories as its
choices.

View File

@ -159,8 +159,7 @@ The file extension(s) to examine (default: ".html", separate multiple
extensions with commas, or use -e multiple times). extensions with commas, or use -e multiple times).
.TP .TP
.I \-a, \-\-all .I \-a, \-\-all
Process all available locales when using makemessages. Process all available locales when using makemessages..SH "ENVIRONMENT"
.SH "ENVIRONMENT"
.TP .TP
.I DJANGO_SETTINGS_MODULE .I DJANGO_SETTINGS_MODULE
In the absence of the In the absence of the

View File

@ -1,288 +0,0 @@
==========
Middleware
==========
Middleware is a framework of hooks into Django's request/response processing.
It's a light, low-level "plugin" system for globally altering Django's input
and/or output.
Each middleware component is responsible for doing some specific function. For
example, Django includes a middleware component, ``XViewMiddleware``, that adds
an ``"X-View"`` HTTP header to every response to a ``HEAD`` request.
This document explains all middleware components that come with Django, how to
use them, and how to write your own middleware.
Activating middleware
=====================
To activate a middleware component, add it to the ``MIDDLEWARE_CLASSES`` list
in your Django settings. In ``MIDDLEWARE_CLASSES``, each middleware component
is represented by a string: the full Python path to the middleware's class
name. For example, here's the default ``MIDDLEWARE_CLASSES`` created by
``django-admin.py startproject``::
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.doc.XViewMiddleware',
)
Django applies middleware in the order it's defined in ``MIDDLEWARE_CLASSES``,
except in the case of response and exception middleware, which is applied in
reverse order.
A Django installation doesn't require any middleware -- e.g.,
``MIDDLEWARE_CLASSES`` can be empty, if you'd like -- but it's strongly
suggested that you use ``CommonMiddleware``.
Available middleware
====================
django.middleware.cache.CacheMiddleware
---------------------------------------
Enables site-wide cache. If this is enabled, each Django-powered page will be
cached for as long as the ``CACHE_MIDDLEWARE_SECONDS`` setting defines. See
the `cache documentation`_.
.. _`cache documentation`: ../cache/#the-per-site-cache
django.middleware.common.CommonMiddleware
-----------------------------------------
Adds a few conveniences for perfectionists:
* Forbids access to user agents in the ``DISALLOWED_USER_AGENTS`` setting,
which should be a list of strings.
* Performs URL rewriting based on the ``APPEND_SLASH`` and ``PREPEND_WWW``
settings.
If ``APPEND_SLASH`` is ``True`` and the initial URL doesn't end with a slash,
and it is not found in the URLconf, then a new URL is formed by appending a
slash at the end. If this new URL is found in the URLconf, then Django
redirects the request to this new URL. Otherwise, the initial URL is
processed as usual.
For example, ``foo.com/bar`` will be redirected to ``foo.com/bar/`` if you
don't have a valid URL pattern for ``foo.com/bar`` but *do* have a valid
pattern for ``foo.com/bar/``.
**New in Django development version:** The behavior of ``APPEND_SLASH`` has
changed slightly in the development version. It didn't used to check whether
the pattern was matched in the URLconf.
If ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be
redirected to the same URL with a leading "www."
Both of these options are meant to normalize URLs. The philosophy is that
each URL should exist in one, and only one, place. Technically a URL
``foo.com/bar`` is distinct from ``foo.com/bar/`` -- a search-engine
indexer would treat them as separate URLs -- so it's best practice to
normalize URLs.
* Handles ETags based on the ``USE_ETAGS`` setting. If ``USE_ETAGS`` is set
to ``True``, Django will calculate an ETag for each request by
MD5-hashing the page content, and it'll take care of sending
``Not Modified`` responses, if appropriate.
django.middleware.doc.XViewMiddleware
-------------------------------------
Sends custom ``X-View`` HTTP headers to HEAD requests that come from IP
addresses defined in the ``INTERNAL_IPS`` setting. This is used by Django's
automatic documentation system.
django.middleware.gzip.GZipMiddleware
-------------------------------------
Compresses content for browsers that understand gzip compression (all modern
browsers).
It is suggested to place this first in the middleware list, so that the
compression of the response content is the last thing that happens. Will not
compress content bodies less than 200 bytes long, when the response code is
something other than 200, JavaScript files (for IE compatibitility), or
responses that have the ``Content-Encoding`` header already specified.
django.middleware.http.ConditionalGetMiddleware
-----------------------------------------------
Handles conditional GET operations. If the response has a ``ETag`` or
``Last-Modified`` header, and the request has ``If-None-Match`` or
``If-Modified-Since``, the response is replaced by an HttpNotModified.
Also sets the ``Date`` and ``Content-Length`` response-headers.
django.middleware.http.SetRemoteAddrFromForwardedFor
----------------------------------------------------
Sets ``request.META['REMOTE_ADDR']`` based on
``request.META['HTTP_X_FORWARDED_FOR']``, if the latter is set. This is useful
if you're sitting behind a reverse proxy that causes each request's
``REMOTE_ADDR`` to be set to ``127.0.0.1``.
**Important note:** This does NOT validate ``HTTP_X_FORWARDED_FOR``. If you're
not behind a reverse proxy that sets ``HTTP_X_FORWARDED_FOR`` automatically, do
not use this middleware. Anybody can spoof the value of
``HTTP_X_FORWARDED_FOR``, and because this sets ``REMOTE_ADDR`` based on
``HTTP_X_FORWARDED_FOR``, that means anybody can "fake" their IP address. Only
use this when you can absolutely trust the value of ``HTTP_X_FORWARDED_FOR``.
django.middleware.locale.LocaleMiddleware
-----------------------------------------
Enables language selection based on data from the request. It customizes content
for each user. See the `internationalization documentation`_.
.. _`internationalization documentation`: ../i18n/
django.contrib.sessions.middleware.SessionMiddleware
----------------------------------------------------
Enables session support. See the `session documentation`_.
.. _`session documentation`: ../sessions/
django.contrib.auth.middleware.AuthenticationMiddleware
-------------------------------------------------------
Adds the ``user`` attribute, representing the currently-logged-in user, to
every incoming ``HttpRequest`` object. See `Authentication in Web requests`_.
.. _Authentication in Web requests: ../authentication/#authentication-in-web-requests
django.contrib.csrf.middleware.CsrfMiddleware
---------------------------------------------
**New in Django development version**
Adds protection against Cross Site Request Forgeries by adding hidden form
fields to POST forms and checking requests for the correct value. See the
`Cross Site Request Forgery protection documentation`_.
.. _`Cross Site Request Forgery protection documentation`: ../csrf/
django.middleware.transaction.TransactionMiddleware
---------------------------------------------------
Binds commit and rollback to the request/response phase. If a view function runs
successfully, a commit is done. If it fails with an exception, a rollback is
done.
The order of this middleware in the stack is important: middleware modules
running outside of it run with commit-on-save - the default Django behavior.
Middleware modules running inside it (coming later in the stack) will be under
the same transaction control as the view functions.
See the `transaction management documentation`_.
.. _`transaction management documentation`: ../transactions/
Writing your own middleware
===========================
Writing your own middleware is easy. Each middleware component is a single
Python class that defines one or more of the following methods:
``process_request``
-------------------
Interface: ``process_request(self, request)``
``request`` is an ``HttpRequest`` object. This method is called on each
request, before Django decides which view to execute.
``process_request()`` should return either ``None`` or an ``HttpResponse``
object. If it returns ``None``, Django will continue processing this request,
executing any other middleware and, then, the appropriate view. If it returns
an ``HttpResponse`` object, Django won't bother calling ANY other request,
view or exception middleware, or the appropriate view; it'll return that
``HttpResponse``. Response middleware is always called on every response.
``process_view``
----------------
Interface: ``process_view(self, request, view_func, view_args, view_kwargs)``
``request`` is an ``HttpRequest`` object. ``view_func`` is the Python function
that Django is about to use. (It's the actual function object, not the name of
the function as a string.) ``view_args`` is a list of positional arguments that
will be passed to the view, and ``view_kwargs`` is a dictionary of keyword
arguments that will be passed to the view. Neither ``view_args`` nor
``view_kwargs`` include the first view argument (``request``).
``process_view()`` is called just before Django calls the view. It should
return either ``None`` or an ``HttpResponse`` object. If it returns ``None``,
Django will continue processing this request, executing any other
``process_view()`` middleware and, then, the appropriate view. If it returns an
``HttpResponse`` object, Django won't bother calling ANY other request, view
or exception middleware, or the appropriate view; it'll return that
``HttpResponse``. Response middleware is always called on every response.
``process_response``
--------------------
Interface: ``process_response(self, request, response)``
``request`` is an ``HttpRequest`` object. ``response`` is the ``HttpResponse``
object returned by a Django view.
``process_response()`` should return an ``HttpResponse`` object. It could alter
the given ``response``, or it could create and return a brand-new
``HttpResponse``.
``process_exception``
---------------------
Interface: ``process_exception(self, request, exception)``
``request`` is an ``HttpRequest`` object. ``exception`` is an ``Exception``
object raised by the view function.
Django calls ``process_exception()`` when a view raises an exception.
``process_exception()`` should return either ``None`` or an ``HttpResponse``
object. If it returns an ``HttpResponse`` object, the response will be returned
to the browser. Otherwise, default exception handling kicks in.
``__init__``
------------
Most middleware classes won't need an initializer since middleware classes are
essentially placeholders for the ``process_*`` methods. If you do need some
global state you may use ``__init__`` to set up. However, keep in mind a couple
of caveats:
* Django initializes your middleware without any arguments, so you can't
define ``__init__`` as requiring any arguments.
* Unlike the ``process_*`` methods which get called once per request,
``__init__`` gets called only *once*, when the web server starts up.
Marking middleware as unused
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's sometimes useful to determine at run-time whether a piece of middleware
should be used. In these cases, your middleware's ``__init__`` method may raise
``django.core.exceptions.MiddlewareNotUsed``. Django will then remove that piece
of middleware from the middleware process.
Guidelines
----------
* Middleware classes don't have to subclass anything.
* The middleware class can live anywhere on your Python path. All Django
cares about is that the ``MIDDLEWARE_CLASSES`` setting includes the path
to it.
* Feel free to look at Django's available middleware for examples. The
core Django middleware classes are in ``django/middleware/`` in the
Django distribution. The session middleware is in
``django/contrib/sessions``.
* If you write a middleware component that you think would be useful to
other people, contribute to the community! Let us know, and we'll
consider adding it to Django.

View File

@ -0,0 +1,95 @@
.. _misc-api-stability:
=============
API stability
=============
Although Django has not reached a 1.0 release, the bulk of Django's public APIs are
stable as of the 0.95 release. This document explains which APIs will and will not
change before the 1.0 release.
What "stable" means
===================
In this context, stable means:
- All the public APIs -- everything documented in the linked documents, and
all methods that don't begin with an underscore -- will not be moved or
renamed without providing backwards-compatible aliases.
- If new features are added to these APIs -- which is quite possible --
they will not break or change the meaning of existing methods. In other
words, "stable" does not (necessarily) mean "complete."
- If, for some reason, an API declared stable must be removed or replaced, it
will be declared deprecated but will remain in the API until at least
version 1.1. Warnings will be issued when the deprecated method is
called.
- We'll only break backwards compatibility of these APIs if a bug or
security hole makes it completely unavoidable.
Stable APIs
===========
These APIs are stable:
- :ref:`Caching <topics-cache>`.
- :ref:`Custom template tags and libraries <howto-custom-template-tags>`.
- :ref:`Database lookup <topics-db-queries>` (with the exception of validation; see below).
- :ref:`django-admin utility <ref-django-admin>`.
- :ref:`FastCGI and mod_python integration <howto-deployment-index>`.
- :ref:`Flatpages <ref-contrib-flatpages>`.
- :ref:`Generic views <topics-http-generic-views>`.
- :ref:`Internationalization <topics-i18n>`.
- :ref:`Legacy database integration <howto-legacy-databases>`.
- :ref:`Model definition <topics-db-models>` (with the exception of generic relations; see below).
- :ref:`Redirects <ref-contrib-redirects>`.
- :ref:`Request/response objects <ref-request-response>`.
- :ref:`Sending e-mail <topics-email>`.
- :ref:`Sessions <topics-http-sessions>`.
- :ref:`Settings <topics-settings>`.
- :ref:`Syndication <ref-contrib-syndication>`.
- :ref:`Template language <topics-templates>` (with the exception of some
possible disambiguation of how tag arguments are passed to tags and
filters).
- :ref:`Transactions <topics-db-transactions>`.
- :ref:`URL dispatch <topics-http-urls>`.
You'll notice that this list comprises the bulk of Django's APIs. That's right
-- most of the changes planned between now and Django 1.0 are either under the
hood, feature additions, or changes to a few select bits. A good estimate is
that 90% of Django can be considered forwards-compatible at this point.
That said, these APIs should *not* be considered stable, and are likely to
change:
- :ref:`Serialization <topics-serialization>` is under development; changes
are possible.
- Generic relations will most likely be moved out of core and into the
content-types contrib package to avoid core dependencies on optional
components.
**New in development version**: this has now been done.
- The comments framework, which is yet undocumented, will get a complete
rewrite before Django 1.0.

View File

@ -1,3 +1,5 @@
.. _misc-design-philosophies:
=================== ===================
Design philosophies Design philosophies
=================== ===================
@ -9,9 +11,13 @@ the future.
Overall Overall
======= =======
.. _loose-coupling:
Loose coupling Loose coupling
-------------- --------------
.. index:: coupling; loose
A fundamental goal of Django's stack is `loose coupling and tight cohesion`_. A fundamental goal of Django's stack is `loose coupling and tight cohesion`_.
The various layers of the framework shouldn't "know" about each other unless The various layers of the framework shouldn't "know" about each other unless
absolutely necessary. absolutely necessary.
@ -25,6 +31,8 @@ stack are independent of another wherever possible.
.. _`loose coupling and tight cohesion`: http://c2.com/cgi/wiki?CouplingAndCohesion .. _`loose coupling and tight cohesion`: http://c2.com/cgi/wiki?CouplingAndCohesion
.. _less-code:
Less code Less code
--------- ---------
@ -32,6 +40,8 @@ Django apps should use as little code as possible; they should lack boilerplate.
Django should take full advantage of Python's dynamic capabilities, such as Django should take full advantage of Python's dynamic capabilities, such as
introspection. introspection.
.. _quick-development:
Quick development Quick development
----------------- -----------------
@ -39,15 +49,29 @@ The point of a Web framework in the 21st century is to make the tedious aspects
of Web development fast. Django should allow for incredibly quick Web of Web development fast. Django should allow for incredibly quick Web
development. development.
.. _dry:
Don't repeat yourself (DRY) Don't repeat yourself (DRY)
--------------------------- ---------------------------
.. index::
single: DRY
single: Don't repeat yourself
Every distinct concept and/or piece of data should live in one, and only one, Every distinct concept and/or piece of data should live in one, and only one,
place. Redundancy is bad. Normalization is good. place. Redundancy is bad. Normalization is good.
The framework, within reason, should deduce as much as possible from as little The framework, within reason, should deduce as much as possible from as little
as possible. as possible.
.. seealso::
The `discussion of DRY on the Portland Pattern Repository`__
__ http://c2.com/cgi/wiki?DontRepeatYourself
.. _explicit-is-better-than-implicit:
Explicit is better than implicit Explicit is better than implicit
-------------------------------- --------------------------------
@ -59,6 +83,8 @@ learn how to use the feature.
.. _`core Python principle`: http://www.python.org/dev/peps/pep-0020/ .. _`core Python principle`: http://www.python.org/dev/peps/pep-0020/
.. _consistency:
Consistency Consistency
----------- -----------
@ -155,19 +181,25 @@ File extensions in Web-page URLs should be avoided.
Vignette-style commas in URLs deserve severe punishment. Vignette-style commas in URLs deserve severe punishment.
.. _definitive-urls:
Definitive URLs Definitive URLs
--------------- ---------------
.. index:: urls; definitive
Technically, ``foo.com/bar`` and ``foo.com/bar/`` are two different URLs, and Technically, ``foo.com/bar`` and ``foo.com/bar/`` are two different URLs, and
search-engine robots (and some Web traffic-analyzing tools) would treat them as search-engine robots (and some Web traffic-analyzing tools) would treat them as
separate pages. Django should make an effort to "normalize" URLs so that separate pages. Django should make an effort to "normalize" URLs so that
search-engine robots don't get confused. search-engine robots don't get confused.
This is the reasoning behind the ``APPEND_SLASH`` setting. This is the reasoning behind the :setting:`APPEND_SLASH` setting.
Template system Template system
=============== ===============
.. _separation-of-logic-and-presentation:
Separate logic from presentation Separate logic from presentation
-------------------------------- --------------------------------
@ -186,9 +218,8 @@ a common header, footer, navigation bar, etc. The Django template system should
make it easy to store those elements in a single place, eliminating duplicate make it easy to store those elements in a single place, eliminating duplicate
code. code.
This is the philosophy behind `template inheritance`_. This is the philosophy behind :ref:`template inheritance
<template-inheritance>`.
.. _template inheritance: ../templates/#template-inheritance
Be decoupled from HTML Be decoupled from HTML
---------------------- ----------------------
@ -200,6 +231,8 @@ text.
XML should not be used for template languages XML should not be used for template languages
--------------------------------------------- ---------------------------------------------
.. index:: xml; suckiness of
Using an XML engine to parse templates introduces a whole new world of human Using an XML engine to parse templates introduces a whole new world of human
error in editing templates -- and incurs an unacceptable level of overhead in error in editing templates -- and incurs an unacceptable level of overhead in
template processing. template processing.

View File

@ -1,3 +1,5 @@
.. _misc-distributions:
=================================== ===================================
Third-party distributions of Django Third-party distributions of Django
=================================== ===================================
@ -10,10 +12,8 @@ requires.
Typically, these packages are based on the latest stable release of Django, so Typically, these packages are based on the latest stable release of Django, so
if you want to use the development version of Django you'll need to follow the if you want to use the development version of Django you'll need to follow the
instructions for `installing the development version`_ from our Subversion instructions for :ref:`installing the development version
repository. <installing-development-version>` from our Subversion repository.
.. _installing the development version: ../install/#installing-the-development-version
FreeBSD FreeBSD
======= =======

14
docs/misc/index.txt Normal file
View File

@ -0,0 +1,14 @@
.. _misc-index:
Meta-documentation and miscellany
=================================
Documentation that we can't find a more organized place for. Like that drawer in
your kitchen with the scissors, batteries, duct tape, and other junk.
.. toctree::
:maxdepth: 2
api-stability
design-philosophies
distributions

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Some files were not shown because too many files have changed in this diff Show More