diff --git a/AUTHORS b/AUTHORS index ea83eb92db..1137b7cb8e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -67,6 +67,7 @@ answer newbie questions, and generally made Django that much better: Jiri Barton Ned Batchelder batiste@dosimple.ch + Batman Shannon -jj Behrens Esdras Beleza Chris Bennett diff --git a/docs/Makefile b/docs/Makefile index f79d4299d5..e9c11d0676 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -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 ' where 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 diff --git a/docs/_ext/applyxrefs.py b/docs/_ext/applyxrefs.py new file mode 100644 index 0000000000..3809088c1f --- /dev/null +++ b/docs/_ext/applyxrefs.py @@ -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()) \ No newline at end of file diff --git a/docs/_ext/djangodocs.py b/docs/_ext/djangodocs.py new file mode 100644 index 0000000000..2375be481d --- /dev/null +++ b/docs/_ext/djangodocs.py @@ -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 + diff --git a/docs/_ext/literals_to_xrefs.py b/docs/_ext/literals_to_xrefs.py new file mode 100644 index 0000000000..569193c72d --- /dev/null +++ b/docs/_ext/literals_to_xrefs.py @@ -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 [", 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 \ No newline at end of file diff --git a/docs/_static/default.css b/docs/_static/default.css new file mode 100644 index 0000000000..9dc69ee785 --- /dev/null +++ b/docs/_static/default.css @@ -0,0 +1,3 @@ +@import url(reset-fonts-grids.css); +@import url(djangodocs.css); +@import url(homepage.css); \ No newline at end of file diff --git a/docs/_static/djangodocs.css b/docs/_static/djangodocs.css new file mode 100644 index 0000000000..940bab8388 --- /dev/null +++ b/docs/_static/djangodocs.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%; } \ No newline at end of file diff --git a/docs/_static/docicons-behindscenes.gif b/docs/_static/docicons-behindscenes.gif new file mode 100644 index 0000000000..921bc45c33 Binary files /dev/null and b/docs/_static/docicons-behindscenes.gif differ diff --git a/docs/_static/docicons-note.gif b/docs/_static/docicons-note.gif new file mode 100644 index 0000000000..c0d599e90a Binary files /dev/null and b/docs/_static/docicons-note.gif differ diff --git a/docs/_static/docicons-philosophy.gif b/docs/_static/docicons-philosophy.gif new file mode 100644 index 0000000000..432d93ba79 Binary files /dev/null and b/docs/_static/docicons-philosophy.gif differ diff --git a/docs/_static/homepage.css b/docs/_static/homepage.css new file mode 100644 index 0000000000..276c5470ab --- /dev/null +++ b/docs/_static/homepage.css @@ -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; } \ No newline at end of file diff --git a/docs/_static/reset-fonts-grids.css b/docs/_static/reset-fonts-grids.css new file mode 100644 index 0000000000..f5238d7c91 --- /dev/null +++ b/docs/_static/reset-fonts-grids.css @@ -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;} \ No newline at end of file diff --git a/docs/_templates/genindex.html b/docs/_templates/genindex.html new file mode 100644 index 0000000000..60c19efd45 --- /dev/null +++ b/docs/_templates/genindex.html @@ -0,0 +1,4 @@ +{% extends "!genindex.html" %} + +{% block bodyclass %}{% endblock %} +{% block sidebarwrapper %}{% endblock %} \ No newline at end of file diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html new file mode 100644 index 0000000000..eb42298ab3 --- /dev/null +++ b/docs/_templates/layout.html @@ -0,0 +1,87 @@ +{% extends "!layout.html" %} + +{%- macro secondnav %} + {%- if prev %} + « previous + {{ reldelim2 }} + {%- endif %} + {%- if parents %} + up + {%- else %} + up + {%- endif %} + {%- if next %} + {{ reldelim2 }} + next » + {%- endif %} +{%- endmacro %} + +{% block document %} +
+
+

{{ docstitle }}

+ + +
+ +
+
+
+
+ {% block body %}{% endblock %} +
+
+
+ {% block sidebarwrapper %} + {% if pagename != 'index' %} + + {% endif %} + {% endblock %} +
+ +
+ +
+
+{% endblock %} + +{% block sidebarrel %} +

Browse

+ +

You are here:

+ +{% endblock %} + +{# Empty some default blocks out #} +{% block relbar1 %}{% endblock %} +{% block relbar2 %}{% endblock %} +{% block sidebar1 %}{% endblock %} +{% block sidebar2 %}{% endblock %} +{% block footer %}{% endblock %} \ No newline at end of file diff --git a/docs/_templates/modindex.html b/docs/_templates/modindex.html new file mode 100644 index 0000000000..96a1d2080a --- /dev/null +++ b/docs/_templates/modindex.html @@ -0,0 +1,3 @@ +{% extends "!modindex.html" %} +{% block bodyclass %}{% endblock %} +{% block sidebarwrapper %}{% endblock %} \ No newline at end of file diff --git a/docs/_templates/search.html b/docs/_templates/search.html new file mode 100644 index 0000000000..8bd6dbd332 --- /dev/null +++ b/docs/_templates/search.html @@ -0,0 +1,3 @@ +{% extends "!search.html" %} +{% block bodyclass %}{% endblock %} +{% block sidebarwrapper %}{% endblock %} \ No newline at end of file diff --git a/docs/api_stability.txt b/docs/api_stability.txt deleted file mode 100644 index f56872ca51..0000000000 --- a/docs/api_stability.txt +++ /dev/null @@ -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/ diff --git a/docs/authentication.txt b/docs/authentication.txt deleted file mode 100644 index 4345fc0c11..0000000000 --- a/docs/authentication.txt +++ /dev/null @@ -1,1173 +0,0 @@ -============================= -User authentication in Django -============================= - -Django comes with a user authentication system. It handles user accounts, -groups, permissions and cookie-based user sessions. This document explains how -things work. - -Overview -======== - -The auth system consists of: - - * Users - * Permissions: Binary (yes/no) flags designating whether a user may perform - a certain task. - * Groups: A generic way of applying labels and permissions to more than one - user. - * Messages: A simple way to queue messages for given users. - -Installation -============ - -Authentication support is bundled as a Django application in -``django.contrib.auth``. To install it, do the following: - - 1. Put ``'django.contrib.auth'`` in your ``INSTALLED_APPS`` setting. - 2. Run the command ``manage.py syncdb``. - -Note that the default ``settings.py`` file created by -``django-admin.py startproject`` includes ``'django.contrib.auth'`` in -``INSTALLED_APPS`` for convenience. If your ``INSTALLED_APPS`` already contains -``'django.contrib.auth'``, feel free to run ``manage.py syncdb`` again; you -can run that command as many times as you'd like, and each time it'll only -install what's needed. - -The ``syncdb`` command creates the necessary database tables, creates -permission objects for all installed apps that need 'em, and prompts you to -create a superuser account the first time you run it. - -Once you've taken those steps, that's it. - -Users -===== - -Users are represented by a standard Django model, which lives in -`django/contrib/auth/models.py`_. - -.. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py - -API reference -------------- - -Fields -~~~~~~ - -``User`` objects have the following fields: - - * ``username`` -- Required. 30 characters or fewer. Alphanumeric characters - only (letters, digits and underscores). - * ``first_name`` -- Optional. 30 characters or fewer. - * ``last_name`` -- Optional. 30 characters or fewer. - * ``email`` -- Optional. E-mail address. - * ``password`` -- Required. A hash of, and metadata about, the password. - (Django doesn't store the raw password.) Raw passwords can be arbitrarily - long and can contain any character. See the "Passwords" section below. - * ``is_staff`` -- Boolean. Designates whether this user can access the - admin site. - * ``is_active`` -- Boolean. Designates whether this account can be used - to log in. Set this flag to ``False`` instead of deleting accounts. - * ``is_superuser`` -- Boolean. Designates that this user has all permissions - without explicitly assigning them. - * ``last_login`` -- A datetime of the user's last login. Is set to the - current date/time by default. - * ``date_joined`` -- A datetime designating when the account was created. - Is set to the current date/time by default when the account is created. - -Methods -~~~~~~~ - -``User`` objects have two many-to-many fields: ``groups`` and -``user_permissions``. ``User`` objects can access their related -objects in the same way as any other `Django model`_:: - - myuser.groups = [group_list] - myuser.groups.add(group, group, ...) - myuser.groups.remove(group, group, ...) - myuser.groups.clear() - myuser.user_permissions = [permission_list] - myuser.user_permissions.add(permission, permission, ...) - myuser.user_permissions.remove(permission, permission, ...) - myuser.user_permissions.clear() - -In addition to those automatic API methods, ``User`` objects have the following -custom methods: - - * ``is_anonymous()`` -- Always returns ``False``. This is a way of - differentiating ``User`` and ``AnonymousUser`` objects. Generally, you - should prefer using ``is_authenticated()`` to this method. - - * ``is_authenticated()`` -- Always returns ``True``. This is a way to - tell if the user has been authenticated. This does not imply any - permissions, and doesn't check if the user is active - it only indicates - that the user has provided a valid username and password. - - * ``get_full_name()`` -- Returns the ``first_name`` plus the ``last_name``, - with a space in between. - - * ``set_password(raw_password)`` -- Sets the user's password to the given - raw string, taking care of the password hashing. Doesn't save the - ``User`` object. - - * ``check_password(raw_password)`` -- Returns ``True`` if the given raw - string is the correct password for the user. (This takes care of the - password hashing in making the comparison.) - - * ``set_unusable_password()`` -- **New in Django development version.** - Marks the user as having no password set. This isn't the same as having - a blank string for a password. ``check_password()`` for this user will - never return ``True``. Doesn't save the ``User`` object. - - You may need this if authentication for your application takes place - against an existing external source such as an LDAP directory. - - * ``has_usable_password()`` -- **New in Django development version.** - Returns ``False`` if ``set_unusable_password()`` has been called for this - user. - - * ``get_group_permissions()`` -- Returns a list of permission strings that - the user has, through his/her groups. - - * ``get_all_permissions()`` -- Returns a list of permission strings that - the user has, both through group and user permissions. - - * ``has_perm(perm)`` -- Returns ``True`` if the user has the specified - permission, where perm is in the format ``"package.codename"``. - If the user is inactive, this method will always return ``False``. - - * ``has_perms(perm_list)`` -- Returns ``True`` if the user has each of the - specified permissions, where each perm is in the format - ``"package.codename"``. If the user is inactive, this method will - always return ``False``. - - * ``has_module_perms(package_name)`` -- Returns ``True`` if the user has - any permissions in the given package (the Django app label). - If the user is inactive, this method will always return ``False``. - - * ``get_and_delete_messages()`` -- Returns a list of ``Message`` objects in - the user's queue and deletes the messages from the queue. - - * ``email_user(subject, message, from_email=None)`` -- Sends an e-mail to - the user. If ``from_email`` is ``None``, Django uses the - `DEFAULT_FROM_EMAIL`_ setting. - - * ``get_profile()`` -- Returns a site-specific profile for this user. - Raises ``django.contrib.auth.models.SiteProfileNotAvailable`` if the current site - doesn't allow profiles. For information on how to define a - site-specific user profile, see the section on `storing additional - user information`_ below. - -.. _Django model: ../model-api/ -.. _DEFAULT_FROM_EMAIL: ../settings/#default-from-email -.. _storing additional user information: #storing-additional-information-about-users - -Manager functions -~~~~~~~~~~~~~~~~~ - -The ``User`` model has a custom manager that has the following helper functions: - - * ``create_user(username, email, password=None)`` -- Creates, saves and - returns a ``User``. The ``username``, ``email`` and ``password`` are set - as given, and the ``User`` gets ``is_active=True``. - - If no password is provided, ``set_unusable_password()`` will be called. - - See `Creating users`_ for example usage. - - * ``make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')`` - Returns a random password with the given length and given string of - allowed characters. (Note that the default value of ``allowed_chars`` - doesn't contain letters that can cause user confusion, including - ``1``, ``I`` and ``0``). - -Basic usage ------------ - -Creating users -~~~~~~~~~~~~~~ - -The most basic way to create users is to use the ``create_user`` helper -function that comes with Django:: - - >>> from django.contrib.auth.models import User - >>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword') - - # At this point, user is a User object that has already been saved - # to the database. You can continue to change its attributes - # if you want to change other fields. - >>> user.is_staff = True - >>> user.save() - -Changing passwords -~~~~~~~~~~~~~~~~~~ - -Change a password with ``set_password()``:: - - >>> from django.contrib.auth.models import User - >>> u = User.objects.get(username__exact='john') - >>> u.set_password('new password') - >>> u.save() - -Don't set the ``password`` attribute directly unless you know what you're -doing. This is explained in the next section. - -Passwords ---------- - -The ``password`` attribute of a ``User`` object is a string in this format:: - - hashtype$salt$hash - -That's hashtype, salt and hash, separated by the dollar-sign character. - -Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm -used to perform a one-way hash of the password. Salt is a random string used -to salt the raw password to create the hash. Note that the ``crypt`` method is -only supported on platforms that have the standard Python ``crypt`` module -available, and ``crypt`` support is only available in the Django development -version. - -For example:: - - sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4 - -The ``User.set_password()`` and ``User.check_password()`` functions handle -the setting and checking of these values behind the scenes. - -Previous Django versions, such as 0.90, used simple MD5 hashes without password -salts. For backwards compatibility, those are still supported; they'll be -converted automatically to the new style the first time ``User.check_password()`` -works correctly for a given user. - -Anonymous users ---------------- - -``django.contrib.auth.models.AnonymousUser`` is a class that implements -the ``django.contrib.auth.models.User`` interface, with these differences: - - * ``id`` is always ``None``. - * ``is_staff`` and ``is_superuser`` are always ``False``. - * ``is_active`` is always ``False``. - * ``groups`` and ``user_permissions`` are always empty. - * ``is_anonymous()`` returns ``True`` instead of ``False``. - * ``is_authenticated()`` returns ``False`` instead of ``True``. - * ``has_perm()`` always returns ``False``. - * ``set_password()``, ``check_password()``, ``save()``, ``delete()``, - ``set_groups()`` and ``set_permissions()`` raise ``NotImplementedError``. - -In practice, you probably won't need to use ``AnonymousUser`` objects on your -own, but they're used by Web requests, as explained in the next section. - -Creating superusers -------------------- - -``manage.py syncdb`` prompts you to create a superuser the first time you run -it after adding ``'django.contrib.auth'`` to your ``INSTALLED_APPS``. If you need -to create a superuser at a later date, you can use a command line utility. - -**New in Django development version.**:: - - manage.py createsuperuser --username=joe --email=joe@example.com - -You will be prompted for a password. After you enter one, the user will be -created immediately. If you leave off the ``--username`` or the ``--email`` -options, it will prompt you for those values. - -If you're using an older release of Django, the old way of creating a superuser -on the command line still works:: - - python /path/to/django/contrib/auth/create_superuser.py - -...where ``/path/to`` is the path to the Django codebase on your filesystem. The -``manage.py`` command is preferred because it figures out the correct path and -environment for you. - -Storing additional information about users ------------------------------------------- - -If you'd like to store additional information related to your users, -Django provides a method to specify a site-specific related model -- -termed a "user profile" -- for this purpose. - -To make use of this feature, define a model with fields for the -additional information you'd like to store, or additional methods -you'd like to have available, and also add a ``ForeignKey`` from your -model to the ``User`` model, specified with ``unique=True`` to ensure -only one instance of your model can be created for each ``User``. - -To indicate that this model is the user profile model for a given -site, fill in the setting ``AUTH_PROFILE_MODULE`` with a string -consisting of the following items, separated by a dot: - -1. The (normalized to lower-case) name of the application in which the - user profile model is defined (in other words, an all-lowercase - version of the name which was passed to ``manage.py startapp`` to - create the application). - -2. The (normalized to lower-case) name of the model class. - -For example, if the profile model was a class named ``UserProfile`` -and was defined inside an application named ``accounts``, the -appropriate setting would be:: - - AUTH_PROFILE_MODULE = 'accounts.userprofile' - -When a user profile model has been defined and specified in this -manner, each ``User`` object will have a method -- ``get_profile()`` --- which returns the instance of the user profile model associated -with that ``User``. - -For more information, see `Chapter 12 of the Django book`_. - -.. _Chapter 12 of the Django book: http://www.djangobook.com/en/1.0/chapter12/#cn222 - -Authentication in Web requests -============================== - -Until now, this document has dealt with the low-level APIs for manipulating -authentication-related objects. On a higher level, Django can hook this -authentication framework into its system of `request objects`_. - -First, install the ``SessionMiddleware`` and ``AuthenticationMiddleware`` -middlewares by adding them to your ``MIDDLEWARE_CLASSES`` setting. See the -`session documentation`_ for more information. - -Once you have those middlewares installed, you'll be able to access -``request.user`` in views. ``request.user`` will give you a ``User`` object -representing the currently logged-in user. If a user isn't currently logged in, -``request.user`` will be set to an instance of ``AnonymousUser`` (see the -previous section). You can tell them apart with ``is_authenticated()``, like so:: - - if request.user.is_authenticated(): - # Do something for authenticated users. - else: - # Do something for anonymous users. - -.. _request objects: ../request_response/#httprequest-objects -.. _session documentation: ../sessions/ - -How to log a user in --------------------- - -Django provides two functions in ``django.contrib.auth``: ``authenticate()`` -and ``login()``. - -To authenticate a given username and password, use ``authenticate()``. It -takes two keyword arguments, ``username`` and ``password``, and it returns -a ``User`` object if the password is valid for the given username. If the -password is invalid, ``authenticate()`` returns ``None``. Example:: - - from django.contrib.auth import authenticate - user = authenticate(username='john', password='secret') - if user is not None: - if user.is_active: - print "You provided a correct username and password!" - else: - print "Your account has been disabled!" - else: - print "Your username and password were incorrect." - -To log a user in, in a view, use ``login()``. It takes an ``HttpRequest`` -object and a ``User`` object. ``login()`` saves the user's ID in the session, -using Django's session framework, so, as mentioned above, you'll need to make -sure to have the session middleware installed. - -This example shows how you might use both ``authenticate()`` and ``login()``:: - - from django.contrib.auth import authenticate, login - - def my_view(request): - username = request.POST['username'] - password = request.POST['password'] - user = authenticate(username=username, password=password) - if user is not None: - if user.is_active: - login(request, user) - # Redirect to a success page. - else: - # Return a 'disabled account' error message - else: - # Return an 'invalid login' error message. - -.. admonition:: Calling ``authenticate()`` first - - When you're manually logging a user in, you *must* call - ``authenticate()`` before you call ``login()``. ``authenticate()`` - sets an attribute on the ``User`` noting which authentication - backend successfully authenticated that user (see the `backends - documentation`_ for details), and this information is needed later - during the login process. - -.. _backends documentation: #other-authentication-sources - -Manually checking a user's password ------------------------------------ - -If you'd like to manually authenticate a user by comparing a -plain-text password to the hashed password in the database, use the -convenience function ``django.contrib.auth.models.check_password``. It -takes two arguments: the plain-text password to check, and the full -value of a user's ``password`` field in the database to check against, -and returns ``True`` if they match, ``False`` otherwise. - -How to log a user out ---------------------- - -To log out a user who has been logged in via ``django.contrib.auth.login()``, -use ``django.contrib.auth.logout()`` within your view. It takes an -``HttpRequest`` object and has no return value. Example:: - - from django.contrib.auth import logout - - def logout_view(request): - logout(request) - # Redirect to a success page. - -Note that ``logout()`` doesn't throw any errors if the user wasn't logged in. - -**New in Django development version:** When you call ``logout()``, the session -data for the current request is completely cleaned out. All existing data is -removed. This is to prevent another person from using the same web browser to -log in and have access to the previous user's session data. If you want to put -anything into the session that will be available to the user immediately after -logging out, do that *after* calling ``django.contrib.auth.logout()``. - -Limiting access to logged-in users ----------------------------------- - -The raw way -~~~~~~~~~~~ - -The simple, raw way to limit access to pages is to check -``request.user.is_authenticated()`` and either redirect to a login page:: - - from django.http import HttpResponseRedirect - - def my_view(request): - if not request.user.is_authenticated(): - return HttpResponseRedirect('/login/?next=%s' % request.path) - # ... - -...or display an error message:: - - def my_view(request): - if not request.user.is_authenticated(): - return render_to_response('myapp/login_error.html') - # ... - -The login_required decorator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As a shortcut, you can use the convenient ``login_required`` decorator:: - - from django.contrib.auth.decorators import login_required - - def my_view(request): - # ... - my_view = login_required(my_view) - -Here's an equivalent example, using the more compact decorator syntax -introduced in Python 2.4:: - - from django.contrib.auth.decorators import login_required - - @login_required - def my_view(request): - # ... - -In the Django development version, ``login_required`` also takes an optional -``redirect_field_name`` parameter. Example:: - - from django.contrib.auth.decorators import login_required - - def my_view(request): - # ... - my_view = login_required(redirect_field_name='redirect_to')(my_view) - -Again, an equivalent example of the more compact decorator syntax introduced in Python 2.4:: - - from django.contrib.auth.decorators import login_required - - @login_required(redirect_field_name='redirect_to') - def my_view(request): - # ... - -``login_required`` does the following: - - * If the user isn't logged in, redirect to ``settings.LOGIN_URL`` - (``/accounts/login/`` by default), passing the current absolute URL - in the query string as ``next`` or the value of ``redirect_field_name``. - For example: - ``/accounts/login/?next=/polls/3/``. - * If the user is logged in, execute the view normally. The view code is - free to assume the user is logged in. - -Note that you'll need to map the appropriate Django view to ``settings.LOGIN_URL``. -For example, using the defaults, add the following line to your URLconf:: - - (r'^accounts/login/$', 'django.contrib.auth.views.login'), - -Here's what ``django.contrib.auth.views.login`` does: - - * If called via ``GET``, it displays a login form that POSTs to the same - URL. More on this in a bit. - - * If called via ``POST``, it tries to log the user in. If login is - successful, the view redirects to the URL specified in ``next``. If - ``next`` isn't provided, it redirects to ``settings.LOGIN_REDIRECT_URL`` - (which defaults to ``/accounts/profile/``). If login isn't successful, - it redisplays the login form. - -It's your responsibility to provide the login form in a template called -``registration/login.html`` by default. This template gets passed three -template context variables: - - * ``form``: A ``Form`` object representing the login form. See the - `forms documentation`_ for more on ``FormWrapper`` objects. - * ``next``: The URL to redirect to after successful login. This may contain - a query string, too. - * ``site_name``: The name of the current ``Site``, according to the - ``SITE_ID`` setting. If you're using the Django development version and - you don't have the site framework installed, this will be set to the - value of ``request.META['SERVER_NAME']``. For more on sites, see the - `site framework docs`_. - -If you'd prefer not to call the template ``registration/login.html``, you can -pass the ``template_name`` parameter via the extra arguments to the view in -your URLconf. For example, this URLconf line would use ``myapp/login.html`` -instead:: - - (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}), - -Here's a sample ``registration/login.html`` template you can use as a starting -point. It assumes you have a ``base.html`` template that defines a ``content`` -block:: - - {% extends "base.html" %} - - {% block content %} - - {% if form.errors %} -

Your username and password didn't match. Please try again.

- {% endif %} - -
- - - -
{{ form.username.label_tag }}{{ form.username }}
{{ form.password.label_tag }}{{ form.password }}
- - - -
- - {% endblock %} - -.. _forms documentation: ../forms/ -.. _site framework docs: ../sites/ - -Other built-in views --------------------- - -In addition to the ``login`` view, the authentication system includes a -few other useful built-in views: - -``django.contrib.auth.views.logout`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**Description:** - -Logs a user out. - -**Optional arguments:** - - * ``template_name``: The full name of a template to display after - logging the user out. This will default to - ``registration/logged_out.html`` if no argument is supplied. - -**Template context:** - - * ``title``: The string "Logged out", localized. - -``django.contrib.auth.views.logout_then_login`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**Description:** - -Logs a user out, then redirects to the login page. - -**Optional arguments:** - - * ``login_url``: The URL of the login page to redirect to. This - will default to ``settings.LOGIN_URL`` if not supplied. - -``django.contrib.auth.views.password_change`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**Description:** - -Allows a user to change their password. - -**Optional arguments:** - - * ``template_name``: The full name of a template to use for - displaying the password change form. This will default to - ``registration/password_change_form.html`` if not supplied. - -**Template context:** - - * ``form``: The password change form. - -``django.contrib.auth.views.password_change_done`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**Description:** - -The page shown after a user has changed their password. - -**Optional arguments:** - - * ``template_name``: The full name of a template to use. This will - default to ``registration/password_change_done.html`` if not - supplied. - -``django.contrib.auth.views.password_reset`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**Description:** - -Allows a user to reset their password, and sends them the new password -in an e-mail. - -**Optional arguments:** - - * ``template_name``: The full name of a template to use for - displaying the password reset form. This will default to - ``registration/password_reset_form.html`` if not supplied. - - * ``email_template_name``: The full name of a template to use for - generating the e-mail with the new password. This will default to - ``registration/password_reset_email.html`` if not supplied. - -**Template context:** - - * ``form``: The form for resetting the user's password. - -``django.contrib.auth.views.password_reset_done`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**Description:** - -The page shown after a user has reset their password. - -**Optional arguments:** - - * ``template_name``: The full name of a template to use. This will - default to ``registration/password_reset_done.html`` if not - supplied. - -``django.contrib.auth.views.redirect_to_login`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**Description:** - -Redirects to the login page, and then back to another URL after a -successful login. - -**Required arguments:** - - * ``next``: The URL to redirect to after a successful login. - -**Optional arguments:** - - * ``login_url``: The URL of the login page to redirect to. This - will default to ``settings.LOGIN_URL`` if not supplied. - -Built-in forms --------------- - -**New in Django development version.** - -If you don't want to use the built-in views, but want the convenience -of not having to write forms for this functionality, the authentication -system provides several built-in forms: - - * ``django.contrib.auth.forms.AdminPasswordChangeForm``: A form used in - the admin interface to change a user's password. - - * ``django.contrib.auth.forms.AuthenticationForm``: A form for logging a - user in. - - * ``django.contrib.auth.forms.PasswordChangeForm``: A form for allowing a - user to change their password. - - * ``django.contrib.auth.forms.PasswordResetForm``: A form for resetting a - user's password and e-mailing the new password to them. - - * ``django.contrib.auth.forms.UserCreationForm``: A form for creating a - new user. - -Limiting access to logged-in users that pass a test ---------------------------------------------------- - -To limit access based on certain permissions or some other test, you'd do -essentially the same thing as described in the previous section. - -The simple way is to run your test on ``request.user`` in the view directly. -For example, this view checks to make sure the user is logged in and has the -permission ``polls.can_vote``:: - - def my_view(request): - if not (request.user.is_authenticated() and request.user.has_perm('polls.can_vote')): - return HttpResponse("You can't vote in this poll.") - # ... - -As a shortcut, you can use the convenient ``user_passes_test`` decorator:: - - from django.contrib.auth.decorators import user_passes_test - - def my_view(request): - # ... - my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'))(my_view) - -We're using this particular test as a relatively simple example. However, if -you just want to test whether a permission is available to a user, you can use -the ``permission_required()`` decorator, described later in this document. - -Here's the same thing, using Python 2.4's decorator syntax:: - - from django.contrib.auth.decorators import user_passes_test - - @user_passes_test(lambda u: u.has_perm('polls.can_vote')) - def my_view(request): - # ... - -``user_passes_test`` takes a required argument: a callable that takes a -``User`` object and returns ``True`` if the user is allowed to view the page. -Note that ``user_passes_test`` does not automatically check that the ``User`` -is not anonymous. - -``user_passes_test()`` takes an optional ``login_url`` argument, which lets you -specify the URL for your login page (``settings.LOGIN_URL`` by default). - -Example in Python 2.3 syntax:: - - from django.contrib.auth.decorators import user_passes_test - - def my_view(request): - # ... - my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')(my_view) - -Example in Python 2.4 syntax:: - - from django.contrib.auth.decorators import user_passes_test - - @user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/') - def my_view(request): - # ... - -The permission_required decorator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It's a relatively common task to check whether a user has a particular -permission. For that reason, Django provides a shortcut for that case: the -``permission_required()`` decorator. Using this decorator, the earlier example -can be written as:: - - from django.contrib.auth.decorators import permission_required - - def my_view(request): - # ... - my_view = permission_required('polls.can_vote')(my_view) - -Note that ``permission_required()`` also takes an optional ``login_url`` -parameter. Example:: - - from django.contrib.auth.decorators import permission_required - - def my_view(request): - # ... - my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view) - -As in the ``login_required`` decorator, ``login_url`` defaults to -``settings.LOGIN_URL``. - -Limiting access to generic views --------------------------------- - -To limit access to a `generic view`_, write a thin wrapper around the view, -and point your URLconf to your wrapper instead of the generic view itself. -For example:: - - from django.views.generic.date_based import object_detail - - @login_required - def limited_object_detail(*args, **kwargs): - return object_detail(*args, **kwargs) - -.. _generic view: ../generic_views/ - -Permissions -=========== - -Django comes with a simple permissions system. It provides a way to assign -permissions to specific users and groups of users. - -It's used by the Django admin site, but you're welcome to use it in your own -code. - -The Django admin site uses permissions as follows: - - * Access to view the "add" form and add an object is limited to users with - the "add" permission for that type of object. - * Access to view the change list, view the "change" form and change an - object is limited to users with the "change" permission for that type of - object. - * Access to delete an object is limited to users with the "delete" - permission for that type of object. - -Permissions are set globally per type of object, not per specific object -instance. For example, it's possible to say "Mary may change news stories," but -it's not currently possible to say "Mary may change news stories, but only the -ones she created herself" or "Mary may only change news stories that have a -certain status, publication date or ID." The latter functionality is something -Django developers are currently discussing. - -Default permissions -------------------- - -When ``django.contrib.auth`` is listed in your ``INSTALLED_APPS`` -setting, it will ensure that three default permissions -- add, change -and delete -- are created for each Django model defined in one of your -installed applications. - -These permissions will be created when you run ``manage.py syncdb``; -the first time you run ``syncdb`` after adding ``django.contrib.auth`` -to ``INSTALLED_APPS``, the default permissions will be created for all -previously-installed models, as well as for any new models being -installed at that time. Afterward, it will create default permissions -for new models each time you run ``manage.py syncdb``. - -Custom permissions ------------------- - -To create custom permissions for a given model object, use the ``permissions`` -`model Meta attribute`_. - -This example model creates three custom permissions:: - - class USCitizen(models.Model): - # ... - class Meta: - permissions = ( - ("can_drive", "Can drive"), - ("can_vote", "Can vote in elections"), - ("can_drink", "Can drink alcohol"), - ) - -The only thing this does is create those extra permissions when you run -``syncdb``. - -.. _model Meta attribute: ../model-api/#meta-options - -API reference -------------- - -Just like users, permissions are implemented in a Django model that lives in -`django/contrib/auth/models.py`_. - -.. _django/contrib/auth/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py - -Fields -~~~~~~ - -``Permission`` objects have the following fields: - - * ``name`` -- Required. 50 characters or fewer. Example: ``'Can vote'``. - * ``content_type`` -- Required. A reference to the ``django_content_type`` - database table, which contains a record for each installed Django model. - * ``codename`` -- Required. 100 characters or fewer. Example: ``'can_vote'``. - -Methods -~~~~~~~ - -``Permission`` objects have the standard data-access methods like any other -`Django model`_. - -Authentication data in templates -================================ - -The currently logged-in user and his/her permissions are made available in the -`template context`_ when you use ``RequestContext``. - -.. admonition:: Technicality - - Technically, these variables are only made available in the template context - if you use ``RequestContext`` *and* your ``TEMPLATE_CONTEXT_PROCESSORS`` - setting contains ``"django.core.context_processors.auth"``, which is default. - For more, see the `RequestContext docs`_. - - .. _RequestContext docs: ../templates_python/#subclassing-context-requestcontext - -Users ------ - -The currently logged-in user, either a ``User`` instance or an``AnonymousUser`` -instance, is stored in the template variable ``{{ user }}``:: - - {% if user.is_authenticated %} -

Welcome, {{ user.username }}. Thanks for logging in.

- {% else %} -

Welcome, new user. Please log in.

- {% endif %} - -Permissions ------------ - -The currently logged-in user's permissions are stored in the template variable -``{{ perms }}``. This is an instance of ``django.core.context_processors.PermWrapper``, -which is a template-friendly proxy of permissions. - -In the ``{{ perms }}`` object, single-attribute lookup is a proxy to -``User.has_module_perms``. This example would display ``True`` if the logged-in -user had any permissions in the ``foo`` app:: - - {{ perms.foo }} - -Two-level-attribute lookup is a proxy to ``User.has_perm``. This example would -display ``True`` if the logged-in user had the permission ``foo.can_vote``:: - - {{ perms.foo.can_vote }} - -Thus, you can check permissions in template ``{% if %}`` statements:: - - {% if perms.foo %} -

You have permission to do something in the foo app.

- {% if perms.foo.can_vote %} -

You can vote!

- {% endif %} - {% if perms.foo.can_drive %} -

You can drive!

- {% endif %} - {% else %} -

You don't have permission to do anything in the foo app.

- {% endif %} - -.. _template context: ../templates_python/ - -Groups -====== - -Groups are a generic way of categorizing users so you can apply permissions, or -some other label, to those users. A user can belong to any number of groups. - -A user in a group automatically has the permissions granted to that group. For -example, if the group ``Site editors`` has the permission -``can_edit_home_page``, any user in that group will have that permission. - -Beyond permissions, groups are a convenient way to categorize users to give -them some label, or extended functionality. For example, you could create a -group ``'Special users'``, and you could write code that could, say, give them -access to a members-only portion of your site, or send them members-only e-mail -messages. - -Messages -======== - -The message system is a lightweight way to queue messages for given users. - -A message is associated with a ``User``. There's no concept of expiration or -timestamps. - -Messages are used by the Django admin after successful actions. For example, -``"The poll Foo was created successfully."`` is a message. - -The API is simple: - - * To create a new message, use - ``user_obj.message_set.create(message='message_text')``. - * To retrieve/delete messages, use ``user_obj.get_and_delete_messages()``, - which returns a list of ``Message`` objects in the user's queue (if any) - and deletes the messages from the queue. - -In this example view, the system saves a message for the user after creating -a playlist:: - - def create_playlist(request, songs): - # Create the playlist with the given songs. - # ... - request.user.message_set.create(message="Your playlist was added successfully.") - return render_to_response("playlists/create.html", - context_instance=RequestContext(request)) - -When you use ``RequestContext``, the currently logged-in user and his/her -messages are made available in the `template context`_ as the template variable -``{{ messages }}``. Here's an example of template code that displays messages:: - - {% if messages %} -
    - {% for message in messages %} -
  • {{ message }}
  • - {% endfor %} -
- {% endif %} - -Note that ``RequestContext`` calls ``get_and_delete_messages`` behind the -scenes, so any messages will be deleted even if you don't display them. - -Finally, note that this messages framework only works with users in the user -database. To send messages to anonymous users, use the `session framework`_. - -.. _session framework: ../sessions/ - -Other authentication sources -============================ - -The authentication that comes with Django is good enough for most common cases, -but you may have the need to hook into another authentication source -- that -is, another source of usernames and passwords or authentication methods. - -For example, your company may already have an LDAP setup that stores a username -and password for every employee. It'd be a hassle for both the network -administrator and the users themselves if users had separate accounts in LDAP -and the Django-based applications. - -So, to handle situations like this, the Django authentication system lets you -plug in another authentication sources. You can override Django's default -database-based scheme, or you can use the default system in tandem with other -systems. - -Specifying authentication backends ----------------------------------- - -Behind the scenes, Django maintains a list of "authentication backends" that it -checks for authentication. When somebody calls -``django.contrib.auth.authenticate()`` -- as described in "How to log a user in" -above -- Django tries authenticating across all of its authentication backends. -If the first authentication method fails, Django tries the second one, and so -on, until all backends have been attempted. - -The list of authentication backends to use is specified in the -``AUTHENTICATION_BACKENDS`` setting. This should be a tuple of Python path -names that point to Python classes that know how to authenticate. These classes -can be anywhere on your Python path. - -By default, ``AUTHENTICATION_BACKENDS`` is set to:: - - ('django.contrib.auth.backends.ModelBackend',) - -That's the basic authentication scheme that checks the Django users database. - -The order of ``AUTHENTICATION_BACKENDS`` matters, so if the same username and -password is valid in multiple backends, Django will stop processing at the -first positive match. - -Writing an authentication backend ---------------------------------- - -An authentication backend is a class that implements two methods: -``get_user(user_id)`` and ``authenticate(**credentials)``. - -The ``get_user`` method takes a ``user_id`` -- which could be a username, -database ID or whatever -- and returns a ``User`` object. - -The ``authenticate`` method takes credentials as keyword arguments. Most of -the time, it'll just look like this:: - - class MyBackend: - def authenticate(self, username=None, password=None): - # Check the username/password and return a User. - -But it could also authenticate a token, like so:: - - class MyBackend: - def authenticate(self, token=None): - # Check the token and return a User. - -Either way, ``authenticate`` should check the credentials it gets, and it -should return a ``User`` object that matches those credentials, if the -credentials are valid. If they're not valid, it should return ``None``. - -The Django admin system is tightly coupled to the Django ``User`` object -described at the beginning of this document. For now, the best way to deal with -this is to create a Django ``User`` object for each user that exists for your -backend (e.g., in your LDAP directory, your external SQL database, etc.) You -can either write a script to do this in advance, or your ``authenticate`` -method can do it the first time a user logs in. - -Here's an example backend that authenticates against a username and password -variable defined in your ``settings.py`` file and creates a Django ``User`` -object the first time a user authenticates:: - - from django.conf import settings - from django.contrib.auth.models import User, check_password - - class SettingsBackend: - """ - Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD. - - Use the login name, and a hash of the password. For example: - - ADMIN_LOGIN = 'admin' - ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de' - """ - def authenticate(self, username=None, password=None): - login_valid = (settings.ADMIN_LOGIN == username) - pwd_valid = check_password(password, settings.ADMIN_PASSWORD) - if login_valid and pwd_valid: - try: - user = User.objects.get(username=username) - except User.DoesNotExist: - # Create a new user. Note that we can set password - # to anything, because it won't be checked; the password - # from settings.py will. - user = User(username=username, password='get from settings.py') - user.is_staff = True - user.is_superuser = True - user.save() - return user - return None - - def get_user(self, user_id): - try: - return User.objects.get(pk=user_id) - except User.DoesNotExist: - return None - -Handling authorization in custom backends ------------------------------------------ - -Custom auth backends can provide their own permissions. - -The user model will delegate permission lookup functions -(``get_group_permissions()``, ``get_all_permissions()``, ``has_perm()``, and -``has_module_perms()``) to any authentication backend that implements these -functions. - -The permissions given to the user will be the superset of all permissions -returned by all backends. That is, Django grants a permission to a user that any -one backend grants. - -The simple backend above could implement permissions for the magic admin fairly -simply:: - - class SettingsBackend: - - # ... - - def has_perm(self, user_obj, perm): - if user_obj.username == settings.ADMIN_LOGIN: - return True - else: - return False - -This gives full permissions to the user granted access in the above example. Notice -that the backend auth functions all take the user object as an argument, and -they also accept the same arguments given to the associated ``User`` functions. - -A full authorization implementation can be found in -``django/contrib/auth/backends.py`` _, which is the default backend and queries -the ``auth_permission`` table most of the time. - -.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py diff --git a/docs/conf.py b/docs/conf.py index 0ced57d57b..38edfffcee 100644 --- a/docs/conf.py +++ b/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 + diff --git a/docs/contents.txt b/docs/contents.txt new file mode 100644 index 0000000000..e41b77055e --- /dev/null +++ b/docs/contents.txt @@ -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 \ No newline at end of file diff --git a/docs/contenttypes.txt b/docs/contenttypes.txt deleted file mode 100644 index 84e38020bc..0000000000 --- a/docs/contenttypes.txt +++ /dev/null @@ -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 - - -And then use it to query for a particular ``User``, or to get access -to the ``User`` model class:: - - >>> user_type.model_class() - - >>> user_type.get_object_for_this_type(username='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 - - -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 - - -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() - [, ] - -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) - [, ] - -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/ diff --git a/docs/db-api.txt b/docs/db-api.txt deleted file mode 100644 index 75f9cff198..0000000000 --- a/docs/db-api.txt +++ /dev/null @@ -1,2421 +0,0 @@ -====================== -Database API reference -====================== - -Once you've created your `data models`_, Django automatically gives you a -database-abstraction API that lets you create, retrieve, update and delete -objects. This document explains that API. - -.. _`data models`: ../model-api/ - -Throughout this reference, we'll refer to the following models, which comprise -a weblog application:: - - class Blog(models.Model): - name = models.CharField(max_length=100) - tagline = models.TextField() - - def __unicode__(self): - return self.name - - class Author(models.Model): - name = models.CharField(max_length=50) - email = models.EmailField() - - def __unicode__(self): - return self.name - - class Entry(models.Model): - blog = models.ForeignKey(Blog) - headline = models.CharField(max_length=255) - body_text = models.TextField() - pub_date = models.DateTimeField() - authors = models.ManyToManyField(Author) - - def __unicode__(self): - return self.headline - -Creating objects -================ - -To represent database-table data in Python objects, Django uses an intuitive -system: A model class represents a database table, and an instance of that -class represents a particular record in the database table. - -To create an object, instantiate it using keyword arguments to the model class, -then call ``save()`` to save it to the database. - -You import the model class from wherever it lives on the Python path, as you -may expect. (We point this out here because previous Django versions required -funky model importing.) - -Assuming models live in a file ``mysite/blog/models.py``, here's an example:: - - from mysite.blog.models import Blog - b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') - b.save() - -This performs an ``INSERT`` SQL statement behind the scenes. Django doesn't hit -the database until you explicitly call ``save()``. - -The ``save()`` method has no return value. - -To create an object and save it all in one step see the `create`__ method. - -__ `create(**kwargs)`_ - -Auto-incrementing primary keys ------------------------------- - -If a model has an ``AutoField`` -- an auto-incrementing primary key -- then -that auto-incremented value will be calculated and saved as an attribute on -your object the first time you call ``save()``. - -Example:: - - b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.') - b2.id # Returns None, because b doesn't have an ID yet. - b2.save() - b2.id # Returns the ID of your new object. - -There's no way to tell what the value of an ID will be before you call -``save()``, because that value is calculated by your database, not by Django. - -(For convenience, each model has an ``AutoField`` named ``id`` by default -unless you explicitly specify ``primary_key=True`` on a field. See the -`AutoField documentation`_.) - -.. _AutoField documentation: ../model-api/#autofield - -Explicitly specifying auto-primary-key values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If a model has an ``AutoField`` but you want to define a new object's ID -explicitly when saving, just define it explicitly before saving, rather than -relying on the auto-assignment of the ID. - -Example:: - - b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.') - b3.id # Returns 3. - b3.save() - b3.id # Returns 3. - -If you assign auto-primary-key values manually, make sure not to use an -already-existing primary-key value! If you create a new object with an explicit -primary-key value that already exists in the database, Django will assume -you're changing the existing record rather than creating a new one. - -Given the above ``'Cheddar Talk'`` blog example, this example would override -the previous record in the database:: - - b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.') - b4.save() # Overrides the previous blog with ID=3! - -See `How Django knows to UPDATE vs. INSERT`_, below, for the reason this -happens. - -Explicitly specifying auto-primary-key values is mostly useful for bulk-saving -objects, when you're confident you won't have primary-key collision. - -What happens when you save? ---------------------------- - -When you save an object, Django performs the following steps: - - 1. **Emit a ``pre_save`` signal.** This provides a notification that - an object is about to be saved. You can register a listener that - will be invoked whenever this signal is emitted. (These signals are - not yet documented.) - - 2. **Pre-process the data.** Each field on the object is asked to - perform any automated data modification that the field may need - to perform. - - Most fields do *no* pre-processing -- the field data is kept as-is. - Pre-processing is only used on fields that have special behavior. - For example, if your model has a ``DateField`` with ``auto_now=True``, - the pre-save phase will alter the data in the object to ensure that - the date field contains the current date stamp. (Our documentation - doesn't yet include a list of all the fields with this "special - behavior.") - - 3. **Prepare the data for the database.** Each field is asked to provide - its current value in a data type that can be written to the database. - - Most fields require *no* data preparation. Simple data types, such as - integers and strings, are 'ready to write' as a Python object. However, - more complex data types often require some modification. - - For example, ``DateFields`` use a Python ``datetime`` object to store - data. Databases don't store ``datetime`` objects, so the field value - must be converted into an ISO-compliant date string for insertion - into the database. - - 4. **Insert the data into the database.** The pre-processed, prepared - data is then composed into an SQL statement for insertion into the - database. - - 5. **Emit a ``post_save`` signal.** As with the ``pre_save`` signal, this - is used to provide notification that an object has been successfully - saved. (These signals are not yet documented.) - -Saving changes to objects -========================= - -To save changes to an object that's already in the database, use ``save()``. - -Given a ``Blog`` instance ``b5`` that has already been saved to the database, -this example changes its name and updates its record in the database:: - - b5.name = 'New name' - b5.save() - -This performs an ``UPDATE`` SQL statement behind the scenes. Django doesn't hit -the database until you explicitly call ``save()``. - -The ``save()`` method has no return value. - -Saving ForeignKey and ManyToManyField fields --------------------------------------------- - -Updating ``ForeignKey`` fields works exactly the same way as saving a normal -field; simply assign an object of the right type to the field in question:: - - cheese_blog = Blog.objects.get(name="Cheddar Talk") - entry.blog = cheese_blog - entry.save() - -Updating a ``ManyToManyField`` works a little differently; use the ``add()`` -method on the field to add a record to the relation:: - - joe = Author.objects.create(name="Joe") - entry.authors.add(joe) - -Django will complain if you try to assign or add an object of the wrong type. - -How Django knows to UPDATE vs. INSERT -------------------------------------- - -You may have noticed Django database objects use the same ``save()`` method -for creating and changing objects. Django abstracts the need to use ``INSERT`` -or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django -follows this algorithm: - - * If the object's primary key attribute is set to a value that evaluates to - ``True`` (i.e., a value other than ``None`` or the empty string), Django - executes a ``SELECT`` query to determine whether a record with the given - primary key already exists. - * If the record with the given primary key does already exist, Django - executes an ``UPDATE`` query. - * If the object's primary key attribute is *not* set, or if it's set but a - record doesn't exist, Django executes an ``INSERT``. - -The one gotcha here is that you should be careful not to specify a primary-key -value explicitly when saving new objects, if you cannot guarantee the -primary-key value is unused. For more on this nuance, see `Explicitly -specifying auto-primary-key values`_ above and `Forcing an INSERT or UPDATE`_ -below. - -Forcing an INSERT or UPDATE -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**New in Django development version** - -In some rare circumstances, it's necesary to be able to force the ``save()`` -method to perform an SQL ``INSERT`` and not fall back to doing an ``UPDATE``. -Or vice-versa: update, if possible, but not insert a new row. In these cases -you can pass the ``force_insert=True`` or ``force_update=True`` parameters to -the ``save()`` method. Passing both parameters is an error, since you cannot -both insert *and* update at the same time. - -It should be very rare that you'll need to use these parameters. Django will -almost always do the right thing and trying to override that will lead to -errors that are difficult to track down. This feature is for advanced use -only. - -Retrieving objects -================== - -To retrieve objects from your database, you construct a ``QuerySet`` via a -``Manager`` on your model class. - -A ``QuerySet`` represents a collection of objects from your database. It can -have zero, one or many *filters* -- criteria that narrow down the collection -based on given parameters. In SQL terms, a ``QuerySet`` equates to a ``SELECT`` -statement, and a filter is a limiting clause such as ``WHERE`` or ``LIMIT``. - -You get a ``QuerySet`` by using your model's ``Manager``. Each model has at -least one ``Manager``, and it's called ``objects`` by default. Access it -directly via the model class, like so:: - - Blog.objects # - b = Blog(name='Foo', tagline='Bar') - b.objects # AttributeError: "Manager isn't accessible via Blog instances." - -(``Managers`` are accessible only via model classes, rather than from model -instances, to enforce a separation between "table-level" operations and -"record-level" operations.) - -The ``Manager`` is the main source of ``QuerySets`` for a model. It acts as a -"root" ``QuerySet`` that describes all objects in the model's database table. -For example, ``Blog.objects`` is the initial ``QuerySet`` that contains all -``Blog`` objects in the database. - -Retrieving all objects ----------------------- - -The simplest way to retrieve objects from a table is to get all of them. -To do this, use the ``all()`` method on a ``Manager``. - -Example:: - - all_entries = Entry.objects.all() - -The ``all()`` method returns a ``QuerySet`` of all the objects in the database. - -(If ``Entry.objects`` is a ``QuerySet``, why can't we just do ``Entry.objects``? -That's because ``Entry.objects``, the root ``QuerySet``, is a special case -that cannot be evaluated. The ``all()`` method returns a ``QuerySet`` that -*can* be evaluated.) - -Filtering objects ------------------ - -The root ``QuerySet`` provided by the ``Manager`` describes all objects in the -database table. Usually, though, you'll need to select only a subset of the -complete set of objects. - -To create such a subset, you refine the initial ``QuerySet``, adding filter -conditions. The two most common ways to refine a ``QuerySet`` are: - -``filter(**kwargs)`` - Returns a new ``QuerySet`` containing objects that match the given lookup - parameters. - -``exclude(**kwargs)`` - Returns a new ``QuerySet`` containing objects that do *not* match the given - lookup parameters. - -The lookup parameters (``**kwargs`` in the above function definitions) should -be in the format described in `Field lookups`_ below. - -For example, to get a ``QuerySet`` of blog entries from the year 2006, use -``filter()`` like so:: - - Entry.objects.filter(pub_date__year=2006) - -(Note we don't have to add an ``all()`` -- ``Entry.objects.all().filter(...)``. -That would still work, but you only need ``all()`` when you want all objects -from the root ``QuerySet``.) - -Chaining filters -~~~~~~~~~~~~~~~~ - -The result of refining a ``QuerySet`` is itself a ``QuerySet``, so it's -possible to chain refinements together. For example:: - - Entry.objects.filter( - headline__startswith='What').exclude( - pub_date__gte=datetime.now()).filter( - pub_date__gte=datetime(2005, 1, 1)) - -...takes the initial ``QuerySet`` of all entries in the database, adds a -filter, then an exclusion, then another filter. The final result is a -``QuerySet`` containing all entries with a headline that starts with "What", -that were published between January 1, 2005, and the current day. - -Filtered QuerySets are unique ------------------------------ - -Each time you refine a ``QuerySet``, you get a brand-new ``QuerySet`` that is -in no way bound to the previous ``QuerySet``. Each refinement creates a -separate and distinct ``QuerySet`` that can be stored, used and reused. - -Example:: - - q1 = Entry.objects.filter(headline__startswith="What") - q2 = q1.exclude(pub_date__gte=datetime.now()) - q3 = q1.filter(pub_date__gte=datetime.now()) - -These three ``QuerySets`` are separate. The first is a base ``QuerySet`` -containing all entries that contain a headline starting with "What". The second -is a subset of the first, with an additional criteria that excludes records -whose ``pub_date`` is greater than now. The third is a subset of the first, -with an additional criteria that selects only the records whose ``pub_date`` is -greater than now. The initial ``QuerySet`` (``q1``) is unaffected by the -refinement process. - -QuerySets are lazy ------------------- - -``QuerySets`` are lazy -- the act of creating a ``QuerySet`` doesn't involve -any database activity. You can stack filters together all day long, and Django -won't actually run the query until the ``QuerySet`` is *evaluated*. - -When QuerySets are evaluated -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can evaluate a ``QuerySet`` in the following ways: - - * **Iteration.** A ``QuerySet`` is iterable, and it executes its database - query the first time you iterate over it. For example, this will print - the headline of all entries in the database:: - - for e in Entry.objects.all(): - print e.headline - - * **Slicing.** As explained in `Limiting QuerySets`_ below, a ``QuerySet`` - can be sliced, using Python's array-slicing syntax. Usually slicing a - ``QuerySet`` returns another (unevaluated )``QuerySet``, but Django will - execute the database query if you use the "step" parameter of slice - syntax. - - * **repr().** A ``QuerySet`` is evaluated when you call ``repr()`` on it. - This is for convenience in the Python interactive interpreter, so you can - immediately see your results when using the API interactively. - - * **len().** A ``QuerySet`` is evaluated when you call ``len()`` on it. - This, as you might expect, returns the length of the result list. - - Note: *Don't* use ``len()`` on ``QuerySet``\s if all you want to do is - determine the number of records in the set. It's much more efficient to - handle a count at the database level, using SQL's ``SELECT COUNT(*)``, - and Django provides a ``count()`` method for precisely this reason. See - ``count()`` below. - - * **list().** Force evaluation of a ``QuerySet`` by calling ``list()`` on - it. For example:: - - entry_list = list(Entry.objects.all()) - - Be warned, though, that this could have a large memory overhead, because - Django will load each element of the list into memory. In contrast, - iterating over a ``QuerySet`` will take advantage of your database to - load data and instantiate objects only as you need them. - - -Pickling QuerySets -~~~~~~~~~~~~~~~~~~ - -If you pickle_ a ``QuerySet``, this will also force all the results to be -loaded into memory prior to pickling. This is because pickling is usually used -as a precursor to caching and when the cached ``QuerySet`` is reloaded, you want -the results to already be present. This means that when you unpickle a -``QuerySet``, it contains the results at the moment it was pickled, rather -than the results that are currently in the database. - -If you only want to pickle the necessary information to recreate the -``Queryset`` from the database at a later time, pickle the ``query`` attribute -of the ``QuerySet``. You can then recreate the original ``QuerySet`` (without -any results loaded) using some code like this:: - - >>> import pickle - >>> query = pickle.loads(s) # Assuming 's' is the pickled string. - >>> qs = MyModel.objects.all() - >>> qs.query = query # Restore the original 'query'. - -.. _pickle: http://docs.python.org/lib/module-pickle.html - -Limiting QuerySets ------------------- - -Use Python's array-slicing syntax to limit your ``QuerySet`` to a certain -number of results. This is the equivalent of SQL's ``LIMIT`` and ``OFFSET`` -clauses. - -For example, this returns the first 5 objects (``LIMIT 5``):: - - Entry.objects.all()[:5] - -This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``):: - - Entry.objects.all()[5:10] - -You can also slice from the item ''N'' to the end of the queryset. For -example, to return everything from the sixth item onwards:: - - Entry.objects.all()[5:] - -How this last example is implemented in SQL varies depending upon the database -used, but it is supported in all cases. - -Generally, slicing a ``QuerySet`` returns a new ``QuerySet`` -- it doesn't -evaluate the query. An exception is if you use the "step" parameter of Python -slice syntax. For example, this would actually execute the query in order to -return a list of every *second* object of the first 10:: - - Entry.objects.all()[:10:2] - -To retrieve a *single* object rather than a list -(e.g. ``SELECT foo FROM bar LIMIT 1``), use a simple index instead of a -slice. For example, this returns the first ``Entry`` in the database, after -ordering entries alphabetically by headline:: - - Entry.objects.order_by('headline')[0] - -This is roughly equivalent to:: - - Entry.objects.order_by('headline')[0:1].get() - -Note, however, that the first of these will raise ``IndexError`` while the -second will raise ``DoesNotExist`` if no objects match the given criteria. - -Combining QuerySets -------------------- - -If you have two ``QuerySet`` instances that act on the same model, you can -combine them using ``&`` and ``|`` to get the items that are in both result -sets or in either results set, respectively. For example:: - - Entry.objects.filter(pubdate__gte=date1) & \ - Entry.objects.filter(headline__startswith="What") - -will combine the two queries into a single SQL query. Of course, in this case -you could have achieved the same result using multiple filters on the same -``QuerySet``, but sometimes the ability to combine individual ``QuerySet`` -instance is useful. - -Be careful, if you are using ``extra()`` to add custom handling to your -``QuerySet`` however. All the ``extra()`` components are merged and the result -may or may not make sense. If you are using custom SQL fragments in your -``extra()`` calls, Django will not inspect these fragments to see if they need -to be rewritten because of changes in the merged query. So test the effects -carefully. Also realize that if you are combining two ``QuerySets`` with -``|``, you cannot use ``extra(select=...)`` or ``extra(where=...)`` on *both* -``QuerySets``. You can only use those calls on one or the other (Django will -raise a ``ValueError`` if you try to use this incorrectly). - -QuerySet methods that return new QuerySets ------------------------------------------- - -Django provides a range of ``QuerySet`` refinement methods that modify either -the types of results returned by the ``QuerySet`` or the way its SQL query is -executed. - -``filter(**kwargs)`` -~~~~~~~~~~~~~~~~~~~~ - -Returns a new ``QuerySet`` containing objects that match the given lookup -parameters. - -The lookup parameters (``**kwargs``) should be in the format described in -`Field lookups`_ below. Multiple parameters are joined via ``AND`` in the -underlying SQL statement. - -``exclude(**kwargs)`` -~~~~~~~~~~~~~~~~~~~~~ - -Returns a new ``QuerySet`` containing objects that do *not* match the given -lookup parameters. - -The lookup parameters (``**kwargs``) should be in the format described in -`Field lookups`_ below. Multiple parameters are joined via ``AND`` in the -underlying SQL statement, and the whole thing is enclosed in a ``NOT()``. - -This example excludes all entries whose ``pub_date`` is later than 2005-1-3 -AND whose ``headline`` is "Hello":: - - Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello') - -In SQL terms, that evaluates to:: - - SELECT ... - WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello') - -This example excludes all entries whose ``pub_date`` is later than 2005-1-3 -OR whose headline is "Hello":: - - Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello') - -In SQL terms, that evaluates to:: - - SELECT ... - WHERE NOT pub_date > '2005-1-3' - AND NOT headline = 'Hello' - -Note the second example is more restrictive. - -``order_by(*fields)`` -~~~~~~~~~~~~~~~~~~~~~ - -By default, results returned by a ``QuerySet`` are ordered by the ordering -tuple given by the ``ordering`` option in the model's ``Meta``. You can -override this on a per-``QuerySet`` basis by using the ``order_by`` method. - -Example:: - - Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline') - -The result above will be ordered by ``pub_date`` descending, then by -``headline`` ascending. The negative sign in front of ``"-pub_date"`` indicates -*descending* order. Ascending order is implied. To order randomly, use ``"?"``, -like so:: - - Entry.objects.order_by('?') - -Note: ``order_by('?')`` queries may be expensive and slow, depending on the -database backend you're using. - -To order by a field in a different model, use the same syntax as when you are -querying across model relations. That is, the name of the field, followed by a -double underscore (``__``), followed by the name of the field in the new model, -and so on for as many models as you want to join. For example:: - - Entry.objects.order_by('blog__name', 'headline') - -If you try to order by a field that is a relation to another model, Django will -use the default ordering on the related model (or order by the related model's -primary key if there is no ``Meta.ordering`` specified. For example:: - - Entry.objects.order_by('blog') - -...is identical to:: - - Entry.objects.order_by('blog__id') - -...since the ``Blog`` model has no default ordering specified. - -Be cautious when ordering by fields in related models if you are also using -``distinct()``. See the note in the `distinct()`_ section for an explanation -of how related model ordering can change the expected results. - -It is permissible to specify a multi-valued field to order the results by (for -example, a ``ManyToMany`` field). Normally this won't be a sensible thing to -do and it's really an advanced usage feature. However, if you know that your -queryset's filtering or available data implies that there will only be one -ordering piece of data for each of the main items you are selecting, the -ordering may well be exactly what you want to do. Use ordering on multi-valued -fields with care and make sure the results are what you expect. - -**New in Django development version:** If you don't want any ordering to be -applied to a query, not even the default ordering, call ``order_by()`` with no -parameters. - -**New in Django development version:** The syntax for ordering across related -models has changed. See the `Django 0.96 documentation`_ for the old behavior. - -.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield - -There's no way to specify whether ordering should be case sensitive. With -respect to case-sensitivity, Django will order results however your database -backend normally orders them. - -``reverse()`` -~~~~~~~~~~~~~ - -**New in Django development version** - -Use the ``reverse()`` method to reverse the order in which a queryset's -elements are returned. Calling ``reverse()`` a second time restores the -ordering back to the normal direction. - -To retrieve the ''last'' five items in a queryset, you could do this:: - - my_queryset.reverse()[:5] - -Note that this is not quite the same as slicing from the end of a sequence in -Python. The above example will return the last item first, then the -penultimate item and so on. If we had a Python sequence and looked at -``seq[:-5]``, we would see the fifth-last item first. Django doesn't support -that mode of access (slicing from the end), because it's not possible to do it -efficiently in SQL. - -Also, note that ``reverse()`` should generally only be called on a -``QuerySet`` which has a defined ordering (e.g., when querying against -a model which defines a default ordering, or when using -``order_by()``). If no such ordering is defined for a given -``QuerySet``, calling ``reverse()`` on it has no real effect (the -ordering was undefined prior to calling ``reverse()``, and will remain -undefined afterward). - - -``distinct()`` -~~~~~~~~~~~~~~ - -Returns a new ``QuerySet`` that uses ``SELECT DISTINCT`` in its SQL query. This -eliminates duplicate rows from the query results. - -By default, a ``QuerySet`` will not eliminate duplicate rows. In practice, this -is rarely a problem, because simple queries such as ``Blog.objects.all()`` -don't introduce the possibility of duplicate result rows. However, if your -query spans multiple tables, it's possible to get duplicate results when a -``QuerySet`` is evaluated. That's when you'd use ``distinct()``. - -.. note:: - Any fields used in an ``order_by()`` call are included in the SQL - ``SELECT`` columns. This can sometimes lead to unexpected results when - used in conjunction with ``distinct()``. If you order by fields from a - related model, those fields will be added to the selected columns and they - may make otherwise duplicate rows appear to be distinct. Since the extra - columns don't appear in the returned results (they are only there to - support ordering), it sometimes looks like non-distinct results are being - returned. - - Similarly, if you use a ``values()`` query to restrict the columns - selected, the columns used in any ``order_by()`` (or default model - ordering) will still be involved and may affect uniqueness of the results. - - The moral here is that if you are using ``distinct()`` be careful about - ordering by related models. Similarly, when using ``distinct()`` and - ``values()`` together, be careful when ordering by fields not in the - ``values()`` call. - -``values(*fields)`` -~~~~~~~~~~~~~~~~~~~ - -Returns a ``ValuesQuerySet`` -- a ``QuerySet`` that evaluates to a list of -dictionaries instead of model-instance objects. - -Each of those dictionaries represents an object, with the keys corresponding to -the attribute names of model objects. - -This example compares the dictionaries of ``values()`` with the normal model -objects:: - - # This list contains a Blog object. - >>> Blog.objects.filter(name__startswith='Beatles') - [Beatles Blog] - - # This list contains a dictionary. - >>> Blog.objects.filter(name__startswith='Beatles').values() - [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}] - -``values()`` takes optional positional arguments, ``*fields``, which specify -field names to which the ``SELECT`` should be limited. If you specify the -fields, each dictionary will contain only the field keys/values for the fields -you specify. If you don't specify the fields, each dictionary will contain a -key and value for every field in the database table. - -Example:: - - >>> Blog.objects.values() - [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}], - >>> Blog.objects.values('id', 'name') - [{'id': 1, 'name': 'Beatles Blog'}] - -You can also retrieve values from across ``ForeignKey`` relations by using -double underscores to separate the field names, just as when calling the -``filter()`` command. For example:: - - >>> Entry.objects.values('blog__name').distinct() - [{'name': 'Beatles Blog'}] - -A couple of subtleties that are worth mentioning: - - * The ``values()`` method does not return anything for ``ManyToManyField`` - attributes and will raise an error if you try to pass in this type of - field to it. - * If you have a field called ``foo`` that is a ``ForeignKey``, the default - ``values()`` call will return a dictionary key called ``foo_id``, since - this is the name of the hidden model attribute that stores the actual - value (the ``foo`` attribute refers to the related model). When you are - calling ``values()`` and passing in field names, you can pass in either - ``foo`` or ``foo_id`` and you will get back the same thing (the - dictionary key will match the field name you passed in). - - For example:: - - >>> Entry.objects.values() - [{'blog_id: 1, 'headline': u'First Entry', ...}, ...] - - >>> Entry.objects.values('blog') - [{'blog': 1}, ...] - - >>> Entry.objects.values('blog_id') - [{'blog_id': 1}, ...] - * When using ``values()`` together with ``distinct()``, be aware that - ordering can affect the results. See the note in the `distinct()`_ - section, above, for details. - -**New in Django development version:** Previously, it was not possible to pass -``blog_id`` to ``values()`` in the above example, only ``blog``. - -A ``ValuesQuerySet`` is useful when you know you're only going to need values -from a small number of the available fields and you won't need the -functionality of a model instance object. It's more efficient to select only -the fields you need to use. - -Finally, note a ``ValuesQuerySet`` is a subclass of ``QuerySet``, so it has all -methods of ``QuerySet``. You can call ``filter()`` on it, or ``order_by()``, or -whatever. Yes, that means these two calls are identical:: - - Blog.objects.values().order_by('id') - Blog.objects.order_by('id').values() - -The people who made Django prefer to put all the SQL-affecting methods first, -followed (optionally) by any output-affecting methods (such as ``values()``), -but it doesn't really matter. This is your chance to really flaunt your -individualism. - -``values_list(*fields)`` -~~~~~~~~~~~~~~~~~~~~~~~~ - -**New in Django development version** - -This is similar to ``values()`` except that instead of returning a list of -dictionaries, it returns a list of tuples. Each tuple contains the value from -the respective field passed into the ``values_list()`` call -- so the first -item is the first field, etc. For example:: - - >>> Entry.objects.values_list('id', 'headline') - [(1, u'First entry'), ...] - -If you only pass in a single field, you can also pass in the ``flat`` -parameter. If ``True``, this will mean the returned results are single values, -rather than one-tuples. An example should make the difference clearer:: - - >>> Entry.objects.values_list('id').order_by('id') - [(1,), (2,), (3,), ...] - - >>> Entry.objects.values_list('id', flat=True).order_by('id') - [1, 2, 3, ...] - -It is an error to pass in ``flat`` when there is more than one field. - -If you don't pass any values to ``values_list()``, it will return all the -fields in the model, in the order they were declared. - -``dates(field, kind, order='ASC')`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Returns a ``DateQuerySet`` -- a ``QuerySet`` that evaluates to a list of -``datetime.datetime`` objects representing all available dates of a particular -kind within the contents of the ``QuerySet``. - -``field`` should be the name of a ``DateField`` or ``DateTimeField`` of your -model. - -``kind`` should be either ``"year"``, ``"month"`` or ``"day"``. Each -``datetime.datetime`` object in the result list is "truncated" to the given -``type``. - - * ``"year"`` returns a list of all distinct year values for the field. - * ``"month"`` returns a list of all distinct year/month values for the field. - * ``"day"`` returns a list of all distinct year/month/day values for the field. - -``order``, which defaults to ``'ASC'``, should be either ``'ASC'`` or -``'DESC'``. This specifies how to order the results. - -Examples:: - - >>> Entry.objects.dates('pub_date', 'year') - [datetime.datetime(2005, 1, 1)] - >>> Entry.objects.dates('pub_date', 'month') - [datetime.datetime(2005, 2, 1), datetime.datetime(2005, 3, 1)] - >>> Entry.objects.dates('pub_date', 'day') - [datetime.datetime(2005, 2, 20), datetime.datetime(2005, 3, 20)] - >>> Entry.objects.dates('pub_date', 'day', order='DESC') - [datetime.datetime(2005, 3, 20), datetime.datetime(2005, 2, 20)] - >>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day') - [datetime.datetime(2005, 3, 20)] - -``none()`` -~~~~~~~~~~ - -**New in Django development version** - -Returns an ``EmptyQuerySet`` -- a ``QuerySet`` that always evaluates to -an empty list. This can be used in cases where you know that you should -return an empty result set and your caller is expecting a ``QuerySet`` -object (instead of returning an empty list, for example.) - -Examples:: - - >>> Entry.objects.none() - [] - -``all()`` -~~~~~~~~~~ - -**New in Django development version** - -Returns a ''copy'' of the current ``QuerySet`` (or ``QuerySet`` subclass you -pass in). This can be useful in some situations where you might want to pass -in either a model manager or a ``QuerySet`` and do further filtering on the -result. You can safely call ``all()`` on either object and then you'll -definitely have a ``QuerySet`` to work with. - -``select_related()`` -~~~~~~~~~~~~~~~~~~~~ - -Returns a ``QuerySet`` that will automatically "follow" foreign-key -relationships, selecting that additional related-object data when it executes -its query. This is a performance booster which results in (sometimes much) -larger queries but means later use of foreign-key relationships won't require -database queries. - -The following examples illustrate the difference between plain lookups and -``select_related()`` lookups. Here's standard lookup:: - - # Hits the database. - e = Entry.objects.get(id=5) - - # Hits the database again to get the related Blog object. - b = e.blog - -And here's ``select_related`` lookup:: - - # Hits the database. - e = Entry.objects.select_related().get(id=5) - - # Doesn't hit the database, because e.blog has been prepopulated - # in the previous query. - b = e.blog - -``select_related()`` follows foreign keys as far as possible. If you have the -following models:: - - class City(models.Model): - # ... - - class Person(models.Model): - # ... - hometown = models.ForeignKey(City) - - class Book(models.Model): - # ... - author = models.ForeignKey(Person) - -...then a call to ``Book.objects.select_related().get(id=4)`` will cache the -related ``Person`` *and* the related ``City``:: - - b = Book.objects.select_related().get(id=4) - p = b.author # Doesn't hit the database. - c = p.hometown # Doesn't hit the database. - - b = Book.objects.get(id=4) # No select_related() in this example. - p = b.author # Hits the database. - c = p.hometown # Hits the database. - -Note that, by default, ``select_related()`` does not follow foreign keys that -have ``null=True``. - -Usually, using ``select_related()`` can vastly improve performance because your -app can avoid many database calls. However, in situations with deeply nested -sets of relationships ``select_related()`` can sometimes end up following "too -many" relations, and can generate queries so large that they end up being slow. - -In these situations, you can use the ``depth`` argument to ``select_related()`` -to control how many "levels" of relations ``select_related()`` will actually -follow:: - - b = Book.objects.select_related(depth=1).get(id=4) - p = b.author # Doesn't hit the database. - c = p.hometown # Requires a database call. - -The ``depth`` argument is new in the Django development version. - -**New in Django development version:** Sometimes you only need to access -specific models that are related to your root model, not all of the related -models. In these cases, you can pass the related field names to -``select_related()`` and it will only follow those relations. You can even do -this for models that are more than one relation away by separating the field -names with double underscores, just as for filters. For example, if we have -this model:: - - class Room(models.Model): - # ... - building = models.ForeignKey(...) - - class Group(models.Model): - # ... - teacher = models.ForeignKey(...) - room = models.ForeignKey(Room) - subject = models.ForeignKey(...) - -...and we only needed to work with the ``room`` and ``subject`` attributes, we -could write this:: - - g = Group.objects.select_related('room', 'subject') - -This is also valid:: - - g = Group.objects.select_related('room__building', 'subject') - -...and would also pull in the ``building`` relation. - -You can only refer to ``ForeignKey`` relations in the list of fields passed to -``select_related``. You *can* refer to foreign keys that have ``null=True`` -(unlike the default ``select_related()`` call). It's an error to use both a -list of fields and the ``depth`` parameter in the same ``select_related()`` -call, since they are conflicting options. - -``extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Sometimes, the Django query syntax by itself can't easily express a complex -``WHERE`` clause. For these edge cases, Django provides the ``extra()`` -``QuerySet`` modifier -- a hook for injecting specific clauses into the SQL -generated by a ``QuerySet``. - -By definition, these extra lookups may not be portable to different database -engines (because you're explicitly writing SQL code) and violate the DRY -principle, so you should avoid them if possible. - -Specify one or more of ``params``, ``select``, ``where`` or ``tables``. None -of the arguments is required, but you should use at least one of them. - -``select`` - The ``select`` argument lets you put extra fields in the ``SELECT`` clause. - It should be a dictionary mapping attribute names to SQL clauses to use to - calculate that attribute. - - Example:: - - Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) - - As a result, each ``Entry`` object will have an extra attribute, - ``is_recent``, a boolean representing whether the entry's ``pub_date`` is - greater than Jan. 1, 2006. - - Django inserts the given SQL snippet directly into the ``SELECT`` - statement, so the resulting SQL of the above example would be:: - - SELECT blog_entry.*, (pub_date > '2006-01-01') - FROM blog_entry; - - - The next example is more advanced; it does a subquery to give each - resulting ``Blog`` object an ``entry_count`` attribute, an integer count - of associated ``Entry`` objects:: - - Blog.objects.extra( - select={ - 'entry_count': 'SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id' - }, - ) - - (In this particular case, we're exploiting the fact that the query will - already contain the ``blog_blog`` table in its ``FROM`` clause.) - - The resulting SQL of the above example would be:: - - SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) - FROM blog_blog; - - Note that the parenthesis required by most database engines around - subqueries are not required in Django's ``select`` clauses. Also note that - some database backends, such as some MySQL versions, don't support - subqueries. - - **New in Django development version** - In some rare cases, you might wish to pass parameters to the SQL fragments - in ``extra(select=...)```. For this purpose, use the ``select_params`` - parameter. Since ``select_params`` is a sequence and the ``select`` - attribute is a dictionary, some care is required so that the parameters - are matched up correctly with the extra select pieces. In this situation, - you should use a ``django.utils.datastructures.SortedDict`` for the - ``select`` value, not just a normal Python dictionary. - - This will work, for example:: - - Blog.objects.extra( - select=SortedDict([('a', '%s'), ('b', '%s')]), - select_params=('one', 'two')) - - The only thing to be careful about when using select parameters in - ``extra()`` is to avoid using the substring ``"%%s"`` (that's *two* - percent characters before the ``s``) in the select strings. Django's - tracking of parameters looks for ``%s`` and an escaped ``%`` character - like this isn't detected. That will lead to incorrect results. - -``where`` / ``tables`` - You can define explicit SQL ``WHERE`` clauses -- perhaps to perform - non-explicit joins -- by using ``where``. You can manually add tables to - the SQL ``FROM`` clause by using ``tables``. - - ``where`` and ``tables`` both take a list of strings. All ``where`` - parameters are "AND"ed to any other search criteria. - - Example:: - - Entry.objects.extra(where=['id IN (3, 4, 5, 20)']) - - ...translates (roughly) into the following SQL:: - - SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20); - - Be careful when using the ``tables`` parameter if you're specifying - tables that are already used in the query. When you add extra tables - via the ``tables`` parameter, Django assumes you want that table included - an extra time, if it is already included. That creates a problem, - since the table name will then be given an alias. If a table appears - multiple times in an SQL statement, the second and subsequent occurrences - must use aliases so the database can tell them apart. If you're - referring to the extra table you added in the extra ``where`` parameter - this is going to cause errors. - - Normally you'll only be adding extra tables that don't already appear in - the query. However, if the case outlined above does occur, there are a few - solutions. First, see if you can get by without including the extra table - and use the one already in the query. If that isn't possible, put your - ``extra()`` call at the front of the queryset construction so that your - table is the first use of that table. Finally, if all else fails, look at - the query produced and rewrite your ``where`` addition to use the alias - given to your extra table. The alias will be the same each time you - construct the queryset in the same way, so you can rely upon the alias - name to not change. - -``order_by`` - If you need to order the resulting queryset using some of the new fields - or tables you have included via ``extra()`` use the ``order_by`` parameter - to ``extra()`` and pass in a sequence of strings. These strings should - either be model fields (as in the normal ``order_by()`` method on - querysets), of the form ``table_name.column_name`` or an alias for a column - that you specified in the ``select`` parameter to ``extra()``. - - For example:: - - q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) - q = q.extra(order_by = ['-is_recent']) - - This would sort all the items for which ``is_recent`` is true to the front - of the result set (``True`` sorts before ``False`` in a descending - ordering). - - This shows, by the way, that you can make multiple calls to - ``extra()`` and it will behave as you expect (adding new constraints each - time). - -``params`` - The ``where`` parameter described above may use standard Python database - string placeholders -- ``'%s'`` to indicate parameters the database engine - should automatically quote. The ``params`` argument is a list of any extra - parameters to be substituted. - - Example:: - - Entry.objects.extra(where=['headline=%s'], params=['Lennon']) - - Always use ``params`` instead of embedding values directly into ``where`` - because ``params`` will ensure values are quoted correctly according to - your particular backend. (For example, quotes will be escaped correctly.) - - Bad:: - - Entry.objects.extra(where=["headline='Lennon'"]) - - Good:: - - Entry.objects.extra(where=['headline=%s'], params=['Lennon']) - -**New in Django development version** The ``select_params`` argument to -``extra()`` is new. Previously, you could attempt to pass parameters for -``select`` in the ``params`` argument, but it worked very unreliably. - -QuerySet methods that do not return QuerySets ---------------------------------------------- - -The following ``QuerySet`` methods evaluate the ``QuerySet`` and return -something *other than* a ``QuerySet``. - -These methods do not use a cache (see `Caching and QuerySets`_ below). Rather, -they query the database each time they're called. - -``get(**kwargs)`` -~~~~~~~~~~~~~~~~~ - -Returns the object matching the given lookup parameters, which should be in -the format described in `Field lookups`_. - -``get()`` raises ``MultipleObjectsReturned`` if more than one object was found. -The ``MultipleObjectsReturned`` exception is an attribute of the model class. -For example, the following will raise ``MultipleObjectsReturned`` if there -are more than one authors with the name of 'John':: - - Author.objects.get(name='John') # raises Author.MultipleObjectsReturned - -``get()`` raises a ``DoesNotExist`` exception if an object wasn't found for the -given parameters. The ``DoesNotExist`` exception is an attribute of the model -class. Example:: - - Entry.objects.get(id='foo') # raises Entry.DoesNotExist - -The ``DoesNotExist`` exception inherits from -``django.core.exceptions.ObjectDoesNotExist``, so you can target multiple -``DoesNotExist`` exceptions. Example:: - - from django.core.exceptions import ObjectDoesNotExist - try: - e = Entry.objects.get(id=3) - b = Blog.objects.get(id=1) - except ObjectDoesNotExist: - print "Either the entry or blog doesn't exist." - -``create(**kwargs)`` -~~~~~~~~~~~~~~~~~~~~ - -A convenience method for creating an object and saving it all in one step. Thus:: - - p = Person.objects.create(first_name="Bruce", last_name="Springsteen") - -and:: - - p = Person(first_name="Bruce", last_name="Springsteen") - p.save() - -are equivalent. - -``get_or_create(**kwargs)`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A convenience method for looking up an object with the given kwargs, creating -one if necessary. - -Returns a tuple of ``(object, created)``, where ``object`` is the retrieved or -created object and ``created`` is a boolean specifying whether a new object was -created. - -This is meant as a shortcut to boilerplatish code and is mostly useful for -data-import scripts. For example:: - - try: - obj = Person.objects.get(first_name='John', last_name='Lennon') - except Person.DoesNotExist: - obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9)) - obj.save() - -This pattern gets quite unwieldy as the number of fields in a model goes up. -The above example can be rewritten using ``get_or_create()`` like so:: - - obj, created = Person.objects.get_or_create(first_name='John', last_name='Lennon', - defaults={'birthday': date(1940, 10, 9)}) - -Any keyword arguments passed to ``get_or_create()`` -- *except* an optional one -called ``defaults`` -- will be used in a ``get()`` call. If an object is found, -``get_or_create()`` returns a tuple of that object and ``False``. If an object -is *not* found, ``get_or_create()`` will instantiate and save a new object, -returning a tuple of the new object and ``True``. The new object will be -created according to this algorithm:: - - defaults = kwargs.pop('defaults', {}) - params = dict([(k, v) for k, v in kwargs.items() if '__' not in k]) - params.update(defaults) - obj = self.model(**params) - obj.save() - -In English, that means start with any non-``'defaults'`` keyword argument that -doesn't contain a double underscore (which would indicate a non-exact lookup). -Then add the contents of ``defaults``, overriding any keys if necessary, and -use the result as the keyword arguments to the model class. - -If you have a field named ``defaults`` and want to use it as an exact lookup in -``get_or_create()``, just use ``'defaults__exact'``, like so:: - - Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'}) - -Finally, a word on using ``get_or_create()`` in Django views. As mentioned -earlier, ``get_or_create()`` is mostly useful in scripts that need to parse -data and create new records if existing ones aren't available. But if you need -to use ``get_or_create()`` in a view, please make sure to use it only in -``POST`` requests unless you have a good reason not to. ``GET`` requests -shouldn't have any effect on data; use ``POST`` whenever a request to a page -has a side effect on your data. For more, see `Safe methods`_ in the HTTP spec. - -.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 - -``count()`` -~~~~~~~~~~~ - -Returns an integer representing the number of objects in the database matching -the ``QuerySet``. ``count()`` never raises exceptions. - -Example:: - - # Returns the total number of entries in the database. - Entry.objects.count() - - # Returns the number of entries whose headline contains 'Lennon' - Entry.objects.filter(headline__contains='Lennon').count() - -``count()`` performs a ``SELECT COUNT(*)`` behind the scenes, so you should -always use ``count()`` rather than loading all of the record into Python -objects and calling ``len()`` on the result. - -Depending on which database you're using (e.g. PostgreSQL vs. MySQL), -``count()`` may return a long integer instead of a normal Python integer. This -is an underlying implementation quirk that shouldn't pose any real-world -problems. - -``in_bulk(id_list)`` -~~~~~~~~~~~~~~~~~~~~ - -Takes a list of primary-key values and returns a dictionary mapping each -primary-key value to an instance of the object with the given ID. - -Example:: - - >>> Blog.objects.in_bulk([1]) - {1: Beatles Blog} - >>> Blog.objects.in_bulk([1, 2]) - {1: Beatles Blog, 2: Cheddar Talk} - >>> Blog.objects.in_bulk([]) - {} - -If you pass ``in_bulk()`` an empty list, you'll get an empty dictionary. - -``iterator()`` -~~~~~~~~~~~~~~ - -Evaluates the ``QuerySet`` (by performing the query) and returns an -`iterator`_ over the results. A ``QuerySet`` typically reads all of -its results and instantiates all of the corresponding objects the -first time you access it; ``iterator()`` will instead read results and -instantiate objects in discrete chunks, yielding them one at a -time. For a ``QuerySet`` which returns a large number of objects, this -often results in better performance and a significant reduction in -memory use. - -Note that using ``iterator()`` on a ``QuerySet`` which has already -been evaluated will force it to evaluate again, repeating the query. - -.. _iterator: http://www.python.org/dev/peps/pep-0234/ - -``latest(field_name=None)`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Returns the latest object in the table, by date, using the ``field_name`` -provided as the date field. - -This example returns the latest ``Entry`` in the table, according to the -``pub_date`` field:: - - Entry.objects.latest('pub_date') - -If your model's ``Meta`` specifies ``get_latest_by``, you can leave off the -``field_name`` argument to ``latest()``. Django will use the field specified in -``get_latest_by`` by default. - -Like ``get()``, ``latest()`` raises ``DoesNotExist`` if an object doesn't -exist with the given parameters. - -Note ``latest()`` exists purely for convenience and readability. - -Field lookups -------------- - -Field lookups are how you specify the meat of an SQL ``WHERE`` clause. They're -specified as keyword arguments to the ``QuerySet`` methods ``filter()``, -``exclude()`` and ``get()``. - -Basic lookups keyword arguments take the form ``field__lookuptype=value``. -(That's a double-underscore). For example:: - - Entry.objects.filter(pub_date__lte='2006-01-01') - -translates (roughly) into the following SQL:: - - SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; - -.. admonition:: How this is possible - - Python has the ability to define functions that accept arbitrary name-value - arguments whose names and values are evaluated at runtime. For more - information, see `Keyword Arguments`_ in the official Python tutorial. - - .. _`Keyword Arguments`: http://docs.python.org/tut/node6.html#SECTION006720000000000000000 - -If you pass an invalid keyword argument, a lookup function will raise -``TypeError``. - -The database API supports the following lookup types: - -exact -~~~~~ - -Exact match. If the value provided for comparison is ``None``, it will -be interpreted as an SQL ``NULL`` (See isnull_ for more details). - -Examples:: - - Entry.objects.get(id__exact=14) - Entry.objects.get(id__exact=None) - -SQL equivalents:: - - SELECT ... WHERE id = 14; - SELECT ... WHERE id IS NULL; - -**New in Django development version:** The semantics of ``id__exact=None`` have -changed in the development version. Previously, it was (intentionally) -converted to ``WHERE id = NULL`` at the SQL level, which would never match -anything. It has now been changed to behave the same as ``id__isnull=True``. - -.. admonition:: MySQL comparisons - - In MySQL, whether or not ``exact`` comparisons are case-sensitive depends - upon the collation setting of the table involved. The default is usually - ``latin1_swedish_ci`` or ``utf8_swedish_ci``, which results in - case-insensitive comparisons. Change the collation to - ``latin1_swedish_cs`` or ``utf8_bin`` for case sensitive comparisons. - - For more details, refer to the MySQL manual section about `character sets - and collations`_. - -.. _character sets and collations: http://dev.mysql.com/doc/refman/5.0/en/charset.html - -iexact -~~~~~~ - -Case-insensitive exact match. - -Example:: - - Blog.objects.get(name__iexact='beatles blog') - -SQL equivalent:: - - SELECT ... WHERE name ILIKE 'beatles blog'; - -Note this will match ``'Beatles Blog'``, ``'beatles blog'``, -``'BeAtLes BLoG'``, etc. - -contains -~~~~~~~~ - -Case-sensitive containment test. - -Example:: - - Entry.objects.get(headline__contains='Lennon') - -SQL equivalent:: - - SELECT ... WHERE headline LIKE '%Lennon%'; - -Note this will match the headline ``'Today Lennon honored'`` but not -``'today lennon honored'``. - -SQLite doesn't support case-sensitive ``LIKE`` statements; ``contains`` acts -like ``icontains`` for SQLite. - -icontains -~~~~~~~~~ - -Case-insensitive containment test. - -Example:: - - Entry.objects.get(headline__icontains='Lennon') - -SQL equivalent:: - - SELECT ... WHERE headline ILIKE '%Lennon%'; - -gt -~~ - -Greater than. - -Example:: - - Entry.objects.filter(id__gt=4) - -SQL equivalent:: - - SELECT ... WHERE id > 4; - -gte -~~~ - -Greater than or equal to. - -lt -~~ - -Less than. - -lte -~~~ - -Less than or equal to. - -in -~~ - -In a given list. - -Example:: - - Entry.objects.filter(id__in=[1, 3, 4]) - -SQL equivalent:: - - SELECT ... WHERE id IN (1, 3, 4); - -You can also use a queryset to dynamically evaluate the list of values -instead of providing a list of literal values. The queryset must be -reduced to a list of individual values using the ``values()`` method, -and then converted into a query using the ``query`` attribute:: - - Entry.objects.filter(blog__in=Blog.objects.filter(name__contains='Cheddar').values('pk').query) - -This queryset will be evaluated as subselect statement:: - - SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%') - -startswith -~~~~~~~~~~ - -Case-sensitive starts-with. - -Example:: - - Entry.objects.filter(headline__startswith='Will') - -SQL equivalent:: - - SELECT ... WHERE headline LIKE 'Will%'; - -SQLite doesn't support case-sensitive ``LIKE`` statements; ``startswith`` acts -like ``istartswith`` for SQLite. - -istartswith -~~~~~~~~~~~ - -Case-insensitive starts-with. - -Example:: - - Entry.objects.filter(headline__istartswith='will') - -SQL equivalent:: - - SELECT ... WHERE headline ILIKE 'Will%'; - -endswith -~~~~~~~~ - -Case-sensitive ends-with. - -Example:: - - Entry.objects.filter(headline__endswith='cats') - -SQL equivalent:: - - SELECT ... WHERE headline LIKE '%cats'; - -SQLite doesn't support case-sensitive ``LIKE`` statements; ``endswith`` acts -like ``iendswith`` for SQLite. - -iendswith -~~~~~~~~~ - -Case-insensitive ends-with. - -Example:: - - Entry.objects.filter(headline__iendswith='will') - -SQL equivalent:: - - SELECT ... WHERE headline ILIKE '%will' - -range -~~~~~ - -Range test (inclusive). - -Example:: - - start_date = datetime.date(2005, 1, 1) - end_date = datetime.date(2005, 3, 31) - Entry.objects.filter(pub_date__range=(start_date, end_date)) - -SQL equivalent:: - - SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31'; - -You can use ``range`` anywhere you can use ``BETWEEN`` in SQL -- for dates, -numbers and even characters. - -year -~~~~ - -For date/datetime fields, exact year match. Takes a four-digit year. - -Example:: - - Entry.objects.filter(pub_date__year=2005) - -SQL equivalent:: - - SELECT ... WHERE EXTRACT('year' FROM pub_date) = '2005'; - -(The exact SQL syntax varies for each database engine.) - -month -~~~~~ - -For date/datetime fields, exact month match. Takes an integer 1 (January) -through 12 (December). - -Example:: - - Entry.objects.filter(pub_date__month=12) - -SQL equivalent:: - - SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12'; - -(The exact SQL syntax varies for each database engine.) - -day -~~~ - -For date/datetime fields, exact day match. - -Example:: - - Entry.objects.filter(pub_date__day=3) - -SQL equivalent:: - - SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3'; - -(The exact SQL syntax varies for each database engine.) - -Note this will match any record with a pub_date on the third day of the month, -such as January 3, July 3, etc. - -isnull -~~~~~~ - -Takes either ``True`` or ``False``, which correspond to SQL queries of -``IS NULL`` and ``IS NOT NULL``, respectively. - -Example:: - - Entry.objects.filter(pub_date__isnull=True) - -SQL equivalent:: - - SELECT ... WHERE pub_date IS NULL; - -search -~~~~~~ - -A boolean full-text search, taking advantage of full-text indexing. This is -like ``contains`` but is significantly faster due to full-text indexing. - -Note this is only available in MySQL and requires direct manipulation of the -database to add the full-text index. - -regex -~~~~~ - -**New in Django development version** - -Case-sensitive regular expression match. - -The regular expression syntax is that of the database backend in use. In the -case of SQLite, which doesn't natively support regular-expression lookups, the -syntax is that of Python's ``re`` module. - -Example:: - - Entry.objects.get(title__regex=r'^(An?|The) +') - -SQL equivalents:: - - SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL - - SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'c'); -- Oracle - - SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL - - SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite - -Using raw strings (e.g., ``r'foo'`` instead of ``'foo'``) for passing in the -regular expression syntax is recommended. - -iregex -~~~~~~ - -**New in Django development version** - -Case-insensitive regular expression match. - -Example:: - - Entry.objects.get(title__iregex=r'^(an?|the) +') - -SQL equivalents:: - - SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL - - SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle - - SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL - - SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite - -Default lookups are exact -------------------------- - -If you don't provide a lookup type -- that is, if your keyword argument doesn't -contain a double underscore -- the lookup type is assumed to be ``exact``. - -For example, the following two statements are equivalent:: - - Blog.objects.get(id__exact=14) # Explicit form - Blog.objects.get(id=14) # __exact is implied - -This is for convenience, because ``exact`` lookups are the common case. - -The pk lookup shortcut ----------------------- - -For convenience, Django provides a ``pk`` lookup type, which stands for -"primary_key". - -In the example ``Blog`` model, the primary key is the ``id`` field, so these -three statements are equivalent:: - - Blog.objects.get(id__exact=14) # Explicit form - Blog.objects.get(id=14) # __exact is implied - Blog.objects.get(pk=14) # pk implies id__exact - -The use of ``pk`` isn't limited to ``__exact`` queries -- any query term -can be combined with ``pk`` to perform a query on the primary key of a model:: - - # Get blogs entries with id 1, 4 and 7 - Blog.objects.filter(pk__in=[1,4,7]) - # Get all blog entries with id > 14 - Blog.objects.filter(pk__gt=14) - -``pk`` lookups also work across joins. For example, these three statements are -equivalent:: - - Entry.objects.filter(blog__id__exact=3) # Explicit form - Entry.objects.filter(blog__id=3) # __exact is implied - Entry.objects.filter(blog__pk=3) # __pk implies __id__exact - -.. note:: - Because of this shortcut, you cannot have a field called ``pk`` that is not - the primary key of the model. It will always be replaced by the name of the - model's primary key in queries. - -Lookups that span relationships -------------------------------- - -Django offers a powerful and intuitive way to "follow" relationships in -lookups, taking care of the SQL ``JOIN``\s for you automatically, behind the -scenes. To span a relationship, just use the field name of related fields -across models, separated by double underscores, until you get to the field you -want. - -This example retrieves all ``Entry`` objects with a ``Blog`` whose ``name`` -is ``'Beatles Blog'``:: - - Entry.objects.filter(blog__name__exact='Beatles Blog') - -This spanning can be as deep as you'd like. - -It works backwards, too. To refer to a "reverse" relationship, just use the -lowercase name of the model. - -This example retrieves all ``Blog`` objects which have at least one ``Entry`` -whose ``headline`` contains ``'Lennon'``:: - - Blog.objects.filter(entry__headline__contains='Lennon') - -If you are filtering across multiple relationships and one of the intermediate -models doesn't have a value that meets the filter condition, Django will treat -it as if there is an empty (all values are ``NULL``), but valid, object there. -All this means is that no error will be raised. For example, in this filter:: - - Blog.objects.filter(entry__author__name='Lennon') - -(if there was a related ``Author`` model), if there was no ``author`` -associated with an entry, it would be treated as if there was also no ``name`` -attached, rather than raising an error because of the missing ``author``. -Usually this is exactly what you want to have happen. The only case where it -might be confusing is if you are using ``isnull``. Thus:: - - Blog.objects.filter(entry__author__name__isnull=True) - -will return ``Blog`` objects that have an empty ``name`` on the ``author`` and -also those which have an empty ``author`` on the ``entry``. If you don't want -those latter objects, you could write:: - - Blog.objetcs.filter(entry__author__isnull=False, - entry__author__name__isnull=True) - -Spanning multi-valued relationships -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**New in Django development version** - -When you are filtering an object based on a ``ManyToManyField`` or a reverse -``ForeignKeyField``, there are two different sorts of filter you may be -interested in. Consider the ``Blog``/``Entry`` relationship (``Blog`` to -``Entry`` is a one-to-many relation). We might be interested in finding blogs -that have an entry which has both *"Lennon"* in the headline and was published -in 2008. Or we might want to find blogs that have an entry with *"Lennon"* in -the headline as well as an entry that was published in 2008. Since there are -multiple entries associated with a single ``Blog``, both of these queries are -possible and make sense in some situations. - -The same type of situation arises with a ``ManyToManyField``. For example, if -an ``Entry`` has a ``ManyToManyField`` called ``tags``, we might want to find -entries linked to tags called *"music"* and *"bands"* or we might want an -entry that contains a tag with a name of *"music"* and a status of *"public"*. - -To handle both of these situations, Django has a consistent way of processing -``filter()`` and ``exclude()`` calls. Everything inside a single ``filter()`` -call is applied simultaneously to filter out items matching all those -requirements. Successive ``filter()`` calls further restrict the set of -objects, but for multi-valued relations, they apply to any object linked to -the primary model, not necessarily those objects that were selected by an -earlier ``filter()`` call. - -That may sound a bit confusing, so hopefully an example will clarify. To -select all blogs that contains entries with *"Lennon"* in the headline and -were published in 2008, we would write:: - - Blog.objects.filter(entry__headline__contains='Lennon', - entry__pub_date__year=2008) - -To select all blogs that contain an entry with *"Lennon"* in the headline -**as well as** an entry that was published in 2008, we would write:: - - Blog.objects.filter(entry__headline__contains='Lennon').filter( - entry__pub_date__year=2008) - -In this second example, the first filter restricted the queryset to all those -blogs linked to that particular type of entry. The second filter restricted -the set of blogs *further* to those that are also linked to the second type of -entry. The entries select by the second filter may or may not be the same as -the entries in the first filter. We are filtering the ``Blog`` items with each -filter statement, not the ``Entry`` items. - -All of this behavior also applies to ``exclude()``: all the conditions in a -single ``exclude()`` statement apply to a single instance (if those conditions -are talking about the same multi-valued relation). Conditions in subsequent -``filter()`` or ``exclude()`` calls that refer to the same relation may end up -filtering on different linked objects. - -Escaping percent signs and underscores in LIKE statements ---------------------------------------------------------- - -The field lookups that equate to ``LIKE`` SQL statements (``iexact``, -``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith`` -and ``iendswith``) will automatically escape the two special characters used in -``LIKE`` statements -- the percent sign and the underscore. (In a ``LIKE`` -statement, the percent sign signifies a multiple-character wildcard and the -underscore signifies a single-character wildcard.) - -This means things should work intuitively, so the abstraction doesn't leak. -For example, to retrieve all the entries that contain a percent sign, just use -the percent sign as any other character:: - - Entry.objects.filter(headline__contains='%') - -Django takes care of the quoting for you; the resulting SQL will look something -like this:: - - SELECT ... WHERE headline LIKE '%\%%'; - -Same goes for underscores. Both percentage signs and underscores are handled -for you transparently. - -Caching and QuerySets ---------------------- - -Each ``QuerySet`` contains a cache, to minimize database access. It's important -to understand how it works, in order to write the most efficient code. - -In a newly created ``QuerySet``, the cache is empty. The first time a -``QuerySet`` is evaluated -- and, hence, a database query happens -- Django -saves the query results in the ``QuerySet``'s cache and returns the results -that have been explicitly requested (e.g., the next element, if the -``QuerySet`` is being iterated over). Subsequent evaluations of the -``QuerySet`` reuse the cached results. - -Keep this caching behavior in mind, because it may bite you if you don't use -your ``QuerySet``\s correctly. For example, the following will create two -``QuerySet``\s, evaluate them, and throw them away:: - - print [e.headline for e in Entry.objects.all()] - print [e.pub_date for e in Entry.objects.all()] - -That means the same database query will be executed twice, effectively doubling -your database load. Also, there's a possibility the two lists may not include -the same database records, because an ``Entry`` may have been added or deleted -in the split second between the two requests. - -To avoid this problem, simply save the ``QuerySet`` and reuse it:: - - queryset = Poll.objects.all() - print [p.headline for p in queryset] # Evaluate the query set. - print [p.pub_date for p in queryset] # Re-use the cache from the evaluation. - -Comparing objects -================= - -To compare two model instances, just use the standard Python comparison operator, -the double equals sign: ``==``. Behind the scenes, that compares the primary -key values of two models. - -Using the ``Entry`` example above, the following two statements are equivalent:: - - some_entry == other_entry - some_entry.id == other_entry.id - -If a model's primary key isn't called ``id``, no problem. Comparisons will -always use the primary key, whatever it's called. For example, if a model's -primary key field is called ``name``, these two statements are equivalent:: - - some_obj == other_obj - some_obj.name == other_obj.name - -Complex lookups with Q objects -============================== - -Keyword argument queries -- in ``filter()``, etc. -- are "AND"ed together. If -you need to execute more complex queries (for example, queries with ``OR`` -statements), you can use ``Q`` objects. - -A ``Q`` object (``django.db.models.Q``) is an object used to encapsulate a -collection of keyword arguments. These keyword arguments are specified as in -"Field lookups" above. - -For example, this ``Q`` object encapsulates a single ``LIKE`` query:: - - Q(question__startswith='What') - -``Q`` objects can be combined using the ``&`` and ``|`` operators. When an -operator is used on two ``Q`` objects, it yields a new ``Q`` object. - -For example, this statement yields a single ``Q`` object that represents the -"OR" of two ``"question__startswith"`` queries:: - - Q(question__startswith='Who') | Q(question__startswith='What') - -This is equivalent to the following SQL ``WHERE`` clause:: - - WHERE question LIKE 'Who%' OR question LIKE 'What%' - -You can compose statements of arbitrary complexity by combining ``Q`` objects -with the ``&`` and ``|`` operators. You can also use parenthetical grouping. - -**New in Django development version:** ``Q`` objects can also be negated using -the ``~`` operator, allowing for combined lookups that combine both a normal -query and a negated (``NOT``) query:: - - Q(question__startswith='Who') | ~Q(pub_date__year=2005) - -Each lookup function that takes keyword-arguments (e.g. ``filter()``, -``exclude()``, ``get()``) can also be passed one or more ``Q`` objects as -positional (not-named) arguments. If you provide multiple ``Q`` object -arguments to a lookup function, the arguments will be "AND"ed together. For -example:: - - Poll.objects.get( - Q(question__startswith='Who'), - Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) - ) - -... roughly translates into the SQL:: - - SELECT * from polls WHERE question LIKE 'Who%' - AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') - -Lookup functions can mix the use of ``Q`` objects and keyword arguments. All -arguments provided to a lookup function (be they keyword arguments or ``Q`` -objects) are "AND"ed together. However, if a ``Q`` object is provided, it must -precede the definition of any keyword arguments. For example:: - - Poll.objects.get( - Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), - question__startswith='Who') - -... would be a valid query, equivalent to the previous example; but:: - - # INVALID QUERY - Poll.objects.get( - question__startswith='Who', - Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))) - -... would not be valid. - -See the `OR lookups examples page`_ for more examples. - -.. _OR lookups examples page: ../models/or_lookups/ - -Related objects -=============== - -When you define a relationship in a model (i.e., a ``ForeignKey``, -``OneToOneField``, or ``ManyToManyField``), instances of that model will have -a convenient API to access the related object(s). - -Using the models at the top of this page, for example, an ``Entry`` object ``e`` -can get its associated ``Blog`` object by accessing the ``blog`` attribute: -``e.blog``. - -(Behind the scenes, this functionality is implemented by Python descriptors_. -This shouldn't really matter to you, but we point it out here for the curious.) - -Django also creates API accessors for the "other" side of the relationship -- -the link from the related model to the model that defines the relationship. -For example, a ``Blog`` object ``b`` has access to a list of all related -``Entry`` objects via the ``entry_set`` attribute: ``b.entry_set.all()``. - -All examples in this section use the sample ``Blog``, ``Author`` and ``Entry`` -models defined at the top of this page. - -.. _descriptors: http://users.rcn.com/python/download/Descriptor.htm - -One-to-many relationships -------------------------- - -Forward -~~~~~~~ - -If a model has a ``ForeignKey``, instances of that model will have access to -the related (foreign) object via a simple attribute of the model. - -Example:: - - e = Entry.objects.get(id=2) - e.blog # Returns the related Blog object. - -You can get and set via a foreign-key attribute. As you may expect, changes to -the foreign key aren't saved to the database until you call ``save()``. -Example:: - - e = Entry.objects.get(id=2) - e.blog = some_blog - e.save() - -If a ``ForeignKey`` field has ``null=True`` set (i.e., it allows ``NULL`` -values), you can assign ``None`` to it. Example:: - - e = Entry.objects.get(id=2) - e.blog = None - e.save() # "UPDATE blog_entry SET blog_id = NULL ...;" - -Forward access to one-to-many relationships is cached the first time the -related object is accessed. Subsequent accesses to the foreign key on the same -object instance are cached. Example:: - - e = Entry.objects.get(id=2) - print e.blog # Hits the database to retrieve the associated Blog. - print e.blog # Doesn't hit the database; uses cached version. - -Note that the ``select_related()`` ``QuerySet`` method recursively prepopulates -the cache of all one-to-many relationships ahead of time. Example:: - - e = Entry.objects.select_related().get(id=2) - print e.blog # Doesn't hit the database; uses cached version. - print e.blog # Doesn't hit the database; uses cached version. - -``select_related()`` is documented in the `QuerySet methods that return new QuerySets`_ section above. - -Backward -~~~~~~~~ - -If a model has a ``ForeignKey``, instances of the foreign-key model will have -access to a ``Manager`` that returns all instances of the first model. By -default, this ``Manager`` is named ``FOO_set``, where ``FOO`` is the source -model name, lowercased. This ``Manager`` returns ``QuerySets``, which can be -filtered and manipulated as described in the "Retrieving objects" section -above. - -Example:: - - b = Blog.objects.get(id=1) - b.entry_set.all() # Returns all Entry objects related to Blog. - - # b.entry_set is a Manager that returns QuerySets. - b.entry_set.filter(headline__contains='Lennon') - b.entry_set.count() - -You can override the ``FOO_set`` name by setting the ``related_name`` -parameter in the ``ForeignKey()`` definition. For example, if the ``Entry`` -model was altered to ``blog = ForeignKey(Blog, related_name='entries')``, the -above example code would look like this:: - - b = Blog.objects.get(id=1) - b.entries.all() # Returns all Entry objects related to Blog. - - # b.entries is a Manager that returns QuerySets. - b.entries.filter(headline__contains='Lennon') - b.entries.count() - -You cannot access a reverse ``ForeignKey`` ``Manager`` from the class; it must -be accessed from an instance. Example:: - - Blog.entry_set # Raises AttributeError: "Manager must be accessed via instance". - -In addition to the ``QuerySet`` methods defined in "Retrieving objects" above, -the ``ForeignKey`` ``Manager`` has these additional methods: - - * ``add(obj1, obj2, ...)``: Adds the specified model objects to the related - object set. - - Example:: - - b = Blog.objects.get(id=1) - e = Entry.objects.get(id=234) - b.entry_set.add(e) # Associates Entry e with Blog b. - - * ``create(**kwargs)``: Creates a new object, saves it and puts it in the - related object set. Returns the newly created object. - - Example:: - - b = Blog.objects.get(id=1) - e = b.entry_set.create(headline='Hello', body_text='Hi', pub_date=datetime.date(2005, 1, 1)) - # No need to call e.save() at this point -- it's already been saved. - - This is equivalent to (but much simpler than):: - - b = Blog.objects.get(id=1) - e = Entry(blog=b, headline='Hello', body_text='Hi', pub_date=datetime.date(2005, 1, 1)) - e.save() - - Note that there's no need to specify the keyword argument of the model - that defines the relationship. In the above example, we don't pass the - parameter ``blog`` to ``create()``. Django figures out that the new - ``Entry`` object's ``blog`` field should be set to ``b``. - - * ``remove(obj1, obj2, ...)``: Removes the specified model objects from the - related object set. - - Example:: - - b = Blog.objects.get(id=1) - e = Entry.objects.get(id=234) - b.entry_set.remove(e) # Disassociates Entry e from Blog b. - - In order to prevent database inconsistency, this method only exists on - ``ForeignKey`` objects where ``null=True``. If the related field can't be - set to ``None`` (``NULL``), then an object can't be removed from a - relation without being added to another. In the above example, removing - ``e`` from ``b.entry_set()`` is equivalent to doing ``e.blog = None``, - and because the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this - is invalid. - - * ``clear()``: Removes all objects from the related object set. - - Example:: - - b = Blog.objects.get(id=1) - b.entry_set.clear() - - Note this doesn't delete the related objects -- it just disassociates - them. - - Just like ``remove()``, ``clear()`` is only available on ``ForeignKey``s - where ``null=True``. - -To assign the members of a related set in one fell swoop, just assign to it -from any iterable object. Example:: - - b = Blog.objects.get(id=1) - b.entry_set = [e1, e2] - -If the ``clear()`` method is available, any pre-existing objects will be -removed from the ``entry_set`` before all objects in the iterable (in this -case, a list) are added to the set. If the ``clear()`` method is *not* -available, all objects in the iterable will be added without removing any -existing elements. - -Each "reverse" operation described in this section has an immediate effect on -the database. Every addition, creation and deletion is immediately and -automatically saved to the database. - -One-to-one relationships ------------------------- - -One-to-one relationships are very similar to many-to-one relationships. -If you define a OneToOneField on your model, instances of that model will have -access to the related object via a simple attribute of the model. - -For example:: - - class EntryDetail(models.Model): - entry = models.OneToOneField(Entry) - details = models.TextField() - - ed = EntryDetail.objects.get(id=2) - ed.entry # Returns the related Entry object. - -The difference comes in "reverse" queries. The related model in a one-to-one -relationship also has access to a ``Manager`` object, but that ``Manager`` -represents a single object, rather than a collection of objects:: - - e = Entry.objects.get(id=2) - e.entrydetail # returns the related EntryDetail object - -If no object has been assigned to this relationship, Django will raise -a ``DoesNotExist`` exception. - -Instances can be assigned to the reverse relationship in the same way as -you would assign the forward relationship:: - - e.entrydetail = ed - -Many-to-many relationships --------------------------- - -Both ends of a many-to-many relationship get automatic API access to the other -end. The API works just as a "backward" one-to-many relationship. See Backward_ -above. - -The only difference is in the attribute naming: The model that defines the -``ManyToManyField`` uses the attribute name of that field itself, whereas the -"reverse" model uses the lowercased model name of the original model, plus -``'_set'`` (just like reverse one-to-many relationships). - -An example makes this easier to understand:: - - e = Entry.objects.get(id=3) - e.authors.all() # Returns all Author objects for this Entry. - e.authors.count() - e.authors.filter(name__contains='John') - - a = Author.objects.get(id=5) - a.entry_set.all() # Returns all Entry objects for this Author. - -Like ``ForeignKey``, ``ManyToManyField`` can specify ``related_name``. In the -above example, if the ``ManyToManyField`` in ``Entry`` had specified -``related_name='entries'``, then each ``Author`` instance would have an -``entries`` attribute instead of ``entry_set``. - -How are the backward relationships possible? --------------------------------------------- - -Other object-relational mappers require you to define relationships on both -sides. The Django developers believe this is a violation of the DRY (Don't -Repeat Yourself) principle, so Django only requires you to define the -relationship on one end. - -But how is this possible, given that a model class doesn't know which other -model classes are related to it until those other model classes are loaded? - -The answer lies in the ``INSTALLED_APPS`` setting. The first time any model is -loaded, Django iterates over every model in ``INSTALLED_APPS`` and creates the -backward relationships in memory as needed. Essentially, one of the functions -of ``INSTALLED_APPS`` is to tell Django the entire model domain. - -Queries over related objects ----------------------------- - -Queries involving related objects follow the same rules as queries involving -normal value fields. When specifying the the value for a query to match, you -may use either an object instance itself, or the primary key value for the -object. - -For example, if you have a Blog object ``b`` with ``id=5``, the following -three queries would be identical:: - - Entry.objects.filter(blog=b) # Query using object instance - Entry.objects.filter(blog=b.id) # Query using id from instance - Entry.objects.filter(blog=5) # Query using id directly - -Deleting objects -================ - -The delete method, conveniently, is named ``delete()``. This method immediately -deletes the object and has no return value. Example:: - - e.delete() - -You can also delete objects in bulk. Every ``QuerySet`` has a ``delete()`` -method, which deletes all members of that ``QuerySet``. - -For example, this deletes all ``Entry`` objects with a ``pub_date`` year of -2005:: - - Entry.objects.filter(pub_date__year=2005).delete() - -Keep in mind that this will, whenever possible, be executed purely in -SQL, and so the ``delete()`` methods of individual object instances -will not necessarily be called during the process. If you've provided -a custom ``delete()`` method on a model class and want to ensure that -it is called, you will need to "manually" delete instances of that -model (e.g., by iterating over a ``QuerySet`` and calling ``delete()`` -on each object individually) rather than using the bulk ``delete()`` -method of a ``QuerySet``. - -When Django deletes an object, it emulates the behavior of the SQL -constraint ``ON DELETE CASCADE`` -- in other words, any objects which -had foreign keys pointing at the object to be deleted will be deleted -along with it. For example:: - - b = Blog.objects.get(pk=1) - # This will delete the Blog and all of its Entry objects. - b.delete() - -Note that ``delete()`` is the only ``QuerySet`` method that is not exposed on a -``Manager`` itself. This is a safety mechanism to prevent you from accidentally -requesting ``Entry.objects.delete()``, and deleting *all* the entries. If you -*do* want to delete all the objects, then you have to explicitly request a -complete query set:: - - Entry.objects.all().delete() - -Updating multiple objects at once -================================= - -**New in Django development version** - -Sometimes you want to set a field to a particular value for all the objects in -a ``QuerySet``. You can do this with the ``update()`` method. For example:: - - # Update all the headlines with pub_date in 2007. - Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same') - -You can only set non-relation fields and ``ForeignKey`` fields using this -method, and the value you set the field to must be a hard-coded Python value -(i.e., you can't set a field to be equal to some other field at the moment). - -To update ``ForeignKey`` fields, set the new value to be the new model -instance you want to point to. Example:: - - b = Blog.objects.get(pk=1) - # Change every Entry so that it belongs to this Blog. - Entry.objects.all().update(blog=b) - -The ``update()`` method is applied instantly and doesn't return anything -(similar to ``delete()``). The only restriction on the ``QuerySet`` that is -updated is that it can only access one database table, the model's main -table. So don't try to filter based on related fields or anything like that; -it won't work. - -Be aware that the ``update()`` method is converted directly to an SQL -statement. It is a bulk operation for direct updates. It doesn't run any -``save()`` methods on your models, or emit the ``pre_save`` or ``post_save`` -signals (which are a consequence of calling ``save()``). If you want to save -every item in a ``QuerySet`` and make sure that the ``save()`` method is -called on each instance, you don't need any special function to handle that. -Just loop over them and call ``save()``:: - - for item in my_queryset: - item.save() - - -Extra instance methods -====================== - -In addition to ``save()``, ``delete()``, a model object might get any or all -of the following methods: - -get_FOO_display() ------------------ - -For every field that has ``choices`` set, the object will have a -``get_FOO_display()`` method, where ``FOO`` is the name of the field. This -method returns the "human-readable" value of the field. For example, in the -following model:: - - GENDER_CHOICES = ( - ('M', 'Male'), - ('F', 'Female'), - ) - class Person(models.Model): - name = models.CharField(max_length=20) - gender = models.CharField(max_length=1, choices=GENDER_CHOICES) - -...each ``Person`` instance will have a ``get_gender_display()`` method. Example:: - - >>> p = Person(name='John', gender='M') - >>> p.save() - >>> p.gender - 'M' - >>> p.get_gender_display() - 'Male' - -get_next_by_FOO(\**kwargs) and get_previous_by_FOO(\**kwargs) -------------------------------------------------------------- - -For every ``DateField`` and ``DateTimeField`` that does not have ``null=True``, -the object will have ``get_next_by_FOO()`` and ``get_previous_by_FOO()`` -methods, where ``FOO`` is the name of the field. This returns the next and -previous object with respect to the date field, raising the appropriate -``DoesNotExist`` exception when appropriate. - -Both methods accept optional keyword arguments, which should be in the format -described in `Field lookups`_ above. - -Note that in the case of identical date values, these methods will use the ID -as a fallback check. This guarantees that no records are skipped or duplicated. -For a full example, see the `lookup API sample model`_. - -.. _lookup API sample model: ../models/lookup/ - - -Shortcuts -========= - -As you develop views, you will discover a number of common idioms in the -way you use the database API. Django encodes some of these idioms as -shortcuts that can be used to simplify the process of writing views. These -functions are in the ``django.shortcuts`` module. - -get_object_or_404() -------------------- - -One common idiom to use ``get()`` and raise ``Http404`` if the -object doesn't exist. This idiom is captured by ``get_object_or_404()``. -This function takes a Django model as its first argument and an -arbitrary number of keyword arguments, which it passes to the default -manager's ``get()`` function. It raises ``Http404`` if the object doesn't -exist. For example:: - - # Get the Entry with a primary key of 3 - e = get_object_or_404(Entry, pk=3) - -When you provide a model to this shortcut function, the default manager -is used to execute the underlying ``get()`` query. If you don't want to -use the default manager, or if you want to search a list of related objects, -you can provide ``get_object_or_404()`` with a ``Manager`` object instead. -For example:: - - # Get the author of blog instance e with a name of 'Fred' - a = get_object_or_404(e.authors, name='Fred') - - # Use a custom manager 'recent_entries' in the search for an - # entry with a primary key of 3 - e = get_object_or_404(Entry.recent_entries, pk=3) - -**New in Django development version:** The first argument to -``get_object_or_404()`` can be a ``QuerySet`` object. This is useful in cases -where you've defined a custom manager method. For example:: - - # Use a QuerySet returned from a 'published' method of a custom manager - # in the search for an entry with primary key of 5 - e = get_object_or_404(Entry.objects.published(), pk=5) - -get_list_or_404() ------------------ - -``get_list_or_404`` behaves the same way as ``get_object_or_404()`` --- except that it uses ``filter()`` instead of ``get()``. It raises -``Http404`` if the list is empty. - -Falling back to raw SQL -======================= - -If you find yourself needing to write an SQL query that is too complex for -Django's database-mapper to handle, you can fall back into raw-SQL statement -mode. - -The preferred way to do this is by giving your model custom methods or custom -manager methods that execute queries. Although there's nothing in Django that -*requires* database queries to live in the model layer, this approach keeps all -your data-access logic in one place, which is smart from an code-organization -standpoint. For instructions, see `Executing custom SQL`_. - -Finally, it's important to note that the Django database layer is merely an -interface to your database. You can access your database via other tools, -programming languages or database frameworks; there's nothing Django-specific -about your database. - -.. _Executing custom SQL: ../model-api/#executing-custom-sql diff --git a/docs/documentation.txt b/docs/documentation.txt deleted file mode 100644 index decb066fa1..0000000000 --- a/docs/documentation.txt +++ /dev/null @@ -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/ diff --git a/docs/faq.txt b/docs/faq.txt deleted file mode 100644 index 2c1ffa72db..0000000000 --- a/docs/faq.txt +++ /dev/null @@ -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. - - does -- 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 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__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 `` - - -Here's a list of all possible ``Media`` options. There are no required options. - -``css`` -~~~~~~~ - -A dictionary describing the CSS files required for various forms of output -media. - -The values in the dictionary should be a tuple/list of file names. See -`the section on media paths`_ for details of how to specify paths to media -files. - -.. _the section on media paths: `Paths in media definitions`_ - -The keys in the dictionary are the output media types. These are the same -types accepted by CSS files in media declarations: 'all', 'aural', 'braille', -'embossed', 'handheld', 'print', 'projection', 'screen', 'tty' and 'tv'. If -you need to have different stylesheets for different media types, provide -a list of CSS files for each output medium. The following example would -provide two CSS options -- one for the screen, and one for print:: - - class Media: - css = { - 'screen': ('pretty.css',), - 'print': ('newspaper.css',) - } - -If a group of CSS files are appropriate for multiple output media types, -the dictionary key can be a comma separated list of output media types. -In the following example, TV's and projectors will have the same media -requirements:: - - class Media: - css = { - 'screen': ('pretty.css',), - 'tv,projector': ('lo_res.css',), - 'print': ('newspaper.css',) - } - -If this last CSS definition were to be rendered, it would become the following HTML:: - - - - - -``js`` -~~~~~~ - -A tuple describing the required JavaScript files. See -`the section on media paths`_ for details of how to specify paths to media -files. - -``extend`` -~~~~~~~~~~ - -A boolean defining inheritance behavior for media declarations. - -By default, any object using a static media definition will inherit all the -media associated with the parent widget. This occurs regardless of how the -parent defines its media requirements. For example, if we were to extend our -basic Calendar widget from the example above:: - - class FancyCalendarWidget(CalendarWidget): - class Media: - css = { - 'all': ('fancy.css',) - } - js = ('whizbang.js',) - - >>> w = FancyCalendarWidget() - >>> print w.media - - - - - - -The FancyCalendar widget inherits all the media from it's parent widget. If -you don't want media to be inherited in this way, add an ``extend=False`` -declaration to the media declaration:: - - class FancyCalendar(Calendar): - class Media: - extend = False - css = { - 'all': ('fancy.css',) - } - js = ('whizbang.js',) - - >>> w = FancyCalendarWidget() - >>> print w.media - - - -If you require even more control over media inheritance, define your media -using a `dynamic property`_. Dynamic properties give you complete control over -which media files are inherited, and which are not. - -.. _dynamic property: `Media as a dynamic property`_ - -Media as a dynamic property ---------------------------- - -If you need to perform some more sophisticated manipulation of media -requirements, you can define the media property directly. This is done -by defining a model property that returns an instance of ``forms.Media``. -The constructor for ``forms.Media`` accepts ``css`` and ``js`` keyword -arguments in the same format as that used in a static media definition. - -For example, the static media definition for our Calendar Widget could -also be defined in a dynamic fashion:: - - class CalendarWidget(forms.TextInput): - def _media(self): - return forms.Media(css={'all': ('pretty.css',)}, - js=('animations.js', 'actions.js')) - media = property(_media) - -See the section on `Media objects`_ for more details on how to construct -return values for dynamic media properties. - -Paths in media definitions --------------------------- - -Paths used to specify media can be either relative or absolute. If a path -starts with '/', 'http://' or 'https://', it will be interpreted as an absolute -path, and left as-is. All other paths will be prepended with the value of -``settings.MEDIA_URL``. For example, if the MEDIA_URL for your site was -``http://media.example.com/``:: - - class CalendarWidget(forms.TextInput): - class Media: - css = { - 'all': ('/css/pretty.css',), - } - js = ('animations.js', 'http://othersite.com/actions.js') - - >>> w = CalendarWidget() - >>> print w.media - - - - -Media objects -------------- - -When you interrogate the media attribute of a widget or form, the value that -is returned is a ``forms.Media`` object. As we have already seen, the string -representation of a Media object is the HTML required to include media -in the ```` block of your HTML page. - -However, Media objects have some other interesting properties. - -Media subsets -~~~~~~~~~~~~~ - -If you only want media of a particular type, you can use the subscript operator -to filter out a medium of interest. For example:: - - >>> w = CalendarWidget() - >>> print w.media - - - - - >>> print w.media['css'] - - -When you use the subscript operator, the value that is returned is a new -Media object -- but one that only contains the media of interest. - -Combining media objects -~~~~~~~~~~~~~~~~~~~~~~~ - -Media objects can also be added together. When two media objects are added, -the resulting Media object contains the union of the media from both files:: - - class CalendarWidget(forms.TextInput): - class Media: - css = { - 'all': ('pretty.css',) - } - js = ('animations.js', 'actions.js') - - class OtherWidget(forms.TextInput): - class Media: - js = ('whizbang.js',) - - >>> w1 = CalendarWidget() - >>> w2 = OtherWidget() - >>> print w1.media + w2.media - - - - - -Media on Forms --------------- - -Widgets aren't the only objects that can have media definitions -- forms -can also define media. The rules for media definitions on forms are the -same as the rules for widgets: declarations can be static or dynamic; -path and inheritance rules for those declarations are exactly the same. - -Regardless of whether you define a media declaration, *all* Form objects -have a media property. The default value for this property is the result -of adding the media definitions for all widgets that are part of the form:: - - class ContactForm(forms.Form): - date = DateField(widget=CalendarWidget) - name = CharField(max_length=40, widget=OtherWidget) - - >>> f = ContactForm() - >>> f.media - - - - - -If you want to associate additional media with a form -- for example, CSS for form -layout -- simply add a media declaration to the form:: - - class ContactForm(forms.Form): - date = DateField(widget=CalendarWidget) - name = CharField(max_length=40, widget=OtherWidget) - - class Media: - css = { - 'all': ('layout.css',) - } - - >>> f = ContactForm() - >>> f.media - - - - - - -Formsets -======== - -A formset is a layer of abstraction to working with multiple forms on the same -page. It can be best compared to a data grid. Let's say you have the following -form:: - - >>> from django import forms - >>> class ArticleForm(forms.Form): - ... title = forms.CharField() - ... pub_date = forms.DateField() - -You might want to allow the user to create several articles at once. To create -a formset out of an ``ArticleForm`` you would do:: - - >>> from django.forms.formsets import formset_factory - >>> ArticleFormSet = formset_factory(ArticleForm) - -You now have created a formset named ``ArticleFormSet``. The formset gives you -the ability to iterate over the forms in the formset and display them as you -would with a regular form:: - - >>> formset = ArticleFormSet() - >>> for form in formset.forms: - ... print form.as_table() - - - -As you can see it only displayed one form. This is because by default the -``formset_factory`` defines one extra form. This can be controlled with the -``extra`` parameter:: - - >>> ArticleFormSet = formset_factory(ArticleForm, extra=2) - -Using initial data with a formset ---------------------------------- - -Initial data is what drives the main usability of a formset. As shown above -you can define the number of extra forms. What this means is that you are -telling the formset how many additional forms to show in addition to the -number of forms it generates from the initial data. Lets take a look at an -example:: - - >>> ArticleFormSet = formset_factory(ArticleForm, extra=2) - >>> formset = ArticleFormSet(initial=[ - ... {'title': u'Django is now open source', - ... 'pub_date': datetime.date.today()}, - ... ]) - - >>> for form in formset.forms: - ... print form.as_table() - - - - - - - -There are now a total of three forms showing above. One for the initial data -that was passed in and two extra forms. Also note that we are passing in a -list of dictionaries as the initial data. - -Limiting the maximum number of forms ------------------------------------- - -The ``max_num`` parameter to ``formset_factory`` gives you the ability to -force the maximum number of forms the formset will display:: - - >>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1) - >>> formset = ArticleFormset() - >>> for form in formset.forms: - ... print form.as_table() - - - -The default value of ``max_num`` is ``0`` which is the same as saying put no -limit on the number forms displayed. - -Formset validation ------------------- - -Validation with a formset is about identical to a regular ``Form``. There is -an ``is_valid`` method on the formset to provide a convenient way to validate -each form in the formset:: - - >>> ArticleFormSet = formset_factory(ArticleForm) - >>> formset = ArticleFormSet({}) - >>> formset.is_valid() - True - -We passed in no data to the formset which is resulting in a valid form. The -formset is smart enough to ignore extra forms that were not changed. If we -attempt to provide an article, but fail to do so:: - - >>> data = { - ... 'form-TOTAL_FORMS': u'1', - ... 'form-INITIAL_FORMS': u'1', - ... 'form-0-title': u'Test', - ... 'form-0-pub_date': u'', - ... } - >>> formset = ArticleFormSet(data) - >>> formset.is_valid() - False - >>> formset.errors - [{'pub_date': [u'This field is required.']}] - -As we can see the formset properly performed validation and gave us the -expected errors. - -Understanding the ManagementForm -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You may have noticed the additional data that was required in the formset's -data above. This data is coming from the ``ManagementForm``. This form is -dealt with internally to the formset. If you don't use it, it will result in -an exception:: - - >>> data = { - ... 'form-0-title': u'Test', - ... 'form-0-pub_date': u'', - ... } - >>> formset = ArticleFormSet(data) - Traceback (most recent call last): - ... - django.forms.util.ValidationError: [u'ManagementForm data is missing or has been tampered with'] - -It is used to keep track of how many form instances are being displayed. If -you are adding new forms via JavaScript, you should increment the count fields -in this form as well. - -Custom formset validation -~~~~~~~~~~~~~~~~~~~~~~~~~ - -A formset has a ``clean`` method similar to the one on a ``Form`` class. This -is where you define your own validation that deals at the formset level:: - - >>> from django.forms.formsets import BaseFormSet - - >>> class BaseArticleFormSet(BaseFormSet): - ... def clean(self): - ... raise forms.ValidationError, u'An error occured.' - - >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet) - >>> formset = ArticleFormSet({}) - >>> formset.is_valid() - False - >>> formset.non_form_errors() - [u'An error occured.'] - -The formset ``clean`` method is called after all the ``Form.clean`` methods -have been called. The errors will be found using the ``non_form_errors()`` -method on the formset. - -Dealing with ordering and deletion of forms -------------------------------------------- - -Common use cases with a formset is dealing with ordering and deletion of the -form instances. This has been dealt with for you. The ``formset_factory`` -provides two optional parameters ``can_order`` and ``can_delete`` that will do -the extra work of adding the extra fields and providing simpler ways of -getting to that data. - -``can_order`` -~~~~~~~~~~~~~ - -Default: ``False`` - -Lets create a formset with the ability to order:: - - >>> ArticleFormSet = formset_factory(ArticleForm, can_order=True) - >>> formset = ArticleFormSet(initial=[ - ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, - ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, - ... ]) - >>> for form in formset.forms: - ... print form.as_table() - - - - - - - - - - -This adds an additional field to each form. This new field is named ``ORDER`` -and is an ``forms.IntegerField``. For the forms that came from the initial -data it automatically assigned them a numeric value. Lets look at what will -happen when the user changes these values:: - - >>> data = { - ... 'form-TOTAL_FORMS': u'3', - ... 'form-INITIAL_FORMS': u'2', - ... 'form-0-title': u'Article #1', - ... 'form-0-pub_date': u'2008-05-10', - ... 'form-0-ORDER': u'2', - ... 'form-1-title': u'Article #2', - ... 'form-1-pub_date': u'2008-05-11', - ... 'form-1-ORDER': u'1', - ... 'form-2-title': u'Article #3', - ... 'form-2-pub_date': u'2008-05-01', - ... 'form-2-ORDER': u'0', - ... } - - >>> formset = ArticleFormSet(data, initial=[ - ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, - ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, - ... ]) - >>> formset.is_valid() - True - >>> for form in formset.ordered_forms: - ... print form.cleaned_data - {'pub_date': datetime.date(2008, 5, 1), 'ORDER': 0, 'title': u'Article #3'} - {'pub_date': datetime.date(2008, 5, 11), 'ORDER': 1, 'title': u'Article #2'} - {'pub_date': datetime.date(2008, 5, 10), 'ORDER': 2, 'title': u'Article #1'} - -``can_delete`` -~~~~~~~~~~~~~~ - -Default: ``False`` - -Lets create a formset with the ability to delete:: - - >>> ArticleFormSet = formset_factory(ArticleForm, can_delete=True) - >>> formset = ArticleFormSet(initial=[ - ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, - ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, - ... ]) - >>> for form in formset.forms: - .... print form.as_table() - - - - - - - - - - - -Similar to ``can_order`` this adds a new field to each form named ``DELETE`` -and is a ``forms.BooleanField``. When data comes through marking any of the -delete fields you can access them with ``deleted_forms``:: - - >>> data = { - ... 'form-TOTAL_FORMS': u'3', - ... 'form-INITIAL_FORMS': u'2', - ... 'form-0-title': u'Article #1', - ... 'form-0-pub_date': u'2008-05-10', - ... 'form-0-DELETE': u'on', - ... 'form-1-title': u'Article #2', - ... 'form-1-pub_date': u'2008-05-11', - ... 'form-1-DELETE': u'', - ... 'form-2-title': u'', - ... 'form-2-pub_date': u'', - ... 'form-2-DELETE': u'', - ... } - - >>> formset = ArticleFormSet(data, initial=[ - ... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)}, - ... {'title': u'Article #2', 'pub_date': datetime.date(2008, 5, 11)}, - ... ]) - >>> [form.cleaned_data for form in formset.deleted_forms] - [{'DELETE': True, 'pub_date': datetime.date(2008, 5, 10), 'title': u'Article #1'}] - -Adding additional fields to a formset -------------------------------------- - -If you need to add additional fields to the formset this can be easily -accomplished. The formset base class provides an ``add_fields`` method. You -can simply override this method to add your own fields or even redefine the -default fields/attributes of the order and deletion fields:: - - >>> class BaseArticleFormSet(BaseFormSet): - ... def add_fields(self, form, index): - ... super(BaseArticleFormSet, self).add_fields(form, index) - ... form.fields["my_field"] = forms.CharField() - - >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet) - >>> formset = ArticleFormSet() - >>> for form in formset.forms: - ... print form.as_table() - - - - -Using a formset in views and templates --------------------------------------- - -Using a formset inside a view is as easy as using a regular ``Form`` class. -The only thing you will want to be aware of is making sure to use the -management form inside the template. Lets look at a sample view:: - - def manage_articles(request): - ArticleFormSet = formset_factory(ArticleForm) - if request.method == 'POST': - formset = ArticleFormSet(request.POST, request.FILES) - if formset.is_valid(): - # do something with the formset.cleaned_data - else: - formset = ArticleFormSet() - return render_to_response('manage_articles.html', {'formset': formset}) - -The ``manage_articles.html`` template might look like this:: - -
- {{ formset.management_form }} - - {% for form in formset.forms %} - {{ form }} - {% endfor %} -
-
- -However the above can be slightly shortcutted and let the formset itself deal -with the management form:: - -
- - {{ formset }} -
-
- -The above ends up calling the ``as_table`` method on the formset class. diff --git a/docs/generic_views.txt b/docs/generic_views.txt deleted file mode 100644 index 8c0fec2ded..0000000000 --- a/docs/generic_views.txt +++ /dev/null @@ -1,1273 +0,0 @@ -============= -Generic views -============= - -Writing Web applications can be monotonous, because we repeat certain patterns -again and again. In Django, the most common of these patterns have been -abstracted into "generic views" that let you quickly provide common views of -an object without actually needing to write any Python code. - -Django's generic views contain the following: - - * A set of views for doing list/detail interfaces (for example, - Django's `documentation index`_ and `detail pages`_). - - * A set of views for year/month/day archive pages and associated - detail and "latest" pages (for example, the Django weblog's year_, - month_, day_, detail_, and latest_ pages). - - * A set of views for creating, editing, and deleting objects. - -.. _`documentation index`: http://www.djangoproject.com/documentation/ -.. _`detail pages`: http://www.djangoproject.com/documentation/faq/ -.. _year: http://www.djangoproject.com/weblog/2005/ -.. _month: http://www.djangoproject.com/weblog/2005/jul/ -.. _day: http://www.djangoproject.com/weblog/2005/jul/20/ -.. _detail: http://www.djangoproject.com/weblog/2005/jul/20/autoreload/ -.. _latest: http://www.djangoproject.com/weblog/ - -All of these views are used by creating configuration dictionaries in -your URLconf files and passing those dictionaries as the third member of the -URLconf tuple for a given pattern. For example, here's the URLconf for the -simple weblog app that drives the blog on djangoproject.com:: - - from django.conf.urls.defaults import * - from django_website.apps.blog.models import Entry - - info_dict = { - 'queryset': Entry.objects.all(), - 'date_field': 'pub_date', - } - - urlpatterns = patterns('django.views.generic.date_based', - (r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/(?P[-\w]+)/$', 'object_detail', info_dict), - (r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/$', 'archive_day', info_dict), - (r'^(?P\d{4})/(?P[a-z]{3})/$', 'archive_month', info_dict), - (r'^(?P\d{4})/$', 'archive_year', info_dict), - (r'^$', 'archive_index', info_dict), - ) - -As you can see, this URLconf defines a few options in ``info_dict``. -``'queryset'`` gives the generic view a ``QuerySet`` of objects to use (in this -case, all of the ``Entry`` objects) and tells the generic view which model is -being used. - -Documentation of each generic view follows, along with a list of all keyword -arguments that a generic view expects. Remember that as in the example above, -arguments may either come from the URL pattern (as ``month``, ``day``, -``year``, etc. do above) or from the additional-information dictionary (as for -``queryset``, ``date_field``, etc.). - -Most generic views require the ``queryset`` key, which is a ``QuerySet`` -instance; see the `database API docs`_ for more information about ``Queryset`` -objects. - -Most views also take an optional ``extra_context`` dictionary that you can use -to pass any auxiliary information you wish to the view. The values in the -``extra_context`` dictionary can be either functions (or other callables) or -other objects. Functions are evaluated just before they are passed to the -template. However, note that QuerySets retrieve and cache their data when they -are first evaluated, so if you want to pass in a QuerySet via -``extra_context`` that is always fresh you need to wrap it in a function or -lambda that returns the QuerySet. - -.. _database API docs: ../db-api/ - -"Simple" generic views -====================== - -The ``django.views.generic.simple`` module contains simple views to handle a -couple of common cases: rendering a template when no view logic is needed, -and issuing a redirect. - -``django.views.generic.simple.direct_to_template`` --------------------------------------------------- - -Description -~~~~~~~~~~~ - -Renders a given template, passing it a ``{{ params }}`` template variable, -which is a dictionary of the parameters captured in the URL. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``template`` - The full name of a template to use. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -**Example:** - -Given the following URL patterns:: - - urlpatterns = patterns('django.views.generic.simple', - (r'^foo/$', 'direct_to_template', {'template': 'foo_index.html'}), - (r'^foo/(?P\d+)/$', 'direct_to_template', {'template': 'foo_detail.html'}), - ) - -... a request to ``/foo/`` would render the template ``foo_index.html``, and a -request to ``/foo/15/`` would render the ``foo_detail.html`` with a context -variable ``{{ params.id }}`` that is set to ``15``. - -``django.views.generic.simple.redirect_to`` -------------------------------------------- - -Description -~~~~~~~~~~~ - -Redirects to a given URL. - -The given URL may contain dictionary-style string formatting, which will be -interpolated against the parameters captured in the URL. - -If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410). - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``url`` - The URL to redirect to, as a string. Or ``None`` to raise a 410 (Gone) - HTTP error. - -**Example:** - -This example redirects from ``/foo//`` to ``/bar//``:: - - urlpatterns = patterns('django.views.generic.simple', - ('^foo/(?P\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}), - ) - -This example returns a 410 HTTP error for requests to ``/bar/``:: - - urlpatterns = patterns('django.views.generic.simple', - ('^bar/$', 'redirect_to', {'url': None}), - ) - -Date-based generic views -======================== - -Date-based generic views (in the module ``django.views.generic.date_based``) -are views for displaying drilldown pages for date-based data. - -``django.views.generic.date_based.archive_index`` -------------------------------------------------- - -Description -~~~~~~~~~~~ - -A top-level index page showing the "latest" objects, by date. Objects with -a date in the *future* are not included unless you set ``allow_future`` to -``True``. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``queryset`` - A ``QuerySet`` of objects for which the archive serves. - -``date_field`` - The name of the ``DateField`` or ``DateTimeField`` in the ``QuerySet``'s - model that the date-based archive should use to determine the objects on - the page. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``num_latest`` - The number of latest objects to send to the template context. By default, - it's 15. - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``allow_empty`` - A boolean specifying whether to display the page if no objects are - available. If this is ``False`` and no objects are available, the view will - raise a 404 instead of displaying an empty page. By default, this is - ``True``. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -``allow_future`` - A boolean specifying whether to include "future" objects on this page, - where "future" means objects in which the field specified in ``date_field`` - is greater than the current date/time. By default, this is ``False``. - -``template_object_name`` (**New in Django development version**) - Designates the name of the template variable to use in the template - context. By default, this is ``'latest'``. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_archive.html`` by default, where: - - * ```` is your model's name in all lowercase. For a model - ``StaffMember``, that'd be ``staffmember``. - - * ```` is the right-most part of the full Python path to - your model's app. For example, if your model lives in - ``apps/blog/models.py``, that'd be ``blog``. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``date_list`` - A list of ``datetime.date`` objects representing all years that have - objects available according to ``queryset``. These are ordered in reverse. - This is equivalent to ``queryset.dates(date_field, 'year')[::-1]``. - -``latest`` - The ``num_latest`` objects in the system, ordered descending by - ``date_field``. For example, if ``num_latest`` is ``10``, then ``latest`` - will be a list of the latest 10 objects in ``queryset``. - - **New in Django development version:** This variable's name depends on the - ``template_object_name`` parameter, which is ``'latest'`` by default. - If ``template_object_name`` is ``'foo'``, this variable's name will be - ``foo``. - -.. _RequestContext docs: ../templates_python/#subclassing-context-requestcontext - -``django.views.generic.date_based.archive_year`` ------------------------------------------------- - -Description -~~~~~~~~~~~ - -A yearly archive page showing all available months in a given year. Objects -with a date in the *future* are not displayed unless you set ``allow_future`` -to ``True``. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``year`` - The four-digit year for which the archive serves. - -``queryset`` - A ``QuerySet`` of objects for which the archive serves. - -``date_field`` - The name of the ``DateField`` or ``DateTimeField`` in the ``QuerySet``'s - model that the date-based archive should use to determine the objects on - the page. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``allow_empty`` - A boolean specifying whether to display the page if no objects are - available. If this is ``False`` and no objects are available, the view will - raise a 404 instead of displaying an empty page. By default, this is - ``False``. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. The view will append ``'_list'`` - to the value of this parameter in determining the variable's name. - -``make_object_list`` - A boolean specifying whether to retrieve the full list of objects for this - year and pass those to the template. If ``True``, this list of objects will - be made available to the template as ``object_list``. (The name - ``object_list`` may be different; see the docs for ``object_list`` in the - "Template context" section below.) By default, this is ``False``. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -``allow_future`` - A boolean specifying whether to include "future" objects on this page, - where "future" means objects in which the field specified in ``date_field`` - is greater than the current date/time. By default, this is ``False``. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_archive_year.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``date_list`` - A list of ``datetime.date`` objects representing all months that have - objects available in the given year, according to ``queryset``, in - ascending order. - -``year`` - The given year, as a four-character string. - -``object_list`` - If the ``make_object_list`` parameter is ``True``, this will be set to a - list of objects available for the given year, ordered by the date field. - This variable's name depends on the ``template_object_name`` parameter, - which is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, - this variable's name will be ``foo_list``. - - If ``make_object_list`` is ``False``, ``object_list`` will be passed to the - template as an empty list. - -``django.views.generic.date_based.archive_month`` -------------------------------------------------- - -Description -~~~~~~~~~~~ - -A monthly archive page showing all objects in a given month. Objects with a -date in the *future* are not displayed unless you set ``allow_future`` to -``True``. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``year`` - The four-digit year for which the archive serves (a string). - -``month`` - The month for which the archive serves, formatted according to the - ``month_format`` argument. - -``queryset`` - A ``QuerySet`` of objects for which the archive serves. - -``date_field`` - The name of the ``DateField`` or ``DateTimeField`` in the ``QuerySet``'s - model that the date-based archive should use to determine the objects on - the page. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``month_format`` - A format string that regulates what format the ``month`` parameter uses. - This should be in the syntax accepted by Python's ``time.strftime``. (See - the `strftime docs`_.) It's set to ``"%b"`` by default, which is a three- - letter month abbreviation. To change it to use numbers, use ``"%m"``. - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``allow_empty`` - A boolean specifying whether to display the page if no objects are - available. If this is ``False`` and no objects are available, the view will - raise a 404 instead of displaying an empty page. By default, this is - ``False``. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. The view will append ``'_list'`` - to the value of this parameter in determining the variable's name. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -``allow_future`` - A boolean specifying whether to include "future" objects on this page, - where "future" means objects in which the field specified in ``date_field`` - is greater than the current date/time. By default, this is ``False``. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_archive_month.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``month`` - A ``datetime.date`` object representing the given month. - -``next_month`` - A ``datetime.date`` object representing the first day of the next month. If - the next month is in the future, this will be ``None``. - -``previous_month`` - A ``datetime.date`` object representing the first day of the previous - month. Unlike ``next_month``, this will never be ``None``. - -``object_list`` - A list of objects available for the given month. This variable's name - depends on the ``template_object_name`` parameter, which is ``'object'`` by - default. If ``template_object_name`` is ``'foo'``, this variable's name - will be ``foo_list``. - -.. _strftime docs: http://www.python.org/doc/current/lib/module-time.html#l2h-1941 - -``django.views.generic.date_based.archive_week`` ------------------------------------------------- - -Description -~~~~~~~~~~~ - -A weekly archive page showing all objects in a given week. Objects with a date -in the *future* are not displayed unless you set ``allow_future`` to ``True``. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``year`` - The four-digit year for which the archive serves (a string). - -``week`` - The week of the year for which the archive serves (a string). Weeks start - with Sunday. - -``queryset`` - A ``QuerySet`` of objects for which the archive serves. - -``date_field`` - The name of the ``DateField`` or ``DateTimeField`` in the ``QuerySet``'s - model that the date-based archive should use to determine the objects on - the page. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``allow_empty`` - A boolean specifying whether to display the page if no objects are - available. If this is ``False`` and no objects are available, the view will - raise a 404 instead of displaying an empty page. By default, this is - ``True``. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. The view will append ``'_list'`` - to the value of this parameter in determining the variable's name. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -``allow_future`` - A boolean specifying whether to include "future" objects on this page, - where "future" means objects in which the field specified in ``date_field`` - is greater than the current date/time. By default, this is ``False``. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_archive_week.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``week`` - A ``datetime.date`` object representing the first day of the given week. - -``object_list`` - A list of objects available for the given week. This variable's name - depends on the ``template_object_name`` parameter, which is ``'object'`` by - default. If ``template_object_name`` is ``'foo'``, this variable's name - will be ``foo_list``. - -``django.views.generic.date_based.archive_day`` ------------------------------------------------ - -Description -~~~~~~~~~~~ - -A day archive page showing all objects in a given day. Days in the future throw -a 404 error, regardless of whether any objects exist for future days, unless -you set ``allow_future`` to ``True``. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``year`` - The four-digit year for which the archive serves (a string). - -``month`` - The month for which the archive serves, formatted according to the - ``month_format`` argument. - -``day`` - The day for which the archive serves, formatted according to the - ``day_format`` argument. - -``queryset`` - A ``QuerySet`` of objects for which the archive serves. - -``date_field`` - The name of the ``DateField`` or ``DateTimeField`` in the ``QuerySet``'s - model that the date-based archive should use to determine the objects on - the page. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``month_format`` - A format string that regulates what format the ``month`` parameter uses. - This should be in the syntax accepted by Python's ``time.strftime``. (See - the `strftime docs`_.) It's set to ``"%b"`` by default, which is a three- - letter month abbreviation. To change it to use numbers, use ``"%m"``. - -``day_format`` - Like ``month_format``, but for the ``day`` parameter. It defaults to - ``"%d"`` (day of the month as a decimal number, 01-31). - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``allow_empty`` - A boolean specifying whether to display the page if no objects are - available. If this is ``False`` and no objects are available, the view will - raise a 404 instead of displaying an empty page. By default, this is - ``False``. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. The view will append - ``'_list'`` to the value of this parameter in determining the variable's - name. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -``allow_future`` - A boolean specifying whether to include "future" objects on this page, - where "future" means objects in which the field specified in ``date_field`` - is greater than the current date/time. By default, this is ``False``. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_archive_day.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``day`` - A ``datetime.date`` object representing the given day. - -``next_day`` - A ``datetime.date`` object representing the next day. If the next day is in - the future, this will be ``None``. - -``previous_day`` - A ``datetime.date`` object representing the given day. Unlike ``next_day``, - this will never be ``None``. - -``object_list`` - A list of objects available for the given day. This variable's name depends - on the ``template_object_name`` parameter, which is ``'object'`` by - default. If ``template_object_name`` is ``'foo'``, this variable's name - will be ``foo_list``. - -``django.views.generic.date_based.archive_today`` -------------------------------------------------- - -Description -~~~~~~~~~~~ - -A day archive page showing all objects for *today*. This is exactly the same as -``archive_day``, except the ``year``/``month``/``day`` arguments are not used, -and today's date is used instead. - -``django.views.generic.date_based.object_detail`` -------------------------------------------------- - -Description -~~~~~~~~~~~ - -A page representing an individual object. If the object has a date value in the -future, the view will throw a 404 error by default, unless you set -``allow_future`` to ``True``. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``year`` - The object's four-digit year (a string). - -``month`` - The object's month , formatted according to the ``month_format`` argument. - -``day`` - The object's day , formatted according to the ``day_format`` argument. - -``queryset`` - A ``QuerySet`` that contains the object. - -``date_field`` - The name of the ``DateField`` or ``DateTimeField`` in the ``QuerySet``'s - model that the generic view should use to look up the object according to - ``year``, ``month`` and ``day``. - -Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. - If you provide ``object_id``, it should be the value of the primary-key - field for the object being displayed on this page. - - Otherwise, ``slug`` should be the slug of the given object, and - ``slug_field`` should be the name of the slug field in the ``QuerySet``'s - model. By default, ``slug_field`` is ``'slug'``. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``month_format`` - A format string that regulates what format the ``month`` parameter uses. - This should be in the syntax accepted by Python's ``time.strftime``. (See - the `strftime docs`_.) It's set to ``"%b"`` by default, which is a three- - letter month abbreviation. To change it to use numbers, use ``"%m"``. - -``day_format`` - Like ``month_format``, but for the ``day`` parameter. It defaults to - ``"%d"`` (day of the month as a decimal number, 01-31). - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_name_field`` - The name of a field on the object whose value is the template name to use. - This lets you store template names in the data. In other words, if your - object has a field ``'the_template'`` that contains a string - ``'foo.html'``, and you set ``template_name_field`` to ``'the_template'``, - then the generic view for this object will use the template ``'foo.html'``. - - It's a bit of a brain-bender, but it's useful in some cases. - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -``allow_future`` - A boolean specifying whether to include "future" objects on this page, - where "future" means objects in which the field specified in ``date_field`` - is greater than the current date/time. By default, this is ``False``. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_detail.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``object`` - The object. This variable's name depends on the ``template_object_name`` - parameter, which is ``'object'`` by default. If ``template_object_name`` is - ``'foo'``, this variable's name will be ``foo``. - -List/detail generic views -========================= - -The list-detail generic-view framework (in the -``django.views.generic.list_detail`` module) is similar to the date-based one, -except the former simply has two views: a list of objects and an individual -object page. - -``django.views.generic.list_detail.object_list`` ------------------------------------------------- - -Description -~~~~~~~~~~~ - -A page representing a list of objects. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``queryset`` - A ``QuerySet`` that represents the objects. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``paginate_by`` - An integer specifying how many objects should be displayed per page. If - this is given, the view will paginate objects with ``paginate_by`` objects - per page. The view will expect either a ``page`` query string parameter - (via ``GET``) or a ``page`` variable specified in the URLconf. See `Notes - on pagination`_ below. - -``page`` - The current (1-based) page number, as an integer, or the string ``'last'``. - See `Notes on pagination`_ below. - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``allow_empty`` - A boolean specifying whether to display the page if no objects are - available. If this is ``False`` and no objects are available, the view will - raise a 404 instead of displaying an empty page. By default, this is - ``True``. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. The view will append ``'_list'`` - to the value of this parameter in determining the variable's name. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_list.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``object_list`` - The list of objects. This variable's name depends on the - ``template_object_name`` parameter, which is ``'object'`` by default. If - ``template_object_name`` is ``'foo'``, this variable's name will be - ``foo_list``. - -``is_paginated`` - A boolean representing whether the results are paginated. Specifically, - this is set to ``False`` if the number of available objects is less than or - equal to ``paginate_by``. - -If the results are paginated, the context will contain these extra variables: - -``paginator`` (**New in Django development version**) - An instance of ``django.core.paginator.Paginator``. - -``page_obj`` (**New in Django development version**) - An instance of ``django.core.paginator.Page``. - -See the `pagination documentation`_ for more information on the ``Paginator`` -and ``Page`` objects. - -Notes on pagination -~~~~~~~~~~~~~~~~~~~ - -If ``paginate_by`` is specified, Django will paginate the results. You can -specify the page number in the URL in one of two ways: - - * Use the ``page`` parameter in the URLconf. For example, this is what - your URLconf might look like:: - - (r'^objects/page(?P[0-9]+)/$', 'object_list', dict(info_dict)) - - * Pass the page number via the ``page`` query-string parameter. For - example, a URL would look like this:: - - /objects/?page=3 - - * To loop over all the available page numbers, use the ``page_range`` - variable. You can iterate over the list provided by ``page_range`` - to create a link to every page of results. - -These values and lists are 1-based, not 0-based, so the first page would be -represented as page ``1``. - -For more on pagination, read the `pagination documentation`_. - -.. _`pagination documentation`: ../pagination/ - -**New in Django development version:** - -As a special case, you are also permitted to use ``last`` as a value for -``page``:: - - /objects/?page=last - -This allows you to access the final page of results without first having to -determine how many pages there are. - -Note that ``page`` *must* be either a valid page number or the value ``last``; -any other value for ``page`` will result in a 404 error. - -``django.views.generic.list_detail.object_detail`` --------------------------------------------------- - -A page representing an individual object. - -Description -~~~~~~~~~~~ - -A page representing an individual object. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``queryset`` - A ``QuerySet`` that contains the object. - -Either ``object_id`` or (``slug`` *and* ``slug_field``) - If you provide ``object_id``, it should be the value of the primary-key - field for the object being displayed on this page. - - Otherwise, ``slug`` should be the slug of the given object, and - ``slug_field`` should be the name of the slug field in the ``QuerySet``'s - model. By default, ``slug_field`` is ``'slug'``. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_name_field`` - The name of a field on the object whose value is the template name to use. - This lets you store template names in the data. In other words, if your - object has a field ``'the_template'`` that contains a string - ``'foo.html'``, and you set ``template_name_field`` to ``'the_template'``, - then the generic view for this object will use the template ``'foo.html'``. - - It's a bit of a brain-bender, but it's useful in some cases. - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the ``DEFAULT_CONTENT_TYPE`` setting. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_detail.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``object`` - The object. This variable's name depends on the ``template_object_name`` - parameter, which is ``'object'`` by default. If ``template_object_name`` is - ``'foo'``, this variable's name will be ``foo``. - -Create/update/delete generic views -================================== - -The ``django.views.generic.create_update`` module contains a set of functions -for creating, editing and deleting objects. - -**Changed in Django development version:** - -``django.views.generic.create_update.create_object`` and -``django.views.generic.create_update.update_object`` now use the new `forms -library`_ to build and display the form. - -.. _forms library: ../forms/ - -``django.views.generic.create_update.create_object`` ----------------------------------------------------- - -Description -~~~~~~~~~~~ - -A page that displays a form for creating an object, redisplaying the form with -validation errors (if there are any) and saving the object. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -Either ``form_class`` or ``model`` - If you provide ``form_class``, it should be a ``django.forms.ModelForm`` - subclass. Use this argument when you need to customize the model's form. - See the `ModelForm docs`_ for more information. - - Otherwise, ``model`` should be a Django model class and the form used will - be a standard ``ModelForm`` for ``model``. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``post_save_redirect`` - A URL to which the view will redirect after saving the object. By default, - it's ``object.get_absolute_url()``. - - ``post_save_redirect`` may contain dictionary string formatting, which will - be interpolated against the object's field attributes. For example, you - could use ``post_save_redirect="/polls/%(slug)s/"``. - -``login_required`` - A boolean that designates whether a user must be logged in, in order to see - the page and save changes. This hooks into the Django `authentication - system`_. By default, this is ``False``. - - If this is ``True``, and a non-logged-in user attempts to visit this page - or save the form, Django will redirect the request to ``/accounts/login/``. - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_form.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``form`` - A ``django.forms.ModelForm`` instance representing the form for creating - the object. This lets you refer to form fields easily in the template - system. - - For example, if the model has two fields, ``name`` and ``address``:: - -
-

{{ form.name.label_tag }} {{ form.name }}

-

{{ form.address.label_tag }} {{ form.address }}

-
- - See the `forms documentation`_ for more information about using ``Form`` - objects in templates. - -.. _authentication system: ../authentication/ -.. _ModelForm docs: ../modelforms/ -.. _forms documentation: ../forms/ - -``django.views.generic.create_update.update_object`` ----------------------------------------------------- - -Description -~~~~~~~~~~~ - -A page that displays a form for editing an existing object, redisplaying the -form with validation errors (if there are any) and saving changes to the -object. This uses a form automatically generated from the object's -model class. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -Either ``form_class`` or ``model`` - If you provide ``form_class``, it should be a ``django.forms.ModelForm`` - subclass. Use this argument when you need to customize the model's form. - See the `ModelForm docs`_ for more information. - - Otherwise, ``model`` should be a Django model class and the form used will - be a standard ``ModelForm`` for ``model``. - -Either ``object_id`` or (``slug`` *and* ``slug_field``) - If you provide ``object_id``, it should be the value of the primary-key - field for the object being displayed on this page. - - Otherwise, ``slug`` should be the slug of the given object, and - ``slug_field`` should be the name of the slug field in the ``QuerySet``'s - model. By default, ``slug_field`` is ``'slug'``. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``post_save_redirect`` - A URL to which the view will redirect after saving the object. By default, - it's ``object.get_absolute_url()``. - - ``post_save_redirect`` may contain dictionary string formatting, which will - be interpolated against the object's field attributes. For example, you - could use ``post_save_redirect="/polls/%(slug)s/"``. - -``login_required`` - A boolean that designates whether a user must be logged in, in order to see - the page and save changes. This hooks into the Django `authentication - system`_. By default, this is ``False``. - - If this is ``True``, and a non-logged-in user attempts to visit this page - or save the form, Django will redirect the request to ``/accounts/login/``. - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``context_processors``: A list of template-context processors to apply to - the view's template. See the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_form.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``form`` - A ``django.forms.ModelForm`` instance representing the form for editing the - object. This lets you refer to form fields easily in the template system. - - For example, if the model has two fields, ``name`` and ``address``:: - -
-

{{ form.name.label_tag }} {{ form.name }}

-

{{ form.address.label_tag }} {{ form.address }}

-
- - See the `forms documentation`_ for more information about using ``Form`` - objects in templates. - -``object`` - The original object being edited. This variable's name depends on the - ``template_object_name`` parameter, which is ``'object'`` by default. If - ``template_object_name`` is ``'foo'``, this variable's name will be - ``foo``. - -``django.views.generic.create_update.delete_object`` ----------------------------------------------------- - -Description -~~~~~~~~~~~ - -A view that displays a confirmation page and deletes an existing object. The -given object will only be deleted if the request method is ``POST``. If this -view is fetched via ``GET``, it will display a confirmation page that should -contain a form that POSTs to the same URL. - -Required arguments -~~~~~~~~~~~~~~~~~~ - -``model`` - The Django model class of the object that the form will create. - -Either ``object_id`` or (``slug`` *and* ``slug_field``) - If you provide ``object_id``, it should be the value of the primary-key - field for the object being displayed on this page. - - Otherwise, ``slug`` should be the slug of the given object, and - ``slug_field`` should be the name of the slug field in the ``QuerySet``'s - model. By default, ``slug_field`` is ``'slug'``. - -``post_delete_redirect`` - A URL to which the view will redirect after deleting the object. - -Optional arguments -~~~~~~~~~~~~~~~~~~ - -``login_required`` - A boolean that designates whether a user must be logged in, in order to see - the page and save changes. This hooks into the Django `authentication - system`_. By default, this is ``False``. - - If this is ``True``, and a non-logged-in user attempts to visit this page - or save the form, Django will redirect the request to ``/accounts/login/``. - -``template_name`` - The full name of a template to use in rendering the page. This lets you - override the default template name (see below). - -``template_loader`` - The template loader to use when loading the template. By default, it's - ``django.template.loader``. - -``extra_context`` - A dictionary of values to add to the template context. By default, this is - an empty dictionary. If a value in the dictionary is callable, the generic - view will call it just before rendering the template. - -``context_processors`` - A list of template-context processors to apply to the view's template. See - the `RequestContext docs`_. - -``template_object_name`` - Designates the name of the template variable to use in the template - context. By default, this is ``'object'``. - -Template name -~~~~~~~~~~~~~ - -If ``template_name`` isn't specified, this view will use the template -``/_confirm_delete.html`` by default. - -Template context -~~~~~~~~~~~~~~~~ - -In addition to ``extra_context``, the template's context will be: - -``object`` - The original object that's about to be deleted. This variable's name - depends on the ``template_object_name`` parameter, which is ``'object'`` by - default. If ``template_object_name`` is ``'foo'``, this variable's name - will be ``foo``. diff --git a/docs/glossary.txt b/docs/glossary.txt new file mode 100644 index 0000000000..c67c522ef7 --- /dev/null +++ b/docs/glossary.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 `. + + __ 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. \ No newline at end of file diff --git a/docs/apache_auth.txt b/docs/howto/apache-auth.txt similarity index 91% rename from docs/apache_auth.txt rename to docs/howto/apache-auth.txt index 62fd191896..585e5b32c4 100644 --- a/docs/apache_auth.txt +++ b/docs/howto/apache-auth.txt @@ -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 ` 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 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 + ` 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 diff --git a/docs/howto/custom-file-storage.txt b/docs/howto/custom-file-storage.txt new file mode 100644 index 0000000000..c5f6b740a8 --- /dev/null +++ b/docs/howto/custom-file-storage.txt @@ -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. diff --git a/docs/howto/custom-management-commands.txt b/docs/howto/custom-management-commands.txt new file mode 100644 index 0000000000..00f656b92e --- /dev/null +++ b/docs/howto/custom-management-commands.txt @@ -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``. \ No newline at end of file diff --git a/docs/custom_model_fields.txt b/docs/howto/custom-model-fields.txt similarity index 65% rename from docs/custom_model_fields.txt rename to docs/howto/custom-model-fields.txt index 5dec22f6e3..aa14c3cb4e 100644 --- a/docs/custom_model_fields.txt +++ b/docs/howto/custom-model-fields.txt @@ -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 ` 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 `) 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 `. 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 ``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 + `. 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 +` 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 +` 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..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..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) +` 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 `. 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 ------------------ diff --git a/docs/templates_python.txt b/docs/howto/custom-template-tags.txt similarity index 55% rename from docs/templates_python.txt rename to docs/howto/custom-template-tags.txt index a03ea215d2..4477f6bb83 100644 --- a/docs/templates_python.txt +++ b/docs/howto/custom-template-tags.txt @@ -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 +` 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 - - -.. 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

The time is {% current_time "%Y-%m-%d %I:%M %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

This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %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 `. 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
  • First choice
  • @@ -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
      {% 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 {{ title }}. 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" %}

      The time is {{ current_time }}.

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

      The current time is {{ my_current_time }}.

      @@ -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/ diff --git a/docs/fastcgi.txt b/docs/howto/deployment/fastcgi.txt similarity index 86% rename from docs/fastcgi.txt rename to docs/howto/deployment/fastcgi.txt index edd4c8a83d..f9f9a8184a 100644 --- a/docs/fastcgi.txt +++ b/docs/howto/deployment/fastcgi.txt @@ -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 `, 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 ` 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=`` option with -``./manage.py runfcgi`` -- where ```` may be one of: ``fcgi`` -(the default), ``scgi`` or ``ajp``. For example:: +protocol by using the ``protocol=`` option with ``./manage.py +runfcgi`` -- where ```` 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 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 ` 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. + diff --git a/docs/howto/deployment/index.txt b/docs/howto/deployment/index.txt new file mode 100644 index 0000000000..80c16fcd82 --- /dev/null +++ b/docs/howto/deployment/index.txt @@ -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 ` 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 \ No newline at end of file diff --git a/docs/modpython.txt b/docs/howto/deployment/modpython.txt similarity index 83% rename from docs/modpython.txt rename to docs/howto/deployment/modpython.txt index 44de0e1bd2..0303e13153 100644 --- a/docs/modpython.txt +++ b/docs/howto/deployment/modpython.txt @@ -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 +` (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 @@ -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 +` 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"** 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 +` 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 ` 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 diff --git a/docs/howto/error-reporting.txt b/docs/howto/error-reporting.txt new file mode 100644 index 0000000000..e0750ce327 --- /dev/null +++ b/docs/howto/error-reporting.txt @@ -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 `. 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``. diff --git a/docs/howto/index.txt b/docs/howto/index.txt new file mode 100644 index 0000000000..e8f30888ab --- /dev/null +++ b/docs/howto/index.txt @@ -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/ \ No newline at end of file diff --git a/docs/howto/initial-data.txt b/docs/howto/initial-data.txt new file mode 100644 index 0000000000..871c5e8fa1 --- /dev/null +++ b/docs/howto/initial-data.txt @@ -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 ` has more details +about each of these supported :ref:`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 +`, 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 + ` 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/.sql``, +in your app directory, where ```` 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 +`. Refer to the :ref:`manage.py documentation +` 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 ``/sql/..sql``, where +```` is your app directory, ```` is the model's name in +lowercase and ```` 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``. diff --git a/docs/howto/legacy-databases.txt b/docs/howto/legacy-databases.txt new file mode 100644 index 0000000000..c4eb1d82c7 --- /dev/null +++ b/docs/howto/legacy-databases.txt @@ -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 `. + +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 `: + + * :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 ` 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. diff --git a/docs/outputting_csv.txt b/docs/howto/outputting-csv.txt similarity index 72% rename from docs/outputting_csv.txt rename to docs/howto/outputting-csv.txt index d6ec3f62a0..5192c51228 100644 --- a/docs/outputting_csv.txt +++ b/docs/howto/outputting-csv.txt @@ -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 ` +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. diff --git a/docs/outputting_pdf.txt b/docs/howto/outputting-pdf.txt similarity index 85% rename from docs/outputting_pdf.txt rename to docs/howto/outputting-pdf.txt index dd8a262812..13e07f8202 100644 --- a/docs/outputting_pdf.txt +++ b/docs/howto/outputting-pdf.txt @@ -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. diff --git a/docs/static_files.txt b/docs/howto/static-files.txt similarity index 72% rename from docs/static_files.txt rename to docs/howto/static-files.txt index 846c3eb56b..2f4e8fc8f3 100644 --- a/docs/static_files.txt +++ b/docs/howto/static-files.txt @@ -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 `. 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 `:: (r'^site_media/(?P.*)$', '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.*)$', '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 @@ -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 diff --git a/docs/index.txt b/docs/index.txt index e7e28a930c..7b339001e5 100644 --- a/docs/index.txt +++ b/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 ` -- 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 `. + +* 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 ` + See what writing a database-driven application with Django looks like. + +:ref:`Installation ` + Get Django installed on your computer. + +Tutorial: Writing your first Django application +=============================================== + +:ref:`Part 1 ` + Get set up, create models, and play with the database API. + +:ref:`Part 2 ` + Explore the automatically-generated admin site. + +:ref:`Part 3 ` + Write the public interface views. + +:ref:`Part 4 ` + Learn how to process forms. + +Using Django +============ + +:ref:`Models ` + Design a single, definitive source of data about your data. + +:ref:`Handling web requests ` + Handle web requests, map them to views, and return pages. + +:ref:`Forms ` + Build and handle HTML forms. + +:ref:`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 ` + Get a clean interface to your data with no effort at all. + +:ref:`Form tools ` + Easily handle complex form workflows. + +:ref:`Syndication feeds ` + Generate RSS and Atom feeds of your data. + +:ref:`"Local flavor" ` + 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 ` + Release your project to the world. + +:ref:`Importing data from legacy databases ` + Use Django with an existing database or alongside other web development + toolkits. + +:ref:`Custom template tags ` + Add your own extensions to Django's template language. + +:ref:`Generating CSV ` & :ref:`PDF ` + Produce non-HTML content with Django. + +And more: +--------- + +:ref:`Authenticating in Apache ` ... +: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 ` + See all of Django's settings and what they do. -Solving specific problems -------------------------- +:ref:`Request & response objects ` + 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 ` + Revel in the gory details of Django's model system. + +:ref:`Form API reference ` + 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 ` + 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 ` + See what is and was new in each release of Django. +:ref:`Miscellany ` + Stuff we can't find a more organized place for. Like that drawer in your + kitchen with the scissors, batteries, and duct tape. diff --git a/docs/internals/_images/djangotickets.png b/docs/internals/_images/djangotickets.png new file mode 100644 index 0000000000..34a2a41852 Binary files /dev/null and b/docs/internals/_images/djangotickets.png differ diff --git a/docs/contributing.txt b/docs/internals/contributing.txt similarity index 97% rename from docs/contributing.txt rename to docs/internals/contributing.txt index d0d56a0e39..b96ed4360c 100644 --- a/docs/contributing.txt +++ b/docs/internals/contributing.txt @@ -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 ` 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 `. * Create a diff of the ``.po`` file against the current Subversion trunk. * Make sure that `` django-admin.py compilemessages -l `` 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 ` 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 ` +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// @@ -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// @@ -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 diff --git a/docs/internals/documentation.txt b/docs/internals/documentation.txt new file mode 100644 index 0000000000..ebd62b9a6c --- /dev/null +++ b/docs/internals/documentation.txt @@ -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 + `. + + * 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:: `` 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". diff --git a/docs/internals/index.txt b/docs/internals/index.txt new file mode 100644 index 0000000000..b1647e983f --- /dev/null +++ b/docs/internals/index.txt @@ -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 diff --git a/docs/intro/_images/admin01.png b/docs/intro/_images/admin01.png new file mode 100644 index 0000000000..8d746d452c Binary files /dev/null and b/docs/intro/_images/admin01.png differ diff --git a/docs/intro/_images/admin02.png b/docs/intro/_images/admin02.png new file mode 100644 index 0000000000..0c122bdce7 Binary files /dev/null and b/docs/intro/_images/admin02.png differ diff --git a/docs/intro/_images/admin02t.png b/docs/intro/_images/admin02t.png new file mode 100644 index 0000000000..d7519d19ab Binary files /dev/null and b/docs/intro/_images/admin02t.png differ diff --git a/docs/intro/_images/admin03.png b/docs/intro/_images/admin03.png new file mode 100644 index 0000000000..77549e7c09 Binary files /dev/null and b/docs/intro/_images/admin03.png differ diff --git a/docs/intro/_images/admin03t.png b/docs/intro/_images/admin03t.png new file mode 100644 index 0000000000..94273cb583 Binary files /dev/null and b/docs/intro/_images/admin03t.png differ diff --git a/docs/intro/_images/admin04.png b/docs/intro/_images/admin04.png new file mode 100644 index 0000000000..4090f892e7 Binary files /dev/null and b/docs/intro/_images/admin04.png differ diff --git a/docs/intro/_images/admin04t.png b/docs/intro/_images/admin04t.png new file mode 100644 index 0000000000..a2ec8bb893 Binary files /dev/null and b/docs/intro/_images/admin04t.png differ diff --git a/docs/intro/_images/admin05.png b/docs/intro/_images/admin05.png new file mode 100644 index 0000000000..b424393f56 Binary files /dev/null and b/docs/intro/_images/admin05.png differ diff --git a/docs/intro/_images/admin05t.png b/docs/intro/_images/admin05t.png new file mode 100644 index 0000000000..a5da9504f3 Binary files /dev/null and b/docs/intro/_images/admin05t.png differ diff --git a/docs/intro/_images/admin06.png b/docs/intro/_images/admin06.png new file mode 100644 index 0000000000..5f24d4e3a4 Binary files /dev/null and b/docs/intro/_images/admin06.png differ diff --git a/docs/intro/_images/admin06t.png b/docs/intro/_images/admin06t.png new file mode 100644 index 0000000000..fb65e0aead Binary files /dev/null and b/docs/intro/_images/admin06t.png differ diff --git a/docs/intro/_images/admin07.png b/docs/intro/_images/admin07.png new file mode 100644 index 0000000000..b21022f55d Binary files /dev/null and b/docs/intro/_images/admin07.png differ diff --git a/docs/intro/_images/admin08.png b/docs/intro/_images/admin08.png new file mode 100644 index 0000000000..ddac57e4ae Binary files /dev/null and b/docs/intro/_images/admin08.png differ diff --git a/docs/intro/_images/admin08t.png b/docs/intro/_images/admin08t.png new file mode 100644 index 0000000000..83773bb833 Binary files /dev/null and b/docs/intro/_images/admin08t.png differ diff --git a/docs/intro/_images/admin09.png b/docs/intro/_images/admin09.png new file mode 100644 index 0000000000..ba7de1b9d2 Binary files /dev/null and b/docs/intro/_images/admin09.png differ diff --git a/docs/intro/_images/admin10.png b/docs/intro/_images/admin10.png new file mode 100644 index 0000000000..20b085b5b4 Binary files /dev/null and b/docs/intro/_images/admin10.png differ diff --git a/docs/intro/_images/admin11.png b/docs/intro/_images/admin11.png new file mode 100644 index 0000000000..6c583fd2dc Binary files /dev/null and b/docs/intro/_images/admin11.png differ diff --git a/docs/intro/_images/admin11t.png b/docs/intro/_images/admin11t.png new file mode 100644 index 0000000000..af792b899d Binary files /dev/null and b/docs/intro/_images/admin11t.png differ diff --git a/docs/intro/_images/admin12.png b/docs/intro/_images/admin12.png new file mode 100644 index 0000000000..aac5c0d6b5 Binary files /dev/null and b/docs/intro/_images/admin12.png differ diff --git a/docs/intro/_images/admin13.png b/docs/intro/_images/admin13.png new file mode 100644 index 0000000000..49a5950409 Binary files /dev/null and b/docs/intro/_images/admin13.png differ diff --git a/docs/intro/_images/admin13t.png b/docs/intro/_images/admin13t.png new file mode 100644 index 0000000000..7dc01e186a Binary files /dev/null and b/docs/intro/_images/admin13t.png differ diff --git a/docs/intro/_images/admin14.png b/docs/intro/_images/admin14.png new file mode 100644 index 0000000000..b1f4a5420a Binary files /dev/null and b/docs/intro/_images/admin14.png differ diff --git a/docs/intro/_images/admin14t.png b/docs/intro/_images/admin14t.png new file mode 100644 index 0000000000..86c3accbbd Binary files /dev/null and b/docs/intro/_images/admin14t.png differ diff --git a/docs/intro/index.txt b/docs/intro/index.txt new file mode 100644 index 0000000000..2135bc7fe9 --- /dev/null +++ b/docs/intro/index.txt @@ -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 \ No newline at end of file diff --git a/docs/intro/install.txt b/docs/intro/install.txt new file mode 100644 index 0000000000..bb361d52b6 --- /dev/null +++ b/docs/intro/install.txt @@ -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 ` 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 +`. + +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 `. + +Install Django +-------------- + +You've got three easy options to install Django: + + * Install a version of Django :ref:`provided by your operating system + distribution `. This is the quickest option for those + who have operating systems that distribute Django. + + * :ref:`Install an 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 + `. 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 `. + + + diff --git a/docs/overview.txt b/docs/intro/overview.txt similarity index 81% rename from docs/overview.txt rename to docs/intro/overview.txt index dae0ffbd76..79ce653106 100644 --- a/docs/overview.txt +++ b/docs/intro/overview.txt @@ -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 ` or :ref:`dive right into more +detailed documentation `. 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 ` 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 ` 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 ` -- 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 +`. 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 `, 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 @@ -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 ` that integrates with memcached + or other backends. + + * A :ref:`syndication framework ` 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 ` 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/ diff --git a/docs/tutorial01.txt b/docs/intro/tutorial01.txt similarity index 51% rename from docs/tutorial01.txt rename to docs/intro/tutorial01.txt index 6d7b10a053..08ebe1adbb 100644 --- a/docs/tutorial01.txt +++ b/docs/intro/tutorial01.txt @@ -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 ` 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 + ` 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 ` 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 +` 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 `. + + * :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 `. 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 ` 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 ` -- 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 ` -- Outputs any + :ref:`custom SQL statements ` (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 ` -- 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 ` -- Outputs the + ``CREATE INDEX`` statements for this app. + + * :djadmin:`python manage.py sqlall polls ` -- 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 ` 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 `. -Once you're in the shell, explore the database API:: +Once you're in the shell, explore the :ref:`database API `:: - # 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:: [] -Wait a minute. ```` 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. ```` 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 ` 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 +`. -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 +` to get Django's automatic admin working. diff --git a/docs/tutorial02.txt b/docs/intro/tutorial02.txt similarity index 72% rename from docs/tutorial02.txt rename to docs/intro/tutorial02.txt index 0b17593165..4af08c48af 100644 --- a/docs/tutorial02.txt +++ b/docs/intro/tutorial02.txt @@ -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 ` 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 ```` 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 ` 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 +` to start working on public poll views. diff --git a/docs/tutorial03.txt b/docs/intro/tutorial03.txt similarity index 65% rename from docs/tutorial03.txt rename to docs/intro/tutorial03.txt index 2ac106229f..6d40a5bfcb 100644 --- a/docs/tutorial03.txt +++ b/docs/intro/tutorial03.txt @@ -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 ` 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\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\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=, poll_id='23') -The ``poll_id='23'`` part comes from ``(?P\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`` 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\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`` 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 `. 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 %}
        @@ -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

        {{ poll.question }}

          @@ -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 ` 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\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 +` to learn about simple form processing and generic views. diff --git a/docs/tutorial04.txt b/docs/intro/tutorial04.txt similarity index 52% rename from docs/tutorial04.txt rename to docs/intro/tutorial04.txt index 78f954d632..fb0b206326 100644 --- a/docs/tutorial04.txt +++ b/docs/intro/tutorial04.txt @@ -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 ` 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 ``
          `` element:: +tutorial, so that the template contains an HTML ```` element: + +.. code-block:: html+django

          {{ poll.question }}

          @@ -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 `, we created +a URLconf for the polls application that includes this line:: (r'^(?P\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 ` 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 ` 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 + ` for accessing GET data in the same way -- + but we're explicitly using :attr:`request.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 `. 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 +`. 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

          {{ poll.question }}

          @@ -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 `) 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\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 ` 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 ``/_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 -``/_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 ``/_list.html``. Thus, rename +``polls/index.html`` to ``polls/poll_list.html``. -Similarly, the ``object_list`` generic view uses a template called -``/_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 + `. -.. _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 +`. 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 ` diff --git a/docs/intro/whatsnext.txt b/docs/intro/whatsnext.txt new file mode 100644 index 0000000000..ae67220f58 --- /dev/null +++ b/docs/intro/whatsnext.txt @@ -0,0 +1,235 @@ +.. _intro-whatsnext: + +================= +What to read next +================= + +So you've read all the :ref:`introductory material ` 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 ` 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 `, on the other hand, dive deep into + individual parts of Django. There are complete guides to Django's + :ref:`model system `, :ref:`template engine + `, :ref:`forms framework `, 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 ` that answer + common "How do I ...?" questions. Here you'll find information about + :ref:`generating PDFs with Django `, :ref:`writing + custom template tags `, and more. + + Answers to really common questions can also be found in the :ref:`FAQ + `. + + * 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 `. 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 `, + :ref:`documentation of obsolete features `, + :ref:`internals documentation ` for those who want to add + code to Django itself, and a :ref:`few other things that simply don't fit + elsewhere `. + + +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/ diff --git a/docs/legacy_databases.txt b/docs/legacy_databases.txt deleted file mode 100644 index b87a661f90..0000000000 --- a/docs/legacy_databases.txt +++ /dev/null @@ -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. diff --git a/docs/localflavor.txt b/docs/localflavor.txt deleted file mode 100644 index 71e353c5d8..0000000000 --- a/docs/localflavor.txt +++ /dev/null @@ -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. diff --git a/docs/man/django-admin.1 b/docs/man/django-admin.1 index 2f4b5a02d8..6b58c9183b 100644 --- a/docs/man/django-admin.1 +++ b/docs/man/django-admin.1 @@ -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 diff --git a/docs/middleware.txt b/docs/middleware.txt deleted file mode 100644 index c61bd7c5cc..0000000000 --- a/docs/middleware.txt +++ /dev/null @@ -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. diff --git a/docs/misc/api-stability.txt b/docs/misc/api-stability.txt new file mode 100644 index 0000000000..0bf4b984c4 --- /dev/null +++ b/docs/misc/api-stability.txt @@ -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 `. + + - :ref:`Custom template tags and libraries `. + + - :ref:`Database lookup ` (with the exception of validation; see below). + + - :ref:`django-admin utility `. + + - :ref:`FastCGI and mod_python integration `. + + - :ref:`Flatpages `. + + - :ref:`Generic views `. + + - :ref:`Internationalization `. + + - :ref:`Legacy database integration `. + + - :ref:`Model definition ` (with the exception of generic relations; see below). + + - :ref:`Redirects `. + + - :ref:`Request/response objects `. + + - :ref:`Sending e-mail `. + + - :ref:`Sessions `. + + - :ref:`Settings `. + + - :ref:`Syndication `. + + - :ref:`Template language ` (with the exception of some + possible disambiguation of how tag arguments are passed to tags and + filters). + + - :ref:`Transactions `. + + - :ref:`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: + + - :ref:`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. diff --git a/docs/design_philosophies.txt b/docs/misc/design-philosophies.txt similarity index 93% rename from docs/design_philosophies.txt rename to docs/misc/design-philosophies.txt index 465c4b547e..43bb8096c9 100644 --- a/docs/design_philosophies.txt +++ b/docs/misc/design-philosophies.txt @@ -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 +`. 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. diff --git a/docs/distributions.txt b/docs/misc/distributions.txt similarity index 95% rename from docs/distributions.txt rename to docs/misc/distributions.txt index 0c051c8da5..c94c399ce0 100644 --- a/docs/distributions.txt +++ b/docs/misc/distributions.txt @@ -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 +` from our Subversion repository. FreeBSD ======= diff --git a/docs/misc/index.txt b/docs/misc/index.txt new file mode 100644 index 0000000000..534171b6ed --- /dev/null +++ b/docs/misc/index.txt @@ -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 diff --git a/docs/model-api.txt b/docs/model-api.txt deleted file mode 100644 index a203aa38c8..0000000000 --- a/docs/model-api.txt +++ /dev/null @@ -1,2145 +0,0 @@ -=============== -Model reference -=============== - -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. Generally, each -model maps to a single database table. - -The basics: - - * Each model is a Python class that subclasses ``django.db.models.Model``. - * Each attribute of the model represents a database field. - * Model metadata (non-field information) goes in an inner class named - ``Meta``. - * With all of this, Django gives you an automatically-generated - database-access API, which is explained in the `Database API reference`_. - -A companion to this document is the `official repository of model examples`_. -(In the Django source distribution, these examples are in the -``tests/modeltests`` directory.) - -.. _Database API reference: ../db-api/ -.. _official repository of model examples: ../models/ - -Quick example -============= - -This example model defines a ``Person``, which has a ``first_name`` and -``last_name``:: - - from django.db import models - - class Person(models.Model): - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - -``first_name`` and ``last_name`` are *fields* of the model. Each field is -specified as a class attribute, and each attribute maps to a database column. - -The above ``Person`` model would create a database table like this:: - - CREATE TABLE myapp_person ( - "id" serial NOT NULL PRIMARY KEY, - "first_name" varchar(30) NOT NULL, - "last_name" varchar(30) NOT NULL - ); - -Some technical notes: - - * The name of the table, ``myapp_person``, is automatically derived from - some model metadata but can be overridden. See `Table names`_ below. - * An ``id`` field is added automatically, but this behavior can be - overridden. See `Automatic primary key fields`_ below. - * The ``CREATE TABLE`` SQL in this example is formatted using PostgreSQL - syntax, but it's worth noting Django uses SQL tailored to the database - backend specified in your `settings file`_. - -.. _settings file: ../settings/ - -Fields -====== - -The most important part of a model -- and the only required part of a model -- -is the list of database fields it defines. Fields are specified by class -attributes. - -Example:: - - class Musician(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - instrument = models.CharField(max_length=100) - - class Album(models.Model): - artist = models.ForeignKey(Musician) - name = models.CharField(max_length=100) - release_date = models.DateField() - num_stars = models.IntegerField() - -Field name restrictions ------------------------ - -Django places only two restrictions on model field names: - - 1. A field name cannot be a Python reserved word, because that would result - in a Python syntax error. For example:: - - class Example(models.Model): - pass = models.IntegerField() # 'pass' is a reserved word! - - 2. A field name cannot contain more than one underscore in a row, due to - the way Django's query lookup syntax works. For example:: - - class Example(models.Model): - foo__bar = models.IntegerField() # 'foo__bar' has two underscores! - -These limitations can be worked around, though, because your field name doesn't -necessarily have to match your database column name. See `db_column`_ below. - -SQL reserved words, such as ``join``, ``where`` or ``select``, *are* allowed as -model field names, because Django escapes all database table names and column -names in every underlying SQL query. It uses the quoting syntax of your -particular database engine. - -Field types ------------ - -Each field in your model should be an instance of the appropriate ``Field`` -class. Django uses the field class types to determine a few things: - - * The database column type (e.g. ``INTEGER``, ``VARCHAR``). - * The widget to use in Django's admin interface, if you care to use it - (e.g. ````, ```` (a single-line input). - -``CharField`` has an extra required argument, ``max_length``, the maximum length -(in characters) of the field. The max_length is enforced at the database level -and in Django's validation. - -``CommaSeparatedIntegerField`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A field of integers separated by commas. As in ``CharField``, the ``max_length`` -argument is required. - -``DateField`` -~~~~~~~~~~~~~ - -A date field. Has a few extra optional arguments: - - ====================== =================================================== - Argument Description - ====================== =================================================== - ``auto_now`` Automatically set the field to now every time the - object is saved. Useful for "last-modified" - timestamps. Note that the current date is *always* - used; it's not just a default value that you can - override. - - ``auto_now_add`` Automatically set the field to now when the object - is first created. Useful for creation of - timestamps. Note that the current date is *always* - used; it's not just a default value that you can - override. - ====================== =================================================== - -The admin represents this as an ```` with a JavaScript -calendar, and a shortcut for "Today." The JavaScript calendar will always start -the week on a Sunday. - -``DateTimeField`` -~~~~~~~~~~~~~~~~~ - -A date and time field. Takes the same extra options as ``DateField``. - -The admin represents this as two ```` fields, with -JavaScript shortcuts. - -``DecimalField`` -~~~~~~~~~~~~~~~~ - -**New in Django development version** - -A fixed-precision decimal number, represented in Python by a ``Decimal`` instance. -Has two **required** arguments: - - ====================== =================================================== - Argument Description - ====================== =================================================== - ``max_digits`` The maximum number of digits allowed in the number. - - ``decimal_places`` The number of decimal places to store with the - number. - ====================== =================================================== - -For example, to store numbers up to 999 with a resolution of 2 decimal places, -you'd use:: - - models.DecimalField(..., max_digits=5, decimal_places=2) - -And to store numbers up to approximately one billion with a resolution of 10 -decimal places:: - - models.DecimalField(..., max_digits=19, decimal_places=10) - -The admin represents this as an ```` (a single-line input). - -``EmailField`` -~~~~~~~~~~~~~~ - -A ``CharField`` that checks that the value is a valid e-mail address. - -In Django 0.96, this doesn't accept ``max_length``; its ``max_length`` is -automatically set to 75. In the Django development version, ``max_length`` is -set to 75 by default, but you can specify it to override default behavior. - -``FileField`` -~~~~~~~~~~~~~ - -A file-upload field. Has two special arguments, of which the first is -**required**: - - ====================== =================================================== - Argument Description - ====================== =================================================== - ``upload_to`` Required. A filesystem-style path that will be - prepended to the filename before being committed to - the final storage destination. - - **New in Django development version** - - This may also be a callable, such as a function, - which will be called to obtain the upload path, - including the filename. See below for details. - - ``storage`` **New in Django development version** - - Optional. A storage object, which handles the - storage and retrieval of your files. See `managing - files`_ for details on how to provide this object. - ====================== =================================================== - -.. _managing files: ../files/ - -The ``upload_to`` path may contain `strftime formatting`_, which will be -replaced by the date/time of the file upload (so that uploaded files don't fill -up the given directory). - -**New in Django development version** - -If a callable is provided for the ``upload_to`` argument, that callable must be -able to accept two arguments, and return a Unix-style path (with forward -slashes) to be passed along to the storage system. The two arguments that will -be passed are: - - ====================== =================================================== - Argument Description - ====================== =================================================== - ``instance`` An instance of the model where the ``FileField`` is - defined. More specifically, this is the particular - instance where the current file is being attached. - - **Note**: In most cases, this object will not have - been saved to the database yet, so if it uses the - default ``AutoField``, *it might not yet have a - value for its primary key field*. - - ``filename`` The filename that was originally given to the file. - This may or may not be taken into account when - determining the final destination path. - ====================== =================================================== - -The admin represents this field as an ```` (a file-upload -widget). - -Using a ``FileField`` or an ``ImageField`` (see below) in a model without a -specified storage system takes a few steps: - - 1. In your settings file, you'll need to 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. - - 2. 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. - - 3. 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 - ``object..url`` to get the actual URL. For example, if your - ``ImageField`` is called ``mug_shot``, you can get the absolute URL to - your image in a template with ``{{ object.mug_shot.url }}``. - -For example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and -``upload_to`` is set to ``'photos/%Y/%m/%d'``. The ``'%Y/%m/%d'`` part of -``upload_to`` is strftime formatting; ``'%Y'`` is the four-digit year, -``'%m'`` is the two-digit month and ``'%d'`` is the two-digit day. If you -upload a file on Jan. 15, 2007, it will be saved in the directory -``/home/media/photos/2007/01/15``. - -Information about the uploaded ``File`` object, such as its on-disk filename, -its size, or its URL, is available via attributes on the object itself. See the -`managing files`__ documentation for more information about ``File`` objects. - -__ ../files/ - -Note that whenever you deal with uploaded files, you should pay close attention -to where you're uploading them and what type of files they are, to avoid -security holes. *Validate all uploaded files* so that you're sure the files are -what you think they are. For example, if you blindly let somebody upload files, -without validation, to a directory that's within your Web server's document -root, then somebody could upload a CGI or PHP script and execute that script by -visiting its URL on your site. Don't allow that. - -.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941 - -**New in development version:** By default, ``FileField`` instances are -created as ``varchar(100)`` columns in your database. As with other fields, you -can change the maximum length using the ``max_length`` argument. - -``FilePathField`` -~~~~~~~~~~~~~~~~~ - -A field whose choices are limited to the filenames in a certain directory -on the filesystem. Has three special arguments, of which the first is -**required**: - - ====================== =================================================== - Argument Description - ====================== =================================================== - ``path`` Required. The absolute filesystem path to a - directory from which this ``FilePathField`` should - get its choices. Example: ``"/home/images"``. - - ``match`` Optional. A regular expression, as a string, that - ``FilePathField`` will use to filter filenames. - Note that the regex will be applied to the - base filename, not the full path. Example: - ``"foo.*\.txt$"``, which will match a file called - ``foo23.txt`` but not ``bar.txt`` or ``foo23.gif``. - - ``recursive`` Optional. Either ``True`` or ``False``. Default is - ``False``. Specifies whether all subdirectories of - ``path`` should be included. - ====================== =================================================== - -Of course, these arguments can be used together. - -The one potential gotcha is that ``match`` applies to the base filename, -not the full path. So, this example:: - - FilePathField(path="/home/images", match="foo.*", recursive=True) - -...will match ``/home/images/foo.gif`` but not ``/home/images/foo/bar.gif`` -because the ``match`` applies to the base filename (``foo.gif`` and -``bar.gif``). - -**New in development version:** By default, ``FilePathField`` instances are -created as ``varchar(100)`` columns in your database. As with other fields, you -can change the maximum length using the ``max_length`` argument. - -``FloatField`` -~~~~~~~~~~~~~~ - -**Changed in Django development version** - -A floating-point number represented in Python by a ``float`` instance. - -The admin represents this as an ```` (a single-line input). - -**NOTE:** The semantics of ``FloatField`` have changed in the Django -development version. See the `Django 0.96 documentation`_ for the old behavior. - -.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield - -``ImageField`` -~~~~~~~~~~~~~~ - -Like `FileField`_, but validates that the uploaded object is a valid -image. Has two extra optional arguments, ``height_field`` and -``width_field``, which, if set, will be auto-populated with the height and -width of the image each time a model instance is saved. - -In addition to the `standard attributes and methods`_ that are available for -``FileField``, an ``ImageField`` also has ``width`` and ``height`` attributes. - -Requires the `Python Imaging Library`_. - -**New in development version:** By default, ``ImageField`` instances are -created as ``varchar(100)`` columns in your database. As with other fields, you -can change the maximum length using the ``max_length`` argument. - -.. _standard attributes and methods: ../files/#file-attributes-and-methods -.. _Python Imaging Library: http://www.pythonware.com/products/pil/ - -``IntegerField`` -~~~~~~~~~~~~~~~~ - -An integer. - -The admin represents this as an ```` (a single-line input). - -``IPAddressField`` -~~~~~~~~~~~~~~~~~~ - -An IP address, in string format (e.g. "192.0.2.30"). - -The admin represents this as an ```` (a single-line input). - -``NullBooleanField`` -~~~~~~~~~~~~~~~~~~~~ - -Like a ``BooleanField``, but allows ``NULL`` as one of the options. Use this -instead of a ``BooleanField`` with ``null=True``. - -The admin represents this as a ```` + +.. class:: CheckboxInput + Checkbox: ```` + +.. class:: Select + Select widget: ```` + +.. class:: NullBooleanSelect + Select widget with options 'Unknown', 'Yes' and 'No' + +.. class:: SelectMultiple + Select widget allowing multiple selection: ```` + +.. class:: RadioSelect + A list of radio buttons: + + .. code-block:: html + +
            +
          • + ... +
          + +.. class:: CheckboxSelectMultiple + A list of checkboxes: + + .. code-block:: html + +
            +
          • + ... +
          + +.. class:: MultiWidget + Wrapper around multiple other widgets + +.. class:: SplitDateTimeWidget + Wrapper around two ``TextInput`` widgets: one for the date, and one for the + time. + +Specifying widgets +------------------ + +.. attribute:: Form.widget + +Whenever you specify a field on a form, Django will use a default widget +that is appropriate to the type of data that is to be displayed. To find +which widget is used on which field, see the documentation for the +built-in Field classes. + +However, if you want to use a different widget for a field, you can - +just use the 'widget' argument on the field definition. For example:: + + class CommentForm(forms.Form): + name = forms.CharField() + url = forms.URLField() + comment = forms.CharField(widget=forms.Textarea) + +This would specify a form with a comment that uses a larger Textarea widget, +rather than the default TextInput widget. + +Customizing widget instances +---------------------------- + +When Django renders a widget as HTML, it only renders the bare minimum +HTML - Django doesn't add a class definition, or any other widget-specific +attributes. This means that all 'TextInput' widgets will appear the same +on your web page. + +If you want to make one widget look different to another, you need to +specify additional attributes for each widget. When you specify a +widget, you can provide a list of attributes that will be added to the +rendered HTML for the widget. + +For example, take the following simple form:: + + class CommentForm(forms.Form): + name = forms.CharField() + url = forms.URLField() + comment = forms.CharField() + +This form will include three default TextInput widgets, with default rendering - +no CSS class, no extra attributes. This means that the input boxes provided for +each widget will be rendered exactly the same:: + + >>> f = CommentForm(auto_id=False) + >>> f.as_table() + Name: + Url: + Comment: + + +On a real web page, you probably don't want every widget to look the same. You +might want a larger input element for the comment, and you might want the 'name' +widget to have some special CSS class. To do this, you use the ``attrs`` +argument when creating the widget: + +.. attribute:: Widget.attrs + +For example:: + + class CommentForm(forms.Form): + name = forms.CharField( + widget=forms.TextInput(attrs={'class':'special'})) + url = forms.URLField() + comment = forms.CharField( + widget=forms.TextInput(attrs={'size':'40'})) + +Django will then include the extra attributes in the rendered output:: + + >>> f = CommentForm(auto_id=False) + >>> f.as_table() + Name: + Url: + Comment: diff --git a/docs/ref/generic-views.txt b/docs/ref/generic-views.txt new file mode 100644 index 0000000000..f92a301c2f --- /dev/null +++ b/docs/ref/generic-views.txt @@ -0,0 +1,1106 @@ +.. _ref-generic-views: + +============= +Generic views +============= + +Writing Web applications can be monotonous, because we repeat certain patterns +again and again. In Django, the most common of these patterns have been +abstracted into "generic views" that let you quickly provide common views of +an object without actually needing to write any Python code. + +Django's generic views contain the following: + + * A set of views for doing list/detail interfaces. + + * A set of views for year/month/day archive pages and associated + detail and "latest" pages (for example, the Django weblog's year_, + month_, day_, detail_, and latest_ pages). + + * A set of views for creating, editing, and deleting objects. + +.. _year: http://www.djangoproject.com/weblog/2005/ +.. _month: http://www.djangoproject.com/weblog/2005/jul/ +.. _day: http://www.djangoproject.com/weblog/2005/jul/20/ +.. _detail: http://www.djangoproject.com/weblog/2005/jul/20/autoreload/ +.. _latest: http://www.djangoproject.com/weblog/ + +All of these views are used by creating configuration dictionaries in +your URLconf files and passing those dictionaries as the third member of the +URLconf tuple for a given pattern. For example, here's the URLconf for the +simple weblog app that drives the blog on djangoproject.com:: + + from django.conf.urls.defaults import * + from django_website.apps.blog.models import Entry + + info_dict = { + 'queryset': Entry.objects.all(), + 'date_field': 'pub_date', + } + + urlpatterns = patterns('django.views.generic.date_based', + (r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/(?P[-\w]+)/$', 'object_detail', info_dict), + (r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/$', 'archive_day', info_dict), + (r'^(?P\d{4})/(?P[a-z]{3})/$', 'archive_month', info_dict), + (r'^(?P\d{4})/$', 'archive_year', info_dict), + (r'^$', 'archive_index', info_dict), + ) + +As you can see, this URLconf defines a few options in ``info_dict``. +``'queryset'`` gives the generic view a ``QuerySet`` of objects to use (in this +case, all of the ``Entry`` objects) and tells the generic view which model is +being used. + +Documentation of each generic view follows, along with a list of all keyword +arguments that a generic view expects. Remember that as in the example above, +arguments may either come from the URL pattern (as ``month``, ``day``, +``year``, etc. do above) or from the additional-information dictionary (as for +``queryset``, ``date_field``, etc.). + +Most generic views require the ``queryset`` key, which is a ``QuerySet`` +instance; see :ref:`topics-db-queries` for more information about ``QuerySet`` +objects. + +Most views also take an optional ``extra_context`` dictionary that you can use +to pass any auxiliary information you wish to the view. The values in the +``extra_context`` dictionary can be either functions (or other callables) or +other objects. Functions are evaluated just before they are passed to the +template. However, note that QuerySets retrieve and cache their data when they +are first evaluated, so if you want to pass in a QuerySet via +``extra_context`` that is always fresh you need to wrap it in a function or +lambda that returns the QuerySet. + +"Simple" generic views +====================== + +The ``django.views.generic.simple`` module contains simple views to handle a +couple of common cases: rendering a template when no view logic is needed, +and issuing a redirect. + +``django.views.generic.simple.direct_to_template`` +-------------------------------------------------- + +**Description:** + +Renders a given template, passing it a ``{{ params }}`` template variable, +which is a dictionary of the parameters captured in the URL. + +**Required arguments:** + + * ``template``: The full name of a template to use. + +**Optional arguments:** + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + +**Example:** + +Given the following URL patterns:: + + urlpatterns = patterns('django.views.generic.simple', + (r'^foo/$', 'direct_to_template', {'template': 'foo_index.html'}), + (r'^foo/(?P\d+)/$', 'direct_to_template', {'template': 'foo_detail.html'}), + ) + +... a request to ``/foo/`` would render the template ``foo_index.html``, and a +request to ``/foo/15/`` would render the ``foo_detail.html`` with a context +variable ``{{ params.id }}`` that is set to ``15``. + +``django.views.generic.simple.redirect_to`` +------------------------------------------- + +**Description:** + +Redirects to a given URL. + +The given URL may contain dictionary-style string formatting, which will be +interpolated against the parameters captured in the URL. + +If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410). + +**Required arguments:** + + * ``url``: The URL to redirect to, as a string. Or ``None`` to raise a 410 + (Gone) HTTP error. + +**Example:** + +This example redirects from ``/foo//`` to ``/bar//``:: + + urlpatterns = patterns('django.views.generic.simple', + ('^foo/(?P\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}), + ) + +This example returns a 410 HTTP error for requests to ``/bar/``:: + + urlpatterns = patterns('django.views.generic.simple', + ('^bar/$', 'redirect_to', {'url': None}), + ) + +Date-based generic views +======================== + +Date-based generic views (in the module ``django.views.generic.date_based``) +are views for displaying drilldown pages for date-based data. + +``django.views.generic.date_based.archive_index`` +------------------------------------------------- + +**Description:** + +A top-level index page showing the "latest" objects, by date. Objects with +a date in the *future* are not included unless you set ``allow_future`` to +``True``. + +**Required arguments:** + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``num_latest``: The number of latest objects to send to the template + context. By default, it's 15. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``allow_empty``: A boolean specifying whether to display the page if no + objects are available. If this is ``False`` and no objects are available, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``True``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + + * **New in Django development version:** ``template_object_name``: + Designates the name of the template variable to use in the template + context. By default, this is ``'latest'``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_archive.html`` by default, where: + + * ```` is your model's name in all lowercase. For a model + ``StaffMember``, that'd be ``staffmember``. + + * ```` is the right-most part of the full Python path to + your model's app. For example, if your model lives in + ``apps/blog/models.py``, that'd be ``blog``. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``date_list``: A list of ``datetime.date`` objects representing all + years that have objects available according to ``queryset``. These are + ordered in reverse. This is equivalent to + ``queryset.dates(date_field, 'year')[::-1]``. + + * ``latest``: The ``num_latest`` objects in the system, ordered descending + by ``date_field``. For example, if ``num_latest`` is ``10``, then + ``latest`` will be a list of the latest 10 objects in ``queryset``. + + **New in Django development version:** This variable's name depends on + the ``template_object_name`` parameter, which is ``'latest'`` by default. + If ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo``. + +``django.views.generic.date_based.archive_year`` +------------------------------------------------ + +**Description:** + +A yearly archive page showing all available months in a given year. Objects +with a date in the *future* are not displayed unless you set ``allow_future`` +to ``True``. + +**Required arguments:** + + * ``year``: The four-digit year for which the archive serves. + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``allow_empty``: A boolean specifying whether to display the page if no + objects are available. If this is ``False`` and no objects are available, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``False``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``make_object_list``: A boolean specifying whether to retrieve the full + list of objects for this year and pass those to the template. If ``True``, + this list of objects will be made available to the template as + ``object_list``. (The name ``object_list`` may be different; see the docs + for ``object_list`` in the "Template context" section below.) By default, + this is ``False``. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_archive_year.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``date_list``: A list of ``datetime.date`` objects representing all + months that have objects available in the given year, according to + ``queryset``, in ascending order. + + * ``year``: The given year, as a four-character string. + + * ``object_list``: If the ``make_object_list`` parameter is ``True``, this + will be set to a list of objects available for the given year, ordered by + the date field. This variable's name depends on the + ``template_object_name`` parameter, which is ``'object'`` by default. If + ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo_list``. + + If ``make_object_list`` is ``False``, ``object_list`` will be passed to + the template as an empty list. + +``django.views.generic.date_based.archive_month`` +------------------------------------------------- + +**Description:** + +A monthly archive page showing all objects in a given month. Objects with a +date in the *future* are not displayed unless you set ``allow_future`` to +``True``. + +**Required arguments:** + + * ``year``: The four-digit year for which the archive serves (a string). + + * ``month``: The month for which the archive serves, formatted according to + the ``month_format`` argument. + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``month_format``: A format string that regulates what format the + ``month`` parameter uses. This should be in the syntax accepted by + Python's ``time.strftime``. (See the `strftime docs`_.) It's set to + ``"%b"`` by default, which is a three-letter month abbreviation. To + change it to use numbers, use ``"%m"``. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``allow_empty``: A boolean specifying whether to display the page if no + objects are available. If this is ``False`` and no objects are available, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``False``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_archive_month.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``month``: A ``datetime.date`` object representing the given month. + + * ``next_month``: A ``datetime.date`` object representing the first day of + the next month. If the next month is in the future, this will be + ``None``. + + * ``previous_month``: A ``datetime.date`` object representing the first day + of the previous month. Unlike ``next_month``, this will never be + ``None``. + + * ``object_list``: A list of objects available for the given month. This + variable's name depends on the ``template_object_name`` parameter, which + is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, + this variable's name will be ``foo_list``. + +.. _strftime docs: http://www.python.org/doc/current/lib/module-time.html#l2h-1941 + +``django.views.generic.date_based.archive_week`` +------------------------------------------------ + +**Description:** + +A weekly archive page showing all objects in a given week. Objects with a date +in the *future* are not displayed unless you set ``allow_future`` to ``True``. + +**Required arguments:** + + * ``year``: The four-digit year for which the archive serves (a string). + + * ``week``: The week of the year for which the archive serves (a string). + Weeks start with Sunday. + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``allow_empty``: A boolean specifying whether to display the page if no + objects are available. If this is ``False`` and no objects are available, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``True``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_archive_week.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``week``: A ``datetime.date`` object representing the first day of the + given week. + + * ``object_list``: A list of objects available for the given week. This + variable's name depends on the ``template_object_name`` parameter, which + is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, + this variable's name will be ``foo_list``. + +``django.views.generic.date_based.archive_day`` +----------------------------------------------- + +**Description:** + +A day archive page showing all objects in a given day. Days in the future throw +a 404 error, regardless of whether any objects exist for future days, unless +you set ``allow_future`` to ``True``. + +**Required arguments:** + + * ``year``: The four-digit year for which the archive serves (a string). + + * ``month``: The month for which the archive serves, formatted according to + the ``month_format`` argument. + + * ``day``: The day for which the archive serves, formatted according to the + ``day_format`` argument. + + * ``queryset``: A ``QuerySet`` of objects for which the archive serves. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the date-based archive should use to + determine the objects on the page. + +**Optional arguments:** + + * ``month_format``: A format string that regulates what format the + ``month`` parameter uses. This should be in the syntax accepted by + Python's ``time.strftime``. (See the `strftime docs`_.) It's set to + ``"%b"`` by default, which is a three-letter month abbreviation. To + change it to use numbers, use ``"%m"``. + + * ``day_format``: Like ``month_format``, but for the ``day`` parameter. + It defaults to ``"%d"`` (day of the month as a decimal number, 01-31). + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``allow_empty``: A boolean specifying whether to display the page if no + objects are available. If this is ``False`` and no objects are available, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``False``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_archive_day.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``day``: A ``datetime.date`` object representing the given day. + + * ``next_day``: A ``datetime.date`` object representing the next day. If + the next day is in the future, this will be ``None``. + + * ``previous_day``: A ``datetime.date`` object representing the given day. + Unlike ``next_day``, this will never be ``None``. + + * ``object_list``: A list of objects available for the given day. This + variable's name depends on the ``template_object_name`` parameter, which + is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, + this variable's name will be ``foo_list``. + +``django.views.generic.date_based.archive_today`` +------------------------------------------------- + +**Description:** + +A day archive page showing all objects for *today*. This is exactly the same as +``archive_day``, except the ``year``/``month``/``day`` arguments are not used, +and today's date is used instead. + +``django.views.generic.date_based.object_detail`` +------------------------------------------------- + +**Description:** + +A page representing an individual object. If the object has a date value in the +future, the view will throw a 404 error by default, unless you set +``allow_future`` to ``True``. + +**Required arguments:** + + * ``year``: The object's four-digit year (a string). + + * ``month``: The object's month , formatted according to the + ``month_format`` argument. + + * ``day``: The object's day , formatted according to the ``day_format`` + argument. + + * ``queryset``: A ``QuerySet`` that contains the object. + + * ``date_field``: The name of the ``DateField`` or ``DateTimeField`` in + the ``QuerySet``'s model that the generic view should use to look up the + object according to ``year``, ``month`` and ``day``. + + * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. + + If you provide ``object_id``, it should be the value of the primary-key + field for the object being displayed on this page. + + Otherwise, ``slug`` should be the slug of the given object, and + ``slug_field`` should be the name of the slug field in the ``QuerySet``'s + model. By default, ``slug_field`` is ``'slug'``. + +**Optional arguments:** + + * ``month_format``: A format string that regulates what format the + ``month`` parameter uses. This should be in the syntax accepted by + Python's ``time.strftime``. (See the `strftime docs`_.) It's set to + ``"%b"`` by default, which is a three-letter month abbreviation. To + change it to use numbers, use ``"%m"``. + + * ``day_format``: Like ``month_format``, but for the ``day`` parameter. + It defaults to ``"%d"`` (day of the month as a decimal number, 01-31). + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_name_field``: The name of a field on the object whose value is + the template name to use. This lets you store template names in the data. + In other words, if your object has a field ``'the_template'`` that + contains a string ``'foo.html'``, and you set ``template_name_field`` to + ``'the_template'``, then the generic view for this object will use the + template ``'foo.html'``. + + It's a bit of a brain-bender, but it's useful in some cases. + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + + * ``allow_future``: A boolean specifying whether to include "future" + objects on this page, where "future" means objects in which the field + specified in ``date_field`` is greater than the current date/time. By + default, this is ``False``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_detail.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``object``: The object. This variable's name depends on the + ``template_object_name`` parameter, which is ``'object'`` by default. If + ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo``. + +List/detail generic views +========================= + +The list-detail generic-view framework (in the +``django.views.generic.list_detail`` module) is similar to the date-based one, +except the former simply has two views: a list of objects and an individual +object page. + +``django.views.generic.list_detail.object_list`` +------------------------------------------------ + +**Description:** + +A page representing a list of objects. + +**Required arguments:** + + * ``queryset``: A ``QuerySet`` that represents the objects. + +**Optional arguments:** + + * ``paginate_by``: An integer specifying how many objects should be + displayed per page. If this is given, the view will paginate objects with + ``paginate_by`` objects per page. The view will expect either a ``page`` + query string parameter (via ``GET``) or a ``page`` variable specified in + the URLconf. See `Notes on pagination`_ below. + + * ``page``: The current page number, as an integer, or the string + ``'last'``. This is 1-based. See `Notes on pagination`_ below. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``allow_empty``: A boolean specifying whether to display the page if no + objects are available. If this is ``False`` and no objects are available, + the view will raise a 404 instead of displaying an empty page. By + default, this is ``True``. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. The + view will append ``'_list'`` to the value of this parameter in + determining the variable's name. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_list.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``object_list``: The list of objects. This variable's name depends on the + ``template_object_name`` parameter, which is ``'object'`` by default. If + ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo_list``. + + * ``is_paginated``: A boolean representing whether the results are + paginated. Specifically, this is set to ``False`` if the number of + available objects is less than or equal to ``paginate_by``. + +If the results are paginated, the context will contain these extra variables: + + * **New in Django development version:** ``paginator``: An instance of + ``django.core.paginator.Paginator``. + + * **New in Django development version:** ``page_obj``: An instance of + ``django.core.paginator.Page``. + +Notes on pagination +~~~~~~~~~~~~~~~~~~~ + +If ``paginate_by`` is specified, Django will paginate the results. You can +specify the page number in the URL in one of two ways: + + * Use the ``page`` parameter in the URLconf. For example, this is what + your URLconf might look like:: + + (r'^objects/page(?P[0-9]+)/$', 'object_list', dict(info_dict)) + + * Pass the page number via the ``page`` query-string parameter. For + example, a URL would look like this:: + + /objects/?page=3 + + * To loop over all the available page numbers, use the ``page_range`` + variable. You can iterate over the list provided by ``page_range`` + to create a link to every page of results. + +These values and lists are 1-based, not 0-based, so the first page would be +represented as page ``1``. + +For more on pagination, read the :ref:`pagination documentation +`. + +**New in Django development version:** + +As a special case, you are also permitted to use ``last`` as a value for +``page``:: + + /objects/?page=last + +This allows you to access the final page of results without first having to +determine how many pages there are. + +Note that ``page`` *must* be either a valid page number or the value ``last``; +any other value for ``page`` will result in a 404 error. + +``django.views.generic.list_detail.object_detail`` +-------------------------------------------------- + +A page representing an individual object. + +**Description:** + +A page representing an individual object. + +**Required arguments:** + + * ``queryset``: A ``QuerySet`` that contains the object. + + * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. + + If you provide ``object_id``, it should be the value of the primary-key + field for the object being displayed on this page. + + Otherwise, ``slug`` should be the slug of the given object, and + ``slug_field`` should be the name of the slug field in the ``QuerySet``'s + model. By default, ``slug_field`` is ``'slug'``. + +**Optional arguments:** + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_name_field``: The name of a field on the object whose value is + the template name to use. This lets you store template names in the data. + In other words, if your object has a field ``'the_template'`` that + contains a string ``'foo.html'``, and you set ``template_name_field`` to + ``'the_template'``, then the generic view for this object will use the + template ``'foo.html'``. + + It's a bit of a brain-bender, but it's useful in some cases. + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. + + * ``mimetype``: The MIME type to use for the resulting document. Defaults + to the value of the ``DEFAULT_CONTENT_TYPE`` setting. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_detail.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``object``: The object. This variable's name depends on the + ``template_object_name`` parameter, which is ``'object'`` by default. If + ``template_object_name`` is ``'foo'``, this variable's name will be + ``foo``. + +Create/update/delete generic views +================================== + +The ``django.views.generic.create_update`` module contains a set of functions +for creating, editing and deleting objects. + +**Changed in Django development version:** + +``django.views.generic.create_update.create_object`` and +``django.views.generic.create_update.update_object`` now use the new :ref:`forms +library ` to build and display the form. + +``django.views.generic.create_update.create_object`` +---------------------------------------------------- + +**Description:** + +A page that displays a form for creating an object, redisplaying the form with +validation errors (if there are any) and saving the object. + +**Required arguments:** + + * Either ``form_class`` or ``model`` is required. + + If you provide ``form_class``, it should be a ``django.forms.ModelForm`` + subclass. Use this argument when you need to customize the model's form. + See the :ref:`ModelForm docs ` for more + information. + + Otherwise, ``model`` should be a Django model class and the form used + will be a standard ``ModelForm`` for ``model``. + +**Optional arguments:** + + * ``post_save_redirect``: A URL to which the view will redirect after + saving the object. By default, it's ``object.get_absolute_url()``. + + ``post_save_redirect`` may contain dictionary string formatting, which + will be interpolated against the object's field attributes. For example, + you could use ``post_save_redirect="/polls/%(slug)s/"``. + + * ``login_required``: A boolean that designates whether a user must be + logged in, in order to see the page and save changes. This hooks into the + Django :ref:`authentication system `. By default, this is + ``False``. + + If this is ``True``, and a non-logged-in user attempts to visit this page + or save the form, Django will redirect the request to ``/accounts/login/``. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_form.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``form``: A ``django.forms.ModelForm`` instance representing the form + for creating the object. This lets you refer to form fields easily in the + template system. + + For example, if the model has two fields, ``name`` and ``address``:: + + +

          {{ form.name.label_tag }} {{ form.name }}

          +

          {{ form.address.label_tag }} {{ form.address }}

          + + + See the :ref:`forms documentation ` for more + information about using ``Form`` objects in templates. + +``django.views.generic.create_update.update_object`` +---------------------------------------------------- + +**Description:** + +A page that displays a form for editing an existing object, redisplaying the +form with validation errors (if there are any) and saving changes to the +object. This uses a form automatically generated from the object's +model class. + +**Required arguments:** + + * Either ``form_class`` or ``model`` is required. + + If you provide ``form_class``, it should be a ``django.forms.ModelForm`` + subclass. Use this argument when you need to customize the model's form. + See the :ref:`ModelForm docs ` for more + information. + + Otherwise, ``model`` should be a Django model class and the form used + will be a standard ``ModelForm`` for ``model``. + + * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. + + If you provide ``object_id``, it should be the value of the primary-key + field for the object being displayed on this page. + + Otherwise, ``slug`` should be the slug of the given object, and + ``slug_field`` should be the name of the slug field in the ``QuerySet``'s + model. By default, ``slug_field`` is ``'slug'``. + +**Optional arguments:** + + * ``post_save_redirect``: A URL to which the view will redirect after + saving the object. By default, it's ``object.get_absolute_url()``. + + ``post_save_redirect`` may contain dictionary string formatting, which + will be interpolated against the object's field attributes. For example, + you could use ``post_save_redirect="/polls/%(slug)s/"``. + + * ``login_required``: A boolean that designates whether a user must be + logged in, in order to see the page and save changes. This hooks into the + Django :ref:`authentication system `. By default, this is + ``False``. + + If this is ``True``, and a non-logged-in user attempts to visit this page + or save the form, Django will redirect the request to ``/accounts/login/``. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_form.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``form``: A ``django.forms.ModelForm`` instance representing the form + for editing the object. This lets you refer to form fields easily in the + template system. + + For example, if the model has two fields, ``name`` and ``address``:: + +
          +

          {{ form.name.label_tag }} {{ form.name }}

          +

          {{ form.address.label_tag }} {{ form.address }}

          +
          + + See the :ref:`forms documentation ` for more + information about using ``Form`` objects in templates. + + * ``object``: The original object being edited. This variable's name + depends on the ``template_object_name`` parameter, which is ``'object'`` + by default. If ``template_object_name`` is ``'foo'``, this variable's + name will be ``foo``. + +``django.views.generic.create_update.delete_object`` +---------------------------------------------------- + +**Description:** + +A view that displays a confirmation page and deletes an existing object. The +given object will only be deleted if the request method is ``POST``. If this +view is fetched via ``GET``, it will display a confirmation page that should +contain a form that POSTs to the same URL. + +**Required arguments:** + + * ``model``: The Django model class of the object that the form will + create. + + * Either ``object_id`` or (``slug`` *and* ``slug_field``) is required. + + If you provide ``object_id``, it should be the value of the primary-key + field for the object being displayed on this page. + + Otherwise, ``slug`` should be the slug of the given object, and + ``slug_field`` should be the name of the slug field in the ``QuerySet``'s + model. By default, ``slug_field`` is ``'slug'``. + + * ``post_delete_redirect``: A URL to which the view will redirect after + deleting the object. + +**Optional arguments:** + + * ``login_required``: A boolean that designates whether a user must be + logged in, in order to see the page and save changes. This hooks into the + Django :ref:`authentication system `. By default, this is + ``False``. + + If this is ``True``, and a non-logged-in user attempts to visit this page + or save the form, Django will redirect the request to ``/accounts/login/``. + + * ``template_name``: The full name of a template to use in rendering the + page. This lets you override the default template name (see below). + + * ``template_loader``: The template loader to use when loading the + template. By default, it's ``django.template.loader``. + + * ``extra_context``: A dictionary of values to add to the template + context. By default, this is an empty dictionary. If a value in the + dictionary is callable, the generic view will call it + just before rendering the template. + + * ``context_processors``: A list of template-context processors to apply to + the view's template. + + * ``template_object_name``: Designates the name of the template variable + to use in the template context. By default, this is ``'object'``. + +**Template name:** + +If ``template_name`` isn't specified, this view will use the template +``/_confirm_delete.html`` by default. + +**Template context:** + +In addition to ``extra_context``, the template's context will be: + + * ``object``: The original object that's about to be deleted. This + variable's name depends on the ``template_object_name`` parameter, which + is ``'object'`` by default. If ``template_object_name`` is ``'foo'``, + this variable's name will be ``foo``. diff --git a/docs/ref/index.txt b/docs/ref/index.txt new file mode 100644 index 0000000000..ac71175abf --- /dev/null +++ b/docs/ref/index.txt @@ -0,0 +1,21 @@ +.. _ref-index: + +API Reference +============= + +.. toctree:: + :maxdepth: 1 + + contrib/index + databases + django-admin + forms/index + generic-views + middleware + models/index + request-response + settings + templates/index + unicode + files/index + \ No newline at end of file diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt new file mode 100644 index 0000000000..48a3e81cc4 --- /dev/null +++ b/docs/ref/middleware.txt @@ -0,0 +1,200 @@ +.. _ref-middleware: + +============================= +Built-in middleware reference +============================= + +.. module:: django.middleware + :synopsis: Django's built-in middleware classes. + +This document explains all middleware components that come with Django. For +information on how how to use them and how to write your own middleware, see the +:ref:`middleware usage guide `. + +Available middleware +==================== + +Cache middleware +---------------- + +.. module:: django.middleware.cache + :synopsis: Middleware for the site-wide cache + +.. class:: django.middleware.cache.CacheMiddleware + +Enables the site-wide cache. If this is enabled, each Django-powered page will +be cached for as long as the :setting:`CACHE_MIDDLEWARE_SECONDS` setting +defines. See the :ref:`cache documentation `. + +"Common" middleware +------------------- + +.. module:: django.middleware.common + :synopsis: Middleware adding "common" conveniences for perfectionists. + +.. class:: django.middleware.common.CommonMiddleware + +Adds a few conveniences for perfectionists: + + * Forbids access to user agents in the :setting:`DISALLOWED_USER_AGENTS` + setting, which should be a list of strings. + + * Performs URL rewriting based on the :setting:`APPEND_SLASH` and + :setting:`PREPEND_WWW` settings. + + If :setting:`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 + :setting:`APPEND_SLASH` has changed slightly in the development version. + It didn't used to check whether the pattern was matched in the URLconf. + + If :setting:`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 :setting:`USE_ETAGS` setting. If + :setting:`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. + +View metadata middleware +------------------------ + +.. module:: django.middleware.doc + :synopsis: Middleware to help your app self-document. + +.. class:: django.middleware.doc.XViewMiddleware + +Sends custom ``X-View`` HTTP headers to HEAD requests that come from IP +addresses defined in the :setting:`INTERNAL_IPS` setting. This is used by +Django's automatic documentation system. + +GZIP middleware +--------------- + +.. module:: django.middleware.gzip + :synopsis: Middleware to serve gziped content for performance. + +.. class:: 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 compatibility), or +responses that have the ``Content-Encoding`` header already specified. + +Conditional GET middleware +-------------------------- + +.. module:: django.middleware.http + :synopsis: Middleware handling advanced HTTP features. + +.. class:: 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 +:class:`~django.http.HttpNotModified`. + +Also sets the ``Date`` and ``Content-Length`` response-headers. + +Reverse proxy middleware +------------------------ + +.. class:: 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``. + +Locale middleware +----------------- + +.. module:: django.middleware.locale + :synopsis: Middleware to enable language selection based on the request. + +.. class:: django.middleware.locale.LocaleMiddleware + +Enables language selection based on data from the request. It customizes content +for each user. See the :ref:`internationalization documentation `. + +Session middleware +------------------ + +.. module:: django.contrib.sessions.middleware + :synopsis: Session middleware. + +.. class:: django.contrib.sessions.middleware.SessionMiddleware + +Enables session support. See the :ref:`session documentation +`. + +Authentication middleware +------------------------- + +.. module:: django.contrib.auth.middleware + :synopsis: Authentication middleware + +.. class:: django.contrib.auth.middleware.AuthenticationMiddleware + +Adds the ``user`` attribute, representing the currently-logged-in user, to every +incoming ``HttpRequest`` object. See :ref:` Authentication in Web requests +`. + +CSRF protection middleware +-------------------------- + +.. module:: django.contrib.csrf.middleware + :synopsis: Middleware adding protection against Cross Site Request Forgeries. + +.. class:: 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 +:ref:`Cross Site Request Forgery protection documentation `. + +Transaction middleware +---------------------- + +.. module:: django.middleware.transaction + :synopsis: Middleware binding a database transaction to each web request. + +.. class:: 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 :ref:`transaction management documentation `. + diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt new file mode 100644 index 0000000000..f0638d1ea5 --- /dev/null +++ b/docs/ref/models/fields.txt @@ -0,0 +1,902 @@ +.. _ref-models-fields: + +===================== +Model field reference +===================== + +.. module:: django.db.models.fields + :synopsis: Built-in field types. + +This document contains all the gory details about all the `field options`_ and +`field types`_ Django's got to offer. + +.. seealso:: + + If the built-in fields don't do the trick, you can easily :ref:`write your + own custom model fields `. + +.. note:: + + Technically, these models are defined in :mod:`django.db.models.fields`, but + for convenience they're imported into :mod:`django.db.models`; the standard + convention is to use ``from django.db import models`` and refer to fields as + ``models.Field``. + +.. _common-model-field-options: + +Field options +============= + +The following arguments are available to all field types. All are optional. + +``null`` +-------- + +.. attribute:: Field.null + +If ``True``, Django will store empty values as ``NULL`` in the database. Default +is ``False``. + +Note that empty string values will always get stored as empty strings, not as +``NULL``. Only use ``null=True`` for non-string fields such as integers, +booleans and dates. For both types of fields, you will also need to set +``blank=True`` if you wish to permit empty values in forms, as the +:attr:`~Field.null` parameter only affects database storage (see +:attr:`~Field.blank`). + +Avoid using :attr:`~Field.null` on string-based fields such as +:class:`CharField` and :class:`TextField` unless you have an excellent reason. +If a string-based field has ``null=True``, that means it has two possible values +for "no data": ``NULL``, and the empty string. In most cases, it's redundant to +have two possible values for "no data;" Django convention is to use the empty +string, not ``NULL``. + +.. note:: + + When using the Oracle database backend, the ``null=True`` option will be + coerced for string-based fields that can blank, and the value ``NULL`` will + be stored to denote the empty string. + +``blank`` +--------- + +.. attribute:: Field.blank + +If ``True``, the field is allowed to be blank. Default is ``False``. + +Note that this is different than :attr:`~Field.null`. :attr:`~Field.null` is +purely database-related, whereas :attr:`~Field.blank` is validation-related. If +a field has ``blank=True``, validation on Django's admin site will allow entry +of an empty value. If a field has ``blank=False``, the field will be required. + +``choices`` +----------- + +.. attribute:: Field.choices + +An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this +field. + +If this is given, Django's admin will use a select box instead of the standard +text field and will limit choices to the choices given. + +A choices list looks like this:: + + YEAR_IN_SCHOOL_CHOICES = ( + ('FR', 'Freshman'), + ('SO', 'Sophomore'), + ('JR', 'Junior'), + ('SR', 'Senior'), + ('GR', 'Graduate'), + ) + +The first element in each tuple is the actual value to be stored. The second +element is the human-readable name for the option. + +The choices list can be defined either as part of your model class:: + + class Foo(models.Model): + GENDER_CHOICES = ( + ('M', 'Male'), + ('F', 'Female'), + ) + gender = models.CharField(max_length=1, choices=GENDER_CHOICES) + +or outside your model class altogether:: + + GENDER_CHOICES = ( + ('M', 'Male'), + ('F', 'Female'), + ) + class Foo(models.Model): + gender = models.CharField(max_length=1, choices=GENDER_CHOICES) + +You can also collect your available choices into named groups that can +be used for organizational purposes:: + + MEDIA_CHOICES = ( + ('Audio', ( + ('vinyl', 'Vinyl'), + ('cd', 'CD'), + ) + ), + ('Video', ( + ('vhs', 'VHS Tape'), + ('dvd', 'DVD'), + ) + ), + ('unknown', 'Unknown'), + ) + +The first element in each tuple is the name to apply to the group. The +second element is an iterable of 2-tuples, with each 2-tuple containing +a value and a human-readable name for an option. Grouped options may be +combined with ungrouped options within a single list (such as the +`unknown` option in this example). + +For each model field that has :attr:`~Field.choices` set, Django will add a +method to retrieve the human-readable name for the field's current value. See +:meth:`~django.db.models.Model.get_FOO_display` in the database API +documentation. + +Finally, note that choices can be any iterable object -- not necessarily a list +or tuple. This lets you construct choices dynamically. But if you find yourself +hacking :attr:`~Field.choices` to be dynamic, you're probably better off using a +proper database table with a :class:`ForeignKey`. :attr:`~Field.choices` is +meant for static data that doesn't change much, if ever. + +``core`` +-------- + +.. attribute:: Field.core + +For objects that are edited inline to a related object. + +In the Django admin, if all "core" fields in an inline-edited object are +cleared, the object will be deleted. + +It is an error to have an inline-editable relation without at least one +``core=True`` field. + +Please note that each field marked "core" is treated as a required field by the +Django admin site. Essentially, this means you should put ``core=True`` on all +required fields in your related object that is being edited inline. + +``db_column`` +------------- + +.. attribute:: Field.db_column + +The name of the database column to use for this field. If this isn't given, +Django will use the field's name. + +If your database column name is an SQL reserved word, or contains +characters that aren't allowed in Python variable names -- notably, the +hyphen -- that's OK. Django quotes column and table names behind the +scenes. + +``db_index`` +------------ + +.. attribute:: Field.db_index + +If ``True``, djadmin:`django-admin.py sqlindexes ` will output a +``CREATE INDEX`` statement for this field. + +``db_tablespace`` +----------------- + +.. attribute:: Field.db_tablespace + +**New in Django development version** + +The name of the database tablespace to use for this field's index, if this field +is indexed. The default is the project's :setting:`DEFAULT_INDEX_TABLESPACE` +setting, if set, or the :attr:`~Field.db_tablespace` of the model, if any. If +the backend doesn't support tablespaces, this option is ignored. + +``default`` +----------- + +.. attribute:: Field.default + +The default value for the field. This can be a value or a callable object. If +callable it will be called every time a new object is created. + +``editable`` +------------ + +.. attribute:: Field.editable + +If ``False``, the field will not be editable in the admin or via forms +automatically generated from the model class. Default is ``True``. + +``help_text`` +------------- + +.. attribute:: Field.help_text + +Extra "help" text to be displayed under the field on the object's admin form. +It's useful for documentation even if your object doesn't have an admin form. + +Note that this value is *not* HTML-escaped when it's displayed in the admin +interface. This lets you include HTML in :attr:`~Field.help_text` if you so +desire. For example:: + + help_text="Please use the following format: YYYY-MM-DD." + +Alternatively you can use plain text and +``django.utils.html.escape()`` to escape any HTML special characters. + +``primary_key`` +--------------- + +.. attribute:: Field.primary_key + +If ``True``, this field is the primary key for the model. + +If you don't specify ``primary_key=True`` for any fields in your model, Django +will automatically add an :class:`IntegerField` to hold the primary key, so you +don't need to set ``primary_key=True`` on any of your fields unless you want to +override the default primary-key behavior. For more, see +:ref:`automatic-primary-key-fields`. + +``primary_key=True`` implies :attr:`null=False ` and :attr:`unique=True `. +Only one primary key is allowed on an object. + +``unique`` +---------- + +.. attribute:: Field.unique + +If ``True``, this field must be unique throughout the table. + +This is enforced at the database level and at the Django admin-form level. If +you try to save a model with a duplicate value in a :attr:`~Field.unique` +field, a :exc:`django.db.IntegrityError` will be raised by the model's +:meth:`~django.db.models.Model.save` method. + +This options is valid on all field types except :class:`ManyToManyField`. + +``unique_for_date`` +------------------- + +.. attribute:: Field.unique_for_date + +Set this to the name of a :class:`DateField` or :class:`DateTimeField` to +require that this field be unique for the value of the date field. + +For example, if you have a field ``title`` that has +``unique_for_date="pub_date"``, then Django wouldn't allow the entry of two +records with the same ``title`` and ``pub_date``. + +This is enforced at the Django admin-form level but not at the database level. + +``unique_for_month`` +-------------------- + +.. attribute:: Field.unique_for_month + +Like :attr:`~Field.unique_for_date`, but requires the field to be unique with +respect to the month. + +``unique_for_year`` +------------------- + +.. attribute:: Field.unique_for_year + +Like :attr:`~Field.unique_for_date` and :attr:`~Field.unique_for_month`. + +``validator_list`` +------------------ + +.. attribute:: Field.validator_list + +A list of extra validators to apply to the field. Each should be a callable that +takes the parameters ``field_data, all_data`` and raises +:exc:`django.core.validators.ValidationError` for errors. + +.. _model-field-types: + +Field types +=========== + +.. currentmodule:: django.db.models + +``AutoField`` +------------- + +.. class:: AutoField(**options) + +An :class:`IntegerField` that automatically increments +according to available IDs. You usually won't need to use this directly; a +primary key field will automatically be added to your model if you don't specify +otherwise. See :ref:`automatic-primary-key-fields`. + +``BooleanField`` +---------------- + +.. class:: BooleanField(**options) + +A true/false field. + +The admin represents this as a checkbox. + +``CharField`` +------------- + +.. class:: CharField(max_length=None, [**options]) + +A string field, for small- to large-sized strings. + +For large amounts of text, use :class:`~django.db.models.TextField`. + +The admin represents this as an ```` (a single-line input). + +:class:`CharField` has one extra required argument: + +.. attribute:: CharField.max_length + + The maximum length (in characters) of the field. The max_length is enforced + at the database level and in Django's validation. + +``CommaSeparatedIntegerField`` +------------------------------ + +.. class:: CommaSeparatedIntegerField(max_length=None, [**options]) + +A field of integers separated by commas. As in :class:`CharField`, the +:attr:`~CharField.max_length` argument is required. + +``DateField`` +------------- + +.. class:: DateField([auto_now=False, auto_now_add=False, **options]) + +A date field. Has a few extra optional arguments: + +.. attribute:: DateField.auto_now + + Automatically set the field to now every time the object is saved. Useful + for "last-modified" timestamps. Note that the current date is *always* used; + it's not just a default value that you can override. + +.. attribute:: DateField.auto_now_add + + Automatically set the field to now when the object is first created. Useful + for creation of timestamps. Note that the current date is *always* used; + it's not just a default value that you can override. + +The admin represents this as an ```` with a JavaScript +calendar, and a shortcut for "Today". The JavaScript calendar will always start +the week on a Sunday. + +``DateTimeField`` +----------------- + +.. class:: DateTimeField([auto_now=False, auto_now_add=False, **options]) + +A date and time field. Takes the same extra options as :class:`DateField`. + +The admin represents this as two ```` fields, with JavaScript +shortcuts. + +``DecimalField`` +---------------- + +**New in Django development version** + +.. class:: DecimalField(max_digits=None, decimal_places=None, [**options]) + +A fixed-precision decimal number, represented in Python by a +:class:`~decimal.Decimal` instance. Has two **required** arguments: + +.. attribute:: DecimalField.max_digits + + The maximum number of digits allowed in the number + +.. attribute:: DecimalField.decimal_places + + The number of decimal places to store with the number + +For example, to store numbers up to 999 with a resolution of 2 decimal places, +you'd use:: + + models.DecimalField(..., max_digits=5, decimal_places=2) + +And to store numbers up to approximately one billion with a resolution of 10 +decimal places:: + + models.DecimalField(..., max_digits=19, decimal_places=10) + +The admin represents this as an ```` (a single-line input). + +``EmailField`` +-------------- + +.. class:: EmailField([max_length=75, **options]) + +A :class:`CharField` that checks that the value is a valid e-mail address. + +In Django 0.96, this doesn't accept :attr:`~CharField.max_length`; its +:class:`~CharField.max_length` is automatically set to 75. In the Django +development version, :class:`~CharField.max_length` is set to 75 by default, but +you can specify it to override default behavior. + +``FileField`` +------------- + +.. class:: FileField(upload_to=None, [max_length=100, **options]) + +A file-upload field. Has one **required** argument: + +.. attribute:: FileField.upload_to + + A local filesystem path that will be appended to your :setting:`MEDIA_ROOT` + setting to determine the output of the ``get__url()`` helper + function. + + This path may contain `strftime formatting`_, which will be replaced by the + date/time of the file upload (so that uploaded files don't fill up the given + directory). + + **New in Django development version** + + This may also be a callable, such as a function, which will be called to + obtain the upload path, including the filename. This callable must be + able to accept two arguments, and return a Unix-style path (with forward + slashes) to be passed along to the storage system. The two arguments that will + be passed are: + + ====================== =============================================== + Argument Description + ====================== =============================================== + ``instance`` An instance of the model where the + ``FileField`` is defined. More specifically, + this is the particular instance where the + current file is being attached. + + In most cases, this object will not have been + saved to the database yet, so if it uses the + default ``AutoField``, *it might not yet have a + value for its primary key field*. + + ``filename`` The filename that was originally given to the + file. This may or may not be taken into account + when determining the final destination path. + ====================== =============================================== + +Also has one optional argument: + +.. attribute:: FileField.storage + + **New in Django development version.** + + Optional. A storage object, which handles the storage and retrieval of your + files. See :ref:`topics-files` for details on how to provide this object. + +The admin represents this field as an ```` (a file-upload +widget). + +Using a :class:`FileField` or an :class:`ImageField` (see below) in a model +takes a few steps: + + 1. In your settings file, you'll need to define :setting:`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 + :setting:`MEDIA_URL` as the base public URL of that directory. Make sure + that this directory is writable by the Web server's user account. + + 2. Add the :class:`FileField` or :class:`ImageField` to your model, making + sure to define the :attr:`~FileField.upload_to` option to tell Django to + which subdirectory of :setting:`MEDIA_ROOT` it should upload files. + + 3. All that will be stored in your database is a path to the file + (relative to :setting:`MEDIA_ROOT`). You'll most likely want to use the + convenience ``get__url`` function provided by Django. For + example, if your :class:`ImageField` is called ``mug_shot``, you can get + the absolute URL to your image in a template with ``{{ + object.get_mug_shot_url }}``. + +For example, say your :setting:`MEDIA_ROOT` is set to ``'/home/media'``, and +:attr:`~FileField.upload_to` is set to ``'photos/%Y/%m/%d'``. The ``'%Y/%m/%d'`` +part of :attr:`~FileField.upload_to` is `strftime formatting`_; ``'%Y'`` is the +four-digit year, ``'%m'`` is the two-digit month and ``'%d'`` is the two-digit +day. If you upload a file on Jan. 15, 2007, it will be saved in the directory +``/home/media/photos/2007/01/15``. + +If you want to retrieve the upload file's on-disk filename, or a URL that refers +to that file, or the file's size, you can use the ``File.name``, ``File.url`` +and ``File.size`` attributes; see :ref:`topics-files`. + +Note that whenever you deal with uploaded files, you should pay close attention +to where you're uploading them and what type of files they are, to avoid +security holes. *Validate all uploaded files* so that you're sure the files are +what you think they are. For example, if you blindly let somebody upload files, +without validation, to a directory that's within your Web server's document +root, then somebody could upload a CGI or PHP script and execute that script by +visiting its URL on your site. Don't allow that. + +**New in development version:** By default, :class:`FileField` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the :attr:`~CharField.max_length` argument. + +.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941 + +``FilePathField`` +----------------- + +.. class:: FilePathField(path=None, [match=None, recursive=False, max_length=100, **options]) + +A :class:`CharField` whose choices are limited to the filenames in a certain +directory on the filesystem. Has three special arguments, of which the first is +**required**: + +.. attribute:: FilePathField.path + + Required. The absolute filesystem path to a directory from which this + :class:`FilePathField` should get its choices. Example: ``"/home/images"``. + +.. attribute:: FilePathField.match + + Optional. A regular expression, as a string, that :class:`FilePathField` + will use to filter filenames. Note that the regex will be applied to the + base filename, not the full path. Example: ``"foo.*\.txt$"``, which will + match a file called ``foo23.txt`` but not ``bar.txt`` or ``foo23.gif``. + +.. attribute:: FilePathField.recursive + + Optional. Either ``True`` or ``False``. Default is ``False``. Specifies + whether all subdirectories of :attr:`~FilePathField.path` should be included + +Of course, these arguments can be used together. + +The one potential gotcha is that :attr:`~FilePathField.match` applies to the +base filename, not the full path. So, this example:: + + FilePathField(path="/home/images", match="foo.*", recursive=True) + +...will match ``/home/images/foo.gif`` but not ``/home/images/foo/bar.gif`` +because the :attr:`~FilePathField.match` applies to the base filename +(``foo.gif`` and ``bar.gif``). + +**New in development version:** By default, :class:`FilePathField` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the :attr:`~CharField.max_length` argument. + +``FloatField`` +-------------- + +.. class:: FloatField([**options]) + +**Changed in Django development version** + +A floating-point number represented in Python by a ``float`` instance. + +The admin represents this as an ```` (a single-line input). + +**NOTE:** The semantics of :class:`FloatField` have changed in the Django +development version. See the `Django 0.96 documentation`_ for the old behavior. + +.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield + +``ImageField`` +-------------- + +.. class:: ImageField(upload_to-None, [height_field=None, width_field=None, max_length=100, **options]) + +Like :class:`FileField`, but validates that the uploaded object is a valid +image. Has two extra optional arguments: + +.. attribute:: ImageField.height_field + + Name of a model field which will be auto-populated with the height of the + image each time the model instance is saved. + +.. attribute:: ImageField.width_field` + + Name of a model field which will be auto-populated with the width of the + image each time the model instance is saved. + +In addition to the special attributes that are available for :class:`FileField`, +an :class:`ImageField` also has ``File.height`` and ``File.width`` attributes. +See :ref:`topics-files`. + +Requires the `Python Imaging Library`_. + +.. _Python Imaging Library: http://www.pythonware.com/products/pil/ + +**New in development version:** By default, :class:`ImageField` instances are +created as ``varchar(100)`` columns in your database. As with other fields, you +can change the maximum length using the :attr:`~CharField.max_length` argument. + +``IntegerField`` +---------------- + +.. class:: IntegerField([**options]) + +An integer. The admin represents this as an ```` (a +single-line input). + +``IPAddressField`` +------------------ + +.. class:: IPAddressField([**options]) + +An IP address, in string format (e.g. "192.0.2.30"). The admin represents this +as an ```` (a single-line input). + +``NullBooleanField`` +-------------------- + +.. class:: NullBooleanField([**options]) + +Like a :class:`BooleanField`, but allows ``NULL`` as one of the options. Use +this instead of a :class:`BooleanField` with ``null=True``. The admin represents +this as a ``