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
1
AUTHORS
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
@import url(reset-fonts-grids.css);
|
||||
@import url(djangodocs.css);
|
||||
@import url(homepage.css);
|
|
@ -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%; }
|
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 632 B |
After Width: | Height: | Size: 799 B |
|
@ -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; }
|
|
@ -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;}
|
|
@ -0,0 +1,4 @@
|
|||
{% extends "!genindex.html" %}
|
||||
|
||||
{% block bodyclass %}{% endblock %}
|
||||
{% block sidebarwrapper %}{% endblock %}
|
|
@ -0,0 +1,87 @@
|
|||
{% extends "!layout.html" %}
|
||||
|
||||
{%- macro secondnav %}
|
||||
{%- if prev %}
|
||||
« <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> »
|
||||
{%- 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 %}
|
|
@ -0,0 +1,3 @@
|
|||
{% extends "!modindex.html" %}
|
||||
{% block bodyclass %}{% endblock %}
|
||||
{% block sidebarwrapper %}{% endblock %}
|
|
@ -0,0 +1,3 @@
|
|||
{% extends "!search.html" %}
|
||||
{% block bodyclass %}{% endblock %}
|
||||
{% block sidebarwrapper %}{% endblock %}
|
|
@ -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/
|
31
docs/conf.py
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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/
|
2421
docs/db-api.txt
|
@ -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/
|
744
docs/faq.txt
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,16 @@
|
|||
.. _faq-index:
|
||||
|
||||
==========
|
||||
Django FAQ
|
||||
==========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
general
|
||||
install
|
||||
usage
|
||||
help
|
||||
models
|
||||
admin
|
||||
contributing
|
|
@ -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.
|
|
@ -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()
|
|
@ -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 }}``.
|
388
docs/files.txt
|
@ -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.
|
|
@ -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.
|
|
@ -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):
|
||||
# ...
|
2468
docs/forms.txt
|
@ -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.
|
|
@ -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
|
|
@ -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.
|
|
@ -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``.
|
|
@ -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
|
||||
------------------
|
||||
|
|
@ -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/
|
|
@ -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.
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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``.
|
|
@ -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/
|
|
@ -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``.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
264
docs/index.txt
|
@ -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.
|
||||
|
|
After Width: | Height: | Size: 51 KiB |
|
@ -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
|
|
@ -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".
|
|
@ -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
|
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 23 KiB |
|
@ -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
|
|
@ -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>`.
|
||||
|
||||
|
||||
|
|
@ -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/
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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>`
|
|
@ -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/
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
||||
=======
|
|
@ -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
|
2145
docs/model-api.txt
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 5.7 KiB |