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
Ned Batchelder <http://www.nedbatchelder.com/>
batiste@dosimple.ch
Batman
Shannon -jj Behrens <http://jjinux.blogspot.com/>
Esdras Beleza <linux@esdrasbeleza.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
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:
@echo "Please use \`make <target>' where <target> is one of"
@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 " 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"
@ -31,13 +31,15 @@ html:
@echo
@echo "Build finished. The HTML pages are in _build/html."
web:
mkdir -p _build/web _build/doctrees
$(SPHINXBUILD) -b web $(ALLSPHINXOPTS) _build/web
pickle:
mkdir -p _build/pickle _build/doctrees
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
@echo
@echo "Build finished; now you can run"
@echo " python -m sphinx.web _build/web"
@echo "to start the server."
@echo "Build finished; now you can process the pickle files or run"
@echo " sphinx-web _build/pickle"
@echo "to start the sphinx-web server."
web: pickle
htmlhelp:
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.
import sys
import os
# 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
# ---------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
#extensions = []
extensions = ["djangodocs"]
# Add any paths that contain templates here, relative to this directory.
templates_path = []
templates_path = ["_templates"]
# The suffix of source filenames.
source_suffix = '.txt'
# The master toctree document.
master_doc = 'index'
master_doc = 'contents'
# General substitutions.
project = 'Django'
copyright = '2008, Django Software Foundation'
copyright = 'Django Software Foundation and contributors'
# The default replacements for |version| and |release|, also used in various
# other places throughout the built documents.
#
# The short X.Y version.
version = 'SVN'
version = '1.0'
# The full version, including alpha/beta/rc tags.
release = version
@ -65,7 +66,7 @@ add_module_names = False
show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = 'trac'
# 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,
# relative to this directory. They are copied after the builtin static files,
# 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,
# using the given strftime format.
@ -89,6 +90,9 @@ html_last_updated_fmt = '%b %d, %Y'
# typographically correct entities.
html_use_smartypants = True
# HTML translator class for the builder
html_translator_class = "djangodocs.DjangoHTMLTranslator"
# Content template for the index page.
#html_index = ''
@ -97,7 +101,7 @@ html_use_smartypants = True
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
@ -121,6 +125,9 @@ htmlhelp_basename = 'Djangodoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
#latex_documents = []
latex_documents = [
('index', 'django.tex', 'Django Documentation', 'Django Software Foundation', 'manual'),
]
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
@ -130,3 +137,9 @@ htmlhelp_basename = 'Djangodoc'
# If false, no module index is generated.
#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
=========================================================
Since keeping multiple authentication databases in sync is a common problem when
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.
@ -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_.
.. _Subversion: http://subversion.tigris.org/
.. _mod_dav: http://httpd.apache.org/docs/2.0/mod/mod_dav.html
Configuring Apache
==================
To check against Django's authorization database from a Apache configuration
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/>
AuthType Basic
@ -43,6 +51,8 @@ with the standard ``Auth*`` and ``Require`` directives::
the ``AuthUserFile`` directive and pointing it to ``/dev/null``. Depending
on which other authentication modules you have loaded, you might need one
or more of the following directives::
.. code-block:: apache
AuthBasicAuthoritative Off
AuthDefaultAuthoritative Off
@ -94,8 +104,9 @@ location to users marked as staff members. You can use a set of
Defaults to ``off``.
``DjangoPermissionName`` The name of a permission to require for
access. See `custom permissions`_ for
more information.
access. See :ref:`custom permissions
<custom-permissions>` for more
information.
By default no specific permission will be
required.
@ -109,8 +120,3 @@ are equivalent::
SetEnv 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 @@
===================
Custom model fields
===================
.. _howto-custom-model-fields:
===========================
Writing custom model fields
===========================
**New in Django development version**
Introduction
============
The `model reference`_ documentation explains how to use Django's standard
field classes -- ``CharField``, ``DateField``, etc. For many purposes, those
classes are all you'll need. Sometimes, though, the Django version won't meet
your precise requirements, or you'll want to use a field that is entirely
different from those shipped with Django.
The :ref:`model reference <topics-db-models>` documentation explains how to use
Django's standard field classes -- :class:`~django.db.models.CharField`,
:class:`~django.db.models.DateField`, etc. For many purposes, those classes are
all you'll need. Sometimes, though, the Django version won't meet your precise
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 --
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
`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
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.
@ -40,9 +45,11 @@ Our class looks something like this::
self.east = east
self.south = south
self.west = west
# ... (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.
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``)::
@ -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``
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
=================
@ -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
mean model fields and not `form fields`_) are subclasses of
``django.db.models.Field``. Most of the information that Django records about a
field is common to all fields -- name, help text, validator lists, uniqueness
and so forth. Storing all that information is handled by ``Field``. We'll get
into the precise details of what ``Field`` can do later on; for now, suffice it
to say that everything descends from ``Field`` and then customizes key pieces
of the class behavior.
.. _form fields: ../forms/#fields
mean model fields and not :ref:`form fields <ref-forms-fields>`) are subclasses
of :class:`django.db.models.Field`. Most of the information that Django records
about a field is common to all fields -- name, help text, validator lists,
uniqueness and so forth. Storing all that information is handled by ``Field``.
We'll get into the precise details of what ``Field`` can do later on; for now,
suffice it to say that everything descends from ``Field`` and then customizes
key pieces of the class behavior.
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
@ -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
you're just creating and modifying attributes. Instead, they provide 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``
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
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
existing ``Field`` class your new field is most similar to. Can you subclass an
existing Django field and save yourself some work? If not, you should subclass
the ``Field`` class, from which everything is descended.
When planning your :class:`~django.db.models.Field` subclass, first give some
thought to which existing :class:`~django.db.models.Field` class your new field
is most similar to. Can you subclass an existing Django field and save yourself
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
are specific to your case from the common arguments and passing the latter to
the ``__init__()`` method of ``Field`` (or your parent class).
Initializing your new field is a matter of separating out any arguments that are
specific to your case from the common arguments and passing the latter to the
: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
your ``Field`` subclass ``(Something)Field``, so it's easily identifiable as a
``Field`` subclass.) It doesn't behave like any existing field, so we'll
subclass directly from ``Field``::
your :class:`~django.db.models.Field` subclass ``<Something>Field``, so it's
easily identifiable as a :class:`~django.db.models.Field` subclass.) It doesn't
behave like any existing field, so we'll subclass directly from
:class:`~django.db.models.Field`::
from django.db import models
@ -169,10 +173,13 @@ card values plus their suits; 104 characters in total.
.. note::
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
``DateField`` and it will simply ignore the ``editable`` parameter
(``auto_now`` being set implies ``editable=False``). No error is raised in
this case.
with. For example, you can pass both
:attr:`~django.db.models.Field.editable` and
:attr:`~django.db.models.Field.auto_now` to a
: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
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
to use the simpler, more permissive behavior of the current fields.
The ``Field.__init__()`` method takes the following parameters, in this
order:
The :meth:`~django.db.models.Field.__init__` method takes the following
parameters:
* ``verbose_name``
* ``name``
* ``primary_key``
* ``max_length``
* ``unique``
* ``blank``
* ``null``
* ``db_index``
* ``core``
* ``rel``: Used for related fields (like ``ForeignKey``). For advanced use
only.
* ``default``
* ``editable``
* ``serialize``: If ``False``, the field will not be serialized when the
model is passed to Django's serializers_. Defaults to ``True``.
* ``prepopulate_from``
* ``unique_for_date``
* ``unique_for_month``
* ``unique_for_year``
* ``validator_list``
* ``choices``
* ``help_text``
* ``db_column``
* ``db_tablespace``: Currently only used with the Oracle backend and only
for index creation. You can usually ignore this option.
* :attr:`~django.db.models.Field.verbose_name`
* :attr:`~django.db.models.Field.name`
* :attr:`~django.db.models.Field.primary_key`
* :attr:`~django.db.models.Field.max_length`
* :attr:`~django.db.models.Field.unique`
* :attr:`~django.db.models.Field.blank`
* :attr:`~django.db.models.Field.null`
* :attr:`~django.db.models.Field.db_index`
* :attr:`~django.db.models.Field.core`
* :attr:`~django.db.models.Field.rel`: Used for related fields (like
:attr:`~django.db.models.Field.ForeignKey`). For advanced use only.
* :attr:`~django.db.models.Field.default`
* :attr:`~django.db.models.Field.editable`
* :attr:`~django.db.models.Field.serialize`: If
:attr:`~django.db.models.Field.False`, the field will not be serialized
when the model is passed to Django's :ref:`serializers
<topics-serialization>`. Defaults to
:attr:`~django.db.models.Field.True`.
* :attr:`~django.db.models.Field.prepopulate_from`
* :attr:`~django.db.models.Field.unique_for_date`
* :attr:`~django.db.models.Field.unique_for_month`
* :attr:`~django.db.models.Field.unique_for_year`
* :attr:`~django.db.models.Field.validator_list`
* :attr:`~django.db.models.Field.choices`
* :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
meaning they do for normal Django fields. See the `model documentation`_ for
examples and details.
.. _serializers: ../serialization/
.. _model documentation: ../model-api/
meaning they do for normal Django fields. See the :ref:`field documentation
<ref-models-fields>` for examples and details.
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
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
to make sure that when Django initializes an instance of our model and assigns
a database value to our custom field attribute, we convert that value into the
If you're handling custom Python types, such as our ``Hand`` class, we need to
make sure that when Django initializes an instance of our model and assigns a
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
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
its metaclass::
simple: make sure your field subclass uses a special metaclass:
.. class:: django.db.models.SubfieldBase
For example::
class HandField(models.Field):
__metaclass__ = models.SubfieldBase
@ -240,27 +251,27 @@ its metaclass::
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.
.. _below: #to-python-self-value
Useful methods
--------------
Once you've created your ``Field`` subclass and set up up the
``__metaclass__``, you might consider overriding a few standard methods,
Once you've created your :class:`~django.db.models.Field` subclass and set up up
the ``__metaclass__``, you might consider overriding a few standard methods,
depending on your field's behavior. The list of methods below is in
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
the current ``DATABASE_ENGINE`` setting.
.. method:: db_type(self)
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
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::
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
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
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::
class MyDateField(models.Field):
@ -292,11 +303,11 @@ For example::
else:
return 'timestamp'
The ``db_type()`` method is only called by Django when the framework constructs
the ``CREATE TABLE`` statements for your application -- that is, when you first
create your tables. It's not called at any other time, so it can afford to
execute slightly complex code, such as the ``DATABASE_ENGINE`` check in the
above example.
The :meth:`db_type` method is only called by Django when the framework
constructs the ``CREATE TABLE`` statements for your application -- that is, when
you first create your tables. It's not called at any other time, so it can
afford to execute slightly complex code, such as the :setting:`DATABASE_ENGINE`
check in the above example.
Some database column types accept parameters, such as ``CHAR(25)``, where the
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
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.
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)
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
some other way, of course, but this gives you a way to tell Django to get out
of the way.
some other way, of course, but this gives you a way to tell Django to get out of
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
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
Python string, for example).
If your custom ``Field`` class deals with data structures that are more complex
than strings, dates, integers or floats, then you'll need to override this
method. As a general rule, the method should deal gracefully with any of the
following arguments:
If your custom :class:`~django.db.models.Field` class deals with data structures
that are more complex than strings, dates, integers or floats, then you'll need
to override this method. As a general rule, the method should deal gracefully
with any of the following arguments:
* 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
database, so we need to be able to process strings and ``Hand`` instances in
``to_python()``::
:meth:`to_python`::
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
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`_
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
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
format that can be used as a parameter in a query for the database backend.
cannot retrieve the value itself), and the method should return data in a format
that can be used as a parameter in a query for the database backend.
For example::
@ -403,8 +418,7 @@ For example::
return ''.join([''.join(l) for l in (value.north,
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
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
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 attribute name is in ``self.attname`` (this is set up by ``Field``). If
the model is being saved to the database for the first time, the ``add``
parameter will be ``True``, otherwise it will be ``False``.
The attribute name is in ``self.attname`` (this is set up by
:class:`~django.db.models.Field`). If the model is being saved to the database
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
somehow, just before saving. For example, Django's ``DateTimeField`` uses this
method to set the attribute correctly in the case of ``auto_now`` or
``auto_now_add``.
somehow, just before saving. For example, Django's
`:class:`~django.db.models.DateTimeField` uses this method to set the attribute
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
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
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
``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
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
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
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:
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
in a model.
Returns the default form field to use when this field is displayed 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
``__init__()`` method. Normally, all you need to do is set up a good default
for the ``form_class`` argument and then delegate further handling to the
parent class. This might require you to write a custom form field (and even a
form widget). See the `forms documentation`_ for information about this, and
take a look at the code in ``django.contrib.localflavor`` for some examples of
custom widgets.
:meth:`~django.forms.Field__init__` method. Normally, all you need to do is
set up a good default for the ``form_class`` argument and then delegate further
handling to the parent class. This might require you to write a custom form
field (and even a form widget). See the :ref:`forms documentation
<topics-forms-index>` for information about this, and take a look at the code in
: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):
# ...
@ -512,15 +532,17 @@ fields.
.. _helper functions: ../forms/#generating-forms-for-models
.. _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
the database level. This is used to determine the type of database column for
simple cases.
.. method:: get_internal_type(self)
If you have created a ``db_type()`` method, you don't need to worry about
``get_internal_type()`` -- it won't be used much. Sometimes, though, your
Returns a string giving the name of the :class:`~django.db.models.Field`
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
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``
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
``django.db.backends.<db_name>.creation.DATA_TYPES`` -- the string will still
be used by the serializer, but the default ``db_type()`` method will return
``None``. See the documentation of ``db_type()`` above_ for reasons why this
might be useful. Putting a descriptive string in as the type of the field for
the serializer is a useful idea if you're ever going to be using the
serializer output in some other place, outside of Django.
``django.db.backends.<db_name>.creation.DATA_TYPES`` -- the string will still be
used by the serializer, but the default :meth:`db_type` method will return
``None``. See the documentation of :meth:`db_type` for reasons why this might be
useful. Putting a descriptive string in as the type of the field for the
serializer is a useful idea if you're ever going to be using the serializer
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
Although implementing this method is necessary to allow field
serialization, the API might change in the future.
Returns a dictionary, mapping the field's attribute name to a
flattened string version of the data. This method has some internal
uses that aren't of interest to use here (mostly having to do with
forms). For our purposes, it's sufficient to return a one item
dictionary that maps the attribute name to a string.
Returns a dictionary, mapping the field's attribute name to a flattened string
version of the data. This method has some internal uses that aren't of interest
to use here (mostly having to do with forms). For our purposes, it's sufficient
to return a one item dictionary that maps the attribute name to a string.
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,
although calling ``Field._get_val_from_obj(obj)`` is the best way to get the
value to serialize.
output. You can ignore the input parameters for serialization purposes, although
calling :meth:`Field._get_val_from_obj(obj)
<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,
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:
1. Look at the existing Django fields (in
``django/db/models/fields/__init__.py``) for inspiration. Try to find a
field that's similar to what you want and extend it a little bit,
:file:`django/db/models/fields/__init__.py`) for inspiration. Try to find
a field that's similar to what you want and extend it a little bit,
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
behavior of the field code is to call ``force_unicode()`` on the value.
(In our examples in this document, ``value`` would be a ``Hand``
instance, not a ``HandField``). So if your ``__unicode__()`` method
automatically converts to the string form of your Python object, you can
save yourself a lot of work.
behavior of the field code is to call
:func:`~django.utils.encoding.force_unicode` on the value. (In our
examples in this document, ``value`` would be a ``Hand`` instance, not a
``HandField``). So if your :meth:`__unicode__` method automatically
converts to the string form of your Python object, you can save yourself
a lot of work.
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.
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
``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
told to use it. To do so, simply assign the new ``File`` subclass to the special
``attr_class`` attribute of the ``FileField`` subclass.
.. _file documentation: ../files/
A few suggestions
------------------

View File

@ -1,634 +1,61 @@
====================================================
The Django template language: For Python programmers
====================================================
.. _howto-custom-template-tags:
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
reference on the language syntax, see
`The Django template language: For template authors`_.
================================
Custom template tags and filters
================================
If you're looking to use the Django template system as part of another
application -- i.e., without the rest of the framework -- make sure to read
the `configuration`_ section later in this document.
Introduction
============
.. _`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
using the Django template language. A template can contain **block tags** or
**variables**.
Custom template tags and filters must live inside a Django app. If they relate
to an existing app it makes sense to bundle them there; otherwise, you should
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
content, serve as a control structure (an "if" statement or "for" loop), grab
content from a database or enable access to other template tags.
Your custom tags and filters will live in a module inside the ``templatetags``
directory. The name of the module file is the name you'll use to load the 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 ``"%}"``.
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::
For example, if your custom tags/filters are in a file called
``poll_extras.py``, your app layout might look like this::
polls/
models.py
templatetags/
__init__.py
poll_extras.py
views.py
Add two files to the ``templatetags`` package: an ``__init__.py`` file and a
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
custom tags/filters are in a file called ``poll_extras.py``, you'd do the
following in a template::
And in your template you would use the following:
.. code-block:: html+django
{% load poll_extras %}
The ``{% load %}`` tag looks at your ``INSTALLED_APPS`` setting and only allows
the loading of template libraries within installed Django apps. This is a
security feature: It allows you to host Python code for many template libraries
on a single computer without enabling access to all of them for every Django
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.
The app that contains the custom tags must be in :setting:`INSTALLED_APPS` in
order for the ``{% load %}`` tag to work. This is a security feature: It allows
you to host Python code for many template libraries on a single host machine
without enabling access to all of them for every Django installation.
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
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
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
@ -666,7 +93,9 @@ Here's an example filter definition::
"Removes all values of arg from the given string"
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" }}
@ -790,10 +219,10 @@ Template filter code falls into one of two situations:
the result (aside from any that were already present), you should mark
your filter with ``is_safe``::
@register.filter
def add_xx(value):
return '%sxx' % value
add_xx.is_safe = True
@register.filter
def add_xx(value):
return '%sxx' % value
add_xx.is_safe = True
When this filter is used in a template where auto-escaping is enabled,
Django will escape the output whenever the input is not already marked as
@ -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
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
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
``autoescape`` keyword argument mean that our function will know whether
automatic escaping is in effect when the filter is called. We use
``autoescape`` to decide whether the input data needs to be passed through
``django.utils.html.conditional_escape`` or not. (In the latter case, we
just use the identity function as the "escape" function.) The
``autoescape`` to decide whether the input data needs to be passed
through ``django.utils.html.conditional_escape`` or not. (In the latter
case, we just use the identity function as the "escape" function.) The
``conditional_escape()`` function is like ``escape()`` except it only
escapes input that is **not** a ``SafeData`` instance. If a ``SafeData``
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
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
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>
@ -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
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>
@ -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:
* 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.
* The quotes around the argument (if any) have already been stripped away,
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
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 %}
...and the output will be something like this::
...and the output will be something like this:
.. code-block:: html
<ul>
<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
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>
{% 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``
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>.
Then, any time you want to use that custom tag, load its library and call it
without any arguments, like so::
.. code-block:: html+django
{% jump_link %}
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
difference between this case and the previous ``inclusion_tag`` example.
.. _tutorials: ../tutorial01/#creating-models
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,
``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>
@ -1322,7 +766,9 @@ But, there's a problem with ``CurrentTimeNode2``: The variable name
template doesn't use ``{{ current_time }}`` anywhere else, because the
``{% 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,
like so::
like so:
.. code-block:: html+django
{% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
<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
everything between itself and ``{% endupper %}``.
Usage::
Usage:
.. code-block:: html+django
{% 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 %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in
``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
===========================================
Although the `current preferred setup`_ for running Django is Apache_ with
`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
also allow better security -- and, possibly, better performance -- than mod_python.
.. highlight:: bash
Although the current preferred setup for running Django is :ref:`Apache with
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
This document primarily focuses on FastCGI. Other protocols, such as SCGI
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
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.
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,
persistent process.
.. _current preferred setup: ../modpython/
.. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/
@ -45,9 +48,8 @@ persistent process.
Prerequisite: flup
==================
Before you can start using FastCGI with Django, you'll need to install flup_,
which is a Python library for dealing with FastCGI. Version 0.5 or newer should
work fine.
Before you can start using FastCGI with Django, you'll need to install flup_, a
Python library for dealing with FastCGI. Version 0.5 or newer should work fine.
.. _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.
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]
If you specify ``help`` as the only option after ``runfcgi``, it'll display a
list of all the available options.
If you specify ``help`` as the only option after :djadmin:`runfcgi`, it'll
display a list of all the available options.
You'll need to specify either a ``socket``, ``protocol`` or both ``host`` and
``port``. Then, when you set up your Web server, you'll just need to point it
at the host/port or socket you specified when starting the FastCGI server.
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 at
the host/port or socket you specified when starting the FastCGI server. See the
examples_, below.
Protocols
---------
Django supports all the protocols that flup_ does, namely fastcgi_, `SCGI`_ and
`AJP1.3`_ (the Apache JServ Protocol, version 1.3). Select your preferred
protocol by using the ``protocol=<protocol_name>`` option with
``./manage.py runfcgi`` -- where ``<protocol_name>`` may be one of: ``fcgi``
(the default), ``scgi`` or ``ajp``. For example::
protocol by using the ``protocol=<protocol_name>`` option with ``./manage.py
runfcgi`` -- where ``<protocol_name>`` may be one of: ``fcgi`` (the default),
``scgi`` or ``ajp``. For example::
./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
``kill`` command.
If you specify the ``pidfile`` option to your ``manage.py runfcgi``, you can
kill the running FastCGI daemon like this::
If you specify the ``pidfile`` option to :djadmin:`runfcgi`, you can kill the
running FastCGI daemon like this::
kill `cat $PIDFILE`
@ -170,7 +174,9 @@ Specifying the location of the FastCGI server
The ``FastCGIExternalServer`` directive tells Apache how to find your FastCGI
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.
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
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>
ServerName example.com
@ -215,15 +223,19 @@ constructing URLs with the ``{% url %}`` template tag (and similar methods).
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
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
``mod_rewrite`` and ``mod_access``, but not after ``mod_accesslog``. You'll
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"
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
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
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
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
import sys, os
@ -332,12 +348,10 @@ easily by using the ``touch`` command::
Serving admin media files
=========================
Regardless of the server and configuration you eventually decide to use, you 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
detailed above.
.. _modpython: ../modpython/#serving-the-admin-files
Regardless of the server and configuration you eventually decide to use, you
will also need to give some thought to how to serve the admin media files. The
advice given in the :ref:`modpython <serving-the-admin-files>` documentation
is also applicable in the setups detailed above.
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
``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 @@
=================================
How to use Django with mod_python
=================================
.. _howto-deployment-modpython:
============================================
How to use Django with Apache and mod_python
============================================
.. highlight:: apache
Apache_ with `mod_python`_ currently is the preferred setup for using Django
on a production server.
mod_python is similar to `mod_perl`_ : It embeds Python within Apache and loads
Python code into memory when the server starts. Code stays in memory throughout
the life of an Apache process, which leads to significant performance gains over
other server arrangements.
mod_python is similar to (and inspired by) `mod_perl`_ : It embeds Python within
Apache and loads Python code into memory when the server starts. Code stays in
memory throughout the life of an Apache process, which leads to significant
performance gains over other server arrangements.
Django requires Apache 2.x and mod_python 3.x, and you should use Apache's
`prefork MPM`_, as opposed to the `worker MPM`_.
You may also be interested in `How to use Django with FastCGI, SCGI or AJP`_
(which also covers SCGI and AJP).
You may also be interested in :ref:`How to use Django with FastCGI, SCGI or AJP
<howto-deployment-fastcgi>` (which also covers SCGI and AJP).
.. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/
.. _prefork MPM: http://httpd.apache.org/docs/2.2/mod/prefork.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
===================
@ -35,7 +38,7 @@ Then edit your ``httpd.conf`` file and add the following::
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption django.root /mysite
PythonOption django.root /mysite
PythonDebug On
</Location>
@ -43,8 +46,8 @@ Then edit your ``httpd.conf`` file and add the following::
project's settings file.
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``
so mod_python knows which settings to use.
Django mod_python handler." It passes the value of :ref:`DJANGO_SETTINGS_MODULE
<django-settings-module>` so mod_python knows which settings to use.
**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
@ -78,27 +81,27 @@ computer, you'll have to tell mod_python where your project can be found:
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption django.root /mysite
PythonOption django.root /mysite
PythonDebug On
**PythonPath "['/path/to/project'] + sys.path"**
</Location>
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
include the parent directory of the ``DJANGO_SETTINGS_MODULE`` location. This
is exactly the same situation as setting the Python path for interactive
usage. Whenever you try to import something, Python will run through all the
directories in ``sys.path`` in turn, from first to last, and try to import
from each directory until one succeeds.
include the parent directory of the :ref:`DJANGO_SETTINGS_MODULE
<django-settings-module>` location. This is exactly the same situation as
setting the Python path for interactive usage. Whenever you try to import
something, Python will run through all the directories in ``sys.path`` in turn,
from first to last, and try to import from each directory until one succeeds.
An example might make this clearer. Suppose
you have some applications under ``/usr/local/django-apps/`` (for example,
``/usr/local/django-apps/weblog/`` and so forth), your settings file is at
``/var/www/mysite/settings.py`` and you have specified
``DJANGO_SETTINGS_MODULE`` as in the above example. In this case, you would
need to write your ``PythonPath`` directive as::
An example might make this clearer. Suppose you have some applications under
``/usr/local/django-apps/`` (for example, ``/usr/local/django-apps/weblog/`` and
so forth), your settings file is at ``/var/www/mysite/settings.py`` and you have
specified :ref:`DJANGO_SETTINGS_MODULE <django-settings-module>` as in the above
example. In this case, you would need to write your ``PythonPath`` directive
as::
PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path"
PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path"
With this path, ``import weblog`` and ``import mysite.settings`` will both
work. If you had ``import blogroll`` in your code somewhere and ``blogroll``
@ -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
tracebacks if something goes wrong within mod_python.
Restart Apache, and any request to /mysite/ or below will be served by Django.
Note that Django's URLconfs won't trim the "/mysite/" -- they get passed the
full URL.
Restart Apache, and any request to ``/mysite/`` or below will be served by
Django. Note that Django's URLconfs won't trim the "/mysite/" -- they get passed
the full URL.
When deploying Django sites on mod_python, you'll need to restart Apache each
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
.. _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
Django -- for serving media. Here are some good choices:
* lighttpd_
* TUX_
* A stripped-down version of Apache_
* lighttpd_
* TUX_
* A stripped-down version of 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
@ -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
.. _Apache: http://httpd.apache.org/
.. _howto-deployment-modpython-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
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.
Here are two recommended approaches:
1. Create a symbolic link to the admin media files from within your
document root. This way, all of your Django-related files -- code
**and** templates -- stay in one place, and you'll still be able to
``svn update`` your code to get the latest admin templates, if they
change.
document root. This way, all of your Django-related files -- code **and**
templates -- stay in one place, and you'll still be able to ``svn
update`` your code to get the latest admin templates, if they change.
2. Or, copy the admin media files so that they live within your Apache
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
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
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,
which may conflict with the version embedded in Apache. For full
information, see `Expat Causing Apache Crash`_.
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,
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
==========================
This document explains how to output CSV (Comma Separated Values) dynamically
using Django views.
To do this, you can either use the `Python CSV library`_ or the Django template
system.
using Django views. 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
@ -14,18 +14,8 @@ Using the Python CSV library
============================
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,
and Django's ``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
that the ``csv`` module's CSV-creation capability acts on file-like objects, and
Django's :class:`~django.http.HttpResponse` objects are file-like objects.
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
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
you leave this off, browsers will probably interpret the output as HTML,
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..."
dialogue, etc.
* Hooking into the CSV-generation API is easy: Just pass ``response`` as
the first argument to ``csv.writer``. The ``csv.writer`` function expects
a file-like object, and ``HttpResponse`` objects fit the bill.
* Hooking into the CSV-generation API is easy: Just pass ``response`` as the
first argument to ``csv.writer``. The ``csv.writer`` function expects a
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
iterable object such as a list or tuple.
@ -70,12 +61,12 @@ mention:
Using the template system
=========================
Alternatively, you can use the `Django template system`_ to generate CSV. This
is lower-level than using the convenient CSV, but the solution is presented
here for completeness.
Alternatively, you can use the :ref:`Django template system <topics-templates>`
to generate CSV. This is lower-level than using the convenient CSV, but the
solution is presented here for completeness.
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::
@ -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 --
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 }}"
{% endfor %}
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
there aren't any problems with quotes. If you can be certain your data doesn't
have single or double quotes in it, you can remove the ``addslashes`` filters.
a line of CSV for each row. It uses the :tfilter:`addslashes` template filter to
ensure there aren't any problems with quotes.
.. _Django template system: ../templates/
.. _addslashes template filter: ../templates/#addslashes
Other text-based formats
========================
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
===========================
@ -35,15 +37,8 @@ Write your view
===============
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
objects.
.. admonition:: Note
For more information on ``HttpResponse`` objects, see
`Request and response objects`_.
.. _Request and response objects: ../request_response/
acts on file-like objects, and Django's :class:`~django.http.HttpResponse`
objects are file-like objects.
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
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
you leave this off, browsers will probably interpret the output as HTML,
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
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
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
cStringIO_ library as a temporary holding place for your PDF file. The
cStringIO library provides a file-like object interface that is particularly
efficient. Here's the above "Hello World" example rewritten to use
``cStringIO``::
cStringIO_ library as a temporary holding place for your PDF file. The cStringIO
library provides a file-like object interface that is particularly efficient.
Here's the above "Hello World" example rewritten to use ``cStringIO``::
from cStringIO import StringIO
from reportlab.pdfgen import canvas
@ -144,7 +139,7 @@ Further resources
* PDFlib_ is another PDF-generation library that has Python bindings. To
use it with Django, just use the same concepts explained in this article.
* `Pisa HTML2PDF`_ is yet another PDF-generation library. Pisa ships with
an example of how to integrate Pisa with Django.
an example of how to integrate Pisa with Django.
* HTMLdoc_ is a command-line script that can convert HTML to PDF. It
doesn't have a Python interface, but you can escape out to the shell
using ``system`` or ``popen`` and retrieve the output in Python.
@ -154,3 +149,12 @@ Further resources
.. _`Pisa HTML2PDF`: http://www.htmltopdf.org/
.. _HTMLdoc: http://www.htmldoc.org/
.. _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
=========================
.. module:: django.views.static
:synopsis: Serving of static files during development.
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.
@ -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
framework.
With that said, Django does support static files **during development**. Use
the view ``django.views.static.serve`` to serve media files.
With that said, Django does support static files **during development**. You can
use the :func:`django.views.static.serve` view to serve media files.
.. _Apache: http://httpd.apache.org/
.. _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.
For information on serving static files in an Apache production environment,
see the `Django mod_python documentation`_.
.. _Django mod_python documentation: ../modpython/#serving-media-files
see the :ref:`Django mod_python documentation <serving-media-files>`.
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'}),
...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.
Examples:
Given the above URLconf:
* The file ``/path/to/media/foo.jpg`` will be made available at the URL
``/site_media/foo.jpg``.
@ -49,26 +56,27 @@ Examples:
* The file ``/path/bar.jpg`` will not be accessible, because it doesn't
fall under the document root.
.. _URLconf: ../url_dispatch/
Directory listings
==================
Optionally, you can pass a ``show_indexes`` parameter to the ``static.serve``
view. This is ``False`` by default. If it's ``True``, Django will display file
listings for directories.
Optionally, you can pass the ``show_indexes`` parameter to the
:func:`~django.views.static.serve` view. This is ``False`` by default. If it's
``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}),
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)
* ``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">
<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.
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 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
the ``DEBUG`` setting. If it evaluates to ``True``, then ``site_media`` will be
associated with the ``django.views.static.serve`` view. If not
(``DEBUG == False``), then the view won't be made available.
the :setting:`DEBUG` setting. If it evaluates to ``True``, then ``site_media``
will be associated with the ``django.views.static.serve`` view. If not, then the
view won't be made available.
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.
.. _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
order.. The rest (in the "reference" section below) can be ready in any order as
you need various functionality.
Getting help
============
.. toctree::
:maxdepth: 1
overview
install
tutorial01
tutorial02
tutorial03
tutorial04
faq
documentation
Having trouble? We'd like to help!
* Try the :ref:`FAQ <faq-index>` -- it's got answers to many common questions.
* Looking for specific information? Try the :ref:`genindex`, :ref:`modindex` or
the :ref:`detailed table of contents <contents>`.
* Search for information in the `archives of the django-users mailing list`_, or
`post a question`_
* 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
=========
.. toctree::
:maxdepth: 1
django-admin
model-api
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
--------------------------
.. toctree::
:maxdepth: 1
admin
add_ons
contenttypes
csrf
databrowse
flatpages
form_preview
form_wizard
localflavor
redirects
sites
sitemaps
syndication_feeds
webdesign
Deployment
----------
.. toctree::
:maxdepth: 1
modpython
fastcgi
:ref:`Settings <ref-settings>`
See all of Django's settings and what they do.
Solving specific problems
-------------------------
:ref:`Request & response objects <ref-request-response>`
Understand the classes Django uses to represent HTTP requests and responses.
.. toctree::
:maxdepth: 1
apache_auth
static_files
email
legacy_databases
outputting_pdf
outputting_csv
:ref:`Model API reference <ref-models-index>`
Revel in the gory details of Django's model system.
:ref:`Form API reference <ref-forms-index>`
Learn the details of forms, fields, and widgets.
Et cetera
And more:
---------
.. toctree::
:maxdepth: 1
:ref:`ref-databases` ... :ref:`ref-django-admin` ... :ref:`ref-files-index` ...
:ref:`ref-generic-views` ... :ref:`ref-middleware` ...
:ref:`ref-templates-index` ... :ref:`ref-unicode`
And all the rest
================
design_philosophies
contributing
admin_css
api_stability
distributions
:ref:`Internals <internals-index>`
Learn how Django works under the hood, and how you can contribute to the
project.
Release notes
-------------
.. toctree::
:maxdepth: 1
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:`Release notes <releases-index>`
See what is and was new in each release of Django.
: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
======================
@ -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
Django development.
.. _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
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.
@ -74,6 +78,8 @@ particular:
.. _django-updates: http://groups.google.com/group/django-updates
.. _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:
.. image:: http://media.djangoproject.com/img/doc/djangotickets.png
.. image:: _images/djangotickets.png
:height: 451
:width: 590
: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
concerns on the ticket, or post a message to `django-developers`_.
.. _contributing-translations:
Submitting and maintaining translations
=======================================
@ -390,23 +398,22 @@ translated, here's what to do:
* Join the `Django i18n mailing list`_ and introduce yourself.
* 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.
* Make sure that `` django-admin.py compilemessages -l <lang>`` runs without
producing any warnings.
* Attach the patch to a ticket in Django's ticket system.
.. _Django i18n mailing list: http://groups.google.com/group/django-i18n/
.. _i18n documentation: ../i18n/
Coding style
============
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
the surrounding code as a primary goal.
@ -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
return classes).
* Mark all strings for internationalization; see the `i18n documentation`_
for details.
* Mark all strings for internationalization; see the :ref:`i18n
documentation <topics-i18n>` for details.
* 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
brackets and the tag contents.
Do this::
Do this:
.. code-block:: html+django
{{ foo }}
Don't do this::
Don't do this:
.. code-block:: html+django
{{foo}}
@ -706,15 +717,15 @@ The tests cover:
We appreciate any and all contributions to the test suite!
The Django tests all use the testing infrastructure that ships with Django for
testing applications. See `Testing Django applications`_ for an explanation of
how to write new tests.
.. _Testing Django applications: ../testing/
testing applications. See :ref:`Testing Django applications <topics-testing>`
for an explanation of how to write new 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
@ -727,13 +738,13 @@ needed. A temporary database will be created in memory when running the tests.
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.
* 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
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
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
``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=..
./runtests.py --settings=settings generic_relations i18n
@ -787,6 +800,7 @@ method as above::
./runtests.py --settings=settings markup
Requesting features
===================
@ -854,7 +868,9 @@ To use a branch, you'll need to do two things:
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>/
@ -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
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>/
@ -1025,12 +1043,10 @@ requests for commit access are potential flame-war starters, and will be ignored
.. _community page: http://www.djangoproject.com/community/
.. _ticket tracker: http://code.djangoproject.com/newticket
.. _django-developers: http://groups.google.com/group/django-developers
.. _FAQ: http://www.djangoproject.com/documentation/faq/
.. _search the tracker: http://code.djangoproject.com/search
.. _django-users: http://groups.google.com/group/django-users
.. _`#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
.. _PEP 8: http://www.python.org/peps/pep-0008.html
.. _pep8.py: http://svn.browsershots.org/trunk/devtools/pep8/pep8.py
.. _i18n branch: http://code.djangoproject.com/browser/django/branches/i18n
.. _`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
==================
@ -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
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
to start a project.
.. _documentation: ../
reference -- but we've got both! When you're ready to start a project, you can
:ref:`start with the tutorial <intro-tutorial01>` or :ref:`dive right into more
detailed documentation <topics-index>`.
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
code.
The data-model syntax offers many rich ways of representing your models -- so
far, it's been solving two years' worth of database-schema problems. Here's a
quick example::
The :ref:`data-model syntax <topics-db-models>` offers many rich ways of
representing your models -- so far, it's been solving two years' worth of
database-schema problems. Here's a quick example::
class Reporter(models.Model):
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
automatically::
automatically:
.. code-block:: bash
manage.py syncdb
The ``syncdb`` command looks at all your available models and creates tables
in your database for whichever tables don't already exist.
The :djadmin:`syncdb` command looks at all your available models and creates
tables in your database for whichever tables don't already exist.
Enjoy the free API
==================
With that, you've got a free, and rich, Python API to access your data. The API
is created on the fly, no code generation necessary::
With that, you've got a free, and rich, :ref:`Python API <topics-db-queries>` to
access your data. The API is created on the fly, no code generation necessary::
>>> 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,
production ready administrative interface -- a Web site that lets authenticated
users add, change and delete objects. It's as easy as adding a line of code to
your model classes::
production ready :ref:`administrative interface <ref-contrib-admin>` -- a Web
site that lets authenticated users add, change and delete objects. It's as easy
as adding a line of code to your model classes::
class Article(models.Model):
pub_date = models.DateTimeField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter)
class Admin: pass
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
in URLs, like ``.php`` or ``.asp``.
To design URLs for an app, you create a Python module called a URLconf. A table
of contents for your app, it contains a simple mapping between URL patterns and
Python callback functions. URLconfs also serve to decouple URLs from Python
code.
To design URLs for an app, you create a Python module called a :ref:`URLconf
<topics-http-urls>`. A table of contents for your app, it contains a simple mapping
between URL patterns and Python callback functions. URLconfs also serve to
decouple URLs from Python code.
Here's what a URLconf might look like for the ``Reporter``/``Article``
example above::
@ -190,8 +194,9 @@ Write your views
================
Each view is responsible for doing one of two things: Returning an
``HttpResponse`` object containing the content for the requested page, or
raising an exception such as ``Http404``. The rest is up to you.
:class:`~django.http.HttpResponse` object containing the content for the
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
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)
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
features but strives to stay simple enough for non-programmers to use.
This example uses Django's :ref:`template system <topics-templates>`, which has
several powerful features but strives to stay simple enough for non-programmers
to use.
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.
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" %}
@ -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
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>
<head>
@ -287,17 +297,18 @@ This is just the surface
This has been only a quick overview of Django's functionality. Some more useful
features:
* A caching framework that integrates with memcached or other backends.
* A `syndication framework`_ that makes creating RSS and Atom feeds as easy as
writing a small Python class.
* A :ref:`caching framework <topics-cache>` that integrates with memcached
or other backends.
* 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
scratched the surface.
.. _syndication framework: ../syndication_feeds/
The next obvious steps are for you to `download Django`_, read `the tutorial`_
and join `the community`_. Thanks for your interest!
The next obvious steps are for you to `download Django`_, read :ref:`the
tutorial <intro-tutorial01>` and join `the community`_. Thanks for your
interest!
.. _download Django: http://www.djangoproject.com/download/
.. _the tutorial: ../tutorial01/
.. _the community: http://www.djangoproject.com/community/

View File

@ -1,3 +1,5 @@
.. _intro-tutorial01:
=====================================
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.
* An admin site that lets you add, change and delete polls.
We'll assume you have `Django installed`_ already. You can tell Django is
installed by running the Python interactive interpreter and typing
``import django``. If that command runs successfully, with no errors, Django is
installed.
.. _`Django installed`: ../install/
We'll assume you have :ref:`Django installed <intro-install>` already. You can
tell Django is installed by running the Python interactive interpreter and
typing ``import django``. If that command runs successfully, with no errors,
Django is installed.
.. admonition:: Where to get help:
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.
.. _django-users: http://groups.google.com/group/django-users
.. _#django: irc://irc.freenode.net/django
__ http://groups.google.com/group/django-users
__ irc://irc.freenode.net/django
Creating a project
==================
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
a Django *project* -- a collection of settings for an instance of Django,
initial setup. Namely, you'll need to auto-generate some code that establishes a
Django :term:`project` -- a collection of settings for an instance of Django,
including database configuration, Django-specific options and
application-specific settings.
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
will create a ``mysite`` directory in your current directory.
code, then run the command ``django-admin.py startproject mysite``. This will
create a ``mysite`` directory in your current directory.
.. admonition:: Mac OS X permissions
If you're using Mac OS X, you may see the message "permission
denied" when you try to run ``django-admin.py startproject``. This
is because, on Unix-based systems like OS X, a file must be marked
as "executable" before it can be run as a program. To do this, open
Terminal.app and navigate (using the ``cd`` command) to the directory
where ``django-admin.py`` is installed, then run the command
If you're using Mac OS X, you may see the message "permission denied" when
you try to run ``django-admin.py startproject``. This is because, on
Unix-based systems like OS X, a file must be marked as "executable" before it
can be run as a program. To do this, open Terminal.app and navigate (using
the ``cd`` command) to the directory where :ref:`django-admin.py
<ref-django-admin>` is installed, then run the command
``chmod +x django-admin.py``.
.. note::
You'll need to avoid naming projects after built-in Python or Django
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).
(``django-admin.py`` should be on your system path if you installed Django via
``python setup.py``. If it's not on your path, you can find it in
``site-packages/django/bin``, where ``site-packages`` is a directory within
your Python installation. Consider symlinking to ``django-admin.py`` from some
place on your path, such as ``/usr/local/bin``.)
:ref:`django-admin.py <ref-django-admin>` should be on your system path if you
installed Django via ``python setup.py``. If it's not on your path, you can find
it in ``site-packages/django/bin``, where ```site-packages``` is a directory
within your Python installation. Consider symlinking to :ref:`django-admin.py
<ref-django-admin>` from some place on your path, such as
:file:`/usr/local/bin`.
.. admonition:: Where should this code live?
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,
you don't do that. It's not a good idea to put any of this Python code within
your Web server's document root, because it risks the possibility that
people may be able to view your code over the Web. That's not good for
you don't do that. It's not a good idea to put any of this Python code
within your Web server's document root, because it risks the possibility
that people may be able to view your code over the Web. That's not good for
security.
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/
__init__.py
@ -86,28 +87,34 @@ Let's look at what ``startproject`` created::
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
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.
* ``settings.py``: Settings/configuration for this Django project.
* ``urls.py``: The URL declarations for this Django project; a "table of
contents" of your Django-powered site.
* :file:`manage.py`: A command-line utility that lets you interact with this
Django project in various ways. You can read all the details about
:file:`manage.py` in :ref:`ref-django-admin`.
* :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
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
the following output on the command line::
Validating models...
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/
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
@ -126,40 +133,49 @@ It worked!
.. admonition:: Changing the port
By default, the ``runserver`` command starts the development server on port
8000. If you want to change the server's port, pass it as a command-line
argument. For instance, this command starts the server on port 8080::
By default, the :djadmin:`runserver` command starts the development server
on port 8000. If you want to change the server's port, pass it as a
command-line argument. For instance, this command starts the server on port
8080:
.. code-block:: bash
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
--------------
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
database's connection parameters:
* ``DATABASE_ENGINE`` -- Either 'postgresql_psycopg2', 'mysql' or 'sqlite3'.
Other backends are `also available`_.
* ``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).
* :setting:`DATABASE_ENGINE` -- Either 'postgresql_psycopg2', 'mysql' or
'sqlite3'. Other backends are :setting:`also available <DATABASE_ENGINE>`.
* :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).
* :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).
.. _also available: ../settings/
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.
.. admonition:: Note
.. note::
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
@ -168,35 +184,39 @@ database's connection parameters:
If you're using SQLite, you don't need to create anything beforehand - the
database file will be created automatically when it is needed.
While you're editing ``settings.py``, take note of the ``INSTALLED_APPS``
setting towards the bottom of the file. That variable holds the names of all
Django applications that are activated in this Django instance. Apps can be
used in multiple projects, and you can package and distribute them for use
by others in their projects.
While you're editing :file:`settings.py`, take note of the
:setting:`INSTALLED_APPS` setting towards the bottom of the file. That variable
holds the names of all Django applications that are activated in this Django
instance. Apps can be used in multiple projects, and you can package and
distribute them for use by others in their projects.
By default, ``INSTALLED_APPS`` contains the following apps, all of which come
with Django:
By default, :setting:`INSTALLED_APPS` contains the following apps, all of which
come with Django:
* ``django.contrib.auth`` -- An authentication system.
* ``django.contrib.contenttypes`` -- A framework for content types.
* ``django.contrib.sessions`` -- A session framework.
* ``django.contrib.sites`` -- A framework for managing multiple sites
* :mod:`django.contrib.auth` -- An authentication system.
* :mod:`django.contrib.contenttypes` -- A framework for content types.
* :mod:`django.contrib.sessions` -- A session framework.
* :mod:`django.contrib.sites` -- A framework for managing multiple sites
with one Django installation.
These applications are included by default as a convenience for the common
case.
These applications are included by default as a convenience for the common case.
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
that, run the following command::
that, run the following command:
.. code-block:: bash
python manage.py syncdb
The ``syncdb`` command looks at the ``INSTALLED_APPS`` setting and 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,
and you'll get a prompt asking you if you'd like to create a superuser account
for the authentication system. Go ahead and do that.
The :djadmin:`syncdb` command looks at the :setting:`INSTALLED_APPS` setting and
creates any necessary database tables according to the database settings in your
:file:`settings.py` file. You'll see a message for each database table it
creates, and you'll get a prompt asking you if you'd like to create a superuser
account for the authentication system. Go ahead and do that.
If you're interested, run the command-line client for your database and type
``\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
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
``INSTALLED_APPS`` before running ``syncdb``. The ``syncdb`` command will
only create tables for apps in ``INSTALLED_APPS``.
:setting:`INSTALLED_APPS` before running :djadmin:`syncdb`. The
:djadmin:`syncdb` command will only create tables for apps in
:setting:`INSTALLED_APPS`.
.. _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
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 --
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.
To create your app, make sure you're in the ``mysite`` directory and type
this command::
To create your app, make sure you're in the :file:`mysite` directory and type
this command:
.. code-block:: bash
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/
__init__.py
@ -253,17 +278,17 @@ The first step in writing a database Web app in Django is to define your models
.. admonition:: Philosophy
A model is the single, definitive source of data about your
data. It contains the essential fields and behaviors of the data you're
storing. Django follows the `DRY Principle`_. The goal is to define your
data model in one place and automatically derive things from it.
A model is the single, definitive source of data about your data. It contains
the essential fields and behaviors of the data you're storing. Django follows
the :ref:`DRY Principle <dry>`. The goal is to define your data model in one
place and automatically derive things from it.
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
choice and a vote tally. Each choice is associated with a poll.
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
@ -276,51 +301,54 @@ These concepts are represented by simple Python classes. Edit the
choice = models.CharField(max_length=200)
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
not a valid argument, you're most likely using an old version of
Django. (This version of the tutorial is written for the latest
development version of Django.) If you're using a Subversion checkout
of Django's development version (see `the installation docs`_ for
more information), you shouldn't have any problems.
If Django gives you an error message saying that
:attr:`~django.db.models.Field.max_length` is not a valid argument, you're
most likely using an old version of Django. (This version of the tutorial is
written for the latest development version of Django.) If you're using a
Subversion checkout of Django's development version (see :ref:`the
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
switch to `the Django 0.96 tutorial`_, because this tutorial covers
several features that only exist in the Django development version.
If you want to stick with an older version of Django, you'll want to switch
to `the Django 0.96 tutorial`_, because this tutorial covers several features
that only exist in the Django development version.
.. _the installation docs: ../install/
.. _the Django 0.96 tutorial: ../0.96/tutorial01/
.. _the Django 0.96 tutorial: http://www.djangoproject.com/documentation/0.96/tutorial01/
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.
Each field is represented by an instance of a ``models.*Field`` class -- e.g.,
``models.CharField`` for character fields and ``models.DateTimeField`` for
datetimes. This tells Django what type of data each field holds.
Each field is represented by an instance of a :class:`~django.db.models.Field`
class -- e.g., :class:`~django.db.models.CharField` for character fields and
: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`` )
is the field's name, in machine-friendly format. You'll use this value in your
Python code, and your database will use it as the column name.
The name of each :class:`~django.db.models.Field` instance (e.g. ``question`` or
``pub_date`` ) is the field's name, in machine-friendly format. You'll use this
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
human-readable name. That's used in a couple of introspective parts of Django,
and it doubles as documentation. If this field isn't provided, Django will use
the machine-readable name. In this example, we've only defined a human-readable
name for ``Poll.pub_date``. For all other fields in this model, the field's
machine-readable name will suffice as its human-readable name.
You can use an optional first positional argument to a
:class:`~django.db.models.Field` to designate a human-readable name. That's used
in a couple of introspective parts of Django, and it doubles as documentation.
If this field isn't provided, Django will use the machine-readable name. In this
example, we've only defined a human-readable name for ``Poll.pub_date``. For all
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,
requires that you give it a ``max_length``. That's used not only in the database
Some :class:`~django.db.models.Field` classes have required elements.
: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.
Finally, note a relationship is defined, using ``models.ForeignKey``. That tells
Django each Choice is related to a single Poll. Django supports all the common
database relationships: many-to-ones, many-to-manys and one-to-ones.
Finally, note a relationship is defined, using
:class:`~django.db.models.ForeignKey`. That tells Django each Choice is related
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
.. _DRY Principle: http://c2.com/cgi/wiki?DontRepeatYourself
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
Django installation.
Edit the ``settings.py`` file again, and change the ``INSTALLED_APPS`` setting
to include the string ``'mysite.polls'``. So it'll look like this::
Edit the :file:`settings.py` file again, and change the
:setting:`INSTALLED_APPS` setting to include the string ``'mysite.polls'``. So
it'll look like this::
INSTALLED_APPS = (
'django.contrib.auth',
@ -350,12 +379,17 @@ to include the string ``'mysite.polls'``. So it'll look like this::
'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
You should see something similar to the following (the CREATE TABLE SQL statements
for the polls app)::
You should see something similar to the following (the ``CREATE TABLE`` SQL
statements for the polls app):
.. code-block:: sql
BEGIN;
CREATE TABLE "polls_poll" (
@ -384,7 +418,8 @@ Note the following:
* By convention, Django appends ``"_id"`` to the foreign key field name.
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
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
output is in PostgreSQL syntax.
* The ``sql`` command doesn't actually run the SQL in your database - it just
prints it to the screen so that you can see what SQL Django thinks is required.
If you wanted to, you could copy and paste this SQL into your database prompt.
However, as we will see shortly, Django provides an easier way of committing
the SQL to the database.
* The :djadmin:`sql` command doesn't actually run the SQL in your database -
it just prints it to the screen so that you can see what SQL Django thinks
is required. If you wanted to, you could copy and paste this SQL into your
database prompt. However, as we will see shortly, Django provides an
easier way of committing the SQL to the database.
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
(such as table modifications or constraints) that are defined for the
application.
* :djadmin:`python manage.py validate <validate>` -- Checks for any errors
in the construction of your models.
* ``python manage.py sqlclear polls`` -- Outputs the necessary ``DROP
TABLE`` statements for this app, according to which tables already exist
in your database (if any).
* :djadmin:`python manage.py sqlcustom polls <sqlcustom>` -- Outputs any
:ref:`custom SQL statements <initial-sql>` (such as table modifications or
constraints) that are defined for the application.
* ``python manage.py sqlindexes polls`` -- Outputs the ``CREATE INDEX``
statements for this app.
* :djadmin:`python manage.py sqlclear polls <sqlclear>` -- Outputs the
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
the 'sql', 'sqlcustom', and 'sqlindexes' commands.
* :djadmin:`python manage.py sqlindexes polls <sqlindexes>` -- Outputs the
``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
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
The ``syncdb`` command runs the sql from 'sqlall' on your database for all apps
in ``INSTALLED_APPS`` that don't already exist in your database. This creates
all the tables, initial data and indexes for any apps you have added to your
project since the last time you ran syncdb. ``syncdb`` can be called as often
as you like, and it will only ever create the tables that don't exist.
The :djadmin:`syncdb` command runs the sql from 'sqlall' on your database for
all apps in :setting:`INSTALLED_APPS` that don't already exist in your database.
This creates all the tables, initial data and indexes for any apps you have
added to your project since the last time you ran syncdb. :djadmin:`syncdb` can
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
``manage.py`` utility can do.
.. _django-admin.py documentation: ../django-admin/
Read the :ref:`django-admin.py documentation <ref-django-admin>` for full
information on what the ``manage.py`` utility can do.
Playing with the API
====================
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
@ -449,28 +489,28 @@ things:
* Putting ``mysite`` on ``sys.path``. For flexibility, several pieces of
Django refer to projects in Python dotted-path notation (e.g.
``'mysite.polls.models'``). In order for this to work, the
``mysite`` package has to be on ``sys.path``.
``'mysite.polls.models'``). In order for this to work, the ``mysite``
package has to be on ``sys.path``.
We've already seen one example of this: the ``INSTALLED_APPS`` setting is
a list of packages in dotted-path notation.
We've already seen one example of this: the :setting:`INSTALLED_APPS`
setting is a list of packages in dotted-path notation.
* Setting the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives
Django the path to your ``settings.py`` file.
.. admonition:: Bypassing manage.py
If you'd rather not use ``manage.py``, no problem. Just make sure
``mysite`` is at the root level on the Python path (i.e.,
``import mysite`` works) and set the ``DJANGO_SETTINGS_MODULE``
environment variable to ``mysite.settings``.
If you'd rather not use ``manage.py``, no problem. Just make sure ``mysite``
is at the root level on the Python path (i.e., ``import mysite`` works) and
set the ``DJANGO_SETTINGS_MODULE`` environment variable to
``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
>>> from mysite.polls.models import Poll, Choice # Import the model classes we just wrote.
# No polls are in the system yet.
>>> Poll.objects.all()
@ -505,10 +545,11 @@ Once you're in the shell, explore the database API::
[<Poll: Poll object>]
Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful
representation of this object. Let's fix that by editing the polls model (in
the ``polls/models.py`` file) and adding a ``__unicode__()`` method to both
``Poll`` and ``Choice``::
Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful representation
of this object. Let's fix that by editing the polls model (in the
``polls/models.py`` file) and adding a
:meth:`~django.db.models.Model.__unicode__` method to both ``Poll`` and
``Choice``::
class Poll(models.Model):
# ...
@ -520,43 +561,46 @@ the ``polls/models.py`` file) and adding a ``__unicode__()`` method to both
def __unicode__(self):
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
see any change in how they're represented, you're most likely using
an old version of Django. (This version of the tutorial is written
for the latest development version of Django.) If you're using a
Subversion checkout of of Django's development version (see `the
installation docs`_ for more information), you shouldn't have any
problems.
If you add the :meth:`~django.db.models.Model.__unicode__` method to your
models and don't see any change in how they're represented, you're most
likely using an old version of Django. (This version of the tutorial is
written for the latest development version of Django.) If you're using a
Subversion checkout of of Django's development version (see :ref:`the
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
switch to `the Django 0.96 tutorial`_, because this tutorial covers
several features that only exist in the Django development version.
If you want to stick with an older version of Django, you'll want to switch
to `the Django 0.96 tutorial`_, because this tutorial covers several features
that only exist in the Django development version.
.. _the installation docs: ../install/
.. _the Django 0.96 tutorial: ../0.96/tutorial01/
.. _the Django 0.96 tutorial: http://www.djangoproject.com/documentation/0.96/tutorial01/
It's important to add ``__unicode__()`` methods to your models, not only for
your own sanity when dealing with the interactive prompt, but also because
objects' representations are used throughout Django's automatically-generated
admin.
It's important to add :meth:`~django.db.models.Model.__unicode__` methods to
your models, not only for your own sanity when dealing with the interactive
prompt, but also because objects' representations are used throughout Django's
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
``__str__()`` methods to your classes, not ``__unicode__()`` methods.
We use ``__unicode__()`` here because Django models deal with Unicode by
default. All data stored in your database is converted to Unicode when it's
returned.
:meth:`django.db.models.Model.__str__` methods to your classes, not
:meth:`~django.db.models.Model.__unicode__` methods. We use
:meth:`~django.db.models.Model.__unicode__` here because Django models deal
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
``__unicode__()`` and converts the result to a UTF-8 bytestring. This means
that ``unicode(p)`` will return a Unicode string, and ``str(p)`` will return
a normal string, with characters encoded as UTF-8.
Django models have a default :meth:`django.db.models.Model.__str__` method
that calls :meth:`~django.db.models.Model.__unicode__` and converts the
result to a UTF-8 bytestring. This means that ``unicode(p)`` will return a
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__()``
methods to your models. With any luck, things should Just Work for you.
If all of this is jibberish to you, just remember to add
: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
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.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
Django's automatic admin working.
.. _Database API reference: ../db-api/
.. _part 2 of this tutorial: ../tutorial02/
When you're comfortable with the API, read :ref:`part 2 of this tutorial
<intro-tutorial02>` to get Django's automatic admin working.

View File

@ -1,26 +1,27 @@
.. _intro-tutorial02:
=====================================
Writing your first Django app, part 2
=====================================
This tutorial begins where `Tutorial 1`_ left off. We're continuing the Web-poll
application and will focus on Django's automatically-generated admin site.
.. _Tutorial 1: ../tutorial01/
This tutorial begins where :ref:`Tutorial 1 <intro-tutorial01>` left off. We're
continuing the Web-poll application and will focus on Django's
automatically-generated admin site.
.. admonition:: Philosophy
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,
Django entirely automates creation of admin interfaces for models.
content is tedious work that doesn't require much creativity. For that
reason, Django entirely automates creation of admin interfaces for models.
Django was written in a newsroom environment, with a very clear separation
between "content publishers" and the "public" site. Site managers use the
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
interface for site administrators to edit content.
The admin isn't necessarily intended to be used by site visitors; it's for site
managers.
displayed on the public site. Django solves the problem of creating a
unified interface for site administrators to edit content.
The admin isn't necessarily intended to be used by site visitors; it's for
site managers.
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
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
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
"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.
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
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:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin01.png
.. image:: _images/admin01.png
:alt: Django admin login screen
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
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
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin02.png
You should see a few other types of editable content, including groups, users
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
=========================================
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``
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::
from mysite.polls.models import Poll
from django.contrib import admin
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
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
: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
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:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin04t.png
.. image:: _images/admin04t.png
: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:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin05t.png
.. image:: _images/admin05t.png
:alt: Editing form for poll object
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin05.png
Things to note here:
* 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
how to display itself in the Django admin.
* Each ``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 form is automatically generated from the Poll model.
* The different model field types (:class:`~django.db.models.DateTimeField`,
:class:`~django.db.models.CharField`) correspond to the appropriate HTML
input widget. Each type of field knows how to display itself in the Django
admin.
* 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:
* Save -- Saves changes and returns to the change-list page for this type of
object.
* Save and continue editing -- Saves changes and reloads the admin page for
this object.
* Save and add another -- Saves changes and loads a new, blank form for this
type of object.
* Delete -- Displays a delete confirmation page.
* Save -- Saves changes and returns to the change-list page for this type of
object.
* Save and continue editing -- Saves changes and reloads the admin page for
this object.
* Save and add another -- Saves changes and loads a new, blank form for this
type of object.
* Delete -- Displays a delete confirmation page.
Change the "Date published" by clicking the "Today" and "Now" shortcuts. Then
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,
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
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin06.png
Customize the admin form
========================
@ -184,7 +187,7 @@ admin options for an object.
This particular change above makes the "Publication date" come before the
"Question" field:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin07.png
.. image:: _images/admin07.png
:alt: Fields have been reordered
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.
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
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin08.png
You can assign arbitrary HTML classes to each fieldset. Django provides a
``"collapse"`` class that displays a particular fieldset initially collapsed.
@ -219,7 +221,7 @@ aren't commonly used::
('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
Adding related objects
@ -232,18 +234,21 @@ Yet.
There are two ways to solve this problem. The first register ``Choice`` with the
admin just as we did with ``Poll``. That's easy::
from mysite.polls.models import Choice
admin.site.register(Choice)
Now "Choices" is an available option in the Django admin. The "Add choice" form
looks like this:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin10.png
.. image:: _images/admin10.png
:alt: Choice admin page
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
as a ``<select>`` box. In our case, only one poll exists at this point.
database. Django knows that a :class:`~django.db.models.ForeignKey` should be
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
``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``
registration code to read::
poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3)
class ChoiceInline(admin.StackedInline):
model = Choice
extra = 3
@ -277,16 +283,15 @@ default, provide enough fields for 3 choices."
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
:target: http://media.djangoproject.com/img/doc/tutorial-trunk/admin11.png
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
already-created object, you get another three extra slots.
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
the ``ChoiceInline`` declaration to read::
@ -296,7 +301,7 @@ the ``ChoiceInline`` declaration to read::
With that ``TabularInline`` (instead of ``StackedInline``), the
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
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:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin04t.png
.. image:: _images/admin04t.png
: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
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:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin13t.png
.. image:: _images/admin13t.png
: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
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
``pub_date`` field:
.. image:: http://media.djangoproject.com/img/doc/tutorial-trunk/admin14t.png
.. image:: _images/admin14t.png
: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.
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!)
Open your settings file (``mysite/settings.py``, remember) and look at the
``TEMPLATE_DIRS`` setting. ``TEMPLATE_DIRS`` is a tuple of filesystem
directories to check when loading Django templates. It's a search path.
:setting:`TEMPLATE_DIRS` setting. :setting:`TEMPLATE_DIRS` is a tuple of
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
Django where our templates live::
By default, :setting:`TEMPLATE_DIRS` is empty. So, let's add a line to it, to
tell Django where our templates live::
TEMPLATE_DIRS = (
"/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
admin template directory (``django/contrib/admin/templates``) into an ``admin``
subdirectory of whichever directory you're using in ``TEMPLATE_DIRS``. For
example, if your ``TEMPLATE_DIRS`` includes ``"/home/my_username/mytemplates"``,
as above, then copy ``django/contrib/admin/templates/admin/base_site.html`` to
subdirectory of whichever directory you're using in :setting:`TEMPLATE_DIRS`.
For example, if your :setting:`TEMPLATE_DIRS` includes
``"/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
``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
changes.
Astute readers will ask: But if ``TEMPLATE_DIRS`` was empty by default, how was
Django finding the default admin templates? The answer is that, by default,
Django automatically looks for a ``templates/`` subdirectory within each app
package, for use as a fallback. See the `loader types documentation`_ for full
information.
.. _loader types documentation: ../templates_python/#loader-types
Astute readers will ask: But if :setting:`TEMPLATE_DIRS` was empty by default,
how was Django finding the default admin templates? The answer is that, by
default, Django automatically looks for a ``templates/`` subdirectory within
each app package, for use as a fallback. See the :ref:`template loader
documentation <template-loaders>` for full information.
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
admin index page.
By default, it displays all the apps in your ``INSTALLED_APPS`` setting that
have been registered with the admin application, in alphabetical order. You
may want to make significant changes to the layout. After all, the index is
probably the most important page of the admin, and it should be easy to use.
By default, it displays all the apps in :setting:`INSTALLED_APPS` that have been
registered with the admin application, in alphabetical order. You may want to
make significant changes to the layout. After all, the index is probably the
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
``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
object-specific admin pages in whatever way you think is best.
Django offers another shortcut in this department. Run the command
``python manage.py adminindex polls`` to get a chunk of template code for
inclusion in the admin index template. It's a useful starting point.
Django offers another shortcut in this department. Run the command ``python
manage.py adminindex polls`` to get a chunk of template code for inclusion in
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
general, see the `Django admin CSS guide`_.
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/
When you're comfortable with the admin site, read :ref:`part 3 of this tutorial
<intro-tutorial03>` to start working on public poll views.

View File

@ -1,11 +1,12 @@
.. _intro-tutorial03:
=====================================
Writing your first Django app, part 3
=====================================
This tutorial begins where `Tutorial 2`_ left off. We're continuing the Web-poll
application and will focus on creating the public interface -- "views."
.. _Tutorial 2: ../tutorial02/
This tutorial begins where :ref:`Tutorial 2 <intro-tutorial02>` left off. We're
continuing the Web-poll application and will focus on creating the public
interface -- "views."
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:
* Blog homepage -- displays the latest few entries.
* Entry "detail" page -- permalink page for a single entry.
* Year-based archive page -- displays all months with entries in the
given year.
* Month-based archive page -- displays all days with entries in the
given month.
* Day-based archive page -- displays all entries in the given day.
* Comment action -- handles posting comments to a given entry.
In our poll application, we'll have the following four views:
* Poll "archive" page -- displays the latest few polls.
* Poll "detail" page -- displays a poll question, with no results but
with a form to vote.
* Poll "results" page -- displays results for a particular poll.
* Vote action -- handles voting for a particular choice in a particular
poll.
@ -42,8 +51,8 @@ creating a Python module, called a URLconf. URLconfs are how Django associates
a given URL with given Python code.
When a user requests a Django-powered page, the system looks at the
``ROOT_URLCONF`` setting, which contains a string in Python dotted syntax.
Django loads that module and looks for a module-level variable called
:setting:`ROOT_URLCONF` setting, which contains a string in Python dotted
syntax. Django loads that module and looks for a module-level variable called
``urlpatterns``, which is a sequence of tuples in the following format::
(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.
When it finds a match, Django calls the Python callback function, with an
``HTTPRequest`` object as the first argument, any "captured" values from the
regular expression as keyword arguments, and, optionally, arbitrary keyword
arguments from the dictionary (an optional third item in the tuple).
:class:`~django.http.HttpRequest` object as the first argument, any "captured"
values from the regular expression as keyword arguments, and, optionally,
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 details on URLconfs, see the `URLconf documentation`_.
For more on :class:`~django.http.HttpRequest` objects, see the
: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
Tutorial 1, it created a default URLconf in ``mysite/urls.py``. It also
automatically set your ``ROOT_URLCONF`` setting (in ``settings.py``) to point
at that file::
automatically set your :setting:`ROOT_URLCONF` setting (in ``settings.py``) to
point at that file::
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'),
)
This is worth a review. When somebody requests a page from your Web site --
say, "/polls/23/", Django will load this Python module, because it's pointed to
by the ``ROOT_URLCONF`` setting. It finds the variable named ``urlpatterns``
This is worth a review. When somebody requests a page from your Web site -- say,
"/polls/23/", Django will load this Python module, because it's pointed to by
the :setting:`ROOT_URLCONF` setting. It finds the variable named ``urlpatterns``
and traverses the regular expressions in order. When it finds a regular
expression that matches -- ``r'^polls/(?P<poll_id>\d+)/$'`` -- it loads the
associated Python package/module: ``mysite.polls.views.detail``. That
corresponds to the function ``detail()`` in ``mysite/polls/views.py``.
Finally, it calls that ``detail()`` function like so::
corresponds to the function ``detail()`` in ``mysite/polls/views.py``. Finally,
it calls that ``detail()`` function like so::
detail(request=<HttpRequest object>, poll_id='23')
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parenthesis around a
pattern "captures" the text matched by that pattern and sends it as an argument
to the view function; the ``?P<poll_id>`` defines the name that will be used to
identify the matched pattern; and ``\d+`` is a regular expression to match a sequence of
digits (i.e., a number).
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parenthesis
around a pattern "captures" the text matched by that pattern and sends it as an
argument to the view function; the ``?P<poll_id>`` defines the name that will be
used to identify the matched pattern; and ``\d+`` is a regular expression to
match a sequence of digits (i.e., a number).
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
``.php`` -- unless you have a sick sense of humor, in which case you can do
something like this::
what you can do with them. And there's no need to add URL cruft such as ``.php``
-- unless you have a sick sense of humor, in which case you can do something
like this::
(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/``.
If you need help with regular expressions, see `Wikipedia's entry`_ and the
`Python documentation`_. Also, the O'Reilly book "Mastering Regular
Expressions" by Jeffrey Friedl is fantastic.
`Python documentation`_. Also, the O'Reilly book "Mastering Regular Expressions"
by Jeffrey Friedl is fantastic.
Finally, a performance note: these regular expressions are compiled the first
time the URLconf module is loaded. They're super fast.
.. _Wikipedia's entry: http://en.wikipedia.org/wiki/Regular_expression
.. _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
=====================
@ -127,7 +136,9 @@ Write your first view
Well, we haven't created any views yet -- we just have the URLconf. But let's
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
@ -170,21 +181,22 @@ provide in the URL.
Write views that actually do something
======================================
Each view is responsible for doing one of two things: Returning an ``HttpResponse``
object containing the content for the requested page, or raising an exception
such as ``Http404``. The rest is up to you.
Each view is responsible for doing one of two things: Returning an
:class:`~django.http.HttpResponse` object containing the content for the
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
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
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
in Tutorial 1. Here's one stab at the ``index()`` view, which displays the
latest 5 poll questions in the system, separated by commas, according to
publication date::
in :ref:`Tutorial 1 <intro-tutorial01>`. Here's one stab at the ``index()``
view, which displays the latest 5 poll questions in the system, separated by
commas, according to publication date::
from mysite.polls.models import Poll
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))
That code loads the template called "polls/index.html" and passes it a context. The
context is a dictionary mapping template variable names to Python objects.
That code loads the template called "polls/index.html" and passes it a context.
The context is a dictionary mapping template variable names to Python objects.
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
Ah. There's no template yet. First, create a directory, somewhere on your
filesystem, whose contents Django can access. (Django runs as whatever user
your server runs.) Don't put them under your document root, though. You
probably shouldn't make them public, just for security's sake.
Then edit ``TEMPLATE_DIRS`` in your ``settings.py`` to tell Django where it can
find templates -- just as you did in the "Customize the admin look and feel"
section of Tutorial 2.
filesystem, whose contents Django can access. (Django runs as whatever user your
server runs.) Don't put them under your document root, though. You probably
shouldn't make them public, just for security's sake.
Then edit :setting:`TEMPLATE_DIRS` in your ``settings.py`` to tell Django where
it can find templates -- just as you did in the "Customize the admin look and
feel" section of Tutorial 2.
When you've done that, create a directory ``polls`` in your template directory.
Within that, create a file called ``index.html``. Note that our
``loader.get_template('polls/index.html')`` code from above maps to
"[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 %}
<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
``HttpResponse`` object with the result of the rendered template. Django
provides a shortcut. Here's the full ``index()`` view, rewritten::
:class:`~django.http.HttpResponse` object with the result of the rendered
template. Django provides a shortcut. Here's the full ``index()`` view,
rewritten::
from django.shortcuts import render_to_response
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]
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
argument and a dictionary as its optional second argument. It returns an
``HttpResponse`` object of the given template rendered with the given context.
The :func:`~django.shortcuts.render_to_response` function takes a template name
as its first argument and a dictionary as its optional second argument. It
returns an :class:`~django.http.HttpResponse` object of the given template
rendered with the given context.
Raising 404
===========
@ -282,15 +299,15 @@ for a given poll. Here's the view::
raise Http404
return render_to_response('polls/detail.html', {'poll': p})
The new concept here: The view raises the ``django.http.Http404``
exception if a poll with the requested ID doesn't exist.
The new concept here: The view raises the :exc:`~django.http.Http404` exception
if a poll with the requested ID doesn't exist.
A shortcut: get_object_or_404()
-------------------------------
It's a very common idiom to use ``get()`` and raise ``Http404`` if the
object doesn't exist. Django provides a shortcut. Here's the ``detail()`` view,
rewritten::
It's a very common idiom to use :meth:`~django.db.models.QuerySet.get` and raise
:exc:`~django.http.Http404` if the object doesn't exist. Django provides a
shortcut. Here's the ``detail()`` view, rewritten::
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)
return render_to_response('polls/detail.html', {'poll': p})
The ``get_object_or_404()`` function takes a Django model module as its first
argument and an arbitrary number of keyword arguments, which it passes to the
module's ``get()`` function. It raises ``Http404`` if the object doesn't
exist.
The :func:`~django.shortcuts.get_object_or_404` function takes a Django model
module as its first argument and an arbitrary number of keyword arguments, which
it passes to the module's :meth:`~django.db.models.QuerySet.get` function. It
raises :exc:`~django.http.Http404` if the object doesn't exist.
.. admonition:: Philosophy
Why do we use a helper function ``get_object_or_404()`` instead of
automatically catching the ``DoesNotExist`` exceptions at a higher level,
or having the model API raise ``Http404`` instead of ``DoesNotExist``?
Why do we use a helper function :func:`~django.shortcuts.get_object_or_404`
instead of automatically catching the
: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
foremost design goals of Django is to maintain loose coupling.
There's also a ``get_list_or_404()`` function, which works just as
``get_object_or_404()`` -- except using ``filter()`` instead of
``get()``. It raises ``Http404`` if the list is empty.
There's also a :func:`~django.shortcuts.get_list_or_404` function, which works
just as :func:`~django.shortcuts.get_object_or_404` -- except using
: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
=================================
When you raise ``Http404`` from within a view, Django will load a special view
devoted to handling 404 errors. It finds it by looking for the variable
``handler404``, which is a string in Python dotted syntax -- the same format
the normal URLconf callbacks use. A 404 view itself has nothing special: It's
just a normal view.
When you raise :exc:`~django.http.Http404` from within a view, Django will load
a special view devoted to handling 404 errors. It finds it by looking for the
variable ``handler404``, which is a string in Python dotted syntax -- the same
format the normal URLconf callbacks use. A 404 view itself has nothing special:
It's just a normal view.
You normally won't have to bother with writing 404 views. By default, URLconfs
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
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:
* The 404 view is also called if Django doesn't find a match after checking
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
``404.html`` template in the root of your template directory. The default
404 view will use that template for all 404 errors.
* If ``DEBUG`` is set to ``True`` (in your settings module) then your 404
view will never be used, and the traceback will be displayed instead.
* 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 ``404.html``
template in the root of your template directory. The default 404 view will
use that template for all 404 errors.
* 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
===============================
@ -355,9 +378,11 @@ view code.
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
like::
like:
.. code-block:: html+django
<h1>{{ poll.question }}</h1>
<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
iterable of Choice objects and is suitable for use in the ``{% for %}`` tag.
See the `template guide`_ for full details on how templates work.
.. _template guide: ../templates/
See the :ref:`template guide <topics-templates>` for more about templates.
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
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',
(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
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.
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
URLs within the app directory.
Copy the file ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then,
change ``mysite/urls.py`` to remove the poll-specific URLs and insert an
``include()``::
Copy the file ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then, change
``mysite/urls.py`` to remove the poll-specific URLs and insert an
:func:`~django.conf.urls.defaults.include`::
(r'^polls/', include('mysite.polls.urls')),
``include()``, simply, references another URLconf. Note that the regular
expression doesn't have a ``$`` (end-of-string match character) but has the
trailing slash. Whenever Django encounters ``include()``, it chops off whatever
part of the URL matched up to that point and sends the remaining string to the
included URLconf for further processing.
:func:`~django.conf.urls.defaults.include`, simply, references another URLconf.
Note that the regular expression doesn't have a ``$`` (end-of-string match
character) but has the trailing slash. Whenever Django encounters
:func:`~django.conf.urls.defaults.include`, it chops off whatever part of the
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:
* 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
further processing.
* Django will find the match at ``'^polls/'``
Now that we've decoupled that, we need to decouple the
'mysite.polls.urls' URLconf by removing the leading "polls/" from each
line::
* Then, Django will strip off the matching text (``"polls/"``) and send the
remaining text -- ``"34/"`` -- to the 'mysite.polls.urls' URLconf for
further processing.
Now that we've decoupled that, we need to decouple the 'mysite.polls.urls'
URLconf by removing the leading "polls/" from each line::
urlpatterns = patterns('mysite.polls.views',
(r'^$', 'index'),
@ -455,14 +479,12 @@ line::
(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
)
The idea behind ``include()`` and URLconf decoupling is to make it easy to
plug-and-play URLs. Now that polls are in their own URLconf, they can be placed
under "/polls/", or under "/fun_polls/", or under "/content/polls/", or any
other URL root, and the app will still work.
The idea behind :func:`~django.conf.urls.defaults.include` and URLconf
decoupling is to make it easy to plug-and-play URLs. Now that polls are in their
own URLconf, they can be placed under "/polls/", or under "/fun_polls/", or
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.
When you're comfortable with writing views, read `part 4 of this tutorial`_ to
learn about simple form processing and generic views.
.. _part 4 of this tutorial: ../tutorial04/
When you're comfortable with writing views, read :ref:`part 4 of this tutorial
<intro-tutorial04>` to learn about simple form processing and generic views.

View File

@ -1,15 +1,20 @@
.. _intro-tutorial04:
=====================================
Writing your first Django app, part 4
=====================================
This tutorial begins where `Tutorial 3`_ left off. We're continuing the Web-poll
application and will focus on simple form processing and cutting down our code.
This tutorial begins where :ref:`Tutorial 3 <intro-tutorial03>` left off. We're
continuing the Web-poll application and will focus on simple form processing and
cutting down our code.
Write a simple form
===================
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>
@ -38,15 +43,12 @@ A quick rundown:
data server-side, use ``method="post"``. This tip isn't specific to
Django; it's just good Web development practice.
* ``forloop.counter`` indicates how many times the ``for`` tag has
gone through its loop. For more information, see `the
documentation for the "for" tag`_.
.. _the documentation for the "for" tag: ../templates/#for
* ``forloop.counter`` indicates how many times the ;ttag:`for` tag has gone
through its loop
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
polls application that includes this line::
something with it. Remember, in :ref:`Tutorial 3 <intro-tutorial03>`, we created
a URLconf for the polls application that includes this line::
(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:
* ``request.POST`` is a dictionary-like object that lets you access
submitted data by key name. In this case, ``request.POST['choice']``
returns the ID of the selected choice, as a string. ``request.POST``
values are always strings.
* :attr:`request.POST <django.http.HttpRequest.POST>` is a dictionary-like
object that lets you access submitted data by key name. In this case,
``request.POST['choice']`` returns the ID of the selected choice, as a
string. :attr:`request.POST <django.http.HttpRequest.POST>` values are
always strings.
Note that Django also provides ``request.GET`` for accessing GET data
in the same way -- but we're explicitly using ``request.POST`` in our
code, to ensure that data is only altered via a POST call.
Note that Django also provides :attr:`request.GET
<django.http.HttpRequest.GET>` for accessing GET data in the same way --
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
provided in POST data. The above code checks for ``KeyError`` and
* ``request.POST['choice']`` will raise :exc:`KeyError` if ``choice`` wasn't
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.
* After incrementing the choice count, the code returns an
``HttpResponseRedirect`` rather than a normal ``HttpResponse``.
``HttpResponseRedirect`` takes a single argument: the URL to which the
user will be redirected (see the following point for how we construct
the URL in this case).
:class:`~django.http.HttpResponseRedirect` rather than a normal
:class:`~django.http.HttpResponse`.
:class:`~django.http.HttpResponseRedirect` takes a single argument: the
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
``HttpResponseRedirect`` after successfully dealing with POST data. This
tip isn't specific to Django; it's just good Web development practice.
:class:`~django.http.HttpResponseRedirect` after successfully dealing with
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``
constructor in this example. This function helps avoid having to
hardcode a URL in the view function. It is given the name of the view
that we want to pass control to and the variable portion of the URL
pattern that points to that view. In this case, using the URLConf we set
up in Tutorial 3, this ``reverse()`` call will return a string like ::
* We are using the :func:`~django.core.urlresolvers.reverse` function in the
:class:`~django.http.HttpResponseRedirect` constructor in this example.
This function helps avoid having to hardcode a URL in the view function.
It is given the name of the view that we want to pass control to and the
variable portion of the URL pattern that points to that view. In this
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/'
... 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
you need to use the full name of the view here (including the prefix).
then call the ``'results'`` view to display the final page. Note that you
need to use the full name of the view here (including the prefix).
For more information about ``reverse()``, see the `URL dispatcher`_
documentation.
As mentioned in Tutorial 3, ``request`` is a ``HTTPRequest`` object. For more
on ``HTTPRequest`` objects, see the `request and response documentation`_.
As mentioned in Tutorial 3, ``request`` is a :class:`~django.http.HttpRequest`
object. For more on :class:`~django.http.HttpRequest` objects, see the
:ref:`request and response documentation <ref-request-response>`.
After somebody votes in a poll, the ``vote()`` view redirects to the results
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)
return render_to_response('polls/results.html', {'poll': p})
This is almost exactly the same as the ``detail()`` view from `Tutorial 3`_.
The only difference is the template name. We'll fix this redundancy later.
This is almost exactly the same as the ``detail()`` view from :ref:`Tutorial 3
<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>
@ -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
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
======================================
The ``detail()`` (from `Tutorial 3`_) and ``results()`` views are stupidly
simple -- and, as mentioned above, redundant. The ``index()`` view (also from
Tutorial 3), which displays a list of polls, is similar.
The ``detail()`` (from :ref:`Tutorial 3 <intro-tutorial03>`) and ``results()``
views are stupidly simple -- and, as mentioned above, redundant. The ``index()``
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
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.
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::
from django.conf.urls.defaults import *
@ -203,92 +210,95 @@ Change it like so::
(r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
)
We're using two generic views here: ``object_list`` and ``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."
We're using two generic views here:
:func:`~django.views.generic.list_detail.object_list` and
: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
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.
* The ``object_detail`` generic view expects the ID value captured
from the URL to be called ``"object_id"``, so we've changed ``poll_id`` to
``object_id`` for the generic views.
* The :func:`~django.views.generic.list_detail.object_detail` generic view
expects the ID value captured from the URL to be called ``"object_id"``,
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
have a way to refer to its URL later on (see the documentation about
`naming URL patterns`_ for information). We're also using the `url()`_
function from ``django.conf.urls.defaults`` here. It's a good habit to
use ``url()`` when you are providing a pattern name like this.
* We've added a name, ``poll_results``, to the results view so that we have
a way to refer to its URL later on (see the documentation about
:ref:`naming URL patterns <naming-url-patterns>` for information). We're
also using the :func:`~django.conf.urls.default.url` function from
: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
.. _url(): ../url_dispatch/#url
By default, the :func:`~django.views.generic.list_detail.object_detail` generic
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
``<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 ``render_to_response()`` line in
``vote()``.
Similarly, the :func:`~django.views.generic.list_detail.object_list` generic
view uses a template called ``<app name>/<model name>_list.html``. Thus, rename
``polls/index.html`` to ``polls/poll_list.html``.
Similarly, the ``object_list`` generic view uses a template called
``<app name>/<model name>_list.html``. Thus, rename ``polls/index.html`` to
``polls/poll_list.html``.
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:
Because we have more than one entry in the URLconf that uses
:func:`~django.views.generic.list_detail.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. 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
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``,
which is "lazy" and doesn't hit your database until it absolutely has to. By
the time the database query happens, the ``object_detail`` generic view will
have narrowed its scope down to a single object, so the eventual query will
only select one row from the database.
``Poll.objects.all()`` is actually a special object called a
:class:`~django.db.models.QuerySet`, which is "lazy" and doesn't hit your
database until it absolutely has to. By the time the database query happens,
the :func:`~django.views.generic.list_detail.object_detail` generic view
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
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. However,
the generic views provide the variables ``object`` and ``object_list`` as context.
Therefore, you need to change your templates to match the new context variables.
Go through your templates, and modify any reference to ``latest_poll_list`` to
``object_list``, and change any reference to ``poll`` to ``object``.
In previous parts of the tutorial, the templates have been provided with a
context that contains the ``poll`` and ``latest_poll_list`` context variables.
However, the generic views provide the variables ``object`` and ``object_list``
as context. Therefore, you need to change your templates to match the new
context variables. Go through your templates, and modify any reference to
``latest_poll_list`` to :func:`~django.views.generic.list_detail.object_list`,
and change any reference to ``poll`` to ``object``.
You can now delete the ``index()``, ``detail()`` and ``results()`` views
from ``polls/views.py``. We don't need them anymore -- they have been replaced
by generic views.
The ``vote()`` view is still required. However, it must be modified to match
the new context variables. In the ``render_to_response()`` call, rename the
``poll`` context variable to ``object``.
The ``vote()`` view is still required. However, it must be modified to match the
new context variables. In the :func:`~django.shortcuts.render_to_response` call,
rename the ``poll`` context variable to ``object``.
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
hard-coding our URLs. Now that we've switched to a generic view, we'll need to
change the ``reverse()`` call to point back to our new generic 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::
views. In the vote view above, we used the
:func:`~django.core.urlresolvers.reverse` function to avoid hard-coding our
URLs. Now that we've switched to a generic view, we'll need to change the
:func:`~django.core.urlresolvers.reverse` call to point back to our new generic
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,)))
Run the server, and use your new polling app based on generic views.
For full details on generic views, see the `generic views documentation`_.
.. _generic views documentation: ../generic_views/
For full details on generic views, see the :ref:`generic views documentation
<topics-http-generic-views>`.
Coming soon
===========
The tutorial ends here for the time being. But check back soon for the next
installments:
The tutorial ends here for the time being. Future installments of the tutorial
will cover:
* Advanced form processing
* Using the RSS framework
@ -297,8 +307,5 @@ installments:
* Advanced admin features: Permissions
* Advanced admin features: Custom JavaScript
In the meantime, you can read through the rest of the `Django documentation`_
and start writing your own applications.
.. _Tutorial 3: ../tutorial03/
.. _Django documentation: http://www.djangoproject.com/documentation/
In the meantime, you might want to check out some pointers on :ref:`where to go
from here <intro-whatsnext>`

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).
.TP
.I \-a, \-\-all
Process all available locales when using makemessages.
.SH "ENVIRONMENT"
Process all available locales when using makemessages..SH "ENVIRONMENT"
.TP
.I DJANGO_SETTINGS_MODULE
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
===================
@ -9,9 +11,13 @@ the future.
Overall
=======
.. _loose-coupling:
Loose coupling
--------------
.. index:: coupling; loose
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
absolutely necessary.
@ -25,6 +31,8 @@ stack are independent of another wherever possible.
.. _`loose coupling and tight cohesion`: http://c2.com/cgi/wiki?CouplingAndCohesion
.. _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
introspection.
.. _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
development.
.. _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,
place. Redundancy is bad. Normalization is good.
The framework, within reason, should deduce as much as possible from as little
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
--------------------------------
@ -59,6 +83,8 @@ learn how to use the feature.
.. _`core Python principle`: http://www.python.org/dev/peps/pep-0020/
.. _consistency:
Consistency
-----------
@ -155,19 +181,25 @@ File extensions in Web-page URLs should be avoided.
Vignette-style commas in URLs deserve severe punishment.
.. _definitive-urls:
Definitive URLs
---------------
.. index:: urls; definitive
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
separate pages. Django should make an effort to "normalize" URLs so that
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
===============
.. _separation-of-logic-and-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
code.
This is the philosophy behind `template inheritance`_.
.. _template inheritance: ../templates/#template-inheritance
This is the philosophy behind :ref:`template inheritance
<template-inheritance>`.
Be decoupled from HTML
----------------------
@ -200,6 +231,8 @@ text.
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
error in editing templates -- and incurs an unacceptable level of overhead in
template processing.

View File

@ -1,3 +1,5 @@
.. _misc-distributions:
===================================
Third-party distributions of Django
===================================
@ -10,10 +12,8 @@ requires.
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
instructions for `installing the development version`_ from our Subversion
repository.
.. _installing the development version: ../install/#installing-the-development-version
instructions for :ref:`installing the development version
<installing-development-version>` from our Subversion repository.
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