diff options
Diffstat (limited to 'parts/django/docs')
249 files changed, 0 insertions, 68443 deletions
diff --git a/parts/django/docs/Makefile b/parts/django/docs/Makefile deleted file mode 100644 index 9301315..0000000 --- a/parts/django/docs/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest - -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b djangohtml $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/django" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - make -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/parts/django/docs/_ext/applyxrefs.py b/parts/django/docs/_ext/applyxrefs.py deleted file mode 100644 index 3809088..0000000 --- a/parts/django/docs/_ext/applyxrefs.py +++ /dev/null @@ -1,88 +0,0 @@ -"""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/parts/django/docs/_ext/djangodocs.py b/parts/django/docs/_ext/djangodocs.py deleted file mode 100644 index 8c4b511..0000000 --- a/parts/django/docs/_ext/djangodocs.py +++ /dev/null @@ -1,265 +0,0 @@ -""" -Sphinx plugins for Django documentation. -""" -import os -import re - -from docutils import nodes, transforms -try: - import json -except ImportError: - try: - import simplejson as json - except ImportError: - try: - from django.utils import simplejson as json - except ImportError: - json = None - -from sphinx import addnodes, roles -from sphinx.builders.html import StandaloneHTMLBuilder -from sphinx.writers.html import SmartyPantsHTMLTranslator -from sphinx.util.console import bold -from sphinx.util.compat import Directive - -# RE for option descriptions without a '--' prefix -simple_option_desc_re = re.compile( - r'([-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)') - -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 = parse_django_adminopt_node, - ) - app.add_config_value('django_next_version', '0.0', True) - app.add_directive('versionadded', VersionDirective) - app.add_directive('versionchanged', VersionDirective) - app.add_transform(SuppressBlockquotes) - app.add_builder(DjangoStandaloneHTMLBuilder) - - -class VersionDirective(Directive): - has_content = True - required_arguments = 1 - optional_arguments = 1 - final_argument_whitespace = True - option_spec = {} - - def run(self): - env = self.state.document.settings.env - arg0 = self.arguments[0] - is_nextversion = env.config.django_next_version == arg0 - ret = [] - node = addnodes.versionmodified() - ret.append(node) - if not is_nextversion: - if len(self.arguments) == 1: - linktext = 'Please, see the release notes </releases/%s>' % (arg0) - try: - xrefs = roles.XRefRole()('doc', linktext, linktext, self.lineno, self.state) # Sphinx >= 1.0 - except AttributeError: - xrefs = roles.xfileref_role('doc', linktext, linktext, self.lineno, self.state) # Sphinx < 1.0 - node.extend(xrefs[0]) - node['version'] = arg0 - else: - node['version'] = "Development version" - node['type'] = self.name - if len(self.arguments) == 2: - inodes, messages = self.state.inline_text(self.arguments[1], self.lineno+1) - node.extend(inodes) - if self.content: - self.state.nested_parse(self.content, self.content_offset, node) - ret = ret + messages - env.note_versionchange(node['type'], node['version'], node, self.lineno) - return ret - - -class SuppressBlockquotes(transforms.Transform): - """ - Remove the default blockquotes that encase indented list, tables, etc. - """ - default_priority = 300 - - suppress_blockquote_child_nodes = ( - nodes.bullet_list, - nodes.enumerated_list, - nodes.definition_list, - nodes.literal_block, - nodes.doctest_block, - nodes.line_block, - nodes.table - ) - - def apply(self): - for node in self.document.traverse(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(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')) - - # <big>? Really? - def visit_desc_parameterlist(self, node): - self.body.append('(') - self.first_param = 1 - - def depart_desc_parameterlist(self, node): - self.body.append(')') - - # - # Don't apply smartypants to literal blocks - # - def visit_literal_block(self, node): - self.no_smarty += 1 - SmartyPantsHTMLTranslator.visit_literal_block(self, node) - - def depart_literal_block(self, node): - SmartyPantsHTMLTranslator.depart_literal_block(self, node) - self.no_smarty -= 1 - - # - # Turn the "new in version" stuff (versionadded/versionchanged) into a - # better callout -- the Sphinx default is just a little span, - # which is a bit less obvious that I'd like. - # - # FIXME: these messages are all hardcoded in English. We need to change - # that to accomodate other language docs, but I can't work out how to make - # that work. - # - version_text = { - 'deprecated': 'Deprecated in Django %s', - 'versionchanged': 'Changed in Django %s', - 'versionadded': 'New in Django %s', - } - - def visit_versionmodified(self, node): - self.body.append( - self.starttag(node, 'div', CLASS=node['type']) - ) - title = "%s%s" % ( - self.version_text[node['type']] % node['version'], - len(node) and ":" or "." - ) - self.body.append('<span class="title">%s</span> ' % title) - - def depart_versionmodified(self, node): - self.body.append("</div>\n") - - # Give each section a unique ID -- nice for custom CSS hooks - def visit_section(self, node): - old_ids = node.get('ids', []) - node['ids'] = ['s-' + i for i in old_ids] - node['ids'].extend(old_ids) - 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 += addnodes.desc_name(title, title) - return sig - -def parse_django_adminopt_node(env, sig, signode): - """A copy of sphinx.directives.CmdoptionDesc.parse_signature()""" - try: - from sphinx.domains.std import option_desc_re # Sphinx >= 1.0 - except ImportError: - from sphinx.directives.desc import option_desc_re # Sphinx < 1.0 - count = 0 - firstname = '' - for m in option_desc_re.finditer(sig): - optname, args = m.groups() - if count: - signode += addnodes.desc_addname(', ', ', ') - signode += addnodes.desc_name(optname, optname) - signode += addnodes.desc_addname(args, args) - if not count: - firstname = optname - count += 1 - if not count: - for m in simple_option_desc_re.finditer(sig): - optname, args = m.groups() - if count: - signode += addnodes.desc_addname(', ', ', ') - signode += addnodes.desc_name(optname, optname) - signode += addnodes.desc_addname(args, args) - if not count: - firstname = optname - count += 1 - if not firstname: - raise ValueError - return firstname - - -class DjangoStandaloneHTMLBuilder(StandaloneHTMLBuilder): - """ - Subclass to add some extra things we need. - """ - - name = 'djangohtml' - - def finish(self): - super(DjangoStandaloneHTMLBuilder, self).finish() - if json is None: - self.warn("cannot create templatebuiltins.js due to missing simplejson dependency") - return - self.info(bold("writing templatebuiltins.js...")) - try: - # Sphinx < 1.0 - xrefs = self.env.reftargets.items() - templatebuiltins = dict([('ttags', [n for ((t,n),(l,a)) in xrefs - if t == 'ttag' and - l == 'ref/templates/builtins']), - ('tfilters', [n for ((t,n),(l,a)) in xrefs - if t == 'tfilter' and - l == 'ref/templates/builtins'])]) - except AttributeError: - # Sphinx >= 1.0 - xrefs = self.env.domaindata["std"]["objects"] - templatebuiltins = dict([('ttags', [n for ((t,n), (l,a)) in xrefs.items() - if t == 'templatetag' and - l == 'ref/templates/builtins' ]), - ('tfilters', [n for ((t,n), (l,a)) in xrefs.items() - if t == 'templatefilter' and - t == 'ref/templates/builtins'])]) - outfilename = os.path.join(self.outdir, "templatebuiltins.js") - f = open(outfilename, 'wb') - f.write('var django_template_builtins = ') - json.dump(templatebuiltins, f) - f.write(';\n') - f.close(); diff --git a/parts/django/docs/_ext/literals_to_xrefs.py b/parts/django/docs/_ext/literals_to_xrefs.py deleted file mode 100644 index 569193c..0000000 --- a/parts/django/docs/_ext/literals_to_xrefs.py +++ /dev/null @@ -1,171 +0,0 @@ -""" -Runs through a reST file looking for old-style literals, and helps replace them -with new-style references. -""" - -import re -import sys -import shelve - -refre = re.compile(r'``([^`\s]+?)``') - -ROLES = ( - 'attr', - 'class', - "djadmin", - 'data', - 'exc', - 'file', - 'func', - 'lookup', - 'meth', - 'mod' , - "djadminopt", - "ref", - "setting", - "term", - "tfilter", - "ttag", - - # special - "skip" -) - -ALWAYS_SKIP = [ - "NULL", - "True", - "False", -] - -def fixliterals(fname): - data = open(fname).read() - - last = 0 - new = [] - storage = shelve.open("/tmp/literals_to_xref.shelve") - lastvalues = storage.get("lastvalues", {}) - - for m in refre.finditer(data): - - new.append(data[last:m.start()]) - last = m.end() - - line_start = data.rfind("\n", 0, m.start()) - line_end = data.find("\n", m.end()) - prev_start = data.rfind("\n", 0, line_start) - next_end = data.find("\n", line_end + 1) - - # Skip always-skip stuff - if m.group(1) in ALWAYS_SKIP: - new.append(m.group(0)) - continue - - # skip when the next line is a title - next_line = data[m.end():next_end].strip() - if next_line[0] in "!-/:-@[-`{-~" and all(c == next_line[0] for c in next_line): - new.append(m.group(0)) - continue - - sys.stdout.write("\n"+"-"*80+"\n") - sys.stdout.write(data[prev_start+1:m.start()]) - sys.stdout.write(colorize(m.group(0), fg="red")) - sys.stdout.write(data[m.end():next_end]) - sys.stdout.write("\n\n") - - replace_type = None - while replace_type is None: - replace_type = raw_input( - colorize("Replace role: ", fg="yellow") - ).strip().lower() - if replace_type and replace_type not in ROLES: - replace_type = None - - if replace_type == "": - new.append(m.group(0)) - continue - - if replace_type == "skip": - new.append(m.group(0)) - ALWAYS_SKIP.append(m.group(1)) - continue - - default = lastvalues.get(m.group(1), m.group(1)) - if default.endswith("()") and replace_type in ("class", "func", "meth"): - default = default[:-2] - replace_value = raw_input( - colorize("Text <target> [", fg="yellow") + default + colorize("]: ", fg="yellow") - ).strip() - if not replace_value: - replace_value = default - new.append(":%s:`%s`" % (replace_type, replace_value)) - lastvalues[m.group(1)] = replace_value - - new.append(data[last:]) - open(fname, "w").write("".join(new)) - - storage["lastvalues"] = lastvalues - storage.close() - -# -# The following is taken from django.utils.termcolors and is copied here to -# avoid the dependancy. -# - - -def colorize(text='', opts=(), **kwargs): - """ - Returns your text, enclosed in ANSI graphics codes. - - Depends on the keyword arguments 'fg' and 'bg', and the contents of - the opts tuple/list. - - Returns the RESET code if no parameters are given. - - Valid colors: - 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' - - Valid options: - 'bold' - 'underscore' - 'blink' - 'reverse' - 'conceal' - 'noreset' - string will not be auto-terminated with the RESET code - - Examples: - colorize('hello', fg='red', bg='blue', opts=('blink',)) - colorize() - colorize('goodbye', opts=('underscore',)) - print colorize('first line', fg='red', opts=('noreset',)) - print 'this should be red too' - print colorize('and so should this') - print 'this should not be red' - """ - color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white') - foreground = dict([(color_names[x], '3%s' % x) for x in range(8)]) - background = dict([(color_names[x], '4%s' % x) for x in range(8)]) - - RESET = '0' - opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} - - text = str(text) - code_list = [] - if text == '' and len(opts) == 1 and opts[0] == 'reset': - return '\x1b[%sm' % RESET - for k, v in kwargs.iteritems(): - if k == 'fg': - code_list.append(foreground[v]) - elif k == 'bg': - code_list.append(background[v]) - for o in opts: - if o in opt_dict: - code_list.append(opt_dict[o]) - if 'noreset' not in opts: - text = text + '\x1b[%sm' % RESET - return ('\x1b[%sm' % ';'.join(code_list)) + text - -if __name__ == '__main__': - try: - fixliterals(sys.argv[1]) - except (KeyboardInterrupt, SystemExit): - print
\ No newline at end of file diff --git a/parts/django/docs/_theme/djangodocs/genindex.html b/parts/django/docs/_theme/djangodocs/genindex.html deleted file mode 100644 index 486994a..0000000 --- a/parts/django/docs/_theme/djangodocs/genindex.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "basic/genindex.html" %} - -{% block bodyclass %}{% endblock %} -{% block sidebarwrapper %}{% endblock %}
\ No newline at end of file diff --git a/parts/django/docs/_theme/djangodocs/layout.html b/parts/django/docs/_theme/djangodocs/layout.html deleted file mode 100644 index ef91dd7..0000000 --- a/parts/django/docs/_theme/djangodocs/layout.html +++ /dev/null @@ -1,124 +0,0 @@ -{% extends "basic/layout.html" %} - -{%- macro secondnav() %} - {%- if prev %} - « <a href="{{ prev.link|e }}" title="{{ prev.title|e }}">previous</a> - {{ reldelim2 }} - {%- endif %} - {%- if parents %} - <a href="{{ parents.0.link|e }}" title="{{ parents.0.title|e }}" accesskey="U">up</a> - {%- else %} - <a title="{{ docstitle }}" href="{{ pathto('index') }}" accesskey="U">up</a> - {%- endif %} - {%- if next %} - {{ reldelim2 }} - <a href="{{ next.link|e }}" title="{{ next.title|e }}">next</a> » - {%- endif %} -{%- endmacro %} - -{% block extrahead %} -{{ super() }} -<script type="text/javascript" src="{{ pathto('templatebuiltins.js', 1) }}"></script> -<script type="text/javascript"> -(function($) { - if (!django_template_builtins) { - // templatebuiltins.js missing, do nothing. - return; - } - $(document).ready(function() { - // Hyperlink Django template tags and filters - var base = "{{ pathto('ref/templates/builtins') }}"; - if (base == "#") { - // Special case for builtins.html itself - base = ""; - } - // Tags are keywords, class '.k' - $("div.highlight\\-html\\+django span.k").each(function(i, elem) { - var tagname = $(elem).text(); - if ($.inArray(tagname, django_template_builtins.ttags) != -1) { - var fragment = tagname.replace(/_/, '-'); - $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>"); - } - }); - // Filters are functions, class '.nf' - $("div.highlight\\-html\\+django span.nf").each(function(i, elem) { - var filtername = $(elem).text(); - if ($.inArray(filtername, django_template_builtins.tfilters) != -1) { - var fragment = filtername.replace(/_/, '-'); - $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>"); - } - }); - }); -})(jQuery); -</script> -{% endblock %} - -{% block document %} - <div id="custom-doc" class="{% block bodyclass %}{{ 'yui-t6' if pagename != 'index' else '' }}{% endblock %}"> - <div id="hd"> - <h1><a href="{{ pathto('index') }}">{{ docstitle }}</a></h1> - <div id="global-nav"> - <a title="Home page" href="{{ pathto('index') }}">Home</a> {{ reldelim2 }} - <a title="Table of contents" href="{{ pathto('contents') }}">Table of contents</a> {{ reldelim2 }} - <a title="Global index" href="{{ pathto('genindex') }}">Index</a> {{ reldelim2 }} - <a title="Module index" href="{{ pathto('py-modindex') }}">Modules</a> - </div> - <div class="nav">{{ secondnav() }}</div> - </div> - - <div id="bd"> - <div id="yui-main"> - <div class="yui-b"> - <div class="yui-g" id="{{ pagename|replace('/', '-') }}"> - {% block body %}{% endblock %} - </div> - </div> - </div> - {% block sidebarwrapper %} - {% if pagename != 'index' %} - <div class="yui-b" id="sidebar"> - {{ sidebar() }} - {%- if last_updated %} - <h3>Last update:</h3> - <p class="topless">{{ last_updated }}</p> - {%- endif %} - </div> - {% endif %} - {% endblock %} - </div> - - <div id="ft"> - <div class="nav">{{ secondnav() }}</div> - </div> - </div> -{% endblock %} - -{% block sidebarrel %} - <h3>Browse</h3> - <ul> - {% if prev %} - <li>Prev: <a href="{{ prev.link }}">{{ prev.title }}</a></li> - {% endif %} - {% if next %} - <li>Next: <a href="{{ next.link }}">{{ next.title }}</a></li> - {% endif %} - </ul> - <h3>You are here:</h3> - <ul> - <li> - <a href="{{ pathto('index') }}">{{ docstitle }}</a> - {% for p in parents %} - <ul><li><a href="{{ p.link }}">{{ p.title }}</a> - {% endfor %} - <ul><li>{{ title }}</li></ul> - {% for p in parents %}</li></ul>{% endfor %} - </li> - </ul> -{% endblock %} - -{# Empty some default blocks out #} -{% block relbar1 %}{% endblock %} -{% block relbar2 %}{% endblock %} -{% block sidebar1 %}{% endblock %} -{% block sidebar2 %}{% endblock %} -{% block footer %}{% endblock %}
\ No newline at end of file diff --git a/parts/django/docs/_theme/djangodocs/modindex.html b/parts/django/docs/_theme/djangodocs/modindex.html deleted file mode 100644 index 59a5cb3..0000000 --- a/parts/django/docs/_theme/djangodocs/modindex.html +++ /dev/null @@ -1,3 +0,0 @@ -{% extends "basic/modindex.html" %} -{% block bodyclass %}{% endblock %} -{% block sidebarwrapper %}{% endblock %}
\ No newline at end of file diff --git a/parts/django/docs/_theme/djangodocs/search.html b/parts/django/docs/_theme/djangodocs/search.html deleted file mode 100644 index 943478c..0000000 --- a/parts/django/docs/_theme/djangodocs/search.html +++ /dev/null @@ -1,3 +0,0 @@ -{% extends "basic/search.html" %} -{% block bodyclass %}{% endblock %} -{% block sidebarwrapper %}{% endblock %}
\ No newline at end of file diff --git a/parts/django/docs/_theme/djangodocs/static/default.css b/parts/django/docs/_theme/djangodocs/static/default.css deleted file mode 100644 index 9dc69ee..0000000 --- a/parts/django/docs/_theme/djangodocs/static/default.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url(reset-fonts-grids.css); -@import url(djangodocs.css); -@import url(homepage.css);
\ No newline at end of file diff --git a/parts/django/docs/_theme/djangodocs/static/djangodocs.css b/parts/django/docs/_theme/djangodocs/static/djangodocs.css deleted file mode 100644 index 4adb838..0000000 --- a/parts/django/docs/_theme/djangodocs/static/djangodocs.css +++ /dev/null @@ -1,135 +0,0 @@ -/*** 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 li { 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; } - -/* Restore colors of pygments hyperlinked code */ -#bd .highlight .k a:link, #bd .highlight .k a:visited { color: #000000; text-decoration: none; border-bottom: 1px dotted #000000; } -#bd .highlight .nf a:link, #bd .highlight .nf a:visited { color: #990000; text-decoration: none; border-bottom: 1px dotted #990000; } - - -/*** 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.png) .8em .8em no-repeat;} -div.admonition-philosophy { padding-left:65px; background:url(docicons-philosophy.png) .8em .8em no-repeat;} -div.admonition-behind-the-scenes { padding-left:65px; background:url(docicons-behindscenes.png) .8em .8em no-repeat;} - -/*** versoinadded/changes ***/ -div.versionadded, div.versionchanged { } -div.versionadded span.title, div.versionchanged span.title { font-weight: bold; } - -/*** 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%; } diff --git a/parts/django/docs/_theme/djangodocs/static/docicons-behindscenes.png b/parts/django/docs/_theme/djangodocs/static/docicons-behindscenes.png Binary files differdeleted file mode 100644 index dc901bc..0000000 --- a/parts/django/docs/_theme/djangodocs/static/docicons-behindscenes.png +++ /dev/null diff --git a/parts/django/docs/_theme/djangodocs/static/docicons-note.png b/parts/django/docs/_theme/djangodocs/static/docicons-note.png Binary files differdeleted file mode 100644 index 357545f..0000000 --- a/parts/django/docs/_theme/djangodocs/static/docicons-note.png +++ /dev/null diff --git a/parts/django/docs/_theme/djangodocs/static/docicons-philosophy.png b/parts/django/docs/_theme/djangodocs/static/docicons-philosophy.png Binary files differdeleted file mode 100644 index 09f16c7..0000000 --- a/parts/django/docs/_theme/djangodocs/static/docicons-philosophy.png +++ /dev/null diff --git a/parts/django/docs/_theme/djangodocs/static/homepage.css b/parts/django/docs/_theme/djangodocs/static/homepage.css deleted file mode 100644 index 276c547..0000000 --- a/parts/django/docs/_theme/djangodocs/static/homepage.css +++ /dev/null @@ -1,22 +0,0 @@ -#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/parts/django/docs/_theme/djangodocs/static/reset-fonts-grids.css b/parts/django/docs/_theme/djangodocs/static/reset-fonts-grids.css deleted file mode 100644 index f5238d7..0000000 --- a/parts/django/docs/_theme/djangodocs/static/reset-fonts-grids.css +++ /dev/null @@ -1,8 +0,0 @@ -/* -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/parts/django/docs/_theme/djangodocs/theme.conf b/parts/django/docs/_theme/djangodocs/theme.conf deleted file mode 100644 index be43c72..0000000 --- a/parts/django/docs/_theme/djangodocs/theme.conf +++ /dev/null @@ -1,4 +0,0 @@ -[theme] -inherit = basic -stylesheet = default.css -pygments_style = trac diff --git a/parts/django/docs/conf.py b/parts/django/docs/conf.py deleted file mode 100644 index ac6aed1..0000000 --- a/parts/django/docs/conf.py +++ /dev/null @@ -1,269 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Django documentation build configuration file, created by -# sphinx-quickstart on Thu Mar 27 09:06:53 2008. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# The contents of this file are pickled, so don't put values in the namespace -# that aren't pickleable (module imports are okay, they're removed automatically). -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "_ext"))) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ["djangodocs"] - -# Add any paths that contain templates here, relative to this directory. -# templates_path = [] - -# The suffix of source filenames. -source_suffix = '.txt' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'contents' - -# General substitutions. -project = 'Django' -copyright = 'Django Software Foundation and contributors' - - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '1.2' -# The full version, including alpha/beta/rc tags. -release = version -# The next version to be released -django_next_version = '1.3' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = False - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'trac' - -# Sphinx will recurse into subversion configuration folders and try to read -# any document file within. These should be ignored. -# Note: exclude_dirnames is new in Sphinx 0.5 -exclude_dirnames = ['.svn'] - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "djangodocs" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ["_theme"] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# 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 = ["_static"] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# 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 = '' - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Djangodoc' - -modindex_common_prefix = ["django."] - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# 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 = [ - ('contents', 'django.tex', u'Django Documentation', - u'Django Software Foundation', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('contents', 'django', 'Django Documentation', ['Django Software Foundation'], 1) -] - - -# -- Options for Epub output --------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = u'Django' -epub_author = u'Django Software Foundation' -epub_publisher = u'Django Software Foundation' -epub_copyright = u'2010, Django Software Foundation' - -# The language of the text. It defaults to the language option -# or en if the language is not set. -#epub_language = '' - -# The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -#epub_identifier = '' - -# A unique identification for the text. -#epub_uid = '' - -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_pre_files = [] - -# HTML files shat should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_post_files = [] - -# A list of files that should not be packed into the epub file. -#epub_exclude_files = [] - -# The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 - -# Allow duplicate toc entries. -#epub_tocdup = True diff --git a/parts/django/docs/contents.txt b/parts/django/docs/contents.txt deleted file mode 100644 index 14fe007..0000000 --- a/parts/django/docs/contents.txt +++ /dev/null @@ -1,41 +0,0 @@ -.. _contents: - -============================= -Django documentation contents -============================= - -.. toctree:: - :hidden: - - index - -.. 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 diff --git a/parts/django/docs/faq/admin.txt b/parts/django/docs/faq/admin.txt deleted file mode 100644 index 1512675..0000000 --- a/parts/django/docs/faq/admin.txt +++ /dev/null @@ -1,96 +0,0 @@ -FAQ: The admin -============== - -I can't log in. When I enter a valid username and password, it just brings up the login page again, with no error messages. ---------------------------------------------------------------------------------------------------------------------------- - -The login cookie isn't being set correctly, because the domain of the cookie -sent out by Django doesn't match the domain in your browser. Try these two -things: - - * Set the ``SESSION_COOKIE_DOMAIN`` setting in your admin config file - to match your domain. For example, if you're going to - "http://www.example.com/admin/" in your browser, in - "myproject.settings" you should set ``SESSION_COOKIE_DOMAIN = 'www.example.com'``. - - * Some browsers (Firefox?) don't like to accept cookies from domains that - don't have dots in them. If you're running the admin site on "localhost" - or another domain that doesn't have a dot in it, try going to - "localhost.localdomain" or "127.0.0.1". And set - ``SESSION_COOKIE_DOMAIN`` accordingly. - -I can't log in. When I enter a valid username and password, it brings up the login page again, with a "Please enter a correct username and password" error. ------------------------------------------------------------------------------------------------------------------------------------------------------------ - -If you're sure your username and password are correct, make sure your user -account has ``is_active`` and ``is_staff`` set to True. The admin site only -allows access to users with those two fields both set to True. - -How can I prevent the cache middleware from caching the admin site? -------------------------------------------------------------------- - -Set the :setting:`CACHE_MIDDLEWARE_ANONYMOUS_ONLY` setting to ``True``. See the -:doc:`cache documentation </topics/cache>` for more information. - -How do I automatically set a field's value to the user who last edited the object in the admin? ------------------------------------------------------------------------------------------------ - -The :class:`~django.contrib.admin.ModelAdmin` class provides customization hooks -that allow you to transform an object as it saved, using details from the -request. By extracting the current user from the request, and customizing the -:meth:`~django.contrib.admin.ModelAdmin.save_model` hook, you can update an -object to reflect the user that edited it. See :ref:`the documentation on -ModelAdmin methods <model-admin-methods>` for an example. - -How do I limit admin access so that objects can only be edited by the users who created them? ---------------------------------------------------------------------------------------------- - -The :class:`~django.contrib.admin.ModelAdmin` class also provides customization -hooks that allow you to control the visibility and editability of objects in the -admin. Using the same trick of extracting the user from the request, the -:meth:`~django.contrib.admin.ModelAdmin.queryset` and -:meth:`~django.contrib.admin.ModelAdmin.has_change_permission` can be used to -control the visibility and editability of objects in the admin. - -My admin-site CSS and images showed up fine using the development server, but they're not displaying when using mod_python. ---------------------------------------------------------------------------------------------------------------------------- - -See :ref:`serving the admin files <serving-the-admin-files>` -in the "How to use Django with mod_python" documentation. - -My "list_filter" contains a ManyToManyField, but the filter doesn't display. ----------------------------------------------------------------------------- - -Django won't bother displaying the filter for a ``ManyToManyField`` if there -are fewer than two related objects. - -For example, if your ``list_filter`` includes ``sites``, and there's only one -site in your database, it won't display a "Site" filter. In that case, -filtering by site would be meaningless. - -How can I customize the functionality of the admin interface? -------------------------------------------------------------- - -You've got several options. If you want to piggyback on top of an add/change -form that Django automatically generates, you can attach arbitrary JavaScript -modules to the page via the model's ``class Admin`` ``js`` parameter. That -parameter is a list of URLs, as strings, pointing to JavaScript modules that -will be included within the admin form via a ``<script>`` tag. - -If you want more flexibility than simply tweaking the auto-generated forms, -feel free to write custom views for the admin. The admin is powered by Django -itself, and you can write custom views that hook into the authentication -system, check permissions and do whatever else they need to do. - -If you want to customize the look-and-feel of the admin interface, read the -next question. - -The dynamically-generated admin site is ugly! How can I change it? ------------------------------------------------------------------- - -We like it, but if you don't agree, you can modify the admin site's -presentation by editing the CSS stylesheet and/or associated image files. The -site is built using semantic HTML and plenty of CSS hooks, so any changes you'd -like to make should be possible by editing the stylesheet. We've got a -:doc:`guide to the CSS used in the admin </obsolete/admin-css>` to get you started. - diff --git a/parts/django/docs/faq/contributing.txt b/parts/django/docs/faq/contributing.txt deleted file mode 100644 index 81c06f3..0000000 --- a/parts/django/docs/faq/contributing.txt +++ /dev/null @@ -1,102 +0,0 @@ -FAQ: Contributing code -====================== - -How can I get started contributing code to Django? --------------------------------------------------- - -Thanks for asking! We've written an entire document devoted to this question. -It's titled :doc:`Contributing to Django </internals/contributing>`. - -I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch? --------------------------------------------------------------------------------------------- - -Don't worry: We're not ignoring you! - -It's important to understand there is a difference between "a ticket is being -ignored" and "a ticket has not been attended to yet." Django's ticket system -contains hundreds of open tickets, of various degrees of impact on end-user -functionality, and Django's developers have to review and prioritize. - -On top of that: the people who work on Django are all volunteers. As a result, -the amount of time that we have to work on the framework is limited and will -vary from week to week depending on our spare time. If we're busy, we may not -be able to spend as much time on Django as we might want. - -The best way to make sure tickets do not get hung up on the way to checkin is -to make it dead easy, even for someone who may not be intimately familiar with -that area of the code, to understand the problem and verify the fix: - - * Are there clear instructions on how to reproduce the bug? If this - touches a dependency (such as PIL), a contrib module, or a specific - database, are those instructions clear enough even for someone not - familiar with it? - - * If there are several patches attached to the ticket, is it clear what - each one does, which ones can be ignored and which matter? - - * Does the patch include a unit test? If not, is there a very clear - explanation why not? A test expresses succinctly what the problem is, - and shows that the patch actually fixes it. - -If your patch stands no chance of inclusion in Django, we won't ignore it -- -we'll just close the ticket. So if your ticket is still open, it doesn't mean -we're ignoring you; it just means we haven't had time to look at it yet. - -When and how might I remind the core team of a patch I care about? ------------------------------------------------------------------- - -A polite, well-timed message to the mailing list is one way to get attention. -To determine the right time, you need to keep an eye on the schedule. If you -post your message when the core developers are trying to hit a feature -deadline or manage a planning phase, you're not going to get the sort of -attention you require. However, if you draw attention to a ticket when the -core developers are paying particular attention to bugs -- just before a bug -fixing sprint, or in the lead up to a beta release for example -- you're much -more likely to get a productive response. - -Gentle IRC reminders can also work -- again, strategically timed if possible. -During a bug sprint would be a very good time, for example. - -Another way to get traction is to pull several related tickets together. When -the core developers sit down to fix a bug in an area they haven't touched for -a while, it can take a few minutes to remember all the fine details of how -that area of code works. If you collect several minor bug fixes together into -a similarly themed group, you make an attractive target, as the cost of coming -up to speed on an area of code can be spread over multiple tickets. - -Please refrain from emailing core developers personally, or repeatedly raising -the same issue over and over. This sort of behavior will not gain you any -additional attention -- certainly not the attention that you need in order to -get your pet bug addressed. - -But I've reminded you several times and you keep ignoring my patch! -------------------------------------------------------------------- - -Seriously - we're not ignoring you. If your patch stands no chance of -inclusion in Django, we'll close the ticket. For all the other tickets, we -need to prioritize our efforts, which means that some tickets will be -addressed before others. - -One of the criteria that is used to prioritize bug fixes is the number of -people that will likely be affected by a given bug. Bugs that have the -potential to affect many people will generally get priority over those that -are edge cases. - -Another reason that bugs might be ignored for while is if the bug is a symptom -of a larger problem. While we can spend time writing, testing and applying -lots of little patches, sometimes the right solution is to rebuild. If a -rebuild or refactor of a particular component has been proposed or is -underway, you may find that bugs affecting that component will not get as much -attention. Again, this is just a matter of prioritizing scarce resources. By -concentrating on the rebuild, we can close all the little bugs at once, and -hopefully prevent other little bugs from appearing in the future. - -Whatever the reason, please keep in mind that while you may hit a particular -bug regularly, it doesn't necessarily follow that every single Django user -will hit the same bug. Different users use Django in different ways, stressing -different parts of the code under different conditions. When we evaluate the -relative priorities, we are generally trying to consider the needs of the -entire community, not just the severity for one particular user. This doesn't -mean that we think your problem is unimportant -- just that in the limited -time we have available, we will always err on the side of making 10 people -happy rather than making 1 person happy. diff --git a/parts/django/docs/faq/general.txt b/parts/django/docs/faq/general.txt deleted file mode 100644 index 96abad2..0000000 --- a/parts/django/docs/faq/general.txt +++ /dev/null @@ -1,192 +0,0 @@ -FAQ: General -============ - -Why does this project exist? ----------------------------- - -Django grew from a very practical need: World Online, a newspaper Web -operation, is responsible for building intensive Web applications on journalism -deadlines. In the fast-paced newsroom, World Online often has only a matter of -hours to take a complicated Web application from concept to public launch. - -At the same time, the World Online Web developers have consistently been -perfectionists when it comes to following best practices of Web development. - -In fall 2003, the World Online developers (Adrian Holovaty and Simon Willison) -ditched PHP and began using Python to develop its Web sites. As they built -intensive, richly interactive sites such as Lawrence.com, they began to extract -a generic Web development framework that let them build Web applications more -and more quickly. They tweaked this framework constantly, adding improvements -over two years. - -In summer 2005, World Online decided to open-source the resulting software, -Django. Django would not be possible without a whole host of open-source -projects -- `Apache`_, `Python`_, and `PostgreSQL`_ to name a few -- and we're -thrilled to be able to give something back to the open-source community. - -.. _Apache: http://httpd.apache.org/ -.. _Python: http://www.python.org/ -.. _PostgreSQL: http://www.postgresql.org/ - -What does "Django" mean, and how do you pronounce it? ------------------------------------------------------ - -Django is named after `Django Reinhardt`_, a gypsy jazz guitarist from the 1930s -to early 1950s. To this day, he's considered one of the best guitarists of all time. - -Listen to his music. You'll like it. - -Django is pronounced **JANG**-oh. Rhymes with FANG-oh. The "D" is silent. - -We've also recorded an `audio clip of the pronunciation`_. - -.. _Django Reinhardt: http://en.wikipedia.org/wiki/Django_Reinhardt -.. _audio clip of the pronunciation: http://red-bean.com/~adrian/django_pronunciation.mp3 - -Is Django stable? ------------------ - -Yes. World Online has been using Django for more than three years. Sites built -on Django have weathered traffic spikes of over one million hits an hour and a -number of Slashdottings. Yes, it's quite stable. - -Does Django scale? ------------------- - -Yes. Compared to development time, hardware is cheap, and so Django is -designed to take advantage of as much hardware as you can throw at it. - -Django uses a "shared-nothing" architecture, which means you can add hardware -at any level -- database servers, caching servers or Web/application servers. - -The framework cleanly separates components such as its database layer and -application layer. And it ships with a simple-yet-powerful -:doc:`cache framework </topics/cache>`. - -Who's behind this? ------------------- - -Django was originally developed at World Online, the Web department of a -newspaper in Lawrence, Kansas, USA. Django's now run by an international team of -volunteers; you can read all about them over at the :doc:`list of committers -</internals/committers>` - -Which sites use Django? ------------------------ - -The Django wiki features a consistently growing `list of Django-powered sites`_. -Feel free to add your Django-powered site to the list. - -.. _list of Django-powered sites: http://code.djangoproject.com/wiki/DjangoPoweredSites - -.. _mtv: - -Django appears to be a MVC framework, but you call the Controller the "view", and the View the "template". How come you don't use the standard names? ------------------------------------------------------------------------------------------------------------------------------------------------------ - -Well, the standard names are debatable. - -In our interpretation of MVC, the "view" describes the data that gets presented -to the user. It's not necessarily *how* the data *looks*, but *which* data is -presented. The view describes *which data you see*, not *how you see it.* It's -a subtle distinction. - -So, in our case, a "view" is the Python callback function for a particular URL, -because that callback function describes which data is presented. - -Furthermore, it's sensible to separate content from presentation -- which is -where templates come in. In Django, a "view" describes which data is presented, -but a view normally delegates to a template, which describes *how* the data is -presented. - -Where does the "controller" fit in, then? In Django's case, it's probably the -framework itself: the machinery that sends a request to the appropriate view, -according to the Django URL configuration. - -If you're hungry for acronyms, you might say that Django is a "MTV" framework --- that is, "model", "template", and "view." That breakdown makes much more -sense. - -At the end of the day, of course, it comes down to getting stuff done. And, -regardless of how things are named, Django gets stuff done in a way that's most -logical to us. - -<Framework X> does <feature Y> -- why doesn't Django? ------------------------------------------------------ - -We're well aware that there are other awesome Web frameworks out there, and -we're not averse to borrowing ideas where appropriate. However, Django was -developed precisely because we were unhappy with the status quo, so please be -aware that "because <Framework X> does it" is not going to be sufficient reason -to add a given feature to Django. - -Why did you write all of Django from scratch, instead of using other Python libraries? --------------------------------------------------------------------------------------- - -When Django was originally written a couple of years ago, Adrian and Simon -spent quite a bit of time exploring the various Python Web frameworks -available. - -In our opinion, none of them were completely up to snuff. - -We're picky. You might even call us perfectionists. (With deadlines.) - -Over time, we stumbled across open-source libraries that did things we'd -already implemented. It was reassuring to see other people solving similar -problems in similar ways, but it was too late to integrate outside code: We'd -already written, tested and implemented our own framework bits in several -production settings -- and our own code met our needs delightfully. - -In most cases, however, we found that existing frameworks/tools inevitably had -some sort of fundamental, fatal flaw that made us squeamish. No tool fit our -philosophies 100%. - -Like we said: We're picky. - -We've documented our philosophies on the -:doc:`design philosophies page </misc/design-philosophies>`. - -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/ - -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 (reStructuredText) 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 diff --git a/parts/django/docs/faq/help.txt b/parts/django/docs/faq/help.txt deleted file mode 100644 index d84b3f5..0000000 --- a/parts/django/docs/faq/help.txt +++ /dev/null @@ -1,73 +0,0 @@ -FAQ: Getting Help -================= - -How do I do X? Why doesn't Y work? Where can I go to get help? --------------------------------------------------------------- - -If this FAQ doesn't contain an answer to your question, you might want to -try the `django-users mailing list`_. Feel free to ask any question related -to installing, using, or debugging Django. - -If you prefer IRC, the `#django IRC channel`_ on the Freenode IRC network is an -active community of helpful individuals who may be able to solve your problem. - -.. _`django-users mailing list`: http://groups.google.com/group/django-users -.. _`#django IRC channel`: irc://irc.freenode.net/django - -Why hasn't my message appeared on django-users? ------------------------------------------------ - -django-users_ has a lot of subscribers. This is good for the community, as -it means many people are available to contribute answers to questions. -Unfortunately, it also means that django-users_ is an attractive target for -spammers. - -In order to combat the spam problem, when you join the django-users_ mailing -list, we manually moderate the first message you send to the list. This means -that spammers get caught, but it also means that your first question to the -list might take a little longer to get answered. We apologize for any -inconvenience that this policy may cause. - -.. _django-users: http://groups.google.com/group/django-users - -Nobody on django-users answered my question! What should I do? --------------------------------------------------------------- - -Try making your question more specific, or provide a better example of your -problem. - -As with most open-source mailing lists, the folks on django-users_ are -volunteers. If nobody has answered your question, it may be because nobody -knows the answer, it may be because nobody can understand the question, or it -may be that everybody that can help is busy. One thing you might try is to ask -the question on IRC -- visit the `#django IRC channel`_ on the Freenode IRC -network. - -You might notice we have a second mailing list, called django-developers_ -- -but please don't e-mail support questions to this mailing list. This list is -for discussion of the development of Django itself. Asking a tech support -question there is considered quite impolite. - -.. _django-developers: http://groups.google.com/group/django-developers - -I think I've found a bug! What should I do? -------------------------------------------- - -Detailed instructions on how to handle a potential bug can be found in our -:ref:`Guide to contributing to Django <reporting-bugs>`. - -I think I've found a security problem! What should I do? --------------------------------------------------------- - -If you think you've found a security problem with Django, please send a message -to security@djangoproject.com. This is a private list only open to long-time, -highly trusted Django developers, and its archives are not publicly readable. - -Due to the sensitive nature of security issues, we ask that if you think you -have found a security problem, *please* don't send a message to one of the -public mailing lists. Django has a -:ref:`policy for handling security issues <reporting-security-issues>`; -while a defect is outstanding, we would like to minimize any damage that -could be inflicted through public knowledge of that defect. - -.. _`policy for handling security issues`: ../contributing/#reporting-security-issues diff --git a/parts/django/docs/faq/index.txt b/parts/django/docs/faq/index.txt deleted file mode 100644 index 347caba..0000000 --- a/parts/django/docs/faq/index.txt +++ /dev/null @@ -1,14 +0,0 @@ -========== -Django FAQ -========== - -.. toctree:: - :maxdepth: 2 - - general - install - usage - help - models - admin - contributing
\ No newline at end of file diff --git a/parts/django/docs/faq/install.txt b/parts/django/docs/faq/install.txt deleted file mode 100644 index 3fbcb38..0000000 --- a/parts/django/docs/faq/install.txt +++ /dev/null @@ -1,102 +0,0 @@ -FAQ: Installation -================= - -How do I get started? ---------------------- - - #. `Download the code`_. - #. Install Django (read the :doc:`installation guide </intro/install>`). - #. Walk through the :doc:`tutorial </intro/tutorial01>`. - #. Check out the rest of the :doc:`documentation </index>`, and `ask questions`_ if you - run into trouble. - -.. _`Download the code`: http://www.djangoproject.com/download/ -.. _ask questions: http://www.djangoproject.com/community/ - -What are Django's prerequisites? --------------------------------- - -Django requires Python_, specifically any version of Python from 2.4 -through 2.7. 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, Django -follows the WSGI_ spec, which means it can run on a variety of server -platforms. See :doc:`Deploying Django </howto/deployment/index>` for some -popular alternatives. Also, the `server arrangements wiki page`_ contains -details for several deployment strategies. - -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/ -.. _WSGI: http://www.python.org/dev/peps/pep-0333/ -.. _server arrangements wiki page: http://code.djangoproject.com/wiki/ServerArrangements -.. _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.4 versus newer Python versions, such as Python 2.5 or 2.6? ------------------------------------------------------------------------------------------------ - -Not in the core framework. Currently, Django itself officially supports any -version of Python from 2.4 through 2.7, inclusive. However, newer versions of -Python are often faster, have more features, and are better supported. -Third-party applications for use with Django are, of course, free to set their -own version requirements. - -Over the next year or two Django will begin dropping support for older Python -versions as part of a migration which will end with Django running on Python 3 -(see below for details). - -All else being equal, we recommend that you use the latest 2.x release -(currently Python 2.7). This will let you take advantage of the numerous -improvements and optimizations to the Python language since version 2.4, and -will help ease the process of dropping support for older Python versions on -the road to Python 3. - -Can I use Django with Python 2.3? ---------------------------------- - -Django 1.1 (and earlier) supported Python 2.3. Django 1.2 and newer does not. -We highly recommend you upgrade Python if at all possible, but Django 1.1 will -continue to work on Python 2.3. - -Can I use Django with Python 3? -------------------------------- - -Not at the moment. Python 3.0 introduced a number of -backwards-incompatible changes to the Python language, and although -these changes are generally a good thing for Python's future, it will -be a while before most Python software catches up and is able to run -on Python 3.0. For larger Python-based software like Django, the -transition is expected to take at least a year or two (since it -involves dropping support for older Python releases and so must be -done gradually). - -In the meantime, Python 2.x releases will be supported and provided -with bug fixes and security updates by the Python development team, so -continuing to use a Python 2.x release during the transition should -not present any risk. - -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 stable version or development version? -------------------------------------------------------- - -Generally, if you're using code in production, you should be using a -stable release. The Django project publishes a full stable release -every nine months or so, with bugfix updates in between. These stable -releases contain the API that is covered by our backwards -compatibility guarantees; if you write code against stable releases, -you shouldn't have any problems upgrading when the next official -version is released. diff --git a/parts/django/docs/faq/models.txt b/parts/django/docs/faq/models.txt deleted file mode 100644 index f00d453..0000000 --- a/parts/django/docs/faq/models.txt +++ /dev/null @@ -1,105 +0,0 @@ -FAQ: Databases and models -========================= - -.. _faq-see-raw-sql-queries: - -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. -Note that the raw SQL logged in ``connection.queries`` may not include -parameter quoting. Parameter quoting is performed by the database-specific -backend, and not all backends provide a way to retrieve the SQL after quoting. - -.. versionadded:: 1.2 - -If you are using :doc:`multiple databases</topics/db/multi-db>`, you can use the -same interface on each member of the ``connections`` dictionary:: - - >>> from django.db import connections - >>> connections['my_db_alias'].queries - -Can I use Django with a pre-existing database? ----------------------------------------------- - -Yes. See :doc:`Integrating with a legacy database </howto/legacy-databases>`. - -If I make changes to a model, how do I update the database? ------------------------------------------------------------ - -If you don't mind clearing data, your project's ``manage.py`` utility has an -option to reset the SQL for a particular application:: - - manage.py reset appname - -This drops any tables associated with ``appname`` and recreates them. - -If you do care about deleting data, you'll have to execute the ``ALTER TABLE`` -statements manually in your database. That's the way we've always done it, -because dealing with data is a very sensitive operation that we've wanted to -avoid automating. That said, there's some work being done to add partially -automated database-upgrade functionality. - -Do Django models support multiple-column primary keys? ------------------------------------------------------- - -No. Only single-column primary keys are supported. - -But this isn't an issue in practice, because there's nothing stopping you from -adding other constraints (using the ``unique_together`` model option or -creating the constraint directly in your database), and enforcing the -uniqueness at that level. Single-column primary keys are needed for things such -as the admin interface to work; e.g., you need a simple way of being able to -specify an object to edit or delete. - -How do I add database-specific options to my CREATE TABLE statements, such as specifying MyISAM as the table type? ------------------------------------------------------------------------------------------------------------------- - -We try to avoid adding special cases in the Django code to accommodate all the -database-specific options such as table type, etc. If you'd like to use any of -these options, create an :ref:`SQL initial data file <initial-sql>` that -contains ``ALTER TABLE`` statements that do what you want to do. The initial -data files are executed in your database after the ``CREATE TABLE`` statements. - -For example, if you're using MySQL and want your tables to use the MyISAM table -type, create an initial data file and put something like this in it:: - - ALTER TABLE myapp_mytable ENGINE=MyISAM; - -As explained in the :ref:`SQL initial data file <initial-sql>` documentation, -this SQL file can contain arbitrary SQL, so you can make any sorts of changes -you need to make. - -Why is Django leaking memory? ------------------------------ - -Django isn't known to leak memory. If you find your Django processes are -allocating more and more memory, with no sign of releasing it, check to make -sure your ``DEBUG`` setting is set to ``False``. 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() diff --git a/parts/django/docs/faq/usage.txt b/parts/django/docs/faq/usage.txt deleted file mode 100644 index c11514c..0000000 --- a/parts/django/docs/faq/usage.txt +++ /dev/null @@ -1,77 +0,0 @@ -FAQ: Using Django -================= - -Why do I get an error about importing DJANGO_SETTINGS_MODULE? -------------------------------------------------------------- - -Make sure that: - - * The environment variable DJANGO_SETTINGS_MODULE is set to a - fully-qualified Python module (i.e. "mysite.settings"). - - * Said module is on ``sys.path`` (``import mysite.settings`` should work). - - * The module doesn't contain syntax errors (of course). - - * If you're using mod_python but *not* using Django's request handler, - you'll need to work around a mod_python bug related to the use of - ``SetEnv``; before you import anything from Django you'll need to do - the following:: - - os.environ.update(req.subprocess_env) - - (where ``req`` is the mod_python request object). - -I can't stand your template language. Do I have to use it? ----------------------------------------------------------- - -We happen to think our template engine is the best thing since chunky bacon, -but we recognize that choosing a template language runs close to religion. -There's nothing about Django that requires using the template language, so -if you're attached to ZPT, Cheetah, or whatever, feel free to use those. - -Do I have to use your model/database layer? -------------------------------------------- - -Nope. Just like the template system, the model/database layer is decoupled from -the rest of the framework. - -The one exception is: If you use a different database library, you won't get to -use Django's automatically-generated admin site. That app is coupled to the -Django database layer. - -How do I use image and file fields? ------------------------------------ - -Using a :class:`~django.db.models.FileField` or an -:class:`~django.db.models.ImageField` in a model takes a few steps: - - #. 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. - - #. Add the :class:`~django.db.models.FileField` or - :class:`~django.db.models.ImageField` to your model, making sure to - define the :attr:`~django.db.models.FileField.upload_to` option to tell - Django to which subdirectory of :setting:`MEDIA_ROOT` it should upload - files. - - #. 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 :attr:`~django.core.files.File.url` attribute provided by - Django. For example, if your :class:`~django.db.models.ImageField` is - called ``mug_shot``, you can get the absolute path to your image in a - template with ``{{ object.mug_shot.url }}``. - -How do I make a variable available to all my templates? -------------------------------------------------------- - -Sometimes your templates just all need the same thing. A common example would -be dynamically-generated menus. At first glance, it seems logical to simply -add a common dictionary to the template context. - -The correct solution is to use a ``RequestContext``. Details on how to do this -are here: :ref:`subclassing-context-requestcontext`. diff --git a/parts/django/docs/glossary.txt b/parts/django/docs/glossary.txt deleted file mode 100644 index b8f7a6b..0000000 --- a/parts/django/docs/glossary.txt +++ /dev/null @@ -1,81 +0,0 @@ -.. _glossary: - -======== -Glossary -======== - -.. glossary:: - - field - An attribute on a :term:`model`; a given field usually maps directly to - a single database column. - - See :doc:`/topics/db/models`. - - generic view - A higher-order :term:`view` function that provides an abstract/generic - implementation of a common idiom or pattern found in view development. - - See :doc:`/ref/generic-views`. - - model - Models store your application's data. - - See :doc:`/topics/db/models`. - - MTV - See :ref:`mtv`. - - MVC - `Model-view-controller`__; a software pattern. Django :ref:`follows MVC - to some extent <mtv>`. - - __ http://en.wikipedia.org/wiki/Model-view-controller - - project - A Python package -- i.e. a directory of code -- that contains all the - settings for an instance of Django. This would include database - configuration, Django-specific options and application-specific - settings. - - property - Also known as "managed attributes", and a feature of Python since - version 2.2. From `the property documentation`__: - - Properties are a neat way to implement attributes whose usage - resembles attribute access, but whose implementation uses method - calls. [...] You - could only do this by overriding ``__getattr__`` and - ``__setattr__``; but overriding ``__setattr__`` slows down all - attribute assignments considerably, and overriding ``__getattr__`` - is always a bit tricky to get right. Properties let you do this - painlessly, without having to override ``__getattr__`` or - ``__setattr__``. - - __ http://www.python.org/download/releases/2.2/descrintro/#property - - queryset - An object representing some set of rows to be fetched from the database. - - See :doc:`/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 acts as formatting for representing data. A - template helps to abstract the presentation of data from the data - itself. - - See :doc:`/topics/templates`. - - view - A function responsible for rending a page. diff --git a/parts/django/docs/howto/apache-auth.txt b/parts/django/docs/howto/apache-auth.txt deleted file mode 100644 index 2ebae0b..0000000 --- a/parts/django/docs/howto/apache-auth.txt +++ /dev/null @@ -1,120 +0,0 @@ -========================================================= -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 -:doc:`authentication system </topics/auth>` directly. For example, you -could: - - * Serve static/media files directly from Apache only to authenticated users. - - * Authenticate access to a Subversion_ repository against Django users with - a certain permission. - - * 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: - -.. code-block:: apache - - <Location /example/> - AuthType Basic - AuthName "example.com" - Require valid-user - - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - PythonAuthenHandler django.contrib.auth.handlers.modpython - </Location> - -.. admonition:: Using the authentication handler with Apache 2.2 - - If you're using Apache 2.2, you'll need to take a couple extra steps. - - You'll need to ensure that ``mod_auth_basic`` and ``mod_authz_user`` - are loaded. These might be compiled statically into Apache, or you might - need to use ``LoadModule`` to load them dynamically (as shown in the - example at the bottom of this note). - - You'll also need to insert configuration directives that prevent Apache - from trying to use other authentication modules, as well as specifying - 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 - AuthzLDAPAuthoritative Off - AuthzDBMAuthoritative Off - AuthzDefaultAuthoritative Off - AuthzGroupFileAuthoritative Off - AuthzOwnerAuthoritative Off - AuthzUserAuthoritative Off - - A complete configuration, with differences between Apache 2.0 and - Apache 2.2 marked in bold, would look something like: - - .. parsed-literal:: - - **LoadModule auth_basic_module modules/mod_auth_basic.so** - **LoadModule authz_user_module modules/mod_authz_user.so** - - ... - - <Location /example/> - AuthType Basic - AuthName "example.com" - **AuthUserFile /dev/null** - **AuthBasicAuthoritative Off** - Require valid-user - - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - PythonAuthenHandler django.contrib.auth.handlers.modpython - </Location> - -By default, the authentication handler will limit access to the ``/example/`` -location to users marked as staff members. You can use a set of -``PythonOption`` directives to modify this behavior: - - ================================ ========================================= - ``PythonOption`` Explanation - ================================ ========================================= - ``DjangoRequireStaffStatus`` If set to ``on`` only "staff" users (i.e. - those with the ``is_staff`` flag set) - will be allowed. - - Defaults to ``on``. - - ``DjangoRequireSuperuserStatus`` If set to ``on`` only superusers (i.e. - those with the ``is_superuser`` flag set) - will be allowed. - - Defaults to ``off``. - - ``DjangoPermissionName`` The name of a permission to require for - access. See :ref:`custom permissions - <custom-permissions>` for more - information. - - By default no specific permission will be - required. - ================================ ========================================= - -Note that sometimes ``SetEnv`` doesn't play well in this mod_python -configuration, for reasons unknown. If you're having problems getting -mod_python to recognize your ``DJANGO_SETTINGS_MODULE``, you can set it using -``PythonOption`` instead of ``SetEnv``. Therefore, these two Apache directives -are equivalent:: - - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - PythonOption DJANGO_SETTINGS_MODULE mysite.settings diff --git a/parts/django/docs/howto/auth-remote-user.txt b/parts/django/docs/howto/auth-remote-user.txt deleted file mode 100644 index deab794..0000000 --- a/parts/django/docs/howto/auth-remote-user.txt +++ /dev/null @@ -1,100 +0,0 @@ -==================================== -Authentication using ``REMOTE_USER`` -==================================== - -.. currentmodule:: django.contrib.auth.backends - -This document describes how to make use of external authentication sources -(where the Web server sets the ``REMOTE_USER`` environment variable) in your -Django applications. This type of authentication solution is typically seen on -intranet sites, with single sign-on solutions such as IIS and Integrated -Windows Authentication or Apache and `mod_authnz_ldap`_, `CAS`_, `Cosign`_, -`WebAuth`_, `mod_auth_sspi`_, etc. - -.. _mod_authnz_ldap: http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html -.. _CAS: http://www.jasig.org/cas -.. _Cosign: http://weblogin.org -.. _WebAuth: http://www.stanford.edu/services/webauth/ -.. _mod_auth_sspi: http://sourceforge.net/projects/mod-auth-sspi - -When the Web server takes care of authentication it typically sets the -``REMOTE_USER`` environment variable for use in the underlying application. In -Django, ``REMOTE_USER`` is made available in the :attr:`request.META -<django.http.HttpRequest.META>` attribute. Django can be configured to make -use of the ``REMOTE_USER`` value using the ``RemoteUserMiddleware`` and -``RemoteUserBackend`` classes found in :mod:`django.contrib.auth`. - -Configuration -============= - -First, you must add the -:class:`django.contrib.auth.middleware.RemoteUserMiddleware` to the -:setting:`MIDDLEWARE_CLASSES` setting **after** the -:class:`django.contrib.auth.middleware.AuthenticationMiddleware`:: - - MIDDLEWARE_CLASSES = ( - ... - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.RemoteUserMiddleware', - ... - ) - -Next, you must replace the :class:`~django.contrib.auth.backends.ModelBackend` -with ``RemoteUserBackend`` in the :setting:`AUTHENTICATION_BACKENDS` setting:: - - AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.RemoteUserBackend', - ) - -With this setup, ``RemoteUserMiddleware`` will detect the username in -``request.META['REMOTE_USER']`` and will authenticate and auto-login that user -using the ``RemoteUserBackend``. - -.. note:: - Since the ``RemoteUserBackend`` inherits from ``ModelBackend``, you will - still have all of the same permissions checking that is implemented in - ``ModelBackend``. - -If your authentication mechanism uses a custom HTTP header and not -``REMOTE_USER``, you can subclass ``RemoteUserMiddleware`` and set the -``header`` attribute to the desired ``request.META`` key. For example:: - - from django.contrib.auth.middleware import RemoteUserMiddleware - - class CustomHeaderMiddleware(RemoteUserMiddleware): - header = 'HTTP_AUTHUSER' - - -``RemoteUserBackend`` -===================== - -.. class:: django.contrib.auth.backends.RemoteUserBackend - -If you need more control, you can create your own authentication backend -that inherits from ``RemoteUserBackend`` and overrides certain parts: - -Attributes -~~~~~~~~~~ - -.. attribute:: RemoteUserBackend.create_unknown_user - - ``True`` or ``False``. Determines whether or not a - :class:`~django.contrib.auth.models.User` object is created if not already - in the database. Defaults to ``True``. - -Methods -~~~~~~~ - -.. method:: RemoteUserBackend.clean_username(username) - - Performs any cleaning on the ``username`` (e.g. stripping LDAP DN - information) prior to using it to get or create a - :class:`~django.contrib.auth.models.User` object. Returns the cleaned - username. - -.. method:: RemoteUserBackend.configure_user(user) - - Configures a newly created user. This method is called immediately after a - new user is created, and can be used to perform custom setup actions, such - as setting the user's groups based on attributes in an LDAP directory. - Returns the user object. diff --git a/parts/django/docs/howto/custom-file-storage.txt b/parts/django/docs/howto/custom-file-storage.txt deleted file mode 100644 index 1b0f32f..0000000 --- a/parts/django/docs/howto/custom-file-storage.txt +++ /dev/null @@ -1,90 +0,0 @@ -Writing a custom storage system -=============================== - -.. currentmodule:: django.core.files.storage - -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 -:doc:`/ref/files/storage`, but you **must** implement the following methods: - - * :meth:`Storage.delete` - * :meth:`Storage.exists` - * :meth:`Storage.listdir` - * :meth:`Storage.size` - * :meth:`Storage.url` - -You'll also usually want to use 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. - -Should return the actual name of name of the file saved (usually the ``name`` -passed in, but if the storage needs to change the file name return the new name -instead). - -``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 ``"_1"``, ``"_2"``, etc. to the -filename until it finds one that's available in the destination directory. diff --git a/parts/django/docs/howto/custom-management-commands.txt b/parts/django/docs/howto/custom-management-commands.txt deleted file mode 100644 index 4a1747f..0000000 --- a/parts/django/docs/howto/custom-management-commands.txt +++ /dev/null @@ -1,253 +0,0 @@ -==================================== -Writing custom django-admin commands -==================================== - -.. versionadded:: 1.0 - -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. In this document, we will be building a custom ``closepoll`` -command for the ``polls`` application from the -:doc:`tutorial</intro/tutorial01>`. - -To do this, just add a ``management/commands`` directory to the 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``:: - - polls/ - __init__.py - models.py - management/ - __init__.py - commands/ - __init__.py - closepoll.py - tests.py - views.py - -In this example, the ``closepoll`` command will be made available to any project -that includes the ``polls`` application in :setting:`INSTALLED_APPS`. - -The ``closepoll.py`` module has only one requirement -- it must define a class -``Command`` that extends :class:`BaseCommand` or one of its -:ref:`subclasses<ref-basecommand-subclasses>`. - -.. admonition:: Standalone scripts - - Custom management commands are especially useful for running standalone - scripts or for scripts that are periodically executed from the UNIX crontab - or from Windows scheduled tasks control panel. - -To implement the command, edit ``polls/management/commands/closepoll.py`` to -look like this: - -.. code-block:: python - - from django.core.management.base import BaseCommand, CommandError - from example.polls.models import Poll - - class Command(BaseCommand): - args = '<poll_id poll_id ...>' - help = 'Closes the specified poll for voting' - - def handle(self, *args, **options): - for poll_id in args: - try: - poll = Poll.objects.get(pk=int(poll_id)) - except Poll.DoesNotExist: - raise CommandError('Poll "%s" does not exist' % poll_id) - - poll.opened = False - poll.save() - - print 'Successfully closed poll "%s"' % poll_id - -The new custom command can be called using ``python manage.py closepoll -<poll_id>``. - -The ``handle()`` method takes zero or more ``poll_ids`` and sets ``poll.opened`` -to ``False`` for each one. If the user referenced any nonexistant polls, a -:class:`CommandError` is raised. The ``poll.opened`` attribute does not exist -in the :doc:`tutorial</intro/tutorial01>` and was added to -``polls.models.Poll`` for this example. - -The same ``closepoll`` could be easily modified to delete a given poll instead -of closing it by accepting additional command line options. These custom options -must be added to :attr:`~BaseCommand.option_list` like this: - -.. code-block:: python - - from optparse import make_option - - class Command(BaseCommand): - option_list = BaseCommand.option_list + ( - make_option('--delete', - action='store_true', - dest='delete', - default=False, - help='Delete poll instead of closing it'), - ) - # ... - -In addition to being able to add custom command line options, all -:doc:`management commands</ref/django-admin>` can accept some -default options such as :djadminopt:`--verbosity` and :djadminopt:`--traceback`. - -Command objects -=============== - -.. class:: BaseCommand - -The base class from which all management commands ultimately derive. - -Use this class if you want access to all of the mechanisms which -parse the command-line arguments and work out what code to call in -response; if you don't need to change any of that behavior, -consider using one of its :ref:`subclasses<ref-basecommand-subclasses>`. - -Subclassing the :class:`BaseCommand` class requires that you implement the -:meth:`~BaseCommand.handle` method. - -Attributes ----------- - -All attributes can be set in your derived class and can be used in -:class:`BaseCommand`'s :ref:`subclasses<ref-basecommand-subclasses>`. - -.. attribute:: BaseCommand.args - - A string listing the arguments accepted by the command, - suitable for use in help messages; e.g., a command which takes - a list of application names might set this to '<appname - appname ...>'. - -.. attribute:: BaseCommand.can_import_settings - - A boolean indicating whether the command needs to be able to - import Django settings; if ``True``, ``execute()`` will verify - that this is possible before proceeding. Default value is - ``True``. - -.. attribute:: BaseCommand.help - - A short description of the command, which will be printed in the - help message when the user runs the command - ``python manage.py help <command>``. - -.. attribute:: BaseCommand.option_list - - This is the list of ``optparse`` options which will be fed - into the command's ``OptionParser`` for parsing arguments. - -.. attribute:: BaseCommand.output_transaction - - A boolean indicating whether the command outputs SQL - statements; if ``True``, the output will automatically be - wrapped with ``BEGIN;`` and ``COMMIT;``. Default value is - ``False``. - -.. attribute:: BaseCommand.requires_model_validation - - A boolean; if ``True``, validation of installed models will be - performed prior to executing the command. Default value is - ``True``. To validate an individual application's models - rather than all applications' models, call - :meth:`~BaseCommand.validate` from :meth:`~BaseCommand.handle`. - -Methods -------- - -:class:`BaseCommand` has a few methods that can be overridden but only -the :meth:`~BaseCommand.handle` method must be implemented. - -.. admonition:: Implementing a constructor in a subclass - - If you implement ``__init__`` in your subclass of :class:`BaseCommand`, - you must call :class:`BaseCommand`'s ``__init__``. - - .. code-block:: python - - class Command(BaseCommand): - def __init__(self, *args, **kwargs): - super(Command, self).__init__(*args, **kwargs) - # ... - -.. method:: BaseCommand.get_version() - - Return the Django version, which should be correct for all - built-in Django commands. User-supplied commands can - override this method to return their own version. - -.. method:: BaseCommand.execute(*args, **options) - - Try to execute this command, performing model validation if - needed (as controlled by the attribute - :attr:`requires_model_validation`). If the command raises a - :class:`CommandError`, intercept it and print it sensibly to - stderr. - -.. method:: BaseCommand.handle(*args, **options) - - The actual logic of the command. Subclasses must implement this method. - -.. _ref-basecommand-subclasses: - -BaseCommand subclasses ----------------------- - -.. class:: AppCommand - -A management command which takes one or more installed application -names as arguments, and does something with each of them. - -Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement -:meth:`~AppCommand.handle_app`, which will be called once for each application. - -.. method:: AppCommand.handle_app(app, **options) - - Perform the command's actions for ``app``, which will be the - Python module corresponding to an application name given on - the command line. - -.. class:: LabelCommand - -A management command which takes one or more arbitrary arguments -(labels) on the command line, and does something with each of -them. - -Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement -:meth:`~LabelCommand.handle_label`, which will be called once for each label. - -.. method:: LabelCommand.handle_label(label, **options) - - Perform the command's actions for ``label``, which will be the - string as given on the command line. - -.. class:: NoArgsCommand - -A command which takes no arguments on the command line. - -Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement -:meth:`~NoArgsCommand.handle_noargs`; :meth:`~BaseCommand.handle` itself is -overridden to ensure no arguments are passed to the command. - -.. method:: NoArgsCommand.handle_noargs(**options) - - Perform this command's actions - -.. _ref-command-exceptions: - -Command exceptions ------------------- - -.. class:: CommandError - -Exception class indicating a problem while executing a management -command. - -If this exception is raised during the execution of a management -command, it will be caught and turned into a nicely-printed error -message to the appropriate output stream (i.e., stderr); as a -result, raising this exception (with a sensible description of the -error) is the preferred way to indicate that something has gone -wrong in the execution of a command. diff --git a/parts/django/docs/howto/custom-model-fields.txt b/parts/django/docs/howto/custom-model-fields.txt deleted file mode 100644 index 1840c5b..0000000 --- a/parts/django/docs/howto/custom-model-fields.txt +++ /dev/null @@ -1,745 +0,0 @@ -=========================== -Writing custom model fields -=========================== - -.. versionadded:: 1.0 -.. currentmodule:: django.db.models - -Introduction -============ - -The :doc:`model reference </topics/db/models>` documentation explains how to use -Django's standard field classes -- :class:`~django.db.models.CharField`, -:class:`~django.db.models.DateField`, etc. For many purposes, those classes are -all you'll need. Sometimes, though, the Django version won't meet your precise -requirements, or you'll want to use a field that is entirely different from -those shipped with Django. - -Django's built-in field types don't cover every possible database column type -- -only the common types, such as ``VARCHAR`` and ``INTEGER``. For more obscure -column types, such as geographic polygons or even user-created types such as -`PostgreSQL custom types`_, you can define your own Django ``Field`` subclasses. - -.. _PostgreSQL custom types: http://www.postgresql.org/docs/8.2/interactive/sql-createtype.html - -Alternatively, you may have a complex Python object that can somehow be -serialized to fit into a standard database column type. This is another case -where a ``Field`` subclass will help you use your object with your models. - -Our example object ------------------- - -Creating custom fields requires a bit of attention to detail. To make things -easier to follow, we'll use a consistent example throughout this document: -wrapping a Python object representing the deal of cards in a hand of Bridge_. -Don't worry, you don't have know how to play Bridge to follow this example. -You only need to know that 52 cards are dealt out equally to four players, who -are traditionally called *north*, *east*, *south* and *west*. Our class looks -something like this:: - - class Hand(object): - """A hand of cards (bridge style)""" - - def __init__(self, north, east, south, west): - # Input parameters are lists of cards ('Ah', '9s', etc) - self.north = north - 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``):: - - example = MyModel.objects.get(pk=1) - print example.hand.north - - new_hand = Hand(north, east, south, west) - example.hand = new_hand - example.save() - -We assign to and retrieve from the ``hand`` attribute in our model just like -any other Python class. The trick is to tell Django how to handle saving and -loading such an object. - -In order to use the ``Hand`` class in our models, we **do not** have to change -this class at all. This is ideal, because it means you can easily write -model support for existing classes where you cannot change the source code. - -.. note:: - You might only be wanting to take advantage of custom database column - types and deal with the data as standard Python types in your models; - strings, or floats, for example. This case is similar to our ``Hand`` - example and we'll note any differences as we go along. - -Background theory -================= - -Database storage ----------------- - -The simplest way to think of a model field is that it provides a way to take a -normal Python object -- string, boolean, ``datetime``, or something more -complex like ``Hand`` -- and convert it to and from a format that is useful -when dealing with the database (and serialization, but, as we'll see later, -that falls out fairly naturally once you have the database side under control). - -Fields in a model must somehow be converted to fit into an existing database -column type. Different databases provide different sets of valid column types, -but the rule is still the same: those are the only types you have to work -with. Anything you want to store in the database must fit into one of -those types. - -Normally, you're either writing a Django field to match a particular database -column type, or there's a fairly straightforward way to convert your data to, -say, a string. - -For our ``Hand`` example, we could convert the card data to a string of 104 -characters by concatenating all the cards together in a pre-determined order -- -say, all the *north* cards first, then the *east*, *south* and *west* cards. So -``Hand`` objects can be saved to text or character columns in the database. - -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 :doc:`form fields </ref/forms/fields>`) are subclasses -of :class:`django.db.models.Field`. Most of the information that Django records -about a field is common to all fields -- name, help text, 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 -field classes you define in a model are actually stored in the ``Meta`` class -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 :doc:`serializer </topics/serialization>`. - -Keep this in mind when creating your own custom fields. The Django ``Field`` -subclass you write provides the machinery for converting between your Python -instances and the database/serializer values in various ways (there are -differences between storing a value and using a value for lookups, for -example). If this sounds a bit tricky, don't worry -- it will become clearer in -the examples below. Just remember that you will often end up creating two -classes when you want a custom field: - - * The first class is the Python object that your users will manipulate. - They will assign it to the model attribute, they will read from it for - displaying purposes, things like that. This is the ``Hand`` class in our - example. - - * The second class is the ``Field`` subclass. This is the class that knows - how to convert your first class back and forth between its permanent - storage form and the Python form. - -Writing a field subclass -======================== - -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 -: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 :class:`~django.db.models.Field` subclass ``<Something>Field``, so it's -easily identifiable as a :class:`~django.db.models.Field` subclass.) It doesn't -behave like any existing field, so we'll subclass directly from -:class:`~django.db.models.Field`:: - - from django.db import models - - class HandField(models.Field): - - description = "A hand of cards (bridge style)" - - def __init__(self, *args, **kwargs): - kwargs['max_length'] = 104 - super(HandField, self).__init__(*args, **kwargs) - -Our ``HandField`` accepts most of the standard field options (see the list -below), but we ensure it has a fixed length, since it only needs to hold 52 -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 - :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 - the parent class and then don't use them later on. It's up to you whether - 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 :meth:`~django.db.models.Field.__init__` method takes the following -parameters: - - * :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.rel`: Used for related fields (like - :class:`ForeignKey`). For advanced use only. - * :attr:`~django.db.models.Field.default` - * :attr:`~django.db.models.Field.editable` - * :attr:`~django.db.models.Field.serialize`: If ``False``, the field will - not be serialized when the model is passed to Django's :doc:`serializers - </topics/serialization>`. Defaults to ``True``. - * :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.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. - * :attr:`~django.db.models.Field.auto_created`: True if the field was - automatically created, as for the `OneToOneField` used by model - inheritance. For advanced use only. - -All of the options without an explanation in the above list have the same -meaning they do for normal Django fields. See the :doc:`field documentation -</ref/models/fields>` for examples and details. - -The ``SubfieldBase`` metaclass ------------------------------- - -As we indicated in the introduction_, field subclasses are often needed for -two reasons: either to take advantage of a custom database column type, or to -handle complex Python types. Obviously, a combination of the two is also -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 -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 a special metaclass: - -.. class:: django.db.models.SubfieldBase - -For example:: - - class HandField(models.Field): - - description = "A hand of cards (bridge style)" - - __metaclass__ = models.SubfieldBase - - def __init__(self, *args, **kwargs): - # ... - -This ensures that the :meth:`to_python` method, documented below, will always be -called when the attribute is initialized. - -ModelForms and custom fields -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you use :class:`~django.db.models.SubfieldBase`, :meth:`to_python` -will be called every time an instance of the field is assigned a -value. This means that whenever a value may be assigned to the field, -you need to ensure that it will be of the correct datatype, or that -you handle any exceptions. - -This is especially important if you use :doc:`ModelForms -</topics/forms/modelforms>`. When saving a ModelForm, Django will use -form values to instantiate model instances. However, if the cleaned -form data can't be used as valid input to the field, the normal form -validation process will break. - -Therefore, you must ensure that the form field used to represent your -custom field performs whatever input validation and data cleaning is -necessary to convert user-provided form input into a -`to_python()`-compatible model field value. This may require writing a -custom form field, and/or implementing the :meth:`formfield` method on -your field to return a form field class whose `to_python()` returns the -correct datatype. - -Documenting your Custom Field ------------------------------ - -.. class:: django.db.models.Field - -.. attribute:: description - -As always, you should document your field type, so users will know what it is. -In addition to providing a docstring for it, which is useful for developers, -you can also allow users of the admin app to see a short description of the -field type via the :doc:`django.contrib.admindocs -</ref/contrib/admin/admindocs>` application. To do this simply provide -descriptive text in a ``description`` class attribute of your custom field. In -the above example, the type description displayed by the ``admindocs`` -application for a ``HandField`` will be 'A hand of cards (bridge style)'. - -Useful methods --------------- - -Once you've created your :class:`~django.db.models.Field` subclass and set 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. - -Custom database types -~~~~~~~~~~~~~~~~~~~~~ - -.. method:: db_type(self, connection) - -.. versionadded:: 1.2 - The ``connection`` argument was added to support multiple databases. - -Returns the database column data type for the :class:`~django.db.models.Field`, -taking into account the connection object, and the settings associated with it. - -Say you've created a PostgreSQL custom type called ``mytype``. You can use this -field with Django by subclassing ``Field`` and implementing the :meth:`db_type` -method, like so:: - - from django.db import models - - class MytypeField(models.Field): - def db_type(self, connection): - return 'mytype' - -Once you have ``MytypeField``, you can use it in any model, just like any other -``Field`` type:: - - class Person(models.Model): - name = models.CharField(max_length=80) - gender = models.CharField(max_length=1) - something_else = MytypeField() - -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 -check the ``connection.settings_dict['ENGINE']`` attribute. - -For example:: - - class MyDateField(models.Field): - def db_type(self, connection): - if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql': - return 'datetime' - else: - return 'timestamp' - -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 ``connection.settings_dict`` -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, -it's more flexible if the parameter is specified in the model rather than being -hard-coded in the ``db_type()`` method. For example, it wouldn't make much -sense to have a ``CharMaxlength25Field``, shown here:: - - # This is a silly example of hard-coded parameters. - class CharMaxlength25Field(models.Field): - def db_type(self, connection): - return 'char(25)' - - # In the model: - class MyModel(models.Model): - # ... - my_field = CharMaxlength25Field() - -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 -:meth:`django.db.models.Field.__init__`, like so:: - - # This is a much more flexible example. - class BetterCharField(models.Field): - def __init__(self, max_length, *args, **kwargs): - self.max_length = max_length - super(BetterCharField, self).__init__(*args, **kwargs) - - def db_type(self, connection): - return 'char(%s)' % self.max_length - - # In the model: - class MyModel(models.Model): - # ... - my_field = BetterCharField(25) - -Finally, if your column requires truly complex SQL setup, return ``None`` from -: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. - -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. - -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 :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). - - * A string (e.g., from a deserializer). - - * Whatever the database returns for the column type you're using. - -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 -:meth:`to_python`:: - - import re - - class HandField(models.Field): - # ... - - def to_python(self, value): - if isinstance(value, Hand): - return value - - # The string case. - p1 = re.compile('.{26}') - p2 = re.compile('..') - args = [p2.findall(x) for x in p1.findall(value)] - return Hand(*args) - -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 :meth:`to_python` method to be -called when it is created, you should be using `The SubfieldBase metaclass`_ -mentioned earlier. Otherwise :meth:`to_python` won't be called automatically. - -Converting Python objects to query values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: get_prep_value(self, value) - -.. versionadded:: 1.2 - This method was factored out of ``get_db_prep_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 has been -prepared for use as a parameter in a query. - -This conversion should *not* include any database-specific -conversions. If database-specific conversions are required, they -should be made in the call to :meth:`get_db_prep_value`. - -For example:: - - class HandField(models.Field): - # ... - - def get_prep_value(self, value): - return ''.join([''.join(l) for l in (value.north, - value.east, value.south, value.west)]) - -Converting query values to database values -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: get_db_prep_value(self, value, connection, prepared=False) - -.. versionadded:: 1.2 - The ``connection`` and ``prepared`` arguments were added to support multiple databases. - -Some data types (for example, dates) need to be in a specific format -before they can be used by a database backend. -:meth:`get_db_prep_value` is the method where those conversions should -be made. The specific connection that will be used for the query is -passed as the ``connection`` parameter. This allows you to use -backend-specific conversion logic if it is required. - -The ``prepared`` argument describes whether or not the value has -already been passed through :meth:`get_prep_value` conversions. When -``prepared`` is False, the default implementation of -:meth:`get_db_prep_value` will call :meth:`get_prep_value` to do -initial data conversions before performing any database-specific -processing. - -.. method:: get_db_prep_save(self, value, connection) - -.. versionadded:: 1.2 - The ``connection`` argument was added to support multiple databases. - -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 shouldn't need to implement this method -unless your custom field needs a special conversion when being saved -that is not the same as the conversion used for normal query -parameters (which is implemented by ``get_db_prep_value``). - -Preprocessing values before saving -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: pre_save(self, model_instance, add) - -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 -: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 -: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. - -Preparing values for use in database lookups -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As with value conversions, preparing a value for database lookups is a -two phase process. - -.. method:: get_prep_lookup(self, lookup_type, value) - -.. versionadded:: 1.2 - This method was factored out of ``get_db_prep_lookup()`` - -:meth:`get_prep_lookup` performs the first phase of lookup preparation, -performing generic data validity checks - -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 -Django filter lookups: ``exact``, ``iexact``, ``contains``, ``icontains``, -``gt``, ``gte``, ``lt``, ``lte``, ``in``, ``startswith``, ``istartswith``, -``endswith``, ``iendswith``, ``range``, ``year``, ``month``, ``day``, -``isnull``, ``search``, ``regex``, and ``iregex``. - -Your method must be prepared to handle all of these ``lookup_type`` values and -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 to 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_prep_lookup()``. If you don't, ``get_prep_value`` will be -called by the default implementation, to manage ``exact``, ``gt``, ``gte``, -``lt``, ``lte``, ``in`` and ``range`` lookups. - -You may also want to implement this method to limit the lookup types that could -be used with your custom field type. - -Note that, for ``range`` and ``in`` lookups, ``get_prep_lookup`` will receive -a list of objects (presumably of the right type) and will need to convert them -to a list of things of the right type for passing to the database. Most of the -time, you can reuse ``get_prep_value()``, or at least factor out some common -pieces. - -For example, the following code implements ``get_prep_lookup`` to limit the -accepted lookup types to ``exact`` and ``in``:: - - class HandField(models.Field): - # ... - - def get_prep_lookup(self, lookup_type, value): - # We only handle 'exact' and 'in'. All others are errors. - if lookup_type == 'exact': - return self.get_prep_value(value) - elif lookup_type == 'in': - return [self.get_prep_value(v) for v in value] - else: - raise TypeError('Lookup type %r not supported.' % lookup_type) - -.. method:: get_db_prep_lookup(self, lookup_type, value, connection, prepared=False) - -.. versionadded:: 1.2 - The ``connection`` and ``prepared`` arguments were added to support multiple databases. - -Performs any database-specific data conversions required by a lookup. -As with :meth:`get_db_prep_value`, the specific connection that will -be used for the query is passed as the ``connection`` parameter. -The ``prepared`` argument describes whether the value has already been -prepared with :meth:`get_prep_lookup`. - -Specifying the form field for a model field -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: formfield(self, form_class=forms.CharField, **kwargs) - -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 -: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 :doc:`forms documentation -</topics/forms/index>` for information about this, and take a look at the code in -:mod:`django.contrib.localflavor` for some examples of custom widgets. - -Continuing our ongoing example, we can write the :meth:`formfield` method as:: - - class HandField(models.Field): - # ... - - def formfield(self, **kwargs): - # This is a fairly standard way to set up some defaults - # while letting the caller override them. - defaults = {'form_class': MyFormField} - defaults.update(kwargs) - return super(HandField, self).formfield(**defaults) - -This assumes we've imported a ``MyFormField`` field class (which has its own -default widget). This document doesn't cover the details of writing custom form -fields. - -.. _helper functions: ../forms/#generating-forms-for-models -.. _forms documentation: ../forms/ - -Emulating built-in field types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: get_internal_type(self) - -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. - -For example:: - - class HandField(models.Field): - # ... - - def get_internal_type(self): - return 'CharField' - -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 :meth:`get_internal_type` returns a string that is not known to Django for -the database backend you are using -- that is, it doesn't appear in -``django.db.backends.<db_name>.creation.DATA_TYPES`` -- the string will still be -used by the serializer, but the default :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. - -Converting field data for serialization -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: value_to_string(self, obj) - -This method is used by the serializers to convert the field into a string for -output. 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:: - - class HandField(models.Field): - # ... - - def value_to_string(self, obj): - value = self._get_val_from_obj(obj) - return self.get_db_prep_value(value) - -Some general advice --------------------- - -Writing a custom field can be a tricky process, particularly if you're doing -complex conversions between your Python types and your database and -serialization formats. Here are a couple of tips to make things go more -smoothly: - - 1. Look at the existing Django fields (in - :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 :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 - :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 -================================= - -In addition to the above methods, fields that deal with files have a few other -special requirements which must be taken into account. The majority of the -mechanics provided by ``FileField``, such as controlling database storage and -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 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 -:doc:`file documentation </ref/files/file>`. - -Once a subclass of ``File`` is created, the new ``FileField`` subclass must be -told to use it. To do so, simply assign the new ``File`` subclass to the special -``attr_class`` attribute of the ``FileField`` subclass. - -A few suggestions ------------------- - -In addition to the above details, there are a few guidelines which can greatly -improve the efficiency and readability of the field's code. - - 1. The source for Django's own ``ImageField`` (in - ``django/db/models/fields/files.py``) is a great example of how to - subclass ``FileField`` to support a particular type of file, as it - incorporates all of the techniques described above. - - 2. Cache file attributes wherever possible. Since files may be stored in - remote storage systems, retrieving them may cost extra time, or even - money, that isn't always necessary. Once a file is retrieved to obtain - some data about its content, cache as much of that data as possible to - reduce the number of times the file must be retrieved on subsequent - calls for that information. diff --git a/parts/django/docs/howto/custom-template-tags.txt b/parts/django/docs/howto/custom-template-tags.txt deleted file mode 100644 index 95ce274..0000000 --- a/parts/django/docs/howto/custom-template-tags.txt +++ /dev/null @@ -1,939 +0,0 @@ -================================ -Custom template tags and filters -================================ - -Introduction -============ - -Django's template system comes with a wide variety of :doc:`built-in -tags and filters </ref/templates/builtins>` designed to address the -presentation logic needs of your application. Nevertheless, you may -find yourself needing functionality that is not covered by the core -set of template primitives. You can extend the template engine by -defining custom tags and filters using Python, and then make them -available to your templates using the ``{% load %}`` tag. - -Code layout ------------ - -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. - -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. - -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. - -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 - -And in your template you would use the following: - -.. code-block:: html+django - - {% load poll_extras %} - -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. - -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 -following:: - - from django import template - - register = template.Library() - -.. admonition:: Behind the scenes - - For a ton of examples, read the source code for Django's default filters - and tags. They're in ``django/template/defaultfilters.py`` and - ``django/template/defaulttags.py``, respectively. - -Writing custom template filters -------------------------------- - -Custom filters are just Python functions that take one or two arguments: - - * The value of the variable (input) -- not necessarily a string. - * The value of the argument -- this can have a default value, or be left - out altogether. - -For example, in the filter ``{{ var|foo:"bar" }}``, the filter ``foo`` would be -passed the variable ``var`` and the argument ``"bar"``. - -Filter functions should always return something. They shouldn't raise -exceptions. They should fail silently. In case of error, they should return -either the original input or an empty string -- whichever makes more sense. - -Here's an example filter definition:: - - def cut(value, arg): - "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: - -.. code-block:: html+django - - {{ somevariable|cut:"0" }} - -Most filters don't take arguments. In this case, just leave the argument out of -your function. Example:: - - def lower(value): # Only one argument. - "Converts a string into all lowercase" - return value.lower() - -Template filters that expect strings -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you're writing a template filter that only expects a string as the first -argument, you should use the decorator ``stringfilter``. This will -convert an object to its string value before being passed to your function:: - - from django.template.defaultfilters import stringfilter - - @stringfilter - def lower(value): - return value.lower() - -This way, you'll be able to pass, say, an integer to this filter, and it -won't cause an ``AttributeError`` (because integers don't have ``lower()`` -methods). - -Registering custom filters -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Once you've written your filter definition, you need to register it with -your ``Library`` instance, to make it available to Django's template language:: - - register.filter('cut', cut) - register.filter('lower', lower) - -The ``Library.filter()`` method takes two arguments: - - 1. The name of the filter -- a string. - 2. The compilation function -- a Python function (not the name of the - function as a string). - -You can use ``register.filter()`` as a decorator instead:: - - @register.filter(name='cut') - @stringfilter - def cut(value, arg): - return value.replace(arg, '') - - @register.filter - @stringfilter - def lower(value): - return value.lower() - -If you leave off the ``name`` argument, as in the second example above, Django -will use the function's name as the filter name. - -Filters and auto-escaping -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -When writing a custom filter, give some thought to how the filter will interact -with Django's auto-escaping behavior. Note that three types of strings can be -passed around inside the template code: - - * **Raw strings** are the native Python ``str`` or ``unicode`` types. On - output, they're escaped if auto-escaping is in effect and presented - unchanged, otherwise. - - * **Safe strings** are strings that have been marked safe from further - escaping at output time. Any necessary escaping has already been done. - They're commonly used for output that contains raw HTML that is intended - to be interpreted as-is on the client side. - - Internally, these strings are of type ``SafeString`` or ``SafeUnicode``. - They share a common base class of ``SafeData``, so you can test - for them using code like:: - - if isinstance(value, SafeData): - # Do something with the "safe" string. - - * **Strings marked as "needing escaping"** are *always* escaped on - output, regardless of whether they are in an ``autoescape`` block or not. - These strings are only escaped once, however, even if auto-escaping - applies. - - Internally, these strings are of type ``EscapeString`` or - ``EscapeUnicode``. Generally you don't have to worry about these; they - exist for the implementation of the ``escape`` filter. - -Template filter code falls into one of two situations: - - 1. Your filter does not introduce any HTML-unsafe characters (``<``, ``>``, - ``'``, ``"`` or ``&``) into the result that were not already present. In - this case, you can let Django take care of all the auto-escaping - handling for you. All you need to do is put the ``is_safe`` attribute on - your filter function and set it to ``True``, like so:: - - @register.filter - def myfilter(value): - return value - myfilter.is_safe = True - - This attribute tells Django that if a "safe" string is passed into your - filter, the result will still be "safe" and if a non-safe string is - passed in, Django will automatically escape it, if necessary. - - You can think of this as meaning "this filter is safe -- it doesn't - introduce any possibility of unsafe HTML." - - The reason ``is_safe`` is necessary is because there are plenty of - normal string operations that will turn a ``SafeData`` object back into - a normal ``str`` or ``unicode`` object and, rather than try to catch - them all, which would be very difficult, Django repairs the damage after - the filter has completed. - - For example, suppose you have a filter that adds the string ``xx`` to the - end of any input. Since this introduces no dangerous HTML characters to - 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 - - 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 - "safe". - - By default, ``is_safe`` defaults to ``False``, and you can omit it from - any filters where it isn't required. - - Be careful when deciding if your filter really does leave safe strings - as safe. If you're *removing* characters, you might inadvertently leave - unbalanced HTML tags or entities in the result. For example, removing a - ``>`` from the input might turn ``<a>`` into ``<a``, which would need to - be escaped on output to avoid causing problems. Similarly, removing a - semicolon (``;``) can turn ``&`` into ``&``, which is no longer a - valid entity and thus needs further escaping. Most cases won't be nearly - this tricky, but keep an eye out for any problems like that when - reviewing your code. - - Marking a filter ``is_safe`` will coerce the filter's return value to - a string. If your filter should return a boolean or other non-string - value, marking it ``is_safe`` will probably have unintended - consequences (such as converting a boolean False to the string - 'False'). - - 2. Alternatively, your filter code can manually take care of any necessary - escaping. This is necessary when you're introducing new HTML markup into - the result. You want to mark the output as safe from further - 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 - :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 - whether auto-escaping is in effect. The idea is to write filters than - can operate in templates where auto-escaping is either on or off in - order to make things easier for your template authors. - - In order for your filter to know the current auto-escaping state, set - the ``needs_autoescape`` attribute to ``True`` on your function. (If you - don't specify this attribute, it defaults to ``False``). This attribute - tells Django that your filter function wants to be passed an extra - keyword argument, called ``autoescape``, that is ``True`` if - auto-escaping is in effect and ``False`` otherwise. - - For example, let's write a filter that emphasizes the first character of - a string:: - - from django.utils.html import conditional_escape - from django.utils.safestring import mark_safe - - def initial_letter_filter(text, autoescape=None): - first, other = text[0], text[1:] - if autoescape: - esc = conditional_escape - else: - esc = lambda x: x - result = '<strong>%s</strong>%s' % (esc(first), esc(other)) - return mark_safe(result) - initial_letter_filter.needs_autoescape = True - - 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 - ``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 - unchanged. - - Finally, in the above example, we remember to mark the result as safe - so that our HTML is inserted directly into the template without further - escaping. - - There's no need to worry about the ``is_safe`` attribute in this case - (although including it wouldn't hurt anything). Whenever you manually - handle the auto-escaping issues and return a safe string, the - ``is_safe`` attribute won't change anything either way. - -Writing custom template tags ----------------------------- - -Tags are more complex than filters, because tags can do anything. - -A quick overview -~~~~~~~~~~~~~~~~ - -Above, this document explained that the template system works in a two-step -process: compiling and rendering. To define a custom template tag, you specify -how the compilation works and how the rendering works. - -When Django compiles a template, it splits the raw template text into -''nodes''. Each node is an instance of ``django.template.Node`` and has -a ``render()`` method. A compiled template is, simply, a list of ``Node`` -objects. When you call ``render()`` on a compiled template object, the template -calls ``render()`` on each ``Node`` in its node list, with the given context. -The results are all concatenated together to form the output of the template. - -Thus, to define a custom template tag, you specify how the raw template tag is -converted into a ``Node`` (the compilation function), and what the node's -``render()`` method does. - -Writing the compilation function -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For each template tag the template parser encounters, it calls a Python -function with the tag contents and the parser object itself. This function is -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: - -.. code-block:: html+django - - <p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p> - -.. _`strftime syntax`: http://docs.python.org/library/time.html#time.strftime - -The parser for this function should grab the parameter and create a ``Node`` -object:: - - from django import template - def do_current_time(parser, token): - try: - # split_contents() knows not to split quoted strings. - tag_name, format_string = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0] - if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): - raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name - return CurrentTimeNode(format_string[1:-1]) - -Notes: - - * ``parser`` is the template parser object. We don't need it in this - example. - - * ``token.contents`` is a string of the raw contents of the tag. In our - example, it's ``'current_time "%Y-%m-%d %I:%M %p"'``. - - * The ``token.split_contents()`` method separates the arguments on spaces - while keeping quoted strings together. The more straightforward - ``token.contents.split()`` wouldn't be as robust, as it would naively - split on *all* spaces, including those within quoted strings. It's a good - idea to always use ``token.split_contents()``. - - * This function is responsible for raising - ``django.template.TemplateSyntaxError``, with helpful messages, for - any syntax error. - - * The ``TemplateSyntaxError`` exceptions use the ``tag_name`` variable. - Don't hard-code the tag's name in your error messages, because that - couples the tag's name to your function. ``token.contents.split()[0]`` - will ''always'' be the name of your tag -- even when the tag has no - arguments. - - * The function returns a ``CurrentTimeNode`` with everything the node needs - to know about this tag. In this case, it just passes the argument -- - ``"%Y-%m-%d %I:%M %p"``. The leading and trailing quotes from the - template tag are removed in ``format_string[1:-1]``. - - * The parsing is very low-level. The Django developers have experimented - with writing small frameworks on top of this parsing system, using - techniques such as EBNF grammars, but those experiments made the template - engine too slow. It's low-level because that's fastest. - -Writing the renderer -~~~~~~~~~~~~~~~~~~~~ - -The second step in writing custom tags is to define a ``Node`` subclass that -has a ``render()`` method. - -Continuing the above example, we need to define ``CurrentTimeNode``:: - - from django import template - import datetime - class CurrentTimeNode(template.Node): - def __init__(self, format_string): - self.format_string = format_string - def render(self, context): - return datetime.datetime.now().strftime(self.format_string) - -Notes: - - * ``__init__()`` gets the ``format_string`` from ``do_current_time()``. - Always pass any options/parameters/arguments to a ``Node`` via its - ``__init__()``. - - * The ``render()`` method is where the work actually happens. - - * ``render()`` should never raise ``TemplateSyntaxError`` or any other - exception. It should fail silently, just as template filters should. - -Ultimately, this decoupling of compilation and rendering results in an -efficient template system, because a template can render multiple contexts -without having to be parsed multiple times. - -Auto-escaping considerations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -The output from template tags is **not** automatically run through the -auto-escaping filters. However, there are still a couple of things you should -keep in mind when writing a template tag. - -If the ``render()`` function of your template stores the result in a context -variable (rather than returning the result in a string), it should take care -to call ``mark_safe()`` if appropriate. When the variable is ultimately -rendered, it will be affected by the auto-escape setting in effect at the -time, so content that should be safe from further escaping needs to be marked -as such. - -Also, if your template tag creates a new context for performing some -sub-rendering, set the auto-escape attribute to the current context's value. -The ``__init__`` method for the ``Context`` class takes a parameter called -``autoescape`` that you can use for this purpose. For example:: - - def render(self, context): - # ... - new_context = Context({'var': obj}, autoescape=context.autoescape) - # ... Do something with new_context ... - -This is not a very common situation, but it's useful if you're rendering a -template yourself. For example:: - - def render(self, context): - t = template.loader.get_template('small_fragment.html') - return t.render(Context({'var': obj}, autoescape=context.autoescape)) - -If we had neglected to pass in the current ``context.autoescape`` value to our -new ``Context`` in this example, the results would have *always* been -automatically escaped, which may not be the desired behavior if the template -tag is used inside a ``{% autoescape off %}`` block. - -.. _template_tag_thread_safety: - -Thread-safety considerations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - -Once a node is parsed, its ``render`` method may be called any number of times. -Since Django is sometimes run in multi-threaded environments, a single node may -be simultaneously rendering with different contexts in response to two separate -requests. Therefore, it's important to make sure your template tags are thread -safe. - -To make sure your template tags are thread safe, you should never store state -information on the node itself. For example, Django provides a builtin ``cycle`` -template tag that cycles among a list of given strings each time it's rendered:: - - {% for o in some_list %} - <tr class="{% cycle 'row1' 'row2' %}> - ... - </tr> - {% endfor %} - -A naive implementation of ``CycleNode`` might look something like this:: - - class CycleNode(Node): - def __init__(self, cyclevars): - self.cycle_iter = itertools.cycle(cyclevars) - def render(self, context): - return self.cycle_iter.next() - -But, suppose we have two templates rendering the template snippet from above at -the same time: - - 1. Thread 1 performs its first loop iteration, ``CycleNode.render()`` - returns 'row1' - 2. Thread 2 performs its first loop iteration, ``CycleNode.render()`` - returns 'row2' - 3. Thread 1 performs its second loop iteration, ``CycleNode.render()`` - returns 'row1' - 4. Thread 2 performs its second loop iteration, ``CycleNode.render()`` - returns 'row2' - -The CycleNode is iterating, but it's iterating globally. As far as Thread 1 -and Thread 2 are concerned, it's always returning the same value. This is -obviously not what we want! - -To address this problem, Django provides a ``render_context`` that's associated -with the ``context`` of the template that is currently being rendered. The -``render_context`` behaves like a Python dictionary, and should be used to store -``Node`` state between invocations of the ``render`` method. - -Let's refactor our ``CycleNode`` implementation to use the ``render_context``:: - - class CycleNode(Node): - def __init__(self, cyclevars): - self.cyclevars = cyclevars - def render(self, context): - if self not in context.render_context: - context.render_context[self] = itertools.cycle(self.cyclevars) - cycle_iter = context.render_context[self] - return cycle_iter.next() - -Note that it's perfectly safe to store global information that will not change -throughout the life of the ``Node`` as an attribute. In the case of -``CycleNode``, the ``cyclevars`` argument doesn't change after the ``Node`` is -instantiated, so we don't need to put it in the ``render_context``. But state -information that is specific to the template that is currently being rendered, -like the current iteration of the ``CycleNode``, should be stored in the -``render_context``. - -.. note:: - Notice how we used ``self`` to scope the ``CycleNode`` specific information - within the ``render_context``. There may be multiple ``CycleNodes`` in a - given template, so we need to be careful not to clobber another node's state - information. The easiest way to do this is to always use ``self`` as the key - into ``render_context``. If you're keeping track of several state variables, - make ``render_context[self]`` a dictionary. - -Registering the tag -~~~~~~~~~~~~~~~~~~~ - -Finally, register the tag with your module's ``Library`` instance, as explained -in "Writing custom template filters" above. Example:: - - register.tag('current_time', do_current_time) - -The ``tag()`` method takes two arguments: - - 1. The name of the template tag -- a string. If this is left out, the - name of the compilation function will be used. - 2. The compilation function -- a Python function (not the name of the - function as a string). - -As with filter registration, it is also possible to use this as a decorator:: - - @register.tag(name="current_time") - def do_current_time(parser, token): - # ... - - @register.tag - def shout(parser, token): - # ... - -If you leave off the ``name`` argument, as in the second example above, Django -will use the function's name as the tag name. - -Passing template variables to the tag -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Although you can pass any number of arguments to a template tag using -``token.split_contents()``, the arguments are all unpacked as -string literals. A little more work is required in order to pass dynamic -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: - -.. code-block:: html+django - - <p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p> - -Initially, ``token.split_contents()`` will return three values: - - 1. The tag name ``format_time``. - 2. The string "blog_entry.date_updated" (without the surrounding quotes). - 3. The formatting string "%Y-%m-%d %I:%M %p". The return value from - ``split_contents()`` will include the leading and trailing quotes for - string literals like this. - -Now your tag should begin to look like this:: - - from django import template - def do_format_time(parser, token): - try: - # split_contents() knows not to split quoted strings. - tag_name, date_to_be_formatted, format_string = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0] - if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): - raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name - return FormatTimeNode(date_to_be_formatted, format_string[1:-1]) - -.. versionchanged:: 1.0 - Variable resolution has changed in the 1.0 release of Django. ``template.resolve_variable()`` - has been deprecated in favor of a new ``template.Variable`` class. - -You also have to change the renderer to retrieve the actual contents of the -``date_updated`` property of the ``blog_entry`` object. This can be -accomplished by using the ``Variable()`` class in ``django.template``. - -To use the ``Variable`` class, simply instantiate it with the name of the -variable to be resolved, and then call ``variable.resolve(context)``. So, -for example:: - - class FormatTimeNode(template.Node): - def __init__(self, date_to_be_formatted, format_string): - self.date_to_be_formatted = template.Variable(date_to_be_formatted) - self.format_string = format_string - - def render(self, context): - try: - actual_date = self.date_to_be_formatted.resolve(context) - return actual_date.strftime(self.format_string) - except template.VariableDoesNotExist: - return '' - -Variable resolution will throw a ``VariableDoesNotExist`` exception if it cannot -resolve the string passed to it in the current context of the page. - -Shortcut for simple tags -~~~~~~~~~~~~~~~~~~~~~~~~ - -Many template tags take a number of arguments -- strings or a template variables --- and return a string after doing some processing based solely on -the input argument and some external information. For example, the -``current_time`` tag we wrote above is of this variety: we give it a format -string, it returns the time as a string. - -To ease the creation of the types of tags, Django provides a helper function, -``simple_tag``. This function, which is a method of -``django.template.Library``, takes a function that accepts any number of -arguments, wraps it in a ``render`` function and the other necessary bits -mentioned above and registers it with the template system. - -Our earlier ``current_time`` function could thus be written like this:: - - def current_time(format_string): - return datetime.datetime.now().strftime(format_string) - - register.simple_tag(current_time) - -The decorator syntax also works:: - - @register.simple_tag - def current_time(format_string): - ... - -A couple of things to note about the ``simple_tag`` helper function: - - * 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. - * If the argument was a template variable, our function is passed the - current value of the variable, not the variable itself. - -When your template tag does not need access to the current context, writing a -function to work with the input values and using the ``simple_tag`` helper is -the easiest way to create a new tag. - -.. _howto-custom-template-tags-inclusion-tags: - -Inclusion tags -~~~~~~~~~~~~~~ - -Another common type of template tag is the type that displays some data by -rendering *another* template. For example, Django's admin interface uses custom -template tags to display the buttons along the bottom of the "add/change" form -pages. Those buttons always look the same, but the link targets change depending -on the object being edited -- so they're a perfect case for using a small -template that is filled with details from the current object. (In the admin's -case, this is the ``submit_row`` tag.) - -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 :ref:`tutorials <creating-models>`. We'll use the tag like this: - -.. code-block:: html+django - - {% show_results poll %} - -...and the output will be something like this: - -.. code-block:: html - - <ul> - <li>First choice</li> - <li>Second choice</li> - <li>Third choice</li> - </ul> - -First, define the function that takes the argument and produces a dictionary of -data for the result. The important point here is we only need to return a -dictionary, not anything more complex. This will be used as a template context -for the template fragment. Example:: - - def show_results(poll): - choices = poll.choice_set.all() - return {'choices': choices} - -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: - -.. code-block:: html+django - - <ul> - {% for choice in choices %} - <li> {{ choice }} </li> - {% endfor %} - </ul> - -Now, create and register the inclusion tag by calling the ``inclusion_tag()`` -method on a ``Library`` object. Following our example, if the above template is -in a file called ``results.html`` in a directory that's searched by the template -loader, we'd register the tag like this:: - - # Here, register is a django.template.Library instance, as before - register.inclusion_tag('results.html')(show_results) - -As always, decorator syntax works as well, so we could have written:: - - @register.inclusion_tag('results.html') - def show_results(poll): - ... - -...when first creating the function. - -Sometimes, your inclusion tags might require a large number of arguments, -making it a pain for template authors to pass in all the arguments and remember -their order. To solve this, Django provides a ``takes_context`` option for -inclusion tags. If you specify ``takes_context`` in creating a template tag, -the tag will have no required arguments, and the underlying Python function -will have one argument -- the template context as of when the tag was called. - -For example, say you're writing an inclusion tag that will always be used in a -context that contains ``home_link`` and ``home_title`` variables that point -back to the main page. Here's what the Python function would look like:: - - # The first argument *must* be called "context" here. - def jump_link(context): - return { - 'link': context['home_link'], - 'title': context['home_title'], - } - # Register the custom tag as an inclusion tag with takes_context=True. - register.inclusion_tag('link.html', takes_context=True)(jump_link) - -(Note that the first parameter to the function *must* be called ``context``.) - -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: - -.. code-block:: html+django - - Jump directly to <a href="{{ link }}">{{ title }}</a>. - -Then, any time you want to use that custom tag, load its library and call it -without any arguments, like so: - -.. code-block:: html+django - - {% jump_link %} - -Note that when you're using ``takes_context=True``, there's no need to pass -arguments to the template tag. It automatically gets access to the context. - -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. - -Setting a variable in the context -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The above examples simply output a value. Generally, it's more flexible if your -template tags set template variables instead of outputting values. That way, -template authors can reuse the values that your template tags create. - -To set a variable in the context, just use dictionary assignment on the context -object in the ``render()`` method. Here's an updated version of -``CurrentTimeNode`` that sets a template variable ``current_time`` instead of -outputting it:: - - class CurrentTimeNode2(template.Node): - def __init__(self, format_string): - self.format_string = format_string - def render(self, context): - context['current_time'] = datetime.datetime.now().strftime(self.format_string) - return '' - -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: - -.. code-block:: html+django - - {% current_time "%Y-%M-%d %I:%M %p" %}<p>The time is {{ current_time }}.</p> - -.. admonition:: Variable scope in context - - Any variable set in the context will only be available in the same ``block`` - of the template in which it was assigned. This behaviour is intentional; - it provides a scope for variables so that they don't conflict with - context in other blocks. - -But, there's a problem with ``CurrentTimeNode2``: The variable name -``current_time`` is hard-coded. This means you'll need to make sure your -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: - -.. code-block:: html+django - - {% current_time "%Y-%M-%d %I:%M %p" as my_current_time %} - <p>The current time is {{ my_current_time }}.</p> - -To do that, you'll need to refactor both the compilation function and ``Node`` -class, like so:: - - class CurrentTimeNode3(template.Node): - def __init__(self, format_string, var_name): - self.format_string = format_string - self.var_name = var_name - def render(self, context): - context[self.var_name] = datetime.datetime.now().strftime(self.format_string) - return '' - - import re - def do_current_time(parser, token): - # This version uses a regular expression to parse tag contents. - try: - # Splitting by None == splitting by spaces. - tag_name, arg = token.contents.split(None, 1) - except ValueError: - raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0] - m = re.search(r'(.*?) as (\w+)', arg) - if not m: - raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name - format_string, var_name = m.groups() - if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")): - raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name - return CurrentTimeNode3(format_string[1:-1], var_name) - -The difference here is that ``do_current_time()`` grabs the format string and -the variable name, passing both to ``CurrentTimeNode3``. - -Parsing until another block tag -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Template tags can work in tandem. For instance, the standard ``{% comment %}`` -tag hides everything until ``{% endcomment %}``. To create a template tag such -as this, use ``parser.parse()`` in your compilation function. - -Here's how the standard ``{% comment %}`` tag is implemented:: - - def do_comment(parser, token): - nodelist = parser.parse(('endcomment',)) - parser.delete_first_token() - return CommentNode() - - class CommentNode(template.Node): - def render(self, context): - return '' - -``parser.parse()`` takes a tuple of names of block tags ''to parse until''. It -returns an instance of ``django.template.NodeList``, which is a list of -all ``Node`` objects that the parser encountered ''before'' it encountered -any of the tags named in the tuple. - -In ``"nodelist = parser.parse(('endcomment',))"`` in the above example, -``nodelist`` is a list of all nodes between the ``{% comment %}`` and -``{% endcomment %}``, not counting ``{% comment %}`` and ``{% endcomment %}`` -themselves. - -After ``parser.parse()`` is called, the parser hasn't yet "consumed" the -``{% endcomment %}`` tag, so the code needs to explicitly call -``parser.delete_first_token()``. - -``CommentNode.render()`` simply returns an empty string. Anything between -``{% comment %}`` and ``{% endcomment %}`` is ignored. - -Parsing until another block tag, and saving contents -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the previous example, ``do_comment()`` discarded everything between -``{% comment %}`` and ``{% endcomment %}``. Instead of doing that, it's -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: - -.. code-block:: html+django - - {% upper %}This will appear in uppercase, {{ your_name }}.{% endupper %} - -As in the previous example, we'll use ``parser.parse()``. But this time, we -pass the resulting ``nodelist`` to the ``Node``:: - - def do_upper(parser, token): - nodelist = parser.parse(('endupper',)) - parser.delete_first_token() - return UpperNode(nodelist) - - class UpperNode(template.Node): - def __init__(self, nodelist): - self.nodelist = nodelist - def render(self, context): - output = self.nodelist.render(context) - return output.upper() - -The only new concept here is the ``self.nodelist.render(context)`` in -``UpperNode.render()``. - -For more examples of complex rendering, see the source code for ``{% if %}``, -``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in -``django/template/defaulttags.py``. diff --git a/parts/django/docs/howto/deployment/fastcgi.txt b/parts/django/docs/howto/deployment/fastcgi.txt deleted file mode 100644 index ea14b97..0000000 --- a/parts/django/docs/howto/deployment/fastcgi.txt +++ /dev/null @@ -1,400 +0,0 @@ -============================================ -How to use Django with FastCGI, SCGI, or AJP -============================================ - -.. highlight:: bash - -Although the current preferred setup for running Django is :doc:`Apache with -mod_wsgi </howto/deployment/modwsgi>`, many people use shared hosting, on -which protocols such as FastCGI, SCGI or AJP are the only viable options. In -some setups, these protocols may provide better performance than mod_wsgi_. - -.. 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. - -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 -(via a socket) to FastCGI, which executes the code and passes the response back -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 -process doesn't run inside the Web server process, but in a separate, -persistent process. - -.. _mod_wsgi: http://code.google.com/p/modwsgi/ -.. _mod_perl: http://perl.apache.org/ -.. _mod_python: http://www.modpython.org/ - -.. admonition:: Why run code in a separate process? - - The traditional ``mod_*`` arrangements in Apache embed various scripting - languages (most notably PHP, Python and Perl) inside the process space of - your Web server. Although this lowers startup time -- because code doesn't - have to be read off disk for every request -- it comes at the cost of - memory use. For mod_python, for example, every Apache process gets its own - Python interpreter, which uses up a considerable amount of RAM. - - Due to the nature of FastCGI, it's even possible to have processes that run - under a different user account than the Web server process. That's a nice - security benefit on shared systems, because it means you can secure your - code from other users. - -Prerequisite: flup -================== - -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/ - -Starting your FastCGI server -============================ - -FastCGI operates on a client-server model, and in most cases you'll be starting -the FastCGI process on your own. Your Web server (be it Apache, lighttpd, or -otherwise) only contacts your Django-FastCGI process when the server needs a -dynamic page to be loaded. Because the daemon is already running with the code -in memory, it's able to serve the response very quickly. - -.. admonition:: Note - - If you're on a shared hosting system, you'll probably be forced to use - Web server-managed FastCGI processes. See the section below on running - Django with Web server-managed processes for more information. - -A Web server can connect to a FastCGI server in one of two ways: It can use -either a Unix domain socket (a "named pipe" on Win32 systems), or it can use a -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 :doc:`manage.py </ref/django-admin>` is), and then run the -:djadmin:`runfcgi` command:: - - ./manage.py runfcgi [options] - -If you specify ``help`` as the only option after :djadmin:`runfcgi`, it'll -display a list of all the available options. - -You'll need to specify either a :djadminopt:`socket`, a :djadminopt:`protocol` -or both :djadminopt:`host` and :djadminopt:`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 :djadminopt:`protocol=\<protocol_name\> <protocol>` option -with ``./manage.py runfcgi`` -- where ``<protocol_name>`` may be one of: -``fcgi`` (the default), ``scgi`` or ``ajp``. For example:: - - ./manage.py runfcgi protocol=scgi - -.. _flup: http://www.saddi.com/software/flup/ -.. _fastcgi: http://www.fastcgi.com/ -.. _SCGI: http://python.ca/scgi/protocol.txt -.. _AJP1.3: http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html - -Examples --------- - -Running a threaded server on a TCP port:: - - ./manage.py runfcgi method=threaded host=127.0.0.1 port=3033 - -Running a preforked server on a Unix domain socket:: - - ./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid - -.. admonition:: Socket security - - Django's default umask requires that the webserver and the Django fastcgi - process be run with the same group **and** user. For increased security, - you can run them under the same group but as different users. If you do - this, you will need to set the umask to 0002 using the ``umask`` argument - to ``runfcgi``. - -Run without daemonizing (backgrounding) the process (good for debugging):: - - ./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock maxrequests=1 - -Stopping the FastCGI daemon ---------------------------- - -If you have the process running in the foreground, it's easy enough to stop it: -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 :djadminopt:`pidfile` option to :djadmin:`runfcgi`, you can -kill the running FastCGI daemon like this:: - - kill `cat $PIDFILE` - -...where ``$PIDFILE`` is the ``pidfile`` you specified. - -To easily restart your FastCGI daemon on Unix, try this small shell script:: - - #!/bin/bash - - # Replace these three settings. - PROJDIR="/home/user/myproject" - PIDFILE="$PROJDIR/mysite.pid" - SOCKET="$PROJDIR/mysite.sock" - - cd $PROJDIR - if [ -f $PIDFILE ]; then - kill `cat -- $PIDFILE` - rm -f -- $PIDFILE - fi - - exec /usr/bin/env - \ - PYTHONPATH="../python:.." \ - ./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE - -Apache setup -============ - -To use Django with Apache and FastCGI, you'll need Apache installed and -configured, with `mod_fastcgi`_ installed and enabled. Consult the Apache -documentation for instructions. - -Once you've got that set up, point Apache at your Django FastCGI instance by -editing the ``httpd.conf`` (Apache configuration) file. You'll need to do two -things: - - * Use the ``FastCGIExternalServer`` directive to specify the location of - your FastCGI server. - * Use ``mod_rewrite`` to point URLs at FastCGI as appropriate. - -.. _mod_fastcgi: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html - -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: - -.. code-block:: apache - - # Connect to FastCGI via a socket / named pipe. - FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock - - # Connect to FastCGI via a TCP host/port. - FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033 - -In either case, the file ``/home/user/public_html/mysite.fcgi`` doesn't -actually have to exist. It's just a URL used by the Web server internally -- a -hook for signifying which requests at a URL should be handled by FastCGI. (More -on this in the next section.) - -.. _FastCGIExternalServer docs: http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html#FastCgiExternalServer - -Using mod_rewrite to point URLs at FastCGI ------------------------------------------- - -The second step is telling Apache to use FastCGI for URLs that match a certain -pattern. To do this, use the `mod_rewrite`_ module and rewrite URLs to -``mysite.fcgi`` (or whatever you specified in the ``FastCGIExternalServer`` -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: - -.. code-block:: apache - - <VirtualHost 12.34.56.78> - ServerName example.com - DocumentRoot /home/user/public_html - Alias /media /home/user/python/django/contrib/admin/media - RewriteEngine On - RewriteRule ^/(media.*)$ /$1 [QSA,L,PT] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L] - </VirtualHost> - -.. _mod_rewrite: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html - -Django will automatically use the pre-rewrite version of the URL when -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 -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: - -.. code-block:: lua - - server.document-root = "/home/user/public_html" - fastcgi.server = ( - "/mysite.fcgi" => ( - "main" => ( - # Use host / port instead of socket for TCP fastcgi - # "host" => "127.0.0.1", - # "port" => 3033, - "socket" => "/home/user/mysite.sock", - "check-local" => "disable", - ) - ), - ) - alias.url = ( - "/media" => "/home/user/django/contrib/admin/media/", - ) - - url.rewrite-once = ( - "^(/media.*)$" => "$1", - "^/favicon\.ico$" => "/media/favicon.ico", - "^(/.*)$" => "/mysite.fcgi$1", - ) - -Running multiple Django sites on one lighttpd ---------------------------------------------- - -lighttpd lets you use "conditional configuration" to allow configuration to be -customized per host. To specify multiple FastCGI sites, just add a conditional -block around your FastCGI config for each site:: - - # If the hostname is 'www.example1.com'... - $HTTP["host"] == "www.example1.com" { - server.document-root = "/foo/site1" - fastcgi.server = ( - ... - ) - ... - } - - # If the hostname is 'www.example2.com'... - $HTTP["host"] == "www.example2.com" { - server.document-root = "/foo/site2" - fastcgi.server = ( - ... - ) - ... - } - -You can also run multiple Django installations on the same site simply by -specifying multiple entries in the ``fastcgi.server`` directive. Add one -FastCGI host for each. - -Cherokee setup -============== - -Cherokee is a very fast, flexible and easy to configure Web Server. It -supports the widespread technologies nowadays: FastCGI, SCGI, PHP, CGI, SSI, -TLS and SSL encrypted connections, Virtual hosts, Authentication, on the fly -encoding, Load Balancing, Apache compatible log files, Data Base Balancer, -Reverse HTTP Proxy and much more. - -The Cherokee project provides a documentation to `setting up Django`_ with Cherokee. - -.. _setting up Django: http://www.cherokee-project.com/doc/cookbook_django.html - -Running Django on a shared-hosting provider with Apache -======================================================= - -Many shared-hosting providers don't allow you to run your own server daemons or -edit the ``httpd.conf`` file. In these cases, it's still possible to run Django -using Web server-spawned processes. - -.. admonition:: Note - - If you're using Web server-spawned processes, as explained in this section, - 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``: - -.. code-block:: apache - - AddHandler fastcgi-script .fcgi - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L] - -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: - -.. code-block:: python - - #!/usr/bin/python - import sys, os - - # Add a custom Python path. - sys.path.insert(0, "/home/user/python") - - # Switch to the directory of your project. (Optional.) - # os.chdir("/home/user/myproject") - - # Set the DJANGO_SETTINGS_MODULE environment variable. - os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings" - - from django.core.servers.fastcgi import runfastcgi - runfastcgi(method="threaded", daemonize="false") - -Restarting the spawned server ------------------------------ - -If you change any Python code on your site, you'll need to tell FastCGI the -code has changed. But there's no need to restart Apache in this case. Rather, -just reupload ``mysite.fcgi``, or edit the file, so that the timestamp on the -file will change. When Apache sees the file has been updated, it will restart -your Django application for you. - -If you have access to a command shell on a Unix system, you can accomplish this -easily by using the ``touch`` command:: - - touch mysite.fcgi - -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 :ref:`modpython <serving-the-admin-files>` documentation -is also applicable in the setups detailed above. - -Forcing the URL prefix to a particular value -============================================ - -Because many of these fastcgi-based solutions require rewriting the URL at -some point inside the Web server, the path information that Django sees may not -resemble the original URL that was passed in. This is a problem if the Django -application is being served from under a particular prefix and you want your -URLs from the ``{% url %}`` tag to look like the prefix, rather than the -rewritten version, which might contain, for example, ``mysite.fcgi``. - -Django makes a good attempt to work out what the real script name prefix -should be. In particular, if the Web server sets the ``SCRIPT_URL`` (specific -to Apache's mod_rewrite), or ``REDIRECT_URL`` (set by a few servers, including -Apache + mod_rewrite in some situations), Django will work out the original -prefix automatically. - -In the cases where Django cannot work out the prefix correctly and where you -want the original value to be used in URLs, you can set the -:setting:`FORCE_SCRIPT_NAME` setting in your main ``settings`` file. This sets the -script name uniformly for every URL served via that settings file. Thus you'll -need to use different settings files if you want different sets of URLs to -have different script names in this case, but that is a rare situation. - -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/parts/django/docs/howto/deployment/index.txt b/parts/django/docs/howto/deployment/index.txt deleted file mode 100644 index 740f9bc..0000000 --- a/parts/django/docs/howto/deployment/index.txt +++ /dev/null @@ -1,25 +0,0 @@ -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 - - modwsgi - modpython - fastcgi - -If you're new to deploying Django and/or Python, we'd recommend you try -:doc:`mod_wsgi </howto/deployment/modwsgi>` first. In most cases it'll be the easiest, -fastest, and most stable deployment choice. - -.. seealso:: - - * `Chapter 12 of The Django Book`_ discusses deployment and especially - scaling in more detail. - -.. _chapter 12 of the django book: http://djangobook.com/en/2.0/chapter12/ diff --git a/parts/django/docs/howto/deployment/modpython.txt b/parts/django/docs/howto/deployment/modpython.txt deleted file mode 100644 index ba55335..0000000 --- a/parts/django/docs/howto/deployment/modpython.txt +++ /dev/null @@ -1,418 +0,0 @@ -.. _howto-deployment-modpython: - -============================================ -How to use Django with Apache and mod_python -============================================ - -.. warning:: - - Support for mod_python will be deprecated in a future release of Django. If - you are configuring a new deployment, you are strongly encouraged to - consider using :doc:`mod_wsgi </howto/deployment/modwsgi>` or any of the - other :doc:`supported backends </howto/deployment/index>`. - -.. highlight:: apache - -The `mod_python`_ module for Apache_ can be used to deploy Django to a -production server, although it has been mostly superseded by the simpler -:doc:`mod_wsgi deployment option </howto/deployment/modwsgi>`. - -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`_. - -.. seealso:: - - * Apache is a big, complex animal, and this document only scratches the - surface of what Apache can do. If you need more advanced information about - Apache, there's no better source than `Apache's own official - documentation`_ - - * You may also be interested in :doc:`How to use Django with FastCGI, SCGI, - or AJP </howto/deployment/fastcgi>`. - -.. _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 -.. _apache's own official documentation: http://httpd.apache.org/docs/ - -Basic configuration -=================== - -To configure Django with mod_python, first make sure you have Apache installed, -with the mod_python module activated. - -Then edit your ``httpd.conf`` file and add the following:: - - <Location "/mysite/"> - SetHandler python-program - PythonHandler django.core.handlers.modpython - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - PythonOption django.root /mysite - PythonDebug On - </Location> - -...and replace ``mysite.settings`` with the Python import path to your Django -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 :ref:`DJANGO_SETTINGS_MODULE -<django-settings-module>` so mod_python knows which settings to use. - -.. versionadded:: 1.0 - The ``PythonOption django.root ...`` is new in this version. - -Because mod_python does not know we are serving this site from underneath the -``/mysite/`` prefix, this value needs to be passed through to the mod_python -handler in Django, via the ``PythonOption django.root ...`` line. The value set -on that line (the last item) should match the string given in the ``<Location -...>`` directive. The effect of this is that Django will automatically strip the -``/mysite`` string from the front of any URLs before matching them against your -URLconf patterns. If you later move your site to live under ``/mysite2``, you -will not have to change anything except the ``django.root`` option in the config -file. - -When using ``django.root`` you should make sure that what's left, after the -prefix has been removed, begins with a slash. Your URLconf patterns that are -expecting an initial slash will then work correctly. In the above example, -since we want to send things like ``/mysite/admin/`` to ``/admin/``, we need -to remove the string ``/mysite`` from the beginning, so that is the -``django.root`` value. It would be an error to use ``/mysite/`` (with a -trailing slash) in this case. - -Note that we're using the ``<Location>`` directive, not the ``<Directory>`` -directive. The latter is used for pointing at places on your filesystem, -whereas ``<Location>`` points at places in the URL structure of a Web site. -``<Directory>`` would be meaningless here. - -Also, if your Django project is not on the default ``PYTHONPATH`` for your -computer, you'll have to tell mod_python where your project can be found: - -.. parsed-literal:: - - <Location "/mysite/"> - SetHandler python-program - PythonHandler django.core.handlers.modpython - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - PythonOption django.root /mysite - PythonDebug On - **PythonPath "['/path/to/project'] + sys.path"** - </Location> - -The value you use for ``PythonPath`` should include the parent directories of -all the modules you are going to import in your application. It should also -include the parent directory of the :ref:`DJANGO_SETTINGS_MODULE -<django-settings-module>` location. This is exactly the same situation as -setting the Python path for interactive usage. Whenever you try to import -something, Python will run through all the directories in ``sys.path`` in turn, -from first to last, and try to import from each directory until one succeeds. - -Make sure that your Python source files' permissions are set such that the -Apache user (usually named ``apache`` or ``httpd`` on most systems) will have -read access to the files. - -An example might make this clearer. Suppose you have some applications under -``/usr/local/django-apps/`` (for example, ``/usr/local/django-apps/weblog/`` and -so forth), your settings file is at ``/var/www/mysite/settings.py`` and you have -specified :ref:`DJANGO_SETTINGS_MODULE <django-settings-module>` as in the above -example. In this case, you would need to write your ``PythonPath`` directive -as:: - - PythonPath "['/usr/local/django-apps/', '/var/www'] + sys.path" - -With this path, ``import weblog`` and ``import mysite.settings`` will both -work. If you had ``import blogroll`` in your code somewhere and ``blogroll`` -lived under the ``weblog/`` directory, you would *also* need to add -``/usr/local/django-apps/weblog/`` to your ``PythonPath``. Remember: the -**parent directories** of anything you import directly must be on the Python -path. - -.. note:: - - If you're using Windows, we still recommended that you use forward - slashes in the pathnames, even though Windows normally uses the backslash - character as its native separator. Apache knows how to convert from the - forward slash format to the native format, so this approach is portable and - easier to read. (It avoids tricky problems with having to double-escape - backslashes.) - - This is valid even on a Windows system:: - - PythonPath "['c:/path/to/project'] + sys.path" - -You can also add directives such as ``PythonAutoReload Off`` for performance. -See the `mod_python documentation`_ for a full list of options. - -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. - -When deploying Django sites on mod_python, you'll need to restart Apache each -time you make changes to your Python code. - -.. _mod_python documentation: http://modpython.org/live/current/doc-html/directives.html - -Multiple Django installations on the same Apache -================================================ - -It's entirely possible to run multiple Django installations on the same Apache -instance. Just use ``VirtualHost`` for that, like so:: - - NameVirtualHost * - - <VirtualHost *> - ServerName www.example.com - # ... - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - </VirtualHost> - - <VirtualHost *> - ServerName www2.example.com - # ... - SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings - </VirtualHost> - -If you need to put two Django installations within the same ``VirtualHost`` -(or in different ``VirtualHost`` blocks that share the same server name), -you'll need to take a special precaution to ensure mod_python's cache doesn't -mess things up. Use the ``PythonInterpreter`` directive to give different -``<Location>`` directives separate interpreters:: - - <VirtualHost *> - ServerName www.example.com - # ... - <Location "/something"> - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - PythonInterpreter mysite - </Location> - - <Location "/otherthing"> - SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings - PythonInterpreter othersite - </Location> - </VirtualHost> - -The values of ``PythonInterpreter`` don't really matter, as long as they're -different between the two ``Location`` blocks. - -Running a development server with mod_python -============================================ - -If you use mod_python for your development server, you can avoid the hassle of -having to restart the server each time you make code changes. Just set -``MaxRequestsPerChild 1`` in your ``httpd.conf`` file to force Apache to reload -everything for each request. But don't do that on a production server, or we'll -revoke your Django privileges. - -If you're the type of programmer who debugs using scattered ``print`` -statements, note that output to ``stdout`` will not appear in the Apache -log and can even `cause response errors`_. - -.. _cause response errors: http://blog.dscpl.com.au/2009/04/wsgi-and-printing-to-standard-output.html - -If you have the need to print debugging information in a mod_python setup, you -have a few options. You can print to ``stderr`` explicitly, like so:: - - print >> sys.stderr, 'debug text' - sys.stderr.flush() - -(note that ``stderr`` is buffered, so calling ``flush`` is necessary if you wish -debugging information to be displayed promptly.) - -A more compact approach is to use an assertion:: - - assert False, 'debug text' - -Another alternative is to add debugging information to the template of your page. - -.. _serving-media-files: - -Serving media files -=================== - -Django doesn't serve media files itself; it leaves that job to whichever Web -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_ - * Nginx_ - * TUX_ - * A stripped-down version of Apache_ - * Cherokee_ - -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 -particular part of the site:: - - <Location "/media"> - SetHandler None - </Location> - -Just change ``Location`` to the root URL of your media files. You can also use -``<LocationMatch>`` to match a regular expression. - -This example sets up Django at the site root but explicitly disables Django for -the ``media`` subdirectory and any URL that ends with ``.jpg``, ``.gif`` or -``.png``:: - - <Location "/"> - SetHandler python-program - PythonHandler django.core.handlers.modpython - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - </Location> - - <Location "/media"> - SetHandler None - </Location> - - <LocationMatch "\.(jpg|gif|png)$"> - SetHandler None - </LocationMatch> - - -.. _lighttpd: http://www.lighttpd.net/ -.. _Nginx: http://wiki.nginx.org/Main -.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server -.. _Apache: http://httpd.apache.org/ -.. _Cherokee: http://www.cherokee-project.com/ - -.. _serving-the-admin-files: - -Serving the admin files -======================= - -Note that the Django development server automagically serves admin media files, -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 (: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. - - 2. Or, copy the admin media files so that they live within your Apache - document root. - -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: - -.. code-block:: python - - import os - os.environ['PYTHON_EGG_CACHE'] = '/some/directory' - -Here, ``/some/directory`` is a directory that the Apache Web server process can -write to. It will be used as the location for any unpacking of code the eggs -need to do. - -Then you have to tell mod_python to import this file before doing anything -else. This is done using the PythonImport_ directive to mod_python. You need -to ensure that you have specified the ``PythonInterpreter`` directive to -mod_python as described above__ (you need to do this even if you aren't -serving multiple installations in this case). Then add the ``PythonImport`` -line in the main server configuration (i.e., outside the ``Location`` or -``VirtualHost`` sections). For example:: - - PythonInterpreter my_django - PythonImport /path/to/my/project/file.py my_django - -Note that you can use an absolute path here (or a normal dotted import path), -as described in the `mod_python manual`_. We use an absolute path in the -above example because if any Python path modifications are required to access -your project, they will not have been done at the time the ``PythonImport`` -line is processed. - -.. _Egg: http://peak.telecommunity.com/DevCenter/PythonEggs -.. _PythonImport: http://www.modpython.org/live/current/doc-html/dir-other-pimp.html -.. _mod_python manual: PythonImport_ -__ `Multiple Django installations on the same Apache`_ - -Error handling -============== - -When you use Apache/mod_python, errors will be caught by Django -- in other -words, they won't propagate to the Apache level and won't appear in the Apache -``error_log``. - -The exception for this is if something is really wonky in your Django setup. In -that case, you'll see an "Internal Server Error" page in your browser and the -full Python traceback in your Apache ``error_log`` file. The ``error_log`` -traceback is spread over multiple lines. (Yes, this is ugly and rather hard to -read, but it's how mod_python does things.) - -If you get a segmentation fault -=============================== - -If Apache causes a segmentation fault, there are two probable causes, neither -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 - the Python MySQL backend. There's full information in the - `mod_python FAQ entry`_. - -If you continue to have problems setting up mod_python, a good thing to do is -get a barebones mod_python site working, without the Django framework. This is -an easy way to isolate mod_python-specific problems. `Getting mod_python Working`_ -details this procedure. - -The next step should be to edit your test code and add an import of any -Django-specific code you're using -- your views, your models, your URLconf, -your RSS configuration, etc. Put these imports in your test handler function -and access your test URL in a browser. If this causes a crash, you've confirmed -it's the importing of Django code that causes the problem. Gradually reduce the -set of imports until it stops crashing, so as to find the specific module that -causes the problem. Drop down further into modules and look into their imports, -as necessary. - -.. _Expat Causing Apache Crash: http://www.dscpl.com.au/wiki/ModPython/Articles/ExpatCausingApacheCrash -.. _mod_python FAQ entry: http://modpython.org/FAQ/faqw.py?req=show&file=faq02.013.htp -.. _Getting mod_python Working: http://www.dscpl.com.au/wiki/ModPython/Articles/GettingModPythonWorking - -If you get a UnicodeEncodeError -=============================== - -If you're taking advantage of the internationalization features of Django (see -:doc:`/topics/i18n/index`) and you intend to allow users to upload files, you must -ensure that the environment used to start Apache is configured to accept -non-ASCII file names. If your environment is not correctly configured, you -will trigger ``UnicodeEncodeError`` exceptions when calling functions like -``os.path()`` on filenames that contain non-ASCII characters. - -To avoid these problems, the environment used to start Apache should contain -settings analogous to the following:: - - export LANG='en_US.UTF-8' - export LC_ALL='en_US.UTF-8' - -Consult the documentation for your operating system for the appropriate syntax -and location to put these configuration items; ``/etc/apache2/envvars`` is a -common location on Unix platforms. Once you have added these statements -to your environment, restart Apache. diff --git a/parts/django/docs/howto/deployment/modwsgi.txt b/parts/django/docs/howto/deployment/modwsgi.txt deleted file mode 100644 index 17ba0e3..0000000 --- a/parts/django/docs/howto/deployment/modwsgi.txt +++ /dev/null @@ -1,118 +0,0 @@ -========================================== -How to use Django with Apache and mod_wsgi -========================================== - -Deploying Django with Apache_ and `mod_wsgi`_ is the recommended way to get -Django into production. - -.. _Apache: http://httpd.apache.org/ -.. _mod_wsgi: http://code.google.com/p/modwsgi/ - -mod_wsgi is an Apache module which can be used to host any Python application -which supports the `Python WSGI interface`_, including Django. Django will work -with any version of Apache which supports mod_wsgi. - -.. _python wsgi interface: http://www.python.org/dev/peps/pep-0333/ - -The `official mod_wsgi documentation`_ is fantastic; it's your source for all -the details about how to use mod_wsgi. You'll probably want to start with the -`installation and configuration documentation`_. - -.. _official mod_wsgi documentation: http://code.google.com/p/modwsgi/ -.. _installation and configuration documentation: http://code.google.com/p/modwsgi/wiki/InstallationInstructions - -Basic Configuration -=================== - -Once you've got mod_wsgi installed and activated, edit your ``httpd.conf`` file -and add:: - - WSGIScriptAlias / /path/to/mysite/apache/django.wsgi - -The first bit above is the url you want to be serving your application at (``/`` -indicates the root url), and the second is the location of a "WSGI file" -- see -below -- on your system, usually inside of your project. This tells Apache -to serve any request below the given URL using the WSGI application defined by that file. - -Next we'll need to actually create this WSGI application, so create the file -mentioned in the second part of ``WSGIScriptAlias`` and add:: - - import os - import sys - - os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' - - import django.core.handlers.wsgi - application = django.core.handlers.wsgi.WSGIHandler() - -If your project is not on your ``PYTHONPATH`` by default you can add:: - - path = '/usr/local/django' - if path not in sys.path: - sys.path.append(path) - -just above the final ``import`` line to place your project on the path. Remember to -replace 'mysite.settings' with your correct settings file, and '/usr/local/django' -with your own project's location. - -Serving media files -=================== - -Django doesn't serve media files itself; it leaves that job to whichever Web -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_ - * Nginx_ - * TUX_ - * A stripped-down version of Apache_ - * Cherokee_ - -If, however, you have no option but to serve media files on the same Apache -``VirtualHost`` as Django, you can set up Apache to serve some URLs as -static media, and others using the mod_wsgi interface to Django. - -This example sets up Django at the site root, but explicitly serves ``robots.txt``, -``favicon.ico``, any CSS file, and anything in the ``/media/`` URL space as a static -file. All other URLs will be served using mod_wsgi:: - - Alias /robots.txt /usr/local/wsgi/static/robots.txt - Alias /favicon.ico /usr/local/wsgi/static/favicon.ico - - AliasMatch /([^/]*\.css) /usr/local/wsgi/static/styles/$1 - - Alias /media/ /usr/local/wsgi/static/media/ - - <Directory /usr/local/wsgi/static> - Order deny,allow - Allow from all - </Directory> - - WSGIScriptAlias / /usr/local/wsgi/scripts/django.wsgi - - <Directory /usr/local/wsgi/scripts> - Order allow,deny - Allow from all - </Directory> - -.. _lighttpd: http://www.lighttpd.net/ -.. _Nginx: http://wiki.nginx.org/Main -.. _TUX: http://en.wikipedia.org/wiki/TUX_web_server -.. _Apache: http://httpd.apache.org/ -.. _Cherokee: http://www.cherokee-project.com/ - -More details on configuring a mod_wsgi site to serve static files can be found -in the mod_wsgi documentation on `hosting static files`_. - -.. _hosting static files: http://code.google.com/p/modwsgi/wiki/ConfigurationGuidelines#Hosting_Of_Static_Files - -Details -======= - -For more details, see the `mod_wsgi documentation on Django integration`_, -which explains the above in more detail, and walks through all the various -options you've got when deploying under mod_wsgi. - -.. _mod_wsgi documentation on Django integration: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango diff --git a/parts/django/docs/howto/error-reporting.txt b/parts/django/docs/howto/error-reporting.txt deleted file mode 100644 index 9c61c97..0000000 --- a/parts/django/docs/howto/error-reporting.txt +++ /dev/null @@ -1,78 +0,0 @@ -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 e-mail you details of those errors. - -Server errors -------------- - -When :setting:`DEBUG` is ``False``, Django will e-mail the users listed in the -:setting:`ADMINS` 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. - -.. note:: - - In order to send e-mail, Django requires a few settings telling it - how to connect to your mail server. At the very least, you'll need - to specify :setting:`EMAIL_HOST` and possibly - :setting:`EMAIL_HOST_USER` and :setting:`EMAIL_HOST_PASSWORD`, - though other settings may be also required depending on your mail - server's configuration. Consult :doc:`the Django settings - documentation </ref/settings>` for a full list of email-related - settings. - -By default, Django will send e-mail from root@localhost. However, some mail -providers reject all e-mail from this address. To use a different sender -address, modify the :setting:`SERVER_EMAIL` setting. - -To disable this behavior, just remove all entries from the :setting:`ADMINS` -setting. - -404 errors ----------- - -Django can also be configured to e-mail errors about broken links (404 "page -not found" errors). Django sends e-mails about 404 errors when: - - * :setting:`DEBUG` is ``False`` - - * :setting:`SEND_BROKEN_LINK_EMAILS` is ``True`` - - * Your :setting:`MIDDLEWARE_CLASSES` setting includes ``CommonMiddleware`` - (which it does by default). - -If those conditions are met, Django will e-mail the users listed in the -:setting:`MANAGERS` setting whenever your code raises a 404 and the request has -a referer. (It doesn't bother to e-mail for 404s that don't have a referer -- -those are usually just people typing in broken URLs or broken Web 'bots). - -You can tell Django to stop reporting particular 404s by tweaking the -:setting:`IGNORABLE_404_ENDS` and :setting:`IGNORABLE_404_STARTS` settings. Both -should be a tuple of strings. For example:: - - IGNORABLE_404_ENDS = ('.php', '.cgi') - IGNORABLE_404_STARTS = ('/phpmyadmin/',) - -In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not* be -reported. Neither will any URL starting with ``/phpmyadmin/``. - -The best way to disable this behavior is to set -:setting:`SEND_BROKEN_LINK_EMAILS` to ``False``. - -.. seealso:: - - You can also set up custom error reporting by writing a custom piece of - :ref:`exception middleware <exception-middleware>`. If you do write custom - error handling, it's a good idea to emulate Django's built-in error handling - and only report/log errors if :setting:`DEBUG` is ``False``. diff --git a/parts/django/docs/howto/i18n.txt b/parts/django/docs/howto/i18n.txt deleted file mode 100644 index 64b33d7..0000000 --- a/parts/django/docs/howto/i18n.txt +++ /dev/null @@ -1,103 +0,0 @@ -.. _using-translations-in-your-own-projects: - -=============================================== -Using internationalization in your own projects -=============================================== - -At runtime, Django looks for translations by following this algorithm: - - * First, it looks for a ``locale`` directory in the directory containing - your settings file. - * Second, it looks for a ``locale`` directory in the project directory. - * Third, it looks for a ``locale`` directory in each of the installed apps. - It does this in the reverse order of INSTALLED_APPS - * Finally, it checks the Django-provided base translation in - ``django/conf/locale``. - -In all cases the name of the directory containing the translation is expected to -be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``, -etc. - -This way, you can write applications that include their own translations, and -you can override base translations in your project path. Or, you can just build -a big project out of several apps and put all translations into one big project -message file. The choice is yours. - -.. note:: - - If you're using manually configured settings, as described in - :ref:`settings-without-django-settings-module`, the ``locale`` directory in - the project directory will not be examined, since Django loses the ability - to work out the location of the project directory. (Django normally uses the - location of the settings file to determine this, and a settings file doesn't - exist if you're manually configuring your settings.) - -All message file repositories are structured the same way. They are: - - * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` - * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)`` - * All paths listed in ``LOCALE_PATHS`` in your settings file are - searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)`` - * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)`` - -To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>` -tool. You only need to be in the same directory where the ``locale/`` directory -is located. And you use :djadmin:`django-admin.py compilemessages <compilemessages>` -to produce the binary ``.mo`` files that are used by ``gettext``. Read the -:doc:`/topics/i18n/localization` document for more details. - -You can also run ``django-admin.py compilemessages --settings=path.to.settings`` -to make the compiler process all the directories in your :setting:`LOCALE_PATHS` -setting. - -Application message files are a bit complicated to discover -- they need the -:class:`~django.middleware.locale.LocaleMiddleware`. If you don't use the -middleware, only the Django message files and project message files will be -installed and available at runtime. - -Finally, you should give some thought to the structure of your translation -files. If your applications need to be delivered to other users and will -be used in other projects, you might want to use app-specific translations. -But using app-specific translations and project translations could produce -weird problems with ``makemessages``: It will traverse all directories below -the current path and so might put message IDs into the project message file -that are already in application message files. - -The easiest way out is to store applications that are not part of the project -(and so carry their own translations) outside the project tree. That way, -``django-admin.py makemessages`` on the project level will only translate -strings that are connected to your explicit project and not strings that are -distributed independently. - -Using translations outside views and templates -============================================== - -While Django provides a rich set of i18n tools for use in views and templates, -it does not restrict the usage to Django-specific code. The Django translation -mechanisms can be used to translate arbitrary texts to any language that is -supported by Django (as long as an appropriate translation catalog exists, of -course). You can load a translation catalog, activate it and translate text to -language of your choice, but remember to switch back to original language, as -activating a translation catalog is done on per-thread basis and such change -will affect code running in the same thread. - -For example:: - - from django.utils import translation - def welcome_translated(language): - cur_language = translation.get_language() - try: - translation.activate(language) - text = translation.ugettext('welcome') - finally: - translation.activate(cur_language) - return text - -Calling this function with the value 'de' will give you ``"Willkommen"``, -regardless of :setting:`LANGUAGE_CODE` and language set by middleware. - -Functions of particular interest are ``django.utils.translation.get_language()`` -which returns the language used in the current thread, -``django.utils.translation.activate()`` which activates a translation catalog -for the current thread, and ``django.utils.translation.check_for_language()`` -which checks if the given language is supported by Django. diff --git a/parts/django/docs/howto/index.txt b/parts/django/docs/howto/index.txt deleted file mode 100644 index 49d0644..0000000 --- a/parts/django/docs/howto/index.txt +++ /dev/null @@ -1,34 +0,0 @@ -"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 -:doc:`/topics/index` and the :doc:`/ref/index`. However, these guides will help -you quickly accomplish common tasks. - -.. toctree:: - :maxdepth: 1 - - apache-auth - auth-remote-user - custom-management-commands - custom-model-fields - custom-template-tags - custom-file-storage - deployment/index - error-reporting - initial-data - i18n - jython - 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/ diff --git a/parts/django/docs/howto/initial-data.txt b/parts/django/docs/howto/initial-data.txt deleted file mode 100644 index cf3f65d..0000000 --- a/parts/django/docs/howto/initial-data.txt +++ /dev/null @@ -1,142 +0,0 @@ -================================= -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 <dumpdata>` command. -Or, you can write fixtures by hand; fixtures can be written as XML, YAML, or -JSON documents. The :doc:`serialization documentation </topics/serialization>` -has more details about each of these supported :ref:`serialization formats -<serialization-formats>`. - -As an example, though, here's what a fixture for a simple ``Person`` model might -look like in JSON: - -.. code-block:: js - - [ - { - "model": "myapp.person", - "pk": 1, - "fields": { - "first_name": "John", - "last_name": "Lennon" - } - }, - { - "model": "myapp.person", - "pk": 2, - "fields": { - "first_name": "Paul", - "last_name": "McCartney" - } - } - ] - -And here's that same fixture as YAML: - -.. code-block:: none - - - model: myapp.person - pk: 1 - fields: - first_name: John - last_name: Lennon - - model: myapp.person - pk: 2 - fields: - first_name: Paul - last_name: McCartney - -You'll store this data in a ``fixtures`` directory inside your app. - -Loading data is easy: just call :djadmin:`manage.py loaddata fixturename -<loaddata>`, where *fixturename* is the name of the fixture file you've created. -Every time you run :djadmin:`loaddata` the data will be read from the fixture -and re-loaded into the database. Note that this means that if you change one of -the rows created by a fixture and then 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/yaml/json]``, that fixture will -be loaded every time you run :djadmin:`syncdb`. This is extremely convenient, -but be careful: remember that the data will be refreshed *every time* you run -:djadmin:`syncdb`. So don't use ``initial_data`` for data you'll want to edit. - -.. seealso:: - - Fixtures are also used by the :ref:`testing framework - <topics-testing-fixtures>` to help set up a consistent test environment. - -.. _initial-sql: - -Providing initial SQL data -========================== - -Django provides a hook for passing the database arbitrary SQL that's executed -just after the CREATE TABLE statements when you run :djadmin:`syncdb`. You can -use this hook to populate default records, or you could also create SQL -functions, views, triggers, etc. - -The hook is simple: Django just looks for a file called ``sql/<modelname>.sql``, -in your app directory, where ``<modelname>`` is the model's name in lowercase. - -So, if you had a ``Person`` model in an app called ``myapp``, you could add -arbitrary SQL to the file ``sql/person.sql`` inside your ``myapp`` directory. -Here's an example of what the file might contain: - -.. code-block:: sql - - INSERT INTO myapp_person (first_name, last_name) VALUES ('John', 'Lennon'); - INSERT INTO myapp_person (first_name, last_name) VALUES ('Paul', 'McCartney'); - -Each SQL file, if given, is expected to contain valid SQL statements -which will insert the desired data (e.g., properly-formatted -``INSERT`` statements separated by semicolons). - -The SQL files are read by the :djadmin:`sqlcustom`, :djadmin:`sqlreset`, -:djadmin:`sqlall` and :djadmin:`reset` commands in :doc:`manage.py -</ref/django-admin>`. Refer to the :doc:`manage.py documentation -</ref/django-admin>` for more information. - -Note that if you have multiple SQL data files, there's no guarantee of -the order in which they're executed. The only thing you can assume is -that, by the time your custom data files are executed, all the -database tables already will have been created. - -Database-backend-specific SQL data ----------------------------------- - -There's also a hook for backend-specific SQL data. For example, you -can have separate initial-data files for PostgreSQL and MySQL. For -each app, Django looks for a file called -``<appname>/sql/<modelname>.<backend>.sql``, where ``<appname>`` is -your app directory, ``<modelname>`` is the model's name in lowercase -and ``<backend>`` is the last part of the module name provided for the -:setting:`ENGINE` in your settings file (e.g., if you have defined a -database with an :setting:`ENGINE` value of -``django.db.backends.postgresql``, Django will look for -``<appname>/sql/<modelname>.postgresql.sql``). - -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/parts/django/docs/howto/jython.txt b/parts/django/docs/howto/jython.txt deleted file mode 100644 index 1bf8d6c..0000000 --- a/parts/django/docs/howto/jython.txt +++ /dev/null @@ -1,73 +0,0 @@ -======================== -Running Django on Jython -======================== - -.. index:: Jython, Java, JVM - -Jython_ is an implementation of Python that runs on the Java platform (JVM). -Django runs cleanly on Jython version 2.5 or later, which means you can deploy -Django on any Java platform. - -This document will get you up and running with Django on top of Jython. - -.. _jython: http://www.jython.org/ - -Installing Jython -================= - -Django works with Jython versions 2.5b3 and higher. Download Jython at -http://www.jython.org/. - -Creating a servlet container -============================ - -If you just want to experiment with Django, skip ahead to the next section; -Django includes a lightweight Web server you can use for testing, so you won't -need to set up anything else until you're ready to deploy Django in production. - -If you want to use Django on a production site, use a Java servlet container, -such as `Apache Tomcat`_. Full JavaEE applications servers such as `GlassFish`_ -or `JBoss`_ are also OK, if you need the extra features they include. - -.. _`Apache Tomcat`: http://tomcat.apache.org/ -.. _GlassFish: https://glassfish.dev.java.net/ -.. _JBoss: http://www.jboss.org/ - -Installing Django -================= - -The next step is to install Django itself. This is exactly the same as -installing Django on standard Python, so see -:ref:`removing-old-versions-of-django` and :ref:`install-django-code` for -instructions. - -Installing Jython platform support libraries -============================================ - -The `django-jython`_ project contains database backends and management commands -for Django/Jython development. Note that the builtin Django backends won't work -on top of Jython. - -.. _`django-jython`: http://code.google.com/p/django-jython/ - -To install it, follow the `installation instructions`_ detailed on the project -Web site. Also, read the `database backends`_ documentation there. - -.. _`installation instructions`: http://code.google.com/p/django-jython/wiki/Install -.. _`database backends`: http://code.google.com/p/django-jython/wiki/DatabaseBackends - -Differences with Django on Jython -================================= - -.. index:: JYTHONPATH - -At this point, Django on Jython should behave nearly identically to Django -running on standard Python. However, are a few differences to keep in mind: - - * Remember to use the ``jython`` command instead of ``python``. The - documentation uses ``python`` for consistancy, but if you're using Jython - you'll want to mentally replace ``python`` with ``jython`` every time it - occurs. - - * Similarly, you'll need to use the ``JYTHONPATH`` environment variable - instead of ``PYTHONPATH``. diff --git a/parts/django/docs/howto/legacy-databases.txt b/parts/django/docs/howto/legacy-databases.txt deleted file mode 100644 index 2121871..0000000 --- a/parts/django/docs/howto/legacy-databases.txt +++ /dev/null @@ -1,66 +0,0 @@ -========================================= -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 -:doc:`tutorial </intro/tutorial01>`. - -Once you've got Django set up, you'll follow this general process to integrate -with an existing database. - -Give Django your database parameters -==================================== - -You'll need to tell Django what your database connection parameters are, and -what the name of the database is. Do that by editing the :setting:`DATABASES` -setting and assigning values to the following keys for the ``'default'`` -connection: - - * :setting:`NAME` - * :setting:`ENGINE` - * :setting:`USER` - * :setting:`PASSWORD` - * :setting:`HOST` - * :setting:`PORT` - -Auto-generate the models -======================== - -.. highlight:: bash - -Django comes with a utility called :djadmin:`inspectdb` that can create models -by introspecting an existing database. You can view the output by running this -command:: - - python manage.py inspectdb - -Save this as a file by using standard Unix output redirection:: - - python manage.py inspectdb > models.py - -This feature is meant as a shortcut, not as definitive model generation. See the -:djadmin:`documentation of inspectdb <inspectdb>` for more information. - -Once you've cleaned up your models, name the file ``models.py`` and put it in -the Python package that holds your app. Then add the app to your -:setting:`INSTALLED_APPS` setting. - -Install the core Django tables -============================== - -Next, run the :djadmin:`syncdb` command to install any extra needed database -records such as admin permissions and content types:: - - python manage.py syncdb - -Test and tweak -============== - -Those are the basic steps -- from here you'll want to tweak the models Django -generated until they work the way you'd like. Try accessing your data via the -Django database API, and try editing objects via Django's admin site, and edit -the models file accordingly. diff --git a/parts/django/docs/howto/outputting-csv.txt b/parts/django/docs/howto/outputting-csv.txt deleted file mode 100644 index 46e111d..0000000 --- a/parts/django/docs/howto/outputting-csv.txt +++ /dev/null @@ -1,137 +0,0 @@ -========================== -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. - -.. _Python CSV library: http://docs.python.org/library/csv.html - -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 :class:`~django.http.HttpResponse` objects are file-like objects. - -Here's an example:: - - import csv - from django.http import HttpResponse - - def some_view(request): - # Create the HttpResponse object with the appropriate CSV header. - response = HttpResponse(mimetype='text/csv') - response['Content-Disposition'] = 'attachment; filename=somefilename.csv' - - writer = csv.writer(response) - writer.writerow(['First row', 'Foo', 'Bar', 'Baz']) - writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"]) - - return response - -The code and comments should be self-explanatory, but a few things deserve a -mention: - - * 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. - - * The response gets an additional ``Content-Disposition`` header, which - contains the name of the CSV file. This filename is arbitrary; call it - 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 :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. - - * The CSV module takes care of quoting for you, so you don't have to worry - about escaping strings with quotes or commas in them. Just pass - ``writerow()`` your raw strings, and it'll do the right thing. - -Handling Unicode -~~~~~~~~~~~~~~~~ - -Python's ``csv`` module does not support Unicode input. Since Django uses -Unicode internally this means strings read from sources such as -:class:`~django.http.HttpRequest` are potentially problematic. There are a few -options for handling this: - - * Manually encode all Unicode objects to a compatible encoding. - - * Use the ``UnicodeWriter`` class provided in the `csv module's examples - section`_. - - * Use the `python-unicodecsv module`_, which aims to be a drop-in - replacement for ``csv`` that gracefully handles Unicode. - -For more information, see the Python `CSV File Reading and Writing`_ -documentation. - -.. _`csv module's examples section`: http://docs.python.org/library/csv.html#examples -.. _`python-unicodecsv module`: https://github.com/jdunck/python-unicodecsv -.. _`CSV File Reading and Writing`: http://docs.python.org/library/csv.html - -Using the template system -========================= - -Alternatively, you can use the :doc:`Django template system </topics/templates>` -to generate CSV. This is lower-level than using the convenient Python ``csv`` -module, 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 :ttag:`for` loop. - -Here's an example, which generates the same CSV file as above:: - - from django.http import HttpResponse - from django.template import loader, Context - - def some_view(request): - # Create the HttpResponse object with the appropriate CSV header. - response = HttpResponse(mimetype='text/csv') - response['Content-Disposition'] = 'attachment; filename=somefilename.csv' - - # The data is hard-coded here, but you could load it from a database or - # some other source. - csv_data = ( - ('First row', 'Foo', 'Bar', 'Baz'), - ('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"), - ) - - t = loader.get_template('my_template_name.txt') - c = Context({ - 'data': csv_data, - }) - response.write(t.render(c)) - return response - -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: - -.. 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 :tfilter:`addslashes` template filter to -ensure there aren't any problems with quotes. - -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 :doc:`/howto/outputting-pdf` for an example. diff --git a/parts/django/docs/howto/outputting-pdf.txt b/parts/django/docs/howto/outputting-pdf.txt deleted file mode 100644 index 67950d0..0000000 --- a/parts/django/docs/howto/outputting-pdf.txt +++ /dev/null @@ -1,160 +0,0 @@ -=========================== -Outputting PDFs with Django -=========================== - -This document explains how to output PDF files dynamically using Django views. -This is made possible by the excellent, open-source ReportLab_ Python PDF -library. - -The advantage of generating PDF files dynamically is that you can create -customized PDFs for different purposes -- say, for different users or different -pieces of content. - -For example, Django was used at kusports.com_ to generate customized, -printer-friendly NCAA tournament brackets, as PDF files, for people -participating in a March Madness contest. - -.. _ReportLab: http://www.reportlab.org/oss/rl-toolkit/ -.. _kusports.com: http://www.kusports.com/ - -Install ReportLab -================= - -Download and install the ReportLab library from http://www.reportlab.org/oss/rl-toolkit/download/. -The `user guide`_ (not coincidentally, a PDF file) explains how to install it. - -Test your installation by importing it in the Python interactive interpreter:: - - >>> import reportlab - -If that command doesn't raise any errors, the installation worked. - -.. _user guide: http://www.reportlab.com/docs/reportlab-userguide.pdf - -Write your view -=============== - -The key to generating PDFs dynamically with Django is that the ReportLab API -acts on file-like objects, and Django's :class:`~django.http.HttpResponse` -objects are file-like objects. - -Here's a "Hello World" example:: - - from reportlab.pdfgen import canvas - from django.http import HttpResponse - - def some_view(request): - # Create the HttpResponse object with the appropriate PDF headers. - response = HttpResponse(mimetype='application/pdf') - response['Content-Disposition'] = 'attachment; filename=somefilename.pdf' - - # Create the PDF object, using the response object as its "file." - p = canvas.Canvas(response) - - # Draw things on the PDF. Here's where the PDF generation happens. - # See the ReportLab documentation for the full list of functionality. - p.drawString(100, 100, "Hello world.") - - # Close the PDF object cleanly, and we're done. - p.showPage() - p.save() - return response - -The code and comments should be self-explanatory, but a few things deserve a -mention: - - * 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. - - * The response gets an additional ``Content-Disposition`` header, which - contains the name of the PDF file. This filename is arbitrary: Call it - whatever you want. It'll be used by browsers in the "Save as..." - dialogue, etc. - - * The ``Content-Disposition`` header starts with ``'attachment; '`` in this - example. This forces Web browsers to pop-up a dialog box - prompting/confirming how to handle the document even if a default is set - on the machine. If you leave off ``'attachment;'``, browsers will handle - the PDF using whatever program/plugin they've been configured to use for - PDFs. Here's what that code would look like:: - - response['Content-Disposition'] = 'filename=somefilename.pdf' - - * 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 :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``. - - * Finally, it's important to call ``showPage()`` and ``save()`` on the PDF - file. - -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``:: - - # Fall back to StringIO in environments where cStringIO is not available - try: - from cStringIO import StringIO - except ImportError: - from StringIO import StringIO - from reportlab.pdfgen import canvas - from django.http import HttpResponse - - def some_view(request): - # Create the HttpResponse object with the appropriate PDF headers. - response = HttpResponse(mimetype='application/pdf') - response['Content-Disposition'] = 'attachment; filename=somefilename.pdf' - - buffer = StringIO() - - # Create the PDF object, using the StringIO object as its "file." - p = canvas.Canvas(buffer) - - # Draw things on the PDF. Here's where the PDF generation happens. - # See the ReportLab documentation for the full list of functionality. - p.drawString(100, 100, "Hello world.") - - # Close the PDF object cleanly. - p.showPage() - p.save() - - # Get the value of the StringIO buffer and write it to the response. - pdf = buffer.getvalue() - buffer.close() - response.write(pdf) - return response - -.. _cStringIO: http://docs.python.org/library/stringio.html#module-cStringIO - -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 XHTML2PDF`_ is yet another PDF-generation library. Pisa ships with - 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. - -.. _PDFlib: http://www.pdflib.org/ -.. _`Pisa XHTML2PDF`: http://www.xhtml2pdf.com/ -.. _HTMLdoc: http://www.htmldoc.org/ - -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 -:doc:`/howto/outputting-csv` for another example and some techniques you can use -when generated text-based formats. diff --git a/parts/django/docs/howto/static-files.txt b/parts/django/docs/howto/static-files.txt deleted file mode 100644 index c3692d5..0000000 --- a/parts/django/docs/howto/static-files.txt +++ /dev/null @@ -1,162 +0,0 @@ -========================= -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. - -The reasoning here is that standard Web servers, such as Apache_, lighttpd_ and -Cherokee_, are much more fine-tuned at serving static files than a Web -application framework. - -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/ -.. _Cherokee: http://www.cherokee-project.com/ - -.. seealso:: - - If you just need to serve the admin media from a nonstandard location, see - the :djadminopt:`--adminmedia` parameter to :djadmin:`runserver`. - -The big, fat disclaimer -======================= - -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 :ref:`Django mod_python documentation <serving-media-files>`. - -How to do it -============ - -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 :doc:`URLconf </topics/http/urls>`:: - - (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', - {'document_root': '/path/to/media'}), - -...where ``site_media`` is the URL where your media will be rooted, and -``/path/to/media`` is the filesystem root for your media. This will call the -:func:`~django.views.static.serve` view, passing in the path from the URLconf -and the (required) ``document_root`` parameter. - -Given the above URLconf: - - * The file ``/path/to/media/foo.jpg`` will be made available at the URL - ``/site_media/foo.jpg``. - - * The file ``/path/to/media/css/mystyles.css`` will be made available - at the URL ``/site_media/css/mystyles.css``. - - * The file ``/path/bar.jpg`` will not be accessible, because it doesn't - fall under the document root. - -Of course, it's not compulsory to use a fixed string for the -``'document_root'`` value. You might wish to make that an entry in your -settings file and use the setting value there. That will allow you and -other developers working on the code to easily change the value as -required. For example, if we have a line in ``settings.py`` that says:: - - STATIC_DOC_ROOT = '/path/to/media' - -...we could write the above :doc:`URLconf </topics/http/urls>` entry as:: - - from django.conf import settings - ... - (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', - {'document_root': settings.STATIC_DOC_ROOT}), - -Be careful not to use the same path as your :setting:`ADMIN_MEDIA_PREFIX` (which defaults -to ``/media/``) as this will overwrite your URLconf entry. - -Directory listings -================== - -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. - -For example:: - - (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', - {'document_root': '/path/to/media', 'show_indexes': True}), - -You can customize the index view by creating a template called -``static/directory_index.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.html`` template: - -.. code-block:: html+django - - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - <head> - <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> - <meta http-equiv="Content-Language" content="en-us" /> - <meta name="robots" content="NONE,NOARCHIVE" /> - <title>Index of {{ directory }}</title> - </head> - <body> - <h1>Index of {{ directory }}</h1> - <ul> - {% for f in file_list %} - <li><a href="{{ f }}">{{ f }}</a></li> - {% endfor %} - </ul> - </body> - </html> - -.. versionchanged:: 1.0.3 - Prior to Django 1.0.3, there was a bug in the view that provided directory - listings. The template that was loaded had to be called - ``static/directory_listing`` (with no ``.html`` extension). For backwards - compatibility with earlier versions, Django will still load templates with - the older (no extension) name, but it will prefer the - ``directory_index.html`` version. - -Limiting use to DEBUG=True -========================== - -Because URLconfs are just plain Python modules, you can use Python logic to -make the static-media view available only in development mode. This is a handy -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 -:func:`django.views.static.serve` inclusion. Here's a full example URLconf:: - - from django.conf.urls.defaults import * - from django.conf import settings - - urlpatterns = patterns('', - (r'^articles/2003/$', 'news.views.special_case_2003'), - (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), - (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'), - (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'), - ) - - if settings.DEBUG: - urlpatterns += patterns('', - (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}), - ) - -This code is straightforward. It imports the settings and checks the value of -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. diff --git a/parts/django/docs/index.txt b/parts/django/docs/index.txt deleted file mode 100644 index f163fd9..0000000 --- a/parts/django/docs/index.txt +++ /dev/null @@ -1,213 +0,0 @@ - -.. _index: - -==================== -Django documentation -==================== - -.. rubric:: Everything you need to know about Django (and then some). - -Getting help -============ - -Having trouble? We'd like to help! - -* Try the :doc:`FAQ <faq/index>` -- it's got answers to many common questions. - -* Looking for specific information? Try the :ref:`genindex`, :ref:`modindex` or - the :doc:`detailed table of contents <contents>`. - -* Search for information in the `archives of the django-users mailing list`_, or - `post a question`_. - -* Ask a question in the `#django IRC channel`_, or search the `IRC logs`_ to see - if it's 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://botland.oebfare.com/logger/django/ -.. _ticket tracker: http://code.djangoproject.com/ - -First steps -=========== - - * **From scratch:** - :doc:`Overview <intro/overview>` | - :doc:`Installation <intro/install>` - - * **Tutorial:** - :doc:`Part 1 <intro/tutorial01>` | - :doc:`Part 2 <intro/tutorial02>` | - :doc:`Part 3 <intro/tutorial03>` | - :doc:`Part 4 <intro/tutorial04>` - -The model layer -=============== - - * **Models:** - :doc:`Model syntax <topics/db/models>` | - :doc:`Field types <ref/models/fields>` | - :doc:`Meta options <ref/models/options>` - - * **QuerySets:** - :doc:`Executing queries <topics/db/queries>` | - :doc:`QuerySet method reference <ref/models/querysets>` - - * **Model instances:** - :doc:`Instance methods <ref/models/instances>` | - :doc:`Accessing related objects <ref/models/relations>` - - * **Advanced:** - :doc:`Managers <topics/db/managers>` | - :doc:`Raw SQL <topics/db/sql>` | - :doc:`Transactions <topics/db/transactions>` | - :doc:`Aggregation <topics/db/aggregation>` | - :doc:`Custom fields <howto/custom-model-fields>` | - :doc:`Multiple databases <topics/db/multi-db>` - - * **Other:** - :doc:`Supported databases <ref/databases>` | - :doc:`Legacy databases <howto/legacy-databases>` | - :doc:`Providing initial data <howto/initial-data>` | - :doc:`Optimize database access <topics/db/optimization>` - -The template layer -================== - - * **For designers:** - :doc:`Syntax overview <topics/templates>` | - :doc:`Built-in tags and filters <ref/templates/builtins>` - - * **For programmers:** - :doc:`Template API <ref/templates/api>` | - :doc:`Custom tags and filters <howto/custom-template-tags>` - -The view layer -============== - - * **The basics:** - :doc:`URLconfs <topics/http/urls>` | - :doc:`View functions <topics/http/views>` | - :doc:`Shortcuts <topics/http/shortcuts>` - - * **Reference:** :doc:`Request/response objects <ref/request-response>` - - * **File uploads:** - :doc:`Overview <topics/http/file-uploads>` | - :doc:`File objects <ref/files/file>` | - :doc:`Storage API <ref/files/storage>` | - :doc:`Managing files <topics/files>` | - :doc:`Custom storage <howto/custom-file-storage>` - - * **Generic views:** - :doc:`Overview<topics/generic-views>` | - :doc:`Built-in generic views<ref/generic-views>` - - * **Advanced:** - :doc:`Generating CSV <howto/outputting-csv>` | - :doc:`Generating PDF <howto/outputting-pdf>` - - * **Middleware:** - :doc:`Overview <topics/http/middleware>` | - :doc:`Built-in middleware classes <ref/middleware>` - -Forms -===== - - * **The basics:** - :doc:`Overview <topics/forms/index>` | - :doc:`Form API <ref/forms/api>` | - :doc:`Built-in fields <ref/forms/fields>` | - :doc:`Built-in widgets <ref/forms/widgets>` - - * **Advanced:** - :doc:`Forms for models <topics/forms/modelforms>` | - :doc:`Integrating media <topics/forms/media>` | - :doc:`Formsets <topics/forms/formsets>` | - :doc:`Customizing validation <ref/forms/validation>` - - * **Extras:** - :doc:`Form preview <ref/contrib/formtools/form-preview>` | - :doc:`Form wizard <ref/contrib/formtools/form-wizard>` - -The development process -======================= - - * **Settings:** - :doc:`Overview <topics/settings>` | - :doc:`Full list of settings <ref/settings>` - - * **Exceptions:** - :doc:`Overview <ref/exceptions>` - - * **django-admin.py and manage.py:** - :doc:`Overview <ref/django-admin>` | - :doc:`Adding custom commands <howto/custom-management-commands>` - - * **Testing:** :doc:`Overview <topics/testing>` - - * **Deployment:** - :doc:`Overview <howto/deployment/index>` | - :doc:`Apache/mod_wsgi <howto/deployment/modwsgi>` | - :doc:`Apache/mod_python <howto/deployment/modpython>` | - :doc:`FastCGI/SCGI/AJP <howto/deployment/fastcgi>` | - :doc:`Apache authentication <howto/apache-auth>` | - :doc:`Serving static files <howto/static-files>` | - :doc:`Tracking code errors by e-mail <howto/error-reporting>` - -Other batteries included -======================== - - * :doc:`Admin site <ref/contrib/admin/index>` | :doc:`Admin actions <ref/contrib/admin/actions>` | :doc:`Admin documentation generator<ref/contrib/admin/admindocs>` - * :doc:`Authentication <topics/auth>` - * :doc:`Cache system <topics/cache>` - * :doc:`Conditional content processing <topics/conditional-view-processing>` - * :doc:`Comments <ref/contrib/comments/index>` | :doc:`Moderation <ref/contrib/comments/moderation>` | :doc:`Custom comments <ref/contrib/comments/custom>` - * :doc:`Content types <ref/contrib/contenttypes>` - * :doc:`Cross Site Request Forgery protection <ref/contrib/csrf>` - * :doc:`Databrowse <ref/contrib/databrowse>` - * :doc:`E-mail (sending) <topics/email>` - * :doc:`Flatpages <ref/contrib/flatpages>` - * :doc:`GeoDjango <ref/contrib/gis/index>` - * :doc:`Humanize <ref/contrib/humanize>` - * :doc:`Internationalization <topics/i18n/index>` - * :doc:`Jython support <howto/jython>` - * :doc:`"Local flavor" <ref/contrib/localflavor>` - * :doc:`Messages <ref/contrib/messages>` - * :doc:`Pagination <topics/pagination>` - * :doc:`Redirects <ref/contrib/redirects>` - * :doc:`Serialization <topics/serialization>` - * :doc:`Sessions <topics/http/sessions>` - * :doc:`Signals <topics/signals>` - * :doc:`Sitemaps <ref/contrib/sitemaps>` - * :doc:`Sites <ref/contrib/sites>` - * :doc:`Syndication feeds (RSS/Atom) <ref/contrib/syndication>` - * :doc:`Unicode in Django <ref/unicode>` - * :doc:`Web design helpers <ref/contrib/webdesign>` - * :doc:`Validators <ref/validators>` - -The Django open-source project -============================== - - * **Community:** - :doc:`How to get involved <internals/contributing>` | - :doc:`The release process <internals/release-process>` | - :doc:`Team of committers <internals/committers>` | - :doc:`The Django source code repository <internals/svn>` - - * **Design philosophies:** - :doc:`Overview <misc/design-philosophies>` - - * **Documentation:** - :doc:`About this documentation <internals/documentation>` - - * **Third-party distributions:** - :doc:`Overview <misc/distributions>` - - * **Django over time:** - :doc:`API stability <misc/api-stability>` | - :doc:`Release notes and upgrading instructions <releases/index>` | - :doc:`Deprecation Timeline <internals/deprecation>` diff --git a/parts/django/docs/internals/_images/djangotickets.png b/parts/django/docs/internals/_images/djangotickets.png Binary files differdeleted file mode 100644 index 34a2a41..0000000 --- a/parts/django/docs/internals/_images/djangotickets.png +++ /dev/null diff --git a/parts/django/docs/internals/committers.txt b/parts/django/docs/internals/committers.txt deleted file mode 100644 index ecda1d5..0000000 --- a/parts/django/docs/internals/committers.txt +++ /dev/null @@ -1,344 +0,0 @@ -================= -Django committers -================= - -The original team -================= - -Django originally started at World Online, the Web department of the `Lawrence -Journal-World`_ of Lawrence, Kansas, USA. - -`Adrian Holovaty`_ - Adrian is a Web developer with a background in journalism. He's known in - journalism circles as one of the pioneers of "journalism via computer - programming", and in technical circles as "the guy who invented Django." - - He was lead developer at World Online for 2.5 years, during which time - Django was developed and implemented on World Online's sites. He's now the - leader and founder of EveryBlock_, a "news feed for your block". - - Adrian lives in Chicago, USA. - -`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 maintains a well-read - `web-development blog`_. - - Simon lives in Brighton, England. - -`Jacob Kaplan-Moss`_ - Jacob is a partner at `Revolution Systems`_ which provides support services - around Django and related open source technologies. A good deal of Jacob's - work time is devoted to working on Django. Jacob previously worked at World - Online, where Django was invented, where he was the lead developer of - Ellington, a commercial Web publishing platform for media companies. - - Jacob lives in Lawrence, Kansas, USA. - -`Wilson Miner`_ - Wilson's design-fu is what makes Django look so nice. He designed the - Web site you're looking at right now, as well as Django's acclaimed admin - interface. Wilson is the designer for EveryBlock_. - - Wilson lives in San Francisco, USA. - -.. _lawrence journal-world: http://ljworld.com/ -.. _adrian holovaty: http://holovaty.com/ -.. _everyblock: http://everyblock.com/ -.. _simon willison: http://simonwillison.net/ -.. _web-development blog: `simon willison`_ -.. _jacob kaplan-moss: http://jacobian.org/ -.. _revolution systems: http://revsys.com/ -.. _wilson miner: http://wilsonminer.com/ - -Current developers -================== - -Currently, Django is led by a team of volunteers from around the globe. - -BDFLs ------ - -Adrian and Jacob are the Co-`Benevolent Dictators for Life`_ of Django. When -"rough consensus and working code" fails, they're the ones who make the tough -decisions. - -.. _Benevolent Dictators for Life: http://en.wikipedia.org/wiki/Benevolent_Dictator_For_Life - -Core developers ---------------- - -These are the folks who have a long history of contributions, a solid track -record of being helpful on the mailing lists, and a proven desire to dedicate -serious time to Django. In return, they've been granted the coveted commit bit, -and have free rein to hack on all parts of Django. - -`Malcolm Tredinnick`_ - Malcolm originally wanted to be a mathematician, somehow ended up a software - developer. He's contributed to many Open Source projects, has served on the - board of the GNOME foundation, and will kick your ass at chess. - - When he's not busy being an International Man of Mystery, Malcolm lives in - Sydney, Australia. - -.. _malcolm tredinnick: http://www.pointy-stick.com/ - -`Russell Keith-Magee`_ - Russell studied physics as an undergraduate, and studied neural networks for - his PhD. His first job was with a startup in the defense industry developing - simulation frameworks. Over time, mostly through work with Django, he's - become more involved in Web development. - - Russell has helped with several major aspects of Django, including a - couple major internal refactorings, creation of the test system, and more. - - Russell lives in the most isolated capital city in the world — Perth, - Australia. - -.. _russell keith-magee: http://cecinestpasun.com/ - -Joseph Kocherhans - Joseph is currently a developer at EveryBlock_, and previously worked for - the Lawrence Journal-World where he built most of the backend for their - Marketplace site. He often disappears for several days into the woods, - attempts to teach himself computational linguistics, and annoys his - neighbors with his Charango_ playing. - - Joseph's first contribution to Django was a series of improvements to the - authorization system leading up to support for pluggable authorization. - Since then, he's worked on the new forms system, its use in the admin, and - many other smaller improvements. - - Joseph lives in Chicago, USA. - -.. _charango: http://en.wikipedia.org/wiki/Charango - -`Luke Plant`_ - At University Luke studied physics and Materials Science and also - met `Michael Meeks`_ who introduced him to Linux and Open Source, - re-igniting an interest in programming. Since then he has - contributed to a number of Open Source projects and worked - professionally as a developer. - - Luke has contributed many excellent improvements to Django, - including database-level improvements, the CSRF middleware and - many unit tests. - - Luke currently works for a church in Bradford, UK, and part-time - as a freelance developer. - -.. _luke plant: http://lukeplant.me.uk/ -.. _michael meeks: http://en.wikipedia.org/wiki/Michael_Meeks_(software) - -`Brian Rosner`_ - Brian is currently the tech lead at Eldarion_ managing and developing - Django / Pinax_ based Web sites. He enjoys learning more about programming - languages and system architectures and contributing to open source - projects. Brian is the host of the `Django Dose`_ podcasts. - - Brian helped immensely in getting Django's "newforms-admin" branch finished - in time for Django 1.0; he's now a full committer, continuing to improve on - the admin and forms system. - - Brian lives in Denver, Colorado, USA. - -.. _brian rosner: http://oebfare.com/ -.. _eldarion: http://eldarion.com/ -.. _django dose: http://djangodose.com/ - -`Gary Wilson`_ - Gary starting contributing patches to Django in 2006 while developing Web - applications for `The University of Texas`_ (UT). Since, he has made - contributions to the e-mail and forms systems, as well as many other - improvements and code cleanups throughout the code base. - - Gary is currently a developer and software engineering graduate student at - UT, where his dedication to spreading the ways of Python and Django never - ceases. - - Gary lives in Austin, Texas, USA. - -.. _Gary Wilson: http://gdub.wordpress.com/ -.. _The University of Texas: http://www.utexas.edu/ - -Justin Bronn - Justin Bronn is a computer scientist and attorney specializing - in legal topics related to intellectual property and spatial law. - - In 2007, Justin began developing ``django.contrib.gis`` in a branch, - a.k.a. GeoDjango_, which was merged in time for Django 1.0. While - implementing GeoDjango, Justin obtained a deep knowledge of Django's - internals including the ORM, the admin, and Oracle support. - - Justin lives in Houston, Texas. - -.. _GeoDjango: http://geodjango.org/ - -Karen Tracey - Karen has a background in distributed operating systems (graduate school), - communications software (industry) and crossword puzzle construction - (freelance). The last of these brought her to Django, in late 2006, when - she set out to put a Web front-end on her crossword puzzle database. - That done, she stuck around in the community answering questions, debugging - problems, etc. -- because coding puzzles are as much fun as word puzzles. - - Karen lives in Apex, NC, USA. - -`Jannis Leidel`_ - Jannis graduated in media design from `Bauhaus-University Weimar`_, - is the author of a number of pluggable Django apps and likes to - contribute to Open Source projects like Pinax_. He currently works as - a freelance Web developer and designer. - - Jannis lives in Berlin, Germany. - -.. _Jannis Leidel: http://jezdez.com/ -.. _Bauhaus-University Weimar: http://www.uni-weimar.de/ -.. _pinax: http://pinaxproject.com/ - -`James Tauber`_ - James is the lead developer of Pinax_ and the CEO and founder of - Eldarion_. He has been doing open source software since 1993, Python - since 1998 and Django since 2006. He serves on the board of the Python - Software Foundation and is currently on a leave of absence from a PhD in - linguistics. - - James currently lives in Boston, MA, USA but originally hails from - Perth, Western Australia where he attended the same high school as - Russell Keith-Magee. - -.. _James Tauber: http://jtauber.com/ - -`Alex Gaynor`_ - Alex is a student at Rensselaer Polytechnic Institute, and is also an - independent contractor. He found Django in 2007 and has been addicted ever - since he found out you don't need to write out your forms by hand. He has - a small obsession with compilers. He's contributed to the ORM, forms, - admin, and other components of Django. - - Alex lives in Chicago, IL, but spends most of his time in Troy, NY. - -.. _Alex Gaynor: http://alexgaynor.net - -`Andrew Godwin`_ - Andrew is a freelance Python developer and tinkerer, and has been - developing against Django since 2007. He graduated from Oxford University - with a degree in Computer Science, and has become most well known - in the Django community for his work on South, the schema migrations - library. - - Andrew lives in London, UK. - -.. _Andrew Godwin: http://www.aeracode.org/ - -`Carl Meyer`_ - Carl has been working with Django since 2007 (long enough to remember - queryset-refactor, but not magic-removal), and works as a freelance - developer with OddBird_ and Eldarion_. He became a Django contributor by - accident, because fixing bugs is more interesting than working around - them. - - Carl lives in Elkhart, IN, USA. - -.. _Carl Meyer: http://www.oddbird.net/about/#hcard-carl -.. _OddBird: http://www.oddbird.net/ - -Ramiro Morales - Ramiro has been reading Django source code and submitting patches since - mid-2006 after researching for a Python Web tool with matching awesomeness - and being pointed to it by an old ninja. - - A software developer in the electronic transactions industry, he is a - living proof of the fact that anyone with enough enthusiasm can contribute - to Django, learning a lot and having fun in the process. - - Ramiro lives in Córdoba, Argentina. - -`Chris Beaven`_ - Chris has been submitting patches and suggesting crazy ideas for Django - since early 2006. An advocate for community involvement and a long-term - triager, he is still often found answering questions in the #django IRC - channel. - - Chris lives in Napier, New Zealand (adding to the pool of Oceanic core - developers). He works remotely as a developer for `Lincoln Loop`_. - -.. _Chris Beaven: http://smileychris.com/ -.. _Lincoln Loop: http://lincolnloop.com/ - -Specialists ------------ - -`James Bennett`_ - James is Django's release manager; he also contributes to the documentation. - - James came to Web development from philosophy when he discovered - that programmers get to argue just as much while collecting much - better pay. He lives in Lawrence, Kansas, where he works for the - Journal-World developing Ellington. He `keeps a blog`_, has - written a `book on Django`_, and enjoys fine port and talking to - his car. - -.. _james bennett: http://b-list.org/ -.. _keeps a blog: `james bennett`_ -.. _book on Django: http://www.amazon.com/dp/1590599969/?tag=djangoproject-20 - -Ian Kelly - Ian is responsible for Django's support for Oracle. - -Matt Boersma - Matt is also responsible for Django's Oracle support. - -Jeremy Dunck - Jeremy is the lead developer of Pegasus News, a personalized local site based - in Dallas, Texas. An early contributor to Greasemonkey and Django, he sees - technology as a tool for communication and access to knowledge. - - Jeremy helped kick off GeoDjango development, and is mostly responsible for - the serious speed improvements that signals received in Django 1.0. - - Jeremy lives in Dallas, Texas, USA. - -`Simon Meers`_ - Simon discovered Django 0.96 during his Computer Science PhD research and - has been developing with it full-time ever since. His core code - contributions are mostly in Django's admin application. He is also helping - to improve Django's documentation. - - Simon works as a freelance developer based in Wollongong, Australia. - -.. _simon meers: http://simonmeers.com/ - -`Gabriel Hurley`_ - Gabriel has been working with Django since 2008, shortly after the 1.0 - release. Convinced by his business partner that Python and Django were the - right direction for the company, he couldn't have been more happy with the - decision. His contributions range across many areas in Django, but years of - copy-editing and an eye for detail lead him to be particularly at home - while working on Django's documentation. - - Gabriel works as a web developer in Berkeley, CA, USA. - -.. _gabriel hurley: http://strikeawe.com/ - -Tim Graham - When exploring Web frameworks for an independent study project in the fall - of 2008, Tim discovered Django and was lured to it by the documentation. - He enjoys contributing to the docs because they're awesome. - - Tim works as a software engineer and lives in Philadelphia, PA, USA. - -Developers Emeritus -=================== - -Georg "Hugo" Bauer - Georg created Django's internationalization system, managed i18n - contributions and made a ton of excellent tweaks, feature additions and bug - fixes. - -Robert Wittams - Robert was responsible for the *first* refactoring of Django's admin - application to allow for easier reuse and has made a ton of - excellent tweaks, feature additions and bug fixes. diff --git a/parts/django/docs/internals/contributing.txt b/parts/django/docs/internals/contributing.txt deleted file mode 100644 index fd0e48b..0000000 --- a/parts/django/docs/internals/contributing.txt +++ /dev/null @@ -1,1294 +0,0 @@ -====================== -Contributing to Django -====================== - -If you think working *with* Django is fun, wait until you start working *on* it. -We're passionate about helping Django users make the jump to contributing members -of the community, so there are many ways you can help Django's development: - - * Blog about Django. We syndicate all the Django blogs we know about on - the `community page`_; contact jacob@jacobian.org if you've got a blog - you'd like to see on that page. - - * Report bugs and request features in our `ticket tracker`_. Please read - `Reporting bugs`_, below, for the details on how we like our bug reports - served up. - - * Submit patches for new and/or fixed behavior. Please read `Submitting - patches`_, below, for details on how to submit a patch. If you're looking - for an easy way to start contributing to Django have a look at the - `easy-pickings`_ tickets. - - * Join the `django-developers`_ mailing list and share your ideas for how - to improve Django. We're always open to suggestions, although we're - likely to be skeptical of large-scale suggestions without some code to - back it up. - - * Triage patches that have been submitted by other users. Please read - `Ticket triage`_ below, for details on the triage process. - -That's all you need to know if you'd like to join the Django development -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 -============== - -Well-written bug reports are *incredibly* helpful. However, there's a certain -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 :doc:`FAQ </faq/index>` to see if your issue might be a well-known question. - - * **Do** `search the tracker`_ to see if your issue has already been filed. - - * **Do** ask on `django-users`_ *first* if you're not sure if what you're - seeing is a bug. - - * **Do** write complete, reproducible, specific bug reports. Include as - much information as you possibly can, complete with code snippets, test - cases, etc. This means including a clear, concise description of the - problem, and a clear set of instructions for replicating the problem. - A minimal example that illustrates the bug in a nice small test case - is the best possible bug report. - - * **Don't** use the ticket system to ask support questions. Use the - `django-users`_ list, or the `#django`_ IRC channel for that. - - * **Don't** use the ticket system to make large-scale feature requests. - We like to discuss any big changes to Django's core on the `django-developers`_ - list before actually working on them. - - * **Don't** reopen issues that have been marked "wontfix". This mark means - that the decision has been made that we can't or won't fix this particular - issue. If you're not sure why, please ask on `django-developers`_. - - * **Don't** use the ticket tracker for lengthy discussions, because they're - likely to get lost. If a particular ticket is controversial, please move - discussion to `django-developers`_. - - * **Don't** post to django-developers just to announce that you have filed - a bug report. All the tickets are mailed to another list - (`django-updates`_), which is tracked by developers and triagers, so we - see them as they are filed. - -.. _django-updates: http://groups.google.com/group/django-updates - -.. _reporting-security-issues: - -Reporting security issues -========================= - -Report security issues to security@djangoproject.com. This is a private list -only open to long-time, highly trusted Django developers, and its archives are -not publicly readable. - -In the event of a confirmed vulnerability in Django itself, we will take the -following actions: - - * Acknowledge to the reporter that we've received the report and that a fix - is forthcoming. We'll give a rough timeline and ask the reporter to keep - the issue confidential until we announce it. - - * Halt all other development as long as is needed to develop a fix, including - patches against the current and two previous releases. - - * Determine a go-public date for announcing the vulnerability and the fix. - To try to mitigate a possible "arms race" between those applying the patch - and those trying to exploit the hole, we will not announce security - problems immediately. - - * Pre-notify everyone we know to be running the affected version(s) of - Django. We will send these notifications through private e-mail which will - include documentation of the vulnerability, links to the relevant patch(es), - and a request to keep the vulnerability confidential until the official - go-public date. - - * Publicly announce the vulnerability and the fix on the pre-determined - go-public date. This will probably mean a new release of Django, but - in some cases it may simply be patches against current releases. - -Submitting patches -================== - -We're always grateful for patches to Django's code. Indeed, bug reports with -associated patches will get fixed *far* more quickly than those without patches. - -"Claiming" tickets ------------------- - -In an open-source project with hundreds of contributors around the world, it's -important to manage communication efficiently so that work doesn't get -duplicated and contributors can be as effective as possible. Hence, our policy -is for contributors to "claim" tickets in order to let other developers know -that a particular bug or feature is being worked on. - -If you have identified a contribution you want to make and you're capable of -fixing it (as measured by your coding ability, knowledge of Django internals -and time availability), claim it by following these steps: - - * `Create an account`_ to use in our ticket system. - * If a ticket for this issue doesn't exist yet, create one in our - `ticket tracker`_. - * If a ticket for this issue already exists, make sure nobody else has - claimed it. To do this, look at the "Assigned to" section of the ticket. - If it's assigned to "nobody," then it's available to be claimed. - Otherwise, somebody else is working on this ticket, and you either find - another bug/feature to work on, or contact the developer working on the - ticket to offer your help. - * Log into your account, if you haven't already, by clicking "Login" in the - upper right of the ticket page. - * Claim the ticket by clicking the radio button next to "Accept ticket" - near the bottom of the page, then clicking "Submit changes." - -If you have an account but have forgotten your password, you can reset it -using the `password reset page`_. - -.. _Create an account: http://www.djangoproject.com/accounts/register/ -.. _password reset page: http://www.djangoproject.com/accounts/password/reset/ - -Ticket claimers' responsibility -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Once you've claimed a ticket, you have a responsibility to work on that ticket -in a reasonably timely fashion. If you don't have time to work on it, either -unclaim it or don't claim it in the first place! - -Ticket triagers go through the list of claimed tickets from time to -time, checking whether any progress has been made. If there's no sign of -progress on a particular claimed ticket for a week or two, a triager may ask -you to relinquish the ticket claim so that it's no longer monopolized and -somebody else can claim it. - -If you've claimed a ticket and it's taking a long time (days or weeks) to code, -keep everybody updated by posting comments on the ticket. If you don't provide -regular updates, and you don't respond to a request for a progress report, -your claim on the ticket may be revoked. As always, more communication is -better than less communication! - -Which tickets should be claimed? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Of course, going through the steps of claiming tickets is overkill in some -cases. In the case of small changes, such as typos in the documentation or -small bugs that will only take a few minutes to fix, you don't need to jump -through the hoops of claiming tickets. Just submit your patch and be done with -it. - -Patch style ------------ - - * Make sure your code matches our `coding style`_. - - * Submit patches in the format returned by the ``svn diff`` command. - An exception is for code changes that are described more clearly in plain - English than in code. Indentation is the most common example; it's hard to - read patches when the only difference in code is that it's indented. - - Patches in ``git diff`` format are also acceptable. - - * When creating patches, always run ``svn diff`` from the top-level - ``trunk`` directory -- i.e., the one that contains ``django``, ``docs``, - ``tests``, ``AUTHORS``, etc. This makes it easy for other people to apply - your patches. - - * Attach patches to a ticket in the `ticket tracker`_, using the "attach file" - button. Please *don't* put the patch in the ticket description or comment - unless it's a single line patch. - - * Name the patch file with a ``.diff`` extension; this will let the ticket - tracker apply correct syntax highlighting, which is quite helpful. - - * Check the "Has patch" box on the ticket details. This will make it - obvious that the ticket includes a patch, and it will add the ticket to - the `list of tickets with patches`_. - - * The code required to fix a problem or add a feature is an essential part - of a patch, but it is not the only part. A good patch should also include - a regression test to validate the behavior that has been fixed (and prevent - the problem from arising again). - - * If the code associated with a patch adds a new feature, or modifies behavior - of an existing feature, the patch should also contain documentation. - -Non-trivial patches -------------------- - -A "non-trivial" patch is one that is more than a simple bug fix. It's a patch -that introduces Django functionality and makes some sort of design decision. - -If you provide a non-trivial patch, include evidence that alternatives have -been discussed on `django-developers`_. If you're not sure whether your patch -should be considered non-trivial, just ask. - -Ticket triage -============= - -Unfortunately, not all bug reports in the `ticket tracker`_ provide all -the `required details`_. A number of tickets have patches, but those patches -don't meet all the requirements of a `good patch`_. - -One way to help out is to *triage* bugs that have been reported by other -users. A couple of dedicated volunteers work on this regularly, but more help -is always appreciated. - -Most of the workflow is based around the concept of a ticket's "triage stage". -This stage describes where in its lifetime a given ticket is at any time. -Along with a handful of flags, this field easily tells us what and who each -ticket is waiting on. - -Since a picture is worth a thousand words, let's start there: - -.. image:: _images/djangotickets.png - :height: 451 - :width: 590 - :alt: Django's ticket workflow - -We've got two official roles here: - - * Core developers: people with commit access who make the big decisions - and write the bulk of the code. - - * Ticket triagers: trusted community members with a proven history of - working with the Django community. As a result of this history, they - have been entrusted by the core developers to make some of the smaller - decisions about tickets. - -Second, note the five triage stages: - - 1. A ticket starts as "Unreviewed", meaning that nobody has examined - the ticket. - - 2. "Design decision needed" means "this concept requires a design - decision," which should be discussed either in the ticket comments or on - `django-developers`_. The "Design decision needed" step will generally - only be used for feature requests. It can also be used for issues - that *might* be bugs, depending on opinion or interpretation. Obvious - bugs (such as crashes, incorrect query results, or non-compliance with a - standard) skip this step and move straight to "Accepted". - - 3. Once a ticket is ruled to be approved for fixing, it's moved into the - "Accepted" stage. This stage is where all the real work gets done. - - 4. In some cases, a ticket might get moved to the "Someday/Maybe" state. - This means the ticket is an enhancement request that we might consider - adding to the framework if an excellent patch is submitted. These - tickets are not a high priority. - - 5. If a ticket has an associated patch (see below), a triager will review - the patch. If the patch is complete, it'll be marked as "ready for - checkin" so that a core developer knows to review and check in the - patches. - -The second part of this workflow involves a set of flags the describe what the -ticket has or needs in order to be "ready for checkin": - - "Has patch" - This means the ticket has an associated patch_. These will be - reviewed by the triage team to see if the patch is "good". - - "Needs documentation" - This flag is used for tickets with patches that need associated - documentation. Complete documentation of features is a prerequisite - before we can check a fix into the codebase. - - "Needs tests" - This flags the patch as needing associated unit tests. Again, this is a - required part of a valid patch. - - "Patch needs improvement" - This flag means that although the ticket *has* a patch, it's not quite - ready for checkin. This could mean the patch no longer applies - cleanly, or that the code doesn't live up to our standards. - -A ticket can be resolved in a number of ways: - - "fixed" - Used by one of the core developers once a patch has been rolled into - Django and the issue is fixed. - - "invalid" - Used if the ticket is found to be incorrect. This means that the - issue in the ticket is actually the result of a user error, or - describes a problem with something other than Django, or isn't - a bug report or feature request at all (for example, some new users - submit support queries as tickets). - - "wontfix" - Used when a core developer decides that this request is not - appropriate for consideration in Django. This is usually chosen after - discussion in the ``django-developers`` mailing list, and you should - feel free to join in when it's something you care about. - - "duplicate" - Used when another ticket covers the same issue. By closing duplicate - tickets, we keep all the discussion in one place, which helps everyone. - - "worksforme" - Used when the ticket doesn't contain enough detail to replicate - the original bug. - -If you believe that the ticket was closed in error -- because you're -still having the issue, or it's popped up somewhere else, or the triagers have --- made a mistake, please reopen the ticket and tell us why. Please do not -reopen tickets that have been marked as "wontfix" by core developers. - -.. _required details: `Reporting bugs`_ -.. _good patch: `Patch style`_ -.. _patch: `Submitting patches`_ - -Triage by the general community -------------------------------- - -Although the core developers and ticket triagers make the big decisions in -the ticket triage process, there's also a lot that general community -members can do to help the triage process. In particular, you can help out by: - - * Closing "Unreviewed" tickets as "invalid", "worksforme" or "duplicate." - - * Promoting "Unreviewed" tickets to "Design decision needed" if a design - decision needs to be made, or "Accepted" in case of obvious bugs. - - * Correcting the "Needs tests", "Needs documentation", or "Has patch" flags - for tickets where they are incorrectly set. - - * Adding the `easy-pickings`_ keyword to tickets that are small and - relatively straightforward. - - * Checking that old tickets are still valid. If a ticket hasn't seen - any activity in a long time, it's possible that the problem has been - fixed but the ticket hasn't yet been closed. - - * Contacting the owners of tickets that have been claimed but have not seen - any recent activity. If the owner doesn't respond after a week or so, - remove the owner's claim on the ticket. - - * Identifying trends and themes in the tickets. If there a lot of bug reports - about a particular part of Django, it may indicate we should consider - refactoring that part of the code. If a trend is emerging, you should - raise it for discussion (referencing the relevant tickets) on - `django-developers`_. - -However, we do ask the following of all general community members working in -the ticket database: - - * Please **don't** close tickets as "wontfix." The core developers will - make the final determination of the fate of a ticket, usually after - consultation with the community. - - * Please **don't** promote tickets to "Ready for checkin" unless they are - *trivial* changes -- for example, spelling mistakes or broken links in - documentation. - - * Please **don't** reverse a decision that has been made by a core - developer. If you disagree with a discussion that has been made, - please post a message to `django-developers`_. - - * Please be conservative in your actions. If you're unsure if you should - 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 -======================================= - -Various parts of Django, such as the admin site and validation error messages, -are internationalized. This means they display different text depending on a -user's language setting. For this, Django uses the same internationalization -infrastructure available to Django applications described in the -:doc:`i18n documentation</topics/i18n/index>`. - -These translations are contributed by Django users worldwide. If you find an -incorrect translation, or if you'd like to add a language that isn't yet -translated, here's what to do: - - * Join the `Django i18n mailing list`_ and introduce yourself. - - * Make sure you read the notes about :ref:`specialties-of-django-i18n`. - - * Create translations using the methods described in the - :doc:`localization documentation </topics/i18n/localization>`. For this - you will use the ``django-admin.py makemessages`` tool. In this - particular case it should be run from the top-level ``django`` directory - of the Django source tree. - - The script runs over the entire Django source tree and pulls out all - strings marked for translation. It creates (or updates) a message file in - the directory ``conf/locale`` (for example for ``pt_BR``, the file will be - ``conf/locale/pt_BR/LC_MESSAGES/django.po``). - - * Make sure that ``django-admin.py compilemessages -l <lang>`` runs without - producing any warnings. - - * Repeat the last two steps for the ``djangojs`` domain (by appending the - ``-d djangojs`` command line option to the ``django-admin.py`` - invocations). - - * Optionally, review and update the ``conf/locale/<locale>/formats.py`` - file to describe the date, time and numbers formatting particularities of - your locale. See :ref:`format-localization` for details. - - * Create a diff against the current Subversion trunk. - - * Open a ticket in Django's ticket system, set its ``Component`` field to - ``Translations``, and attach the patch to it. - -.. _Django i18n mailing list: http://groups.google.com/group/django-i18n/ - -Submitting javascript patches -============================= - -.. versionadded:: 1.2 - -Django's admin system leverages the jQuery framework to increase the -capabilities of the admin interface. In conjunction, there is an emphasis on -admin javascript performance and minimizing overall admin media file size. -Serving compressed or "minified" versions of javascript files is considered -best practice in this regard. - -To that end, patches for javascript files should include both the original -code for future development (e.g. "foo.js"), and a compressed version for -production use (e.g. "foo.min.js"). Any links to the file in the codebase -should point to the compressed version. - -To simplify the process of providing optimized javascript code, Django -includes a handy script which should be used to create a "minified" version. -This script is located at ``/contrib/admin/media/js/compress.py``. - -Behind the scenes, ``compress.py`` is a front-end for Google's -`Closure Compiler`_ which is written in Java. However, the Closure Compiler -library is not bundled with Django directly, so those wishing to contribute -complete javascript patches will need to download and install the library -independently. - -The Closure Compiler library requires Java version 6 or higher (Java 1.6 or -higher on Mac OS X). Note that Mac OS X 10.5 and earlier did not ship with Java -1.6 by default, so it may be necessary to upgrade your Java installation before -the tool will be functional. Also note that even after upgrading Java, the -default `/usr/bin/java` command may remain linked to the previous Java -binary, so relinking that command may be necessary as well. - -Please don't forget to run ``compress.py`` and include the ``diff`` of the -minified scripts when submitting patches for Django's javascript. - -.. _Closure Compiler: http://code.google.com/closure/compiler/ - -Django conventions -================== - -Various Django-specific code issues are detailed in this section. - -Use of ``django.conf.settings`` -------------------------------- - -Modules should not in general use settings stored in ``django.conf.settings`` at -the top level (i.e. evaluated when the module is imported). The explanation for -this is as follows: - -Manual configuration of settings (i.e. not relying on the -``DJANGO_SETTINGS_MODULE`` environment variable) is allowed and possible as -follows:: - - from django.conf import settings - - settings.configure({}, SOME_SETTING='foo') - -However, if any setting is accessed before the ``settings.configure`` line, this -will not work. (Internally, ``settings`` is a ``LazyObject`` which configures -itself automatically when the settings are accessed if it has not already been -configured). - -So, if there is a module containing some code as follows:: - - from django.conf import settings - from django.core.urlresolvers import get_callable - - default_foo_view = get_callable(settings.FOO_VIEW) - -...then importing this module will cause the settings object to be configured. -That means that the ability for third parties to import the module at the top -level is incompatible with the ability to configure the settings object -manually, or makes it very difficult in some circumstances. - -Instead of the above code, a level of laziness or indirection must be used, such -as :class:`django.utils.functional.LazyObject`, :func:`django.utils.functional.lazy` or -``lambda``. - -Coding style -============ - -Please follow these coding standards when writing code for inclusion in Django: - - * Unless otherwise specified, follow :pep:`8`. - - 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. - - * Use four spaces for indentation. - - * Use underscores, not camelCase, for variable, function and method names - (i.e. ``poll.get_unique_voters()``, not ``poll.getUniqueVoters``). - - * Use ``InitialCaps`` for class names (or for factory functions that - return classes). - - * Mark all strings for internationalization; see the :doc:`i18n - documentation </topics/i18n/index>` for details. - - * In docstrings, use "action words" such as:: - - def foo(): - """ - Calculates something and returns the result. - """ - pass - - Here's an example of what not to do:: - - def foo(): - """ - Calculate something and return the result. - """ - pass - - * Please don't put your name in the code you contribute. Our policy is to - keep contributors' names in the ``AUTHORS`` file distributed with Django - -- not scattered throughout the codebase itself. Feel free to include a - change to the ``AUTHORS`` file in your patch if you make more than a - single trivial change. - -Template style --------------- - - * In Django template code, put one (and only one) space between the curly - brackets and the tag contents. - - Do this: - - .. code-block:: html+django - - {{ foo }} - - Don't do this: - - .. code-block:: html+django - - {{foo}} - -View style ----------- - - * In Django views, the first parameter in a view function should be called - ``request``. - - Do this:: - - def my_view(request, foo): - # ... - - Don't do this:: - - def my_view(req, foo): - # ... - -Model style ------------ - - * Field names should be all lowercase, using underscores instead of - camelCase. - - Do this:: - - class Person(models.Model): - first_name = models.CharField(max_length=20) - last_name = models.CharField(max_length=40) - - Don't do this:: - - class Person(models.Model): - FirstName = models.CharField(max_length=20) - Last_Name = models.CharField(max_length=40) - - * The ``class Meta`` should appear *after* the fields are defined, with - a single blank line separating the fields and the class definition. - - Do this:: - - class Person(models.Model): - first_name = models.CharField(max_length=20) - last_name = models.CharField(max_length=40) - - class Meta: - verbose_name_plural = 'people' - - Don't do this:: - - class Person(models.Model): - first_name = models.CharField(max_length=20) - last_name = models.CharField(max_length=40) - class Meta: - verbose_name_plural = 'people' - - Don't do this, either:: - - class Person(models.Model): - class Meta: - verbose_name_plural = 'people' - - first_name = models.CharField(max_length=20) - last_name = models.CharField(max_length=40) - - * The order of model inner classes and standard methods should be as - follows (noting that these are not all required): - - * All database fields - * Custom manager attributes - * ``class Meta`` - * ``def __unicode__()`` - * ``def __str__()`` - * ``def save()`` - * ``def get_absolute_url()`` - * Any custom methods - - * If ``choices`` is defined for a given model field, define the choices as - a tuple of tuples, with an all-uppercase name, either near the top of the - model module or just above the model class. Example:: - - GENDER_CHOICES = ( - ('M', 'Male'), - ('F', 'Female'), - ) - -Documentation style -=================== - -We place a high importance on consistency and readability of documentation. -(After all, Django was created in a journalism environment!) - -How to document new features ----------------------------- - -We treat our documentation like we treat our code: we aim to improve it as -often as possible. This section explains how writers can craft their -documentation changes in the most useful and least error-prone ways. - -Documentation changes come in two forms: - - * General improvements -- Typo corrections, error fixes and better - explanations through clearer writing and more examples. - - * New features -- Documentation of features that have been added to the - framework since the last release. - -Our policy is: - - **All documentation of new features should be written in a way that clearly - designates the features are only available in the Django development - version. Assume documentation readers are using the latest release, not the - development version.** - -Our preferred way for marking new features is by prefacing the features' -documentation with: ".. versionadded:: X.Y", followed by an optional one line -comment and a mandatory blank line. - -General improvements, or other changes to the APIs that should be emphasized -should use the ".. versionchanged:: X.Y" directive (with the same format as the -``versionadded`` mentioned above. - -There's a full page of information about the :doc:`Django documentation -system </internals/documentation>` that you should read prior to working on the -documentation. - -Guidelines for reST files -------------------------- - -These guidelines regulate the format of our reST documentation: - - * In section titles, capitalize only initial words and proper nouns. - - * Wrap the documentation at 80 characters wide, unless a code example - is significantly less readable when split over two lines, or for another - good reason. - -Commonly used terms -------------------- - -Here are some style guidelines on commonly used terms throughout the -documentation: - - * **Django** -- when referring to the framework, capitalize Django. It is - lowercase only in Python code and in the djangoproject.com logo. - - * **e-mail** -- it has a hyphen. - - * **MySQL** - - * **PostgreSQL** - - * **Python** -- when referring to the language, capitalize Python. - - * **realize**, **customize**, **initialize**, etc. -- use the American - "ize" suffix, not "ise." - - * **SQLite** - - * **subclass** -- it's a single word without a hyphen, both as a verb - ("subclass that model") and as a noun ("create a subclass"). - - * **Web**, **World Wide Web**, **the Web** -- note Web is always - capitalized when referring to the World Wide Web. - - * **Web site** -- use two words, with Web capitalized. - -Django-specific terminology ---------------------------- - - * **model** -- it's not capitalized. - - * **template** -- it's not capitalized. - - * **URLconf** -- use three capitalized letters, with no space before - "conf." - - * **view** -- it's not capitalized. - -Committing code -=============== - -Please follow these guidelines when committing code to Django's Subversion -repository: - - * For any medium-to-big changes, where "medium-to-big" is according to your - judgment, please bring things up on the `django-developers`_ mailing list - before making the change. - - If you bring something up on `django-developers`_ and nobody responds, - please don't take that to mean your idea is great and should be - implemented immediately because nobody contested it. Django's lead - developers don't have a lot of time to read mailing-list discussions - immediately, so you may have to wait a couple of days before getting a - response. - - * Write detailed commit messages in the past tense, not present tense. - - * Good: "Fixed Unicode bug in RSS API." - * Bad: "Fixes Unicode bug in RSS API." - * Bad: "Fixing Unicode bug in RSS API." - - * For commits to a branch, prefix the commit message with the branch name. - For example: "magic-removal: Added support for mind reading." - - * Limit commits to the most granular change that makes sense. This means, - use frequent small commits rather than infrequent large commits. For - example, if implementing feature X requires a small change to library Y, - first commit the change to library Y, then commit feature X in a separate - commit. This goes a *long way* in helping all core Django developers - follow your changes. - - * Separate bug fixes from feature changes. - - Bug fixes need to be added to the current bugfix branch (e.g. the - ``1.0.X`` branch) as well as the current trunk. - - * If your commit closes a ticket in the Django `ticket tracker`_, begin - your commit message with the text "Fixed #abc", where "abc" is the number - of the ticket your commit fixes. Example: "Fixed #123 -- Added support - for foo". We've rigged Subversion and Trac so that any commit message - in that format will automatically close the referenced ticket and post a - comment to it with the full commit message. - - If your commit closes a ticket and is in a branch, use the branch name - first, then the "Fixed #abc." For example: - "magic-removal: Fixed #123 -- Added whizbang feature." - - For the curious: We're using a `Trac post-commit hook`_ for this. - - .. _Trac post-commit hook: http://trac.edgewall.org/browser/trunk/contrib/trac-post-commit-hook - - * If your commit references a ticket in the Django `ticket tracker`_ but - does *not* close the ticket, include the phrase "Refs #abc", where "abc" - is the number of the ticket your commit references. We've rigged - Subversion and Trac so that any commit message in that format will - automatically post a comment to the appropriate ticket. - -Reverting commits ------------------ - -Nobody's perfect; mistakes will be committed. When a mistaken commit is -discovered, please follow these guidelines: - - * Try very hard to ensure that mistakes don't happen. Just because we - have a reversion policy doesn't relax your responsibility to aim for - the highest quality possible. Really: double-check your work before - you commit it in the first place! - - * If possible, have the original author revert his/her own commit. - - * Don't revert another author's changes without permission from the - original author. - - * If the original author can't be reached (within a reasonable amount - of time -- a day or so) and the problem is severe -- crashing bug, - major test failures, etc -- then ask for objections on django-dev - then revert if there are none. - - * If the problem is small (a feature commit after feature freeze, - say), wait it out. - - * If there's a disagreement between the committer and the - reverter-to-be then try to work it out on the `django-developers`_ - mailing list. If an agreement can't be reached then it should - be put to a vote. - - * If the commit introduced a confirmed, disclosed security - vulnerability then the commit may be reverted immediately without - permission from anyone. - - * The release branch maintainer may back out commits to the release - branch without permission if the commit breaks the release branch. - -.. _unit-tests: - -Unit tests -========== - -Django comes with a test suite of its own, in the ``tests`` directory of the -Django tarball. It's our policy to make sure all tests pass at all times. - -The tests cover: - - * Models and the database API (``tests/modeltests/``). - * Everything else in core Django code (``tests/regressiontests``) - * Contrib apps (``django/contrib/<contribapp>/tests``, see below) - -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 :doc:`Testing Django applications </topics/testing>` -for an explanation of how to write new tests. - -.. _running-unit-tests: - -Running the unit tests ----------------------- - -To run the tests, ``cd`` to the ``tests/`` directory and type: - -.. code-block:: bash - - ./runtests.py --settings=path.to.django.settings - -Yes, the unit tests need a settings module, but only for database connection -info. Your :setting:`DATABASES` setting needs to define two databases: - - * A ``default`` database. This database should use the backend that - you want to use for primary testing - - * A database with the alias ``other``. The ``other`` database is - used to establish that queries can be directed to different - databases. As a result, this database can use any backend you - want. It doesn't need to use the same backend as the ``default`` - database (although it can use the same backend if you want to). - -If you're using the SQLite database backend, you need to define -:setting:`ENGINE` for both databases, plus a -:setting:`TEST_NAME` for the ``other`` database. The -following is a minimal settings file that can be used to test SQLite:: - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3' - }, - 'other': { - 'ENGINE': 'django.db.backends.sqlite3', - 'TEST_NAME': 'other_db' - } - } - -As a convenience, this settings file is included in your Django -distribution. It is called ``test_sqlite``, and is included in -the ``tests`` directory. This allows you to get started running -the tests against the sqlite database without doing anything on -your filesystem. However it should be noted that running against -other database backends is recommended for certain types of test -cases. - -To run the tests with this included settings file, ``cd`` -to the ``tests/`` directory and type: - -.. code-block:: bash - - ./runtests.py --settings=test_sqlite - -If you're using another backend, you will need to provide other details for -each database: - - * The :setting:`USER` option for each of your databases needs to - specify an existing user account for the database. - - * The :setting:`PASSWORD` option needs to provide the password for - the :setting:`USER` that has been specified. - - * The :setting:`NAME` option 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 - :setting:`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``. - -You will also need to ensure that your database uses UTF-8 as the default -character set. If your database server doesn't use UTF-8 as a default charset, -you will need to include a value for ``TEST_CHARSET`` in the settings -dictionary for the applicable database. - -If you want to run the full suite of tests, you'll need to install a number of -dependencies: - - * PyYAML_ - * Markdown_ - * Textile_ - * Docutils_ - * setuptools_ - * memcached_, plus the either the python-memcached_ or cmemcached_ - Python binding - * gettext_ (:ref:`gettext_on_windows`) - -If you want to test the memcached cache backend, you will also need to define -a :setting:`CACHE_BACKEND` setting that points at your memcached instance. - -Each of these dependencies is optional. If you're missing any of them, the -associated tests will be skipped. - -.. _PyYAML: http://pyyaml.org/wiki/PyYAML -.. _Markdown: http://pypi.python.org/pypi/Markdown/1.7 -.. _Textile: http://pypi.python.org/pypi/textile -.. _docutils: http://pypi.python.org/pypi/docutils/0.4 -.. _setuptools: http://pypi.python.org/pypi/setuptools/ -.. _memcached: http://www.danga.com/memcached/ -.. _python-memcached: http://pypi.python.org/pypi/python-memcached/ -.. _cmemcached: http://gijsbert.org/cmemcache/index.html -.. _gettext: http://www.gnu.org/software/gettext/manual/gettext.html - -To run a subset of the unit tests, append the names of the test modules to the -``runtests.py`` command line. See the list of directories in -``tests/modeltests`` and ``tests/regressiontests`` for module names. - -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: - -.. code-block:: bash - - PYTHONPATH=`pwd`/.. - ./runtests.py --settings=settings generic_relations i18n - -Contrib apps ------------- - -Tests for apps in ``django/contrib/`` go in their respective directories under -``django/contrib/``, in a ``tests.py`` file. (You can split the tests over -multiple modules by using a ``tests`` directory in the normal Python way.) - -For the tests to be found, a ``models.py`` file must exist (it doesn't -have to have anything in it). If you have URLs that need to be -mapped, put them in ``tests/urls.py``. - -To run tests for just one contrib app (e.g. ``markup``), use the same -method as above:: - - ./runtests.py --settings=settings markup - -Requesting features -=================== - -We're always trying to make Django better, and your feature requests are a key -part of that. Here are some tips on how to most effectively make a request: - - * Request the feature on `django-developers`_, not in the ticket tracker; - it'll get read more closely if it's on the mailing list. - - * Describe clearly and concisely what the missing feature is and how you'd - like to see it implemented. Include example code (non-functional is OK) - if possible. - - * Explain *why* you'd like the feature. In some cases this is obvious, but - since Django is designed to help real developers get real work done, - you'll need to explain it, if it isn't obvious why the feature would be - useful. - -As with most open-source projects, code talks. If you are willing to write the -code for the feature yourself or if (even better) you've already written it, -it's much more likely to be accepted. If it's a large feature that might need -multiple developers we're always happy to give you an experimental branch in -our repository; see below. - -Branch policy -============= - -In general, the trunk must be kept stable. People should be able to run -production sites against the trunk at any time. Additionally, commits to trunk -ought to be as atomic as possible -- smaller changes are better. Thus, large -feature changes -- that is, changes too large to be encapsulated in a single -patch, or changes that need multiple eyes on them -- must happen on dedicated -branches. - -This means that if you want to work on a large feature -- anything that would -take more than a single patch, or requires large-scale refactoring -- you need -to do it on a feature branch. Our development process recognizes two options -for feature branches: - - 1. Feature branches using a distributed revision control system like - Git_, Mercurial_, Bazaar_, etc. - - If you're familiar with one of these tools, this is probably your best - option since it doesn't require any support or buy-in from the Django - core developers. - - However, do keep in mind that Django will continue to use Subversion for - the foreseeable future, and this will naturally limit the recognition of - your branch. Further, if your branch becomes eligible for merging to - trunk you'll need to find a core developer familiar with your DVCS of - choice who'll actually perform the merge. - - If you do decided to start a distributed branch of Django and choose to make it - public, please add the branch to the `Django branches`_ wiki page. - - 2. Feature branches using SVN have a higher bar. If you want a branch in SVN - itself, you'll need a "mentor" among the :doc:`core committers - </internals/committers>`. This person is responsible for actually creating - the branch, monitoring your process (see below), and ultimately merging - the branch into trunk. - - If you want a feature branch in SVN, you'll need to ask in - `django-developers`_ for a mentor. - -.. _git: http://git-scm.com/ -.. _mercurial: http://mercurial.selenic.com/ -.. _bazaar: http://bazaar.canonical.com/ -.. _django branches: http://code.djangoproject.com/wiki/DjangoBranches - -Branch rules ------------- - -We've got a few rules for branches born out of experience with what makes a -successful Django branch. - -DVCS branches are obviously not under central control, so we have no way of -enforcing these rules. However, if you're using a DVCS, following these rules -will give you the best chance of having a successful branch (read: merged back to -trunk). - -Developers with branches in SVN, however, **must** follow these rules. The -branch mentor will keep on eye on the branch and **will delete it** if these -rules are broken. - - * Only branch entire copies of the Django tree, even if work is only - happening on part of that tree. This makes it painless to switch to a - branch. - - * Merge changes from trunk no less than once a week, and preferably every - couple-three days. - - In our experience, doing regular trunk merges is often the difference - between a successful branch and one that fizzles and dies. - - If you're working on an SVN branch, you should be using `svnmerge.py`_ - to track merges from trunk. - - * Keep tests passing and documentation up-to-date. As with patches, - we'll only merge a branch that comes with tests and documentation. - -.. _svnmerge.py: http://www.orcaware.com/svn/wiki/Svnmerge.py - -Once the branch is stable and ready to be merged into the trunk, alert -`django-developers`_. - -After a branch has been merged, it should be considered "dead"; write access to -it will be disabled, and old branches will be periodically "trimmed." To keep -our SVN wrangling to a minimum, we won't be merging from a given branch into the -trunk more than once. - -Using branches --------------- - -To use a branch, you'll need to do two things: - - * Get the branch's code through Subversion. - - * Point your Python ``site-packages`` directory at the branch's version of - the ``django`` package rather than the version you already have - installed. - -Getting the code from Subversion -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To get the latest version of a branch's code, check it out using Subversion: - -.. code-block:: bash - - svn co http://code.djangoproject.com/svn/django/branches/<branch>/ - -...where ``<branch>`` is the branch's name. See the `list of branch names`_. - -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: - -.. code-block:: bash - - svn switch http://code.djangoproject.com/svn/django/branches/<branch>/ - -The advantage of using ``svn switch`` instead of ``svn co`` is that the -``switch`` command retains any changes you might have made to your local copy -of the code. It attempts to merge those changes into the "switched" code. The -disadvantage is that it may cause conflicts with your local changes if the -"switched" code has altered the same lines of code. - -(Note that if you use ``svn switch``, you don't need to point Python at the new -version, as explained in the next section.) - -.. _list of branch names: http://code.djangoproject.com/browser/django/branches - -Pointing Python at the new Django version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Once you've retrieved the branch's code, you'll need to change your Python -``site-packages`` directory so that it points to the branch version of the -``django`` directory. (The ``site-packages`` directory is somewhere such as -``/usr/lib/python2.4/site-packages`` or -``/usr/local/lib/python2.4/site-packages`` or ``C:\Python\site-packages``.) - -The simplest way to do this is by renaming the old ``django`` directory to -``django.OLD`` and moving the trunk version of the code into the directory -and calling it ``django``. - -Alternatively, you can use a symlink called ``django`` that points to the -location of the branch's ``django`` package. If you want to switch back, just -change the symlink to point to the old code. - -A third option is to use a `path file`_ (``<something>.pth``) which should -work on all systems (including Windows, which doesn't have symlinks -available). First, make sure there are no files, directories or symlinks named -``django`` in your ``site-packages`` directory. Then create a text file named -``django.pth`` and save it to your ``site-packages`` directory. That file -should contain a path to your copy of Django on a single line and optional -comments. Here is an example that points to multiple branches. Just uncomment -the line for the branch you want to use ('Trunk' in this example) and make -sure all other lines are commented:: - - # Trunk is a svn checkout of: - # http://code.djangoproject.com/svn/django/trunk/ - # - /path/to/trunk - - # <branch> is a svn checkout of: - # http://code.djangoproject.com/svn/django/branches/<branch>/ - # - #/path/to/<branch> - - # On windows a path may look like this: - # C:/path/to/<branch> - -If you're using Django 0.95 or earlier and installed it using -``python setup.py install``, you'll have a directory called something like -``Django-0.95-py2.4.egg`` instead of ``django``. In this case, edit the file -``setuptools.pth`` and remove the line that references the Django ``.egg`` -file. Then copy the branch's version of the ``django`` directory into -``site-packages``. - -.. _path file: http://docs.python.org/library/site.html - -How we make decisions -===================== - -Whenever possible, we strive for a rough consensus. To that end, we'll often -have informal votes on `django-developers`_ about a feature. In these votes we -follow the voting style invented by Apache and used on Python itself, where -votes are given as +1, +0, -0, or -1. Roughly translated, these votes mean: - - * +1: "I love the idea and I'm strongly committed to it." - - * +0: "Sounds OK to me." - - * -0: "I'm not thrilled, but I won't stand in the way." - - * -1: "I strongly disagree and would be very unhappy to see the idea turn - into reality." - -Although these votes on django-developers are informal, they'll be taken very -seriously. After a suitable voting period, if an obvious consensus arises -we'll follow the votes. - -However, consensus is not always possible. If consensus cannot be reached, or -if the discussion towards a consensus fizzles out without a concrete decision, -we use a more formal process. - -Any core committer (see below) may call for a formal vote using the same -voting mechanism above. A proposition will be considered carried by the core team -if: - - * There are three "+1" votes from members of the core team. - - * There is no "-1" vote from any member of the core team. - - * The BDFLs haven't stepped in and executed their positive or negative - veto. - -When calling for a vote, the caller should specify a deadline by which -votes must be received. One week is generally suggested as the minimum -amount of time. - -Since this process allows any core committer to veto a proposal, any "-1" -votes (or BDFL vetos) should be accompanied by an explanation that explains -what it would take to convert that "-1" into at least a "+0". - -Whenever possible, these formal votes should be announced and held in -public on the `django-developers`_ mailing list. However, overly sensitive -or contentious issues -- including, most notably, votes on new core -committers -- may be held in private. - -Commit access -============= - -Django has two types of committers: - -Core committers - These are people who have a long history of contributions to Django's - codebase, a solid track record of being polite and helpful on the - mailing lists, and a proven desire to dedicate serious time to Django's - development. The bar is high for full commit access. - -Partial committers - These are people who are "domain experts." They have direct check-in access - to the subsystems that fall under their jurisdiction, and they're given a - formal vote in questions that involve their subsystems. This type of access - is likely to be given to someone who contributes a large subframework to - Django and wants to continue to maintain it. - - Partial commit access is granted by the same process as full - committers. However, the bar is set lower; proven expertise in the area - in question is likely to be sufficient. - -Decisions on new committers will follow the process explained above in `how -we make decisions`_. - -To request commit access, please contact an existing committer privately. Public -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 -.. _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 -.. _pep8.py: http://pypi.python.org/pypi/pep8/ -.. _i18n branch: http://code.djangoproject.com/browser/django/branches/i18n -.. _`tags/releases`: http://code.djangoproject.com/browser/django/tags/releases -.. _`easy-pickings`: http://code.djangoproject.com/query?status=new&status=assigned&status=reopened&keywords=~easy-pickings&order=priority diff --git a/parts/django/docs/internals/deprecation.txt b/parts/django/docs/internals/deprecation.txt deleted file mode 100644 index e045795..0000000 --- a/parts/django/docs/internals/deprecation.txt +++ /dev/null @@ -1,106 +0,0 @@ -=========================== -Django Deprecation Timeline -=========================== - -This document outlines when various pieces of Django will be removed, following -their deprecation, as per the :ref:`Django deprecation policy -<internal-release-deprecation-policy>` - - * 1.3 - * ``AdminSite.root()``. This release will remove the old method for - hooking up admin URLs. This has been deprecated since the 1.1 - release. - - * Authentication backends need to define the boolean attributes - ``supports_object_permissions`` and ``supports_anonymous_user``. - The old backend style is deprecated since the 1.2 release. - - * The :mod:`django.contrib.gis.db.backend` module, including the - ``SpatialBackend`` interface, is deprecated since the 1.2 release. - - * 1.4 - * ``CsrfResponseMiddleware``. This has been deprecated since the 1.2 - release, in favour of the template tag method for inserting the CSRF - token. ``CsrfMiddleware``, which combines ``CsrfResponseMiddleware`` - and ``CsrfViewMiddleware``, is also deprecated. - - * The old imports for CSRF functionality (``django.contrib.csrf.*``), - which moved to core in 1.2, will be removed. - - * ``SMTPConnection``. The 1.2 release deprecated the ``SMTPConnection`` - class in favor of a generic E-mail backend API. - - * The many to many SQL generation functions on the database backends - will be removed. - - * The ability to use the ``DATABASE_*`` family of top-level settings to - define database connections will be removed. - - * The ability to use shorthand notation to specify a database backend - (i.e., ``sqlite3`` instead of ``django.db.backends.sqlite3``) will be - removed. - - * The ``get_db_prep_save``, ``get_db_prep_value`` and - ``get_db_prep_lookup`` methods on Field were modified in 1.2 to support - multiple databases. In 1.4, the support functions that allow methods - with the old prototype to continue working will be removed. - - * The ``Message`` model (in ``django.contrib.auth``), its related - manager in the ``User`` model (``user.message_set``), and the - associated methods (``user.message_set.create()`` and - ``user.get_and_delete_messages()``), which have - been deprecated since the 1.2 release, will be removed. The - :doc:`messages framework </ref/contrib/messages>` should be used - instead. - - * Authentication backends need to support the ``obj`` parameter for - permission checking. The ``supports_object_permissions`` variable - is not checked any longer and can be removed. - - * Authentication backends need to support the ``AnonymousUser`` - being passed to all methods dealing with permissions. - The ``supports_anonymous_user`` variable is not checked any - longer and can be removed. - - * The ability to specify a callable template loader rather than a - ``Loader`` class will be removed, as will the ``load_template_source`` - functions that are included with the built in template loaders for - backwards compatibility. These have been deprecated since the 1.2 - release. - - * ``django.utils.translation.get_date_formats()`` and - ``django.utils.translation.get_partial_date_formats()``. These - functions are replaced by the new locale aware formatting; use - ``django.utils.formats.get_format()`` to get the appropriate - formats. - - * In ``django.forms.fields``: ``DEFAULT_DATE_INPUT_FORMATS``, - ``DEFAULT_TIME_INPUT_FORMATS`` and - ``DEFAULT_DATETIME_INPUT_FORMATS``. Use - ``django.utils.formats.get_format()`` to get the appropriate - formats. - - * The ability to use a function-based test runners will be removed, - along with the ``django.test.simple.run_tests()`` test runner. - - * The ``views.feed()`` view and ``feeds.Feed`` class in - ``django.contrib.syndication`` have been deprecated since the 1.2 - release. The class-based view ``views.Feed`` should be used instead. - - * ``django.core.context_processors.auth``. This release will - remove the old method in favor of the new method in - ``django.contrib.auth.context_processors.auth``. This has been - deprecated since the 1.2 release. - - * The ``postgresql`` database backend has been deprecated in favor of - the ``postgresql_psycopg2`` backend. - - * The ``no`` language code has been deprecated in favor of the ``nb`` - language code. - - * 2.0 - * ``django.views.defaults.shortcut()``. This function has been moved - to ``django.contrib.contenttypes.views.shortcut()`` as part of the - goal of removing all ``django.contrib`` references from the core - Django codebase. The old shortcut will be removed in the 2.0 - release. diff --git a/parts/django/docs/internals/documentation.txt b/parts/django/docs/internals/documentation.txt deleted file mode 100644 index 36270ea..0000000 --- a/parts/django/docs/internals/documentation.txt +++ /dev/null @@ -1,221 +0,0 @@ -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.sourceforge.net/ - -To actually build the documentation locally, you'll currently need to install -Sphinx -- ``easy_install Sphinx`` should do the trick. - -.. note:: - - The Django documentation can be generated with Sphinx version 0.6 or - newer, but we recommend using Sphinx 1.0.2 or newer. - -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 latter, 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, consider this hypothetical -example: - - * First, the ``ref/settings.txt`` document could have an overall layout - like this: - - .. code-block:: rst - - ======== - Settings - ======== - - ... - - .. _available-settings: - - Available settings - ================== - - ... - - .. _deprecated-settings: - - Deprecated settings - =================== - - ... - - * Next, the ``topics/settings.txt`` document could contain something like - this: - - .. code-block:: rst - - You can access a :ref:`listing of all available settings - <available-settings>`. For a list of deprecated settings see - :ref:`deprecated-settings`. - - You can find both in the :doc:`settings reference document </ref/settings>`. - - We use the Sphinx doc_ cross reference element when we want to link to - another document as a whole and the ref_ element when we want to link to - an arbitrary location in a document. - -.. _doc: http://sphinx.pocoo.org/markup/inline.html#role-doc -.. _ref: http://sphinx.pocoo.org/markup/inline.html#role-ref - - * Next, notice how the settings are annotated: - - .. code-block:: rst - - .. 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. - - * Most of the various ``index.txt`` documents have *very* short or even - non-existent intro text. Each of those documents needs a good short intro - the content below that point. - - * The glossary is very perfunctory. It needs to be filled out. - - * Add more metadata targets: there's lots of places that look like:: - - ``File.close()`` - ~~~~~~~~~~~~~~~~ - - \... these should be:: - - .. method:: File.close() - - That is, use metadata instead of titles. - - * Add more links -- nearly everything that's an inline code literal - right now can probably be turned into a xref. - - See the ``literals_to_xrefs.py`` file in ``_ext`` -- it's a shell script - to help do this work. - - This will probably be a continuing, never-ending project. - - * Add `info field lists`__ where appropriate. - - __ http://sphinx.pocoo.org/markup/desc.html#info-field-lists - - * Add ``.. code-block:: <lang>`` to literal blocks so that they get - highlighted. - -Hints ------ - -Some hints for making things look/read better: - - * Whenever possible, use links. So, use ``:setting:`ADMIN_FOR``` instead of - ````ADMIN_FOR````. - - * Some directives (``.. setting::``, for one) are prefix-style directives; - they go *before* the unit they're describing. These are known as - "crossref" directives. Others (``.. class::``, e.g.) generate their own - markup; these should go inside the section they're describing. These are - called "description units". - - You can tell which are which by looking at in :file:`_ext/djangodocs.py`; - it registers roles as one of the other. - - * When referring to classes/functions/modules, etc., you'll want to use the - fully-qualified name of the target - (``:class:`django.contrib.contenttypes.models.ContentType```). - - Since this doesn't look all that awesome in the output -- it shows the - entire path to the object -- you can prefix the target with a ``~`` - (that's a tilde) to get just the "last bit" of that path. So - ``:class:`~django.contrib.contenttypes.models.ContentType``` will just - display a link with the title "ContentType". diff --git a/parts/django/docs/internals/index.txt b/parts/django/docs/internals/index.txt deleted file mode 100644 index 26c941a..0000000 --- a/parts/django/docs/internals/index.txt +++ /dev/null @@ -1,24 +0,0 @@ -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 - committers - release-process - deprecation - svn diff --git a/parts/django/docs/internals/release-process.txt b/parts/django/docs/internals/release-process.txt deleted file mode 100644 index 2a56f0b..0000000 --- a/parts/django/docs/internals/release-process.txt +++ /dev/null @@ -1,205 +0,0 @@ -======================== -Django's release process -======================== - -.. _official-releases: - -Official releases -================= - -Django's release numbering works as follows: - - * Versions are numbered in the form ``A.B`` or ``A.B.C``. - - * ``A`` is the *major version* number, which is only incremented for major - changes to Django, and these changes are not necessarily - backwards-compatible. That is, code you wrote for Django 6.0 may break - when we release Django 7.0. - - * ``B`` is the *minor version* number, which is incremented for large yet - backwards compatible changes. Code written for Django 6.4 will continue - to work under Django 6.5. - - * ``C`` is the *micro version* number which, is incremented for bug and - security fixes. A new micro-release will always be 100% - backwards-compatible with the previous micro-release. - - * In some cases, we'll make alpha, beta, or release candidate releases. - These are of the form ``A.B alpha/beta/rc N``, which means the ``Nth`` - alpha/beta/release candidate of version ``A.B``. - -An exception to this version numbering scheme is the pre-1.0 Django code. -There's no guarantee of backwards-compatibility until the 1.0 release. - -In Subversion, each Django release will be tagged under ``tags/releases``. If -it's necessary to release a bug fix release or a security release that doesn't -come from the trunk, we'll copy that tag to ``branches/releases`` to make the -bug fix release. - -Major releases --------------- - -Major releases (1.0, 2.0, etc.) will happen very infrequently (think "years", -not "months"), and will probably represent major, sweeping changes to Django. - -Minor releases --------------- - -Minor release (1.1, 1.2, etc.) will happen roughly every nine months -- see -`release process`_, below for details. - -.. _internal-release-deprecation-policy: - -These releases will contain new features, improvements to existing features, and -such. A minor release may deprecate certain features from previous releases. If a -feature in version ``A.B`` is deprecated, it will continue to work in version -``A.B+1``. In version ``A.B+2``, use of the feature will raise a -``DeprecationWarning`` but will continue to work. Version ``A.B+3`` will -remove the feature entirely. - -So, for example, if we decided to remove a function that existed in Django 1.0: - - * Django 1.1 will contain a backwards-compatible replica of the function - which will raise a ``PendingDeprecationWarning``. This warning is silent - by default; you need to explicitly turn on display of these warnings. - - * Django 1.2 will contain the backwards-compatible replica, but the warning - will be promoted to a full-fledged ``DeprecationWarning``. This warning is - *loud* by default, and will likely be quite annoying. - - * Django 1.3 will remove the feature outright. - -Micro releases --------------- - -Micro releases (1.0.1, 1.0.2, 1.1.1, etc.) will be issued at least once half-way -between minor releases, and probably more often as needed. - -These releases will always be 100% compatible with the associated minor release --- the answer to "should I upgrade to the latest micro release?" will always be -"yes." - -Each minor release of Django will have a "release maintainer" appointed. This -person will be responsible for making sure that bug fixes are applied to both -trunk and the maintained micro-release branch. This person will also work with -the release manager to decide when to release the micro releases. - -Supported versions -================== - -At any moment in time, Django's developer team will support a set of releases to -varying levels: - - * The current development trunk will get new features and bug fixes - requiring major refactoring. - - * All bug fixes applied to the trunk will also be applied to the last - minor release, to be released as the next micro release. - - * Security fixes will be applied to the current trunk and the previous two - minor releases. - -As a concrete example, consider a moment in time halfway between the release of -Django 1.3 and 1.4. At this point in time: - - * Features will be added to development trunk, to be released as Django 1.4. - - * Bug fixes will be applied to a ``1.3.X`` branch, and released as 1.3.1, - 1.3.2, etc. - - * Security releases will be applied to trunk, a ``1.3.X`` branch and a - ``1.2.X`` branch. Security fixes will trigger the release of ``1.3.1``, - ``1.2.1``, etc. - -.. _release-process: - -Release process -=============== - -Django uses a time-based release schedule, with minor (i.e. 1.1, 1.2, etc.) -releases every nine months, or more, depending on features. - -After each previous release (and after a suitable cooling-off period of a week -or two), the core development team will examine the landscape and announce a -timeline for the next release. Most releases will be scheduled in the 6-9 month -range, but if we have bigger features to development we might schedule a longer -period to allow for more ambitious work. - -Release cycle -------------- - -Each release cycle will be split into three periods, each lasting roughly -one-third of the cycle: - -Phase one: feature proposal -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The first phase of the release process will be devoted to figuring out what -features to include in the next version. This should include a good deal of -preliminary work on those features -- working code trumps grand design. - -At the end of part one, the core developers will propose a feature list for the -upcoming release. This will be broken into: - -* "Must-have": critical features that will delay the release if not finished -* "Maybe" features: that will be pushed to the next release if not finished -* "Not going to happen": features explicitly deferred to a later release. - -Anything that hasn't got at least some work done by the end of the first third -isn't eligible for the next release; a design alone isn't sufficient. - -Phase two: development -~~~~~~~~~~~~~~~~~~~~~~ - -The second third of the release schedule is the "heads-down" working period. -Using the roadmap produced at the end of phase one, we'll all work very hard to -get everything on it done. - -Longer release schedules will likely spend more than a third of the time in this -phase. - -At the end of phase two, any unfinished "maybe" features will be postponed until -the next release. Though it shouldn't happen, any "must-have" features will -extend phase two, and thus postpone the final release. - -Phase two will culminate with an alpha release. - -Phase three: bugfixes -~~~~~~~~~~~~~~~~~~~~~ - -The last third of a release is spent fixing bugs -- no new features will be -accepted during this time. We'll release a beta release about halfway through, -and an rc complete with string freeze two weeks before the end of the schedule. - -Bug-fix releases ----------------- - -After a minor release (i.e 1.1), the previous release will go into bug-fix mode. - -A branch will be created of the form ``branches/releases/1.0.X`` to track -bug-fixes to the previous release. When possible, bugs fixed on trunk must -*also* be fixed on the bug-fix branch; this means that commits need to cleanly -separate bug fixes from feature additions. The developer who commits a fix to -trunk will be responsible for also applying the fix to the current bug-fix -branch. Each bug-fix branch will have a maintainer who will work with the -committers to keep them honest on backporting bug fixes. - -How this all fits together --------------------------- - -Let's look at a hypothetical example for how this all first together. Imagine, -if you will, a point about halfway between 1.1 and 1.2. At this point, -development will be happening in a bunch of places: - - * On trunk, development towards 1.2 proceeds with small additions, bugs - fixes, etc. being checked in daily. - - * On the branch "branches/releases/1.1.X", bug fixes found in the 1.1 - release are checked in as needed. At some point, this branch will be - released as "1.1.1", "1.1.2", etc. - - * On the branch "branches/releases/1.0.X", security fixes are made if - needed and released as "1.0.2", "1.0.3", etc. - - * On feature branches, development of major features is done. These - branches will be merged into trunk before the end of phase two. diff --git a/parts/django/docs/internals/svn.txt b/parts/django/docs/internals/svn.txt deleted file mode 100644 index 9efbe28..0000000 --- a/parts/django/docs/internals/svn.txt +++ /dev/null @@ -1,254 +0,0 @@ -================================= -The Django source code repository -================================= - - -When deploying a Django application into a real production -environment, you will almost always want to use `an official packaged -release of Django`_. However, if you'd like to try out in-development -code from an upcoming release or contribute to the development of -Django, you'll need to obtain a checkout from Django's source code -repository. This document covers the way the code repository is laid -out and how to work with and find things in it. - - -.. _an official packaged release of Django: http://www.djangoproject.com/download/ - - -High-level overview -=================== - -The Django source code repository uses `Subversion`_ to track changes -to the code over time, so you'll need a copy of the Subversion client -(a program called ``svn``) on your computer, and you'll want to -familiarize yourself with the basics of how Subversion -works. Subversion's Web site offers downloads for various operating -systems, and `a free online book`_ is available to help you get up to -speed with using Subversion. - -The Django Subversion repository is located online at -`code.djangoproject.com/svn <http://code.djangoproject.com/svn/>`_. `A -friendly Web-based interface for browsing the code`_ is also -available, though when using Subversion you'll always want to use the -repository address instead. At the top level of the repository are two -directories: ``django`` contains the full source code for all Django -releases, while ``djangoproject.com`` contains the source code and -templates for the `djangoproject.com <http://www.djangoproject.com/>`_ -Web site. For trying out in-development Django code, or contributing -to Django, you'll always want to check out code from some location in -the ``django`` directory. - -Inside the ``django`` directory, Django's source code is organized -into three areas: - -* ``branches`` contains branched copies of Django's code, which are - (or were) maintained for various purposes. Some branches exist to - provide a place to develop major or experimental new features - without affecting the rest of Django's code, while others serve to - provide bug fixes or support for older Django releases. - -* ``tags`` contains snapshots of Django's code at various important - points in its history; mostly these are the exact revisions from - which packaged Django releases were produced. - -* ``trunk`` contains the main in-development code which will become - the next packaged release of Django, and is where most development - activity is focused. - - -.. _Subversion: http://subversion.tigris.org/ -.. _a free online book: http://svnbook.red-bean.com/ -.. _A friendly Web-based interface for browsing the code: http://code.djangoproject.com/browser/ - - -Working with Django's trunk -=========================== - -If you'd like to try out the in-development code for the next release -of Django, or if you'd like to contribute to Django by fixing bugs or -developing new features, you'll want to get the code from trunk. You -can get a complete copy of this code (a "Subversion checkout") by -typing:: - - svn co http://code.djangoproject.com/svn/django/trunk/ - -Note that this will get *all* of Django: in addition to the top-level -``django`` module containing Python code, you'll also get a copy of -Django's documentation, unit-test suite, packaging scripts and other -miscellaneous bits. Django's code will be present in your checkout as -a directory named ``django``. - -To try out the in-development trunk code with your own applications, -simply place the directory containing your checkout on your Python -import path. Then ``import`` statements which look for Django will find -the ``django`` module within your checkout. - -If you're going to be working on Django's code (say, to fix a bug or -develop a new feature), you can probably stop reading here and move -over to :doc:`the documentation for contributing to Django -</internals/contributing>`, which covers things like the preferred -coding style and how to generate and submit a patch. - - -Branches -======== - -Django uses branches for two main purposes: - -1. Development of major or experimental features, to keep them from - affecting progress on other work in trunk. - -2. Security and bug-fix support for older releases of Django, during - their support lifetimes. - - -Feature-development branches ----------------------------- - -Feature-development branches tend by their nature to be -temporary. Some produce successful features which are merged back into -Django's trunk to become part of an official release, but others do -not; in either case there comes a time when the branch is no longer -being actively worked on by any developer. At this point the branch is -considered closed. - -Unfortunately, Subversion has no standard way of indicating this. As a -workaround, branches of Django which are closed and no longer -maintained are moved into the directory ``django/branches/attic``. - -For reference, the following are branches whose code eventually became -part of Django itself, and so are no longer separately maintained: - -* ``boulder-oracle-sprint``: Added support for Oracle databases to - Django's object-relational mapper. This has been part of Django - since the 1.0 release. - -* ``gis``: Added support for geographic/spatial queries to Django's - object-relational mapper. This has been part of Django since the 1.0 - release, as the bundled application ``django.contrib.gis``. - -* ``i18n``: Added :doc:`internationalization support </topics/i18n/index>` to - Django. This has been part of Django since the 0.90 release. - -* ``magic-removal``: A major refactoring of both the internals and - public APIs of Django's object-relational mapper. This has been part - of Django since the 0.95 release. - -* ``multi-auth``: A refactoring of :doc:`Django's bundled - authentication framework </topics/auth>` which added support for - :ref:`authentication backends <authentication-backends>`. This has - been part of Django since the 0.95 release. - -* ``new-admin``: A refactoring of :doc:`Django's bundled - administrative application </ref/contrib/admin/index>`. This became part of - Django as of the 0.91 release, but was superseded by another - refactoring (see next listing) prior to the Django 1.0 release. - -* ``newforms-admin``: The second refactoring of Django's bundled - administrative application. This became part of Django as of the 1.0 - release, and is the basis of the current incarnation of - ``django.contrib.admin``. - -* ``queryset-refactor``: A refactoring of the internals of Django's - object-relational mapper. This became part of Django as of the 1.0 - release. - -* ``unicode``: A refactoring of Django's internals to consistently use - Unicode-based strings in most places within Django and Django - applications. This became part of Django as of the 1.0 release. - -Additionally, the following branches are closed, but their code was -never merged into Django and the features they aimed to implement -were never finished: - -* ``full-history`` - -* ``generic-auth`` - -* ``multiple-db-support`` - -* ``per-object-permissions`` - -* ``schema-evolution`` - -* ``schema-evolution-ng`` - -* ``search-api`` - -* ``sqlalchemy`` - -All of the above-mentioned branches now reside in -``django/branches/attic``. - - -Support and bugfix branches ---------------------------- - -In addition to fixing bugs in current trunk, the Django project -provides official bug-fix support for the most recent released version -of Django, and security support for the two most recently-released -versions of Django. This support is provided via branches in which the -necessary bug or security fixes are applied; the branches are then -used as the basis for issuing bugfix or security releases. - -As of the Django 1.0 release, these branches can be found in the -repository in the directory ``django/branches/releases``, and new branches -will be created there approximately one month after each new Django -release. For example, shortly after the release of Django 1.0, the -branch ``django/branches/releases/1.0.X`` was created to receive bug -fixes, and shortly after the release of Django 1.1 the branch -``django/branches/releases/1.1.X`` was created. - -Prior to the Django 1.0 release, these branches were maintaind within -the top-level ``django/branches`` directory, and so the following -branches exist there and provided support for older Django releases: - -* ``0.90-bugfixes`` - -* ``0.91-bugfixes`` - -* ``0.95-bugfixes`` - -* ``0.96-bugfixes`` - -Official support for those releases has expired, and so they no longer -receive direct maintenance from the Django project. However, the -branches continue to exist and interested community members have -occasionally used them to provide unofficial support for old Django -releases. - - -Tags -==== - -The directory ``django/tags`` within the repository contains complete -copies of the Django source code as it existed at various points in -its history. These "tagged" copies of Django are *never* changed or -updated; new tags may be added as needed, but once added they are -considered read-only and serve as useful guides to Django's -development history. - -Within ``django/tags/releases`` are copies of the code which formed each -packaged release of Django, and each tag is named with the version -number of the release to which it corresponds. So, for example, -``django/tags/releases/1.1`` is a complete copy of the code which was -packaged as the Django 1.1 release. - -Within ``django/tags/notable_moments`` are copies of the Django code from -points which do not directly correspond to releases, but which are -nonetheless important historical milestones for Django -development. The current "notable moments" marked there are: - -* ``ipo``: Django's code as it existed at the moment Django was first - publicly announced in 2005. - -* ``pre-magic-removal``: The state of Django's code just before the - merging of the ``magic-removal`` branch (described above), which - significantly updated Django's object-relational mapper. - -* ``pre-newforms-admin``: The state of Django's code just before the - merging of the ``newforms-admin`` branch (see above), which - significantly updated Django's bundled administrative application. - -* Tags corresponding to each of the alpha, beta and release-candidate - packages in the run up to the Django 1.0 release. diff --git a/parts/django/docs/intro/_images/admin01.png b/parts/django/docs/intro/_images/admin01.png Binary files differdeleted file mode 100644 index 28f14d6..0000000 --- a/parts/django/docs/intro/_images/admin01.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin02.png b/parts/django/docs/intro/_images/admin02.png Binary files differdeleted file mode 100644 index 4b49ebb..0000000 --- a/parts/django/docs/intro/_images/admin02.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin02t.png b/parts/django/docs/intro/_images/admin02t.png Binary files differdeleted file mode 100644 index d7519d1..0000000 --- a/parts/django/docs/intro/_images/admin02t.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin03.png b/parts/django/docs/intro/_images/admin03.png Binary files differdeleted file mode 100644 index 635226c..0000000 --- a/parts/django/docs/intro/_images/admin03.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin03t.png b/parts/django/docs/intro/_images/admin03t.png Binary files differdeleted file mode 100644 index 94273cb..0000000 --- a/parts/django/docs/intro/_images/admin03t.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin04.png b/parts/django/docs/intro/_images/admin04.png Binary files differdeleted file mode 100644 index 982420a..0000000 --- a/parts/django/docs/intro/_images/admin04.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin04t.png b/parts/django/docs/intro/_images/admin04t.png Binary files differdeleted file mode 100644 index a2ec8bb..0000000 --- a/parts/django/docs/intro/_images/admin04t.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin05.png b/parts/django/docs/intro/_images/admin05.png Binary files differdeleted file mode 100644 index b424393..0000000 --- a/parts/django/docs/intro/_images/admin05.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin05t.png b/parts/django/docs/intro/_images/admin05t.png Binary files differdeleted file mode 100644 index a5da950..0000000 --- a/parts/django/docs/intro/_images/admin05t.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin06.png b/parts/django/docs/intro/_images/admin06.png Binary files differdeleted file mode 100644 index 5f24d4e..0000000 --- a/parts/django/docs/intro/_images/admin06.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin06t.png b/parts/django/docs/intro/_images/admin06t.png Binary files differdeleted file mode 100644 index fb65e0a..0000000 --- a/parts/django/docs/intro/_images/admin06t.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin07.png b/parts/django/docs/intro/_images/admin07.png Binary files differdeleted file mode 100644 index b21022f..0000000 --- a/parts/django/docs/intro/_images/admin07.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin08.png b/parts/django/docs/intro/_images/admin08.png Binary files differdeleted file mode 100644 index ddac57e..0000000 --- a/parts/django/docs/intro/_images/admin08.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin08t.png b/parts/django/docs/intro/_images/admin08t.png Binary files differdeleted file mode 100644 index 83773bb..0000000 --- a/parts/django/docs/intro/_images/admin08t.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin09.png b/parts/django/docs/intro/_images/admin09.png Binary files differdeleted file mode 100644 index ba7de1b..0000000 --- a/parts/django/docs/intro/_images/admin09.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin10.png b/parts/django/docs/intro/_images/admin10.png Binary files differdeleted file mode 100644 index 07a9bf3..0000000 --- a/parts/django/docs/intro/_images/admin10.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin11.png b/parts/django/docs/intro/_images/admin11.png Binary files differdeleted file mode 100644 index 6c583fd..0000000 --- a/parts/django/docs/intro/_images/admin11.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin11t.png b/parts/django/docs/intro/_images/admin11t.png Binary files differdeleted file mode 100644 index af792b8..0000000 --- a/parts/django/docs/intro/_images/admin11t.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin12.png b/parts/django/docs/intro/_images/admin12.png Binary files differdeleted file mode 100644 index aac5c0d..0000000 --- a/parts/django/docs/intro/_images/admin12.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin13.png b/parts/django/docs/intro/_images/admin13.png Binary files differdeleted file mode 100644 index 49a5950..0000000 --- a/parts/django/docs/intro/_images/admin13.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin13t.png b/parts/django/docs/intro/_images/admin13t.png Binary files differdeleted file mode 100644 index 7dc01e1..0000000 --- a/parts/django/docs/intro/_images/admin13t.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin14.png b/parts/django/docs/intro/_images/admin14.png Binary files differdeleted file mode 100644 index b1f4a54..0000000 --- a/parts/django/docs/intro/_images/admin14.png +++ /dev/null diff --git a/parts/django/docs/intro/_images/admin14t.png b/parts/django/docs/intro/_images/admin14t.png Binary files differdeleted file mode 100644 index 86c3acc..0000000 --- a/parts/django/docs/intro/_images/admin14t.png +++ /dev/null diff --git a/parts/django/docs/intro/index.txt b/parts/django/docs/intro/index.txt deleted file mode 100644 index bc61be7..0000000 --- a/parts/django/docs/intro/index.txt +++ /dev/null @@ -1,36 +0,0 @@ -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/parts/django/docs/intro/install.txt b/parts/django/docs/intro/install.txt deleted file mode 100644 index 327686f..0000000 --- a/parts/django/docs/intro/install.txt +++ /dev/null @@ -1,84 +0,0 @@ -Quick install guide -=================== - -Before you can use Django, you'll need to get it installed. We have a -:doc:`complete installation guide </topics/install>` that covers all the -possibilities; this guide will guide you to a simple, minimal installation -that'll work while you walk through the introduction. - -Install Python --------------- - -Being a Python Web framework, Django requires Python. It works with any Python -version from 2.4 to 2.7 (due to backwards -incompatibilities in Python 3.0, Django does not currently work with -Python 3.0; see :doc:`the Django FAQ </faq/install>` for more -information on supported Python versions and the 3.0 transition), 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. - -.. admonition:: Django on Jython - - If you use Jython_ (a Python implementation for the Java platform), you'll - need to follow a few additional steps. See :doc:`/howto/jython` for details. - -.. _jython: http://www.jython.org/ - -You can verify that Python's installed by typing ``python`` from your shell; you should see something like:: - - Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) - [GCC 4.0.1 (Apple Inc. build 5465)] on darwin - Type "help", "copyright", "credits" or "license" for more information. - >>> - -Set up a database ------------------ - -If you installed Python 2.5 or later, you can skip this step for now. - -If not, or if you'd like to work with a "large" database engine like PostgreSQL, -MySQL, or Oracle, consult the :ref:`database installation information -<database-installation>`. - -Remove any old versions of Django ---------------------------------- - -If you are upgrading your installation of Django from a previous version, you -will need to :ref:`uninstall the old Django version before installing the new -version <removing-old-versions-of-django>`. - -Install Django --------------- - -You've got three easy options to install Django: - - * Install a version of Django :doc:`provided by your operating system - distribution </misc/distributions>`. This is the quickest option for those - who have operating systems that distribute Django. - - * :ref:`Install an official release <installing-official-release>`. This - is the best approach for users who want a stable version number and aren't - concerned about running a slightly older version of Django. - - * :ref:`Install the latest development version - <installing-development-version>`. This is best for users who want the - latest-and-greatest features and aren't afraid of running brand-new code. - -.. admonition:: Always refer to the documentation that corresponds to the - version of Django you're using! - - If you 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, and - they likely won't work with an official release. - -That's it! ----------- - -That's it -- you can now :doc:`move onto the tutorial </intro/tutorial01>`. - - - diff --git a/parts/django/docs/intro/overview.txt b/parts/django/docs/intro/overview.txt deleted file mode 100644 index 34572a6..0000000 --- a/parts/django/docs/intro/overview.txt +++ /dev/null @@ -1,324 +0,0 @@ -================== -Django at a glance -================== - -Because Django was developed in a fast-paced newsroom environment, it was -designed to make common Web-development tasks fast and easy. Here's an informal -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 -- but we've got both! When you're ready to start a project, you can -:doc:`start with the tutorial </intro/tutorial01>` or :doc:`dive right into more -detailed documentation </topics/index>`. - -Design your model -================= - -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 :doc:`data-model syntax </topics/db/models>` offers many rich ways of -representing your models -- so far, it's been solving two years' worth of -database-schema problems. Here's a quick example, which might be saved in -the file ``mysite/news/models.py``:: - - class Reporter(models.Model): - full_name = models.CharField(max_length=70) - - def __unicode__(self): - return self.full_name - - class Article(models.Model): - pub_date = models.DateTimeField() - headline = models.CharField(max_length=200) - content = models.TextField() - reporter = models.ForeignKey(Reporter) - - def __unicode__(self): - return self.headline - -Install it -========== - -Next, run the Django command-line utility to create the database tables -automatically: - -.. code-block:: bash - - manage.py syncdb - -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, :doc:`Python API </topics/db/queries>` to -access your data. The API is created on the fly, no code generation necessary:: - - # Import the models we created from our "news" app - >>> from news.models import Reporter, Article - - # No reporters are in the system yet. - >>> Reporter.objects.all() - [] - - # Create a new Reporter. - >>> r = Reporter(full_name='John Smith') - - # Save the object into the database. You have to call save() explicitly. - >>> r.save() - - # Now it has an ID. - >>> r.id - 1 - - # Now the new reporter is in the database. - >>> Reporter.objects.all() - [<Reporter: John Smith>] - - # Fields are represented as attributes on the Python object. - >>> r.full_name - 'John Smith' - - # Django provides a rich database lookup API. - >>> Reporter.objects.get(id=1) - <Reporter: John Smith> - >>> Reporter.objects.get(full_name__startswith='John') - <Reporter: John Smith> - >>> Reporter.objects.get(full_name__contains='mith') - <Reporter: John Smith> - >>> Reporter.objects.get(id=2) - Traceback (most recent call last): - ... - DoesNotExist: Reporter matching query does not exist. - - # Create an article. - >>> from datetime import datetime - >>> a = Article(pub_date=datetime.now(), headline='Django is cool', - ... content='Yeah.', reporter=r) - >>> a.save() - - # Now the article is in the database. - >>> Article.objects.all() - [<Article: Django is cool>] - - # Article objects get API access to related Reporter objects. - >>> r = a.reporter - >>> r.full_name - 'John Smith' - - # And vice versa: Reporter objects get API access to Article objects. - >>> r.article_set.all() - [<Article: Django is cool>] - - # The API follows relationships as far as you need, performing efficient - # JOINs for you behind the scenes. - # This finds all articles by a reporter whose name starts with "John". - >>> Article.objects.filter(reporter__full_name__startswith="John") - [<Article: Django is cool>] - - # Change an object by altering its attributes and calling save(). - >>> r.full_name = 'Billy Goat' - >>> r.save() - - # Delete an object with delete(). - >>> r.delete() - -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 :doc:`administrative interface </ref/contrib/admin/index>` -- a Web -site that lets authenticated users add, change and delete objects. It's as easy -as registering your model in the admin site:: - - # In models.py... - - from django.db import models - - class Article(models.Model): - pub_date = models.DateTimeField() - headline = models.CharField(max_length=200) - content = models.TextField() - reporter = models.ForeignKey(Reporter) - - - # In admin.py in the same directory... - - import models - from django.contrib import admin - - admin.site.register(models.Article) - -The philosophy here is that your site is edited by a staff, or a client, or -maybe just you -- and you don't want to have to deal with creating backend -interfaces just to manage content. - -One typical workflow in creating Django apps is to create models and get the -admin sites up and running as fast as possible, so your staff (or clients) can -start populating data. Then, develop the way data is presented to the public. - -Design your URLs -================ - -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 :doc:`URLconf -</topics/http/urls>`. A table of contents for your app, it contains a simple mapping -between URL patterns and Python callback functions. URLconfs also serve to -decouple URLs from Python code. - -Here's what a URLconf might look like for the ``Reporter``/``Article`` -example above:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^articles/(\d{4})/$', 'news.views.year_archive'), - (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), - (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), - ) - -The code above maps URLs, as simple regular expressions, to the location of -Python callback functions ("views"). The regular expressions use parenthesis to -"capture" values from the URLs. When a user requests a page, Django runs -through each pattern, in order, and stops at the first one that matches the -requested URL. (If none of them matches, Django calls a special-case 404 view.) -This is blazingly fast, because the regular expressions are compiled at load -time. - -Once one of the regexes matches, Django imports and calls the given view, which -is a simple Python function. Each view gets passed a request object -- -which contains request metadata -- and the values captured in the regex. - -For example, if a user requested the URL "/articles/2005/05/39323/", Django -would call the function ``news.views.article_detail(request, -'2005', '05', '39323')``. - -Write your views -================ - -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 :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 -``year_archive`` from above:: - - def year_archive(request, year): - 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 :doc:`template system </topics/templates>`, which has -several powerful features but strives to stay simple enough for non-programmers -to use. - -Design your templates -===================== - -The code above loads the ``news/year_archive.html`` template. - -Django has a template search path, which allows you to minimize redundancy among -templates. In your Django settings, you specify a list of directories to check -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: - -.. code-block:: html+django - - {% extends "base.html" %} - - {% block title %}Articles for {{ year }}{% endblock %} - - {% block content %} - <h1>Articles for {{ year }}</h1> - - {% for article in article_list %} - <p>{{ article.headline }}</p> - <p>By {{ article.reporter.full_name }}</p> - <p>Published {{ article.pub_date|date:"F j, Y" }}</p> - {% endfor %} - {% endblock %} - -Variables are surrounded by double-curly braces. ``{{ article.headline }}`` -means "Output the value of the article's headline attribute." But dots aren't -used only for attribute lookup: They also can do dictionary-key lookup, index -lookup and function calls. - -Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|" -character). This is called a template filter, and it's a way to filter the value -of a variable. In this case, the date filter formats a Python datetime object in -the given format (as found in PHP's date function; yes, there is one good idea -in PHP). - -You can chain together as many filters as you'd like. You can write custom -filters. You can write custom template tags, which run custom Python code behind -the scenes. - -Finally, Django uses the concept of "template inheritance": That's what the -``{% extends "base.html" %}`` does. It means "First load the template called -'base', which has defined a bunch of blocks, and fill the blocks with 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: - -.. code-block:: html+django - - <html> - <head> - <title>{% block title %}{% endblock %}</title> - </head> - <body> - <img src="sitelogo.gif" alt="Logo" /> - {% block content %}{% endblock %} - </body> - </html> - -Simplistically, it defines the look-and-feel of the site (with the site's logo), -and provides "holes" for child templates to fill. This makes a site redesign as -easy as changing a single file -- the base template. - -It also lets you create multiple versions of a site, with different base -templates, while reusing child templates. Django's creators have used this -technique to create strikingly different cell-phone editions of sites -- simply -by creating a new base template. - -Note that you don't have to use Django's template system if you prefer another -system. While Django's template system is particularly well-integrated with -Django's model layer, nothing forces you to use it. For that matter, you don't -have to use Django's database API, either. You can use another database -abstraction layer, you can read XML files, you can read files off disk, or -anything you want. Each piece of Django -- models, views, templates -- is -decoupled from the next. - -This is just the surface -======================== - -This has been only a quick overview of Django's functionality. Some more useful -features: - - * A :doc:`caching framework </topics/cache>` that integrates with memcached - or other backends. - - * A :doc:`syndication framework </ref/contrib/syndication>` that makes - creating RSS and Atom feeds as easy as writing a small Python class. - - * More sexy automatically-generated admin features -- this overview barely - scratched the surface. - -The next obvious steps are for you to `download Django`_, read :doc:`the -tutorial </intro/tutorial01>` and join `the community`_. Thanks for your -interest! - -.. _download Django: http://www.djangoproject.com/download/ -.. _the community: http://www.djangoproject.com/community/ diff --git a/parts/django/docs/intro/tutorial01.txt b/parts/django/docs/intro/tutorial01.txt deleted file mode 100644 index 560070b..0000000 --- a/parts/django/docs/intro/tutorial01.txt +++ /dev/null @@ -1,690 +0,0 @@ -===================================== -Writing your first Django app, part 1 -===================================== - -Let's learn by example. - -Throughout this tutorial, we'll walk you through the creation of a basic -poll application. - -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 :doc:`Django installed </intro/install>` already. You can -tell Django is installed by running the Python interactive interpreter and -typing ``import django``. If that command runs successfully, with no errors, -Django is installed. - -.. admonition:: Where to get help: - - If you're having trouble going through this tutorial, please post a message - to `django-users`__ or drop by `#django on irc.freenode.net`__ to chat - with other Django users who might be able to help. - -__ 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 :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. - -.. admonition:: Script name may differ in distribution packages - - If you installed Django using a Linux distribution's package manager - (e.g. apt-get or yum) ``django-admin.py`` may have been renamed to - ``django-admin``. You may continue through this documentation by omitting - ``.py`` from each command. - -.. 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 :doc:`django-admin.py - </ref/django-admin>` is installed, then run the command - ``chmod +x django-admin.py``. - -.. note:: - - You'll need to avoid naming projects after built-in Python or Django - components. In particular, this means you should avoid using names like - ``django`` (which will conflict with Django itself) or ``test`` (which - conflicts with a built-in Python package). - -:doc:`django-admin.py </ref/django-admin>` should be on your system path if you -installed Django via ``python setup.py``. If it's not on your path, you can find -it in ``site-packages/django/bin``, where ```site-packages``` is a directory -within your Python installation. Consider symlinking to :doc:`django-admin.py -</ref/django-admin>` from some place on your path, such as -:file:`/usr/local/bin`. - -.. admonition:: Where should this code live? - - If your background is in PHP, you're probably used to putting code under the - Web server's document root (in a place such as ``/var/www``). With Django, - you don't do that. It's not a good idea to put any of this Python code - within your Web server's document root, because it risks the possibility - that people may be able to view your code over the Web. That's not good for - security. - - Put your code in some directory **outside** of the document root, such as - :file:`/home/mycode`. - -Let's look at what :djadmin:`startproject` created:: - - mysite/ - __init__.py - manage.py - settings.py - urls.py - -These files are: - - * :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.) - - * :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 :doc:`/ref/django-admin`. - - * :file:`settings.py`: Settings/configuration for this Django project. - :doc:`/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 - :doc:`/topics/http/urls`. - -.. _more about packages: http://docs.python.org/tutorial/modules.html#packages - -The development server ----------------------- - -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 1.0, using settings 'mysite.settings' - Development server is running at http://127.0.0.1:8000/ - Quit the server with CONTROL-C. - -You've started the Django development server, a lightweight Web server written -purely in Python. We've included this with Django so you can develop things -rapidly, without having to deal with configuring a production server -- such as -Apache -- until you're ready for production. - -Now's a good time to note: DON'T use this server in anything resembling a -production environment. It's intended only for use while developing. (We're in -the business of making Web frameworks, not Web servers.) - -Now that the server's running, visit http://127.0.0.1:8000/ with your Web -browser. You'll see a "Welcome to Django" page, in pleasant, light-blue pastel. -It worked! - -.. admonition:: Changing the port - - By default, the :djadmin:`runserver` command starts the development server - on the internal IP at 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 - - If you want to change the server's IP, pass it along with the port. So to - listen on all public IPs (useful if you want to show off your work on other - computers), use: - - .. code-block:: bash - - python manage.py runserver 0.0.0.0:8000 - - Full docs for the development server can be found in the - :djadmin:`runserver` reference. - -Database setup --------------- - -Now, edit :file:`settings.py`. It's a normal Python module with -module-level variables representing Django settings. Change the -following keys in the :setting:`DATABASES` ``'default'`` item to match -your databases connection settings. - - * :setting:`ENGINE` -- Either - ``'django.db.backends.postgresql_psycopg2'``, - ``'django.db.backends.mysql'`` or - ``'django.db.backends.sqlite3'``. Other backends are - :setting:`also available <ENGINE>`. - - * :setting:`NAME` -- The name of your database. If you're using - SQLite, the database will be a file on your computer; in that - case, :setting:`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). - - When specifying the path, always use forward slashes, even on - Windows (e.g. ``C:/homes/user/mysite/sqlite3.db``). - - * :setting:`USER` -- Your database username (not used for SQLite). - - * :setting:`PASSWORD` -- Your database password (not used for - SQLite). - - * :setting:`HOST` -- The host your database is on. Leave this as - an empty string if your database server is on the same physical - machine (not used for SQLite). - -If you're new to databases, we recommend simply using SQLite (by -setting :setting:`ENGINE` to ``'django.db.backends.sqlite3'``). SQLite -is included as part of Python 2.5 and later, so you won't need to -install anything else. - -.. note:: - - If you're using PostgreSQL or MySQL, make sure you've created a database by - this point. Do that with "``CREATE DATABASE database_name;``" within your - database's interactive prompt. - - 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 :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, :setting:`INSTALLED_APPS` contains the following apps, all of which -come with Django: - - * :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. - - * :mod:`django.contrib.messages` -- A messaging framework. - -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: - -.. code-block:: bash - - python manage.py syncdb - -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 -display the tables Django created. - -.. admonition:: For the minimalists - - 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 - :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 -=============== - -Now that your environment -- a "project" -- is set up, you're set to start -doing work. - -Each application you write in Django consists of a Python package, somewhere -on your `Python path`_, that follows a certain convention. Django comes with a -utility that automatically generates the basic directory structure of an app, -so you can focus on writing code rather than creating directories. - -.. admonition:: Projects vs. apps - - What's the difference between a project and an app? An app is a Web - application that does something -- e.g., a Weblog system, a database of - public records or a simple poll app. A project is a collection of - configuration and apps for a particular Web site. A project can contain - multiple apps. An app can be in multiple projects. - -Your apps can live anywhere on your `Python path`_. In this tutorial, we'll -create our poll app in the :file:`mysite` directory for simplicity. - -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 :file:`polls`, which is laid out like this:: - - polls/ - __init__.py - models.py - tests.py - views.py - -This directory structure will house the poll application. - -The first step in writing a database Web app in Django is to define your models --- essentially, your database layout, with additional metadata. - -.. 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 :ref:`DRY Principle <dry>`. The goal is to define your data model in one - place and automatically derive things from it. - -In our simple poll app, we'll create two models: polls and choices. A poll has -a question and a publication date. A choice has two fields: the text of the -choice and a vote tally. Each choice is associated with a poll. - -These concepts are represented by simple Python classes. Edit the -:file:`polls/models.py` file so it looks like this:: - - from django.db import models - - class Poll(models.Model): - question = models.CharField(max_length=200) - pub_date = models.DateTimeField('date published') - - class Choice(models.Model): - poll = models.ForeignKey(Poll) - choice = models.CharField(max_length=200) - votes = models.IntegerField() - -The code is straightforward. Each model is represented by a class that -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 :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 :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 -: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 :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 -: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/tutorial/modules.html#the-module-search-path - -Activating models -================= - -That small bit of model code gives Django a lot of information. With it, Django -is able to: - - * Create a database schema (``CREATE TABLE`` statements) for this app. - * Create a Python database-access API for accessing Poll and Choice objects. - -But first we need to tell our project that the ``polls`` app is installed. - -.. admonition:: Philosophy - - Django apps are "pluggable": You can use an app in multiple projects, and - you can distribute apps, because they don't have to be tied to a given - Django installation. - -Edit the :file:`settings.py` file again, and change the -:setting:`INSTALLED_APPS` setting to include the string ``'polls'``. So -it'll look like this:: - - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'polls' - ) - -Now Django knows to include 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): - -.. code-block:: sql - - BEGIN; - CREATE TABLE "polls_poll" ( - "id" serial NOT NULL PRIMARY KEY, - "question" varchar(200) NOT NULL, - "pub_date" timestamp with time zone NOT NULL - ); - CREATE TABLE "polls_choice" ( - "id" serial NOT NULL PRIMARY KEY, - "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"), - "choice" varchar(200) NOT NULL, - "votes" integer NOT NULL - ); - COMMIT; - -Note the following: - - * The exact output will vary depending on the database you are using. - - * Table names are automatically generated by combining the name of the app - (``polls``) and the lowercase name of the model -- ``poll`` and - ``choice``. (You can override this behavior.) - - * Primary keys (IDs) are added automatically. (You can override this, too.) - - * 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. - - * It's tailored to the database you're using, so database-specific field - types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or - ``integer primary key`` (SQLite) are handled for you automatically. Same - goes for quoting of field names -- e.g., using double quotes or single - quotes. The author of this tutorial runs PostgreSQL, so the example - output is in PostgreSQL syntax. - - * 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: - - * :djadmin:`python manage.py validate <validate>` -- Checks for any errors - in the construction of your models. - - * :djadmin:`python manage.py sqlcustom polls <sqlcustom>` -- Outputs any - :ref:`custom SQL statements <initial-sql>` (such as table modifications or - constraints) that are defined for the application. - - * :djadmin:`python manage.py sqlclear polls <sqlclear>` -- Outputs the - necessary ``DROP TABLE`` statements for this app, according to which - tables already exist in your database (if any). - - * :djadmin:`python manage.py sqlindexes polls <sqlindexes>` -- Outputs the - ``CREATE INDEX`` statements for this app. - - * :djadmin:`python manage.py sqlall polls <sqlall>` -- A combination of all - the SQL from the :djadmin:`sql`, :djadmin:`sqlcustom`, and - :djadmin:`sqlindexes` commands. - -Looking at the output of those commands can help you understand what's actually -happening under the hood. - -Now, run :djadmin:`syncdb` again to create those model tables in your database: - -.. code-block:: bash - - python manage.py syncdb - -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 :doc:`django-admin.py documentation </ref/django-admin>` for full -information on what the ``manage.py`` utility can do. - -Playing with the API -==================== - -Now, let's hop into the interactive Python shell and play around with the free -API Django gives you. To invoke the Python shell, use this command: - -.. code-block:: bash - - python manage.py shell - -We're using this instead of simply typing "python", because ``manage.py`` sets -up the project's environment for you. "Setting up the environment" involves two -things: - - * Putting ``polls`` on ``sys.path``. For flexibility, several pieces of - Django refer to projects in Python dotted-path notation (e.g. - ``'polls.models'``). In order for this to work, the ``polls`` - package has to be on ``sys.path``. - - 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`` - and ``polls`` are at the root level on the Python path (i.e., ``import mysite`` - and ``import polls`` work) and set the ``DJANGO_SETTINGS_MODULE`` environment - variable to ``mysite.settings``. - - For more information on all of this, see the :doc:`django-admin.py - documentation </ref/django-admin>`. - -Once you're in the shell, explore the :doc:`database API </topics/db/queries>`:: - - >>> from polls.models import Poll, Choice # Import the model classes we just wrote. - - # No polls are in the system yet. - >>> Poll.objects.all() - [] - - # Create a new Poll. - >>> import datetime - >>> p = Poll(question="What's up?", pub_date=datetime.datetime.now()) - - # Save the object into the database. You have to call save() explicitly. - >>> p.save() - - # Now it has an ID. Note that this might say "1L" instead of "1", depending - # on which database you're using. That's no biggie; it just means your - # database backend prefers to return integers as Python long integer - # objects. - >>> p.id - 1 - - # Access database columns via Python attributes. - >>> p.question - "What's up?" - >>> p.pub_date - datetime.datetime(2007, 7, 15, 12, 00, 53) - - # Change values by changing the attributes, then calling save(). - >>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0) - >>> p.save() - - # objects.all() displays all the polls in the database. - >>> Poll.objects.all() - [<Poll: Poll object>] - - -Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful representation -of this object. Let's fix that by editing the polls model (in the -``polls/models.py`` file) and adding a -:meth:`~django.db.models.Model.__unicode__` method to both ``Poll`` and -``Choice``:: - - class Poll(models.Model): - # ... - def __unicode__(self): - return self.question - - class Choice(models.Model): - # ... - def __unicode__(self): - return self.choice - -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 :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 - :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 :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 - :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:: - - import datetime - # ... - class Poll(models.Model): - # ... - def was_published_today(self): - return self.pub_date.date() == datetime.date.today() - -Note the addition of ``import datetime`` to reference Python's standard -``datetime`` module. - -Save these changes and start a new Python interactive shell by running -``python manage.py shell`` again:: - - >>> from polls.models import Poll, Choice - - # Make sure our __unicode__() addition worked. - >>> Poll.objects.all() - [<Poll: What's up?>] - - # Django provides a rich database lookup API that's entirely driven by - # keyword arguments. - >>> Poll.objects.filter(id=1) - [<Poll: What's up?>] - >>> Poll.objects.filter(question__startswith='What') - [<Poll: What's up?>] - - # Get the poll whose year is 2007. - >>> Poll.objects.get(pub_date__year=2007) - <Poll: What's up?> - - >>> Poll.objects.get(id=2) - Traceback (most recent call last): - ... - DoesNotExist: Poll matching query does not exist. - - # Lookup by a primary key is the most common case, so Django provides a - # shortcut for primary-key exact lookups. - # The following is identical to Poll.objects.get(id=1). - >>> Poll.objects.get(pk=1) - <Poll: What's up?> - - # Make sure our custom method worked. - >>> p = Poll.objects.get(pk=1) - >>> p.was_published_today() - False - - # Give the Poll a couple of Choices. The create call constructs a new - # choice object, does the INSERT statement, adds the choice to the set - # of available choices and returns the new Choice object. Django creates - # a set to hold the "other side" of a ForeignKey relation - # (e.g. a poll's choices) which can be accessed via the API. - >>> p = Poll.objects.get(pk=1) - - # Display any choices from the related object set -- none so far. - >>> p.choice_set.all() - [] - - # Create three choices. - >>> p.choice_set.create(choice='Not much', votes=0) - <Choice: Not much> - >>> p.choice_set.create(choice='The sky', votes=0) - <Choice: The sky> - >>> c = p.choice_set.create(choice='Just hacking again', votes=0) - - # Choice objects have API access to their related Poll objects. - >>> c.poll - <Poll: What's up?> - - # And vice versa: Poll objects get access to Choice objects. - >>> p.choice_set.all() - [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] - >>> p.choice_set.count() - 3 - - # The API automatically follows relationships as far as you need. - # Use double underscores to separate relationships. - # This works as many levels deep as you want; there's no limit. - # Find all Choices for any poll whose pub_date is in 2007. - >>> Choice.objects.filter(poll__pub_date__year=2007) - [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] - - # Let's delete one of the choices. Use delete() for that. - >>> c = p.choice_set.filter(choice__startswith='Just hacking') - >>> c.delete() - -For more information on model relations, see :doc:`Accessing related objects -</ref/models/relations>`. For full details on the database API, see our -:doc:`Database API reference </topics/db/queries>`. - -When you're comfortable with the API, read :doc:`part 2 of this tutorial -</intro/tutorial02>` to get Django's automatic admin working. diff --git a/parts/django/docs/intro/tutorial02.txt b/parts/django/docs/intro/tutorial02.txt deleted file mode 100644 index c80d87d..0000000 --- a/parts/django/docs/intro/tutorial02.txt +++ /dev/null @@ -1,465 +0,0 @@ -===================================== -Writing your first Django app, part 2 -===================================== - -This tutorial begins where :doc:`Tutorial 1 </intro/tutorial01>` left off. We're -continuing the Web-poll application and will focus on Django's -automatically-generated admin site. - -.. admonition:: Philosophy - - Generating admin sites for your staff or clients to add, change and delete - content is tedious work that doesn't require much creativity. For that - reason, Django entirely automates creation of admin interfaces for models. - - 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. - -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 :setting:`INSTALLED_APPS` setting. - - * Run ``python manage.py syncdb``. Since you have added a new application - to :setting:`INSTALLED_APPS`, the database tables need to be updated. - - * Edit your ``mysite/urls.py`` file and uncomment the lines that reference - the admin -- there are three lines in total to uncomment. This file is a - URLconf; we'll dig into URLconfs in the next tutorial. For now, all you - need to know is that it maps URL roots to applications. In the end, you - should have a ``urls.py`` file that looks like this: - - .. versionchanged:: 1.1 - The method for adding admin urls has changed in Django 1.1. - - .. parsed-literal:: - - from django.conf.urls.defaults import * - - # Uncomment the next two lines to enable the admin: - **from django.contrib import admin** - **admin.autodiscover()** - - urlpatterns = patterns('', - # Example: - # (r'^mysite/', include('mysite.foo.urls')), - - # Uncomment the admin/doc line below and add 'django.contrib.admindocs' - # to INSTALLED_APPS to enable admin documentation: - # (r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: - **(r'^admin/', include(admin.site.urls)),** - ) - - (The bold lines are the ones that needed to be uncommented.) - -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: - -.. 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:: _images/admin01.png - :alt: Django admin login screen - -Enter the admin site -==================== - -Now, try logging in. (You created a superuser account in the first part of this -tutorial, remember? If you didn't create one or forgot the password you can -:ref:`create another one <topics-auth-creating-superusers>`.) You should see -the Django admin index page: - -.. image:: _images/admin02t.png - :alt: Django admin index page - -You should see a few other types of editable content, including groups, users -and sites. These are core features Django ships with by default. - -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. To do this, create a file called -``admin.py`` in your ``polls`` directory, and edit it to look like this:: - - from polls.models import Poll - from django.contrib import admin - - admin.site.register(Poll) - -You'll need to restart the development server to see your changes. Normally, -the server auto-reloads code every time you modify a file, but the action of -creating a new file doesn't trigger the auto-reloading logic. - -Explore the free admin functionality -==================================== - -Now that we've registered ``Poll``, Django knows that it should be displayed on -the admin index page: - -.. image:: _images/admin03t.png - :alt: Django admin index page, now with polls displayed - -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:: _images/admin04t.png - :alt: Polls change list page - -Click the "What's up?" poll to edit it: - -.. image:: _images/admin05t.png - :alt: Editing form for poll object - -Things to note here: - - * 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. - -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:: _images/admin06t.png - :alt: History page for poll object - -Customize the admin form -======================== - -Take a few minutes to marvel at all the code you didn't have to write. By -registering the Poll model with ``admin.site.register(Poll)``, Django was able -to construct a default form representation. Often, you'll want to customize how -the admin form looks and works. You'll do this by telling Django the options -you want when you register the object. - -Let's see how this works by re-ordering the fields on the edit form. Replace -the ``admin.site.register(Poll)`` line with:: - - class PollAdmin(admin.ModelAdmin): - fields = ['pub_date', 'question'] - - admin.site.register(Poll, PollAdmin) - -You'll follow this pattern -- create a model admin object, then pass it as the -second argument to ``admin.site.register()`` -- any time you need to change the -admin options for an object. - -This particular change above makes the "Publication date" come before the -"Question" field: - -.. image:: _images/admin07.png - :alt: Fields have been reordered - -This isn't impressive with only two fields, but for admin forms with dozens -of fields, choosing an intuitive order is an important usability detail. - -And speaking of forms with dozens of fields, you might want to split the form -up into fieldsets:: - - class PollAdmin(admin.ModelAdmin): - fieldsets = [ - (None, {'fields': ['question']}), - ('Date information', {'fields': ['pub_date']}), - ] - - admin.site.register(Poll, PollAdmin) - -The first element of each tuple in ``fieldsets`` is the title of the fieldset. -Here's what our form looks like now: - -.. image:: _images/admin08t.png - :alt: Form has fieldsets now - -You can assign arbitrary HTML classes to each fieldset. Django provides a -``"collapse"`` class that displays a particular fieldset initially collapsed. -This is useful when you have a long form that contains a number of fields that -aren't commonly used:: - - class PollAdmin(admin.ModelAdmin): - fieldsets = [ - (None, {'fields': ['question']}), - ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), - ] - -.. image:: _images/admin09.png - :alt: Fieldset is initially collapsed - -Adding related objects -====================== - -OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and -the admin page doesn't display choices. - -Yet. - -There are two ways to solve this problem. The first is to register ``Choice`` -with the admin just as we did with ``Poll``. That's easy:: - - from 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:: _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 :class:`~django.db.models.ForeignKey` should be -represented in the admin as a ``<select>`` box. In our case, only one poll -exists at this point. - -Also note the "Add Another" link next to "Poll." Every object with a -``ForeignKey`` relationship to another gets this for free. When you click "Add -Another," you'll get a popup window with the "Add poll" form. If you add a poll -in that window and click "Save," Django will save the poll to the database and -dynamically add it as the selected choice on the "Add choice" form you're -looking at. - -But, really, this is an inefficient way of adding Choice objects to the system. -It'd be better if you could add a bunch of Choices directly when you create the -Poll object. Let's make that happen. - -Remove the ``register()`` call for the Choice model. Then, edit the ``Poll`` -registration code to read:: - - class ChoiceInline(admin.StackedInline): - model = Choice - extra = 3 - - class PollAdmin(admin.ModelAdmin): - fieldsets = [ - (None, {'fields': ['question']}), - ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), - ] - inlines = [ChoiceInline] - - admin.site.register(Poll, PollAdmin) - -This tells Django: "Choice objects are edited on the Poll admin page. By -default, provide enough fields for 3 choices." - -Load the "Add poll" page to see how that looks, you may need to restart your development server: - -.. image:: _images/admin11t.png - :alt: Add poll page now has choices on it - -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 a -tabular way of displaying inline related objects; you just need to change -the ``ChoiceInline`` declaration to read:: - - class ChoiceInline(admin.TabularInline): - #... - -With that ``TabularInline`` (instead of ``StackedInline``), the -related objects are displayed in a more compact, table-based format: - -.. image:: _images/admin12.png - :alt: Add poll page now has more compact choices - -Customize the admin change list -=============================== - -Now that the Poll admin page is looking good, let's make some tweaks to the -"change list" page -- the one that displays all the polls in the system. - -Here's what it looks like at this point: - -.. image:: _images/admin04t.png - :alt: Polls change list page - -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 -``list_display`` admin option, which is a tuple of field names to display, as -columns, on the change list page for the object:: - - class PollAdmin(admin.ModelAdmin): - # ... - list_display = ('question', 'pub_date') - -Just for good measure, let's also include the ``was_published_today`` custom -method from Tutorial 1:: - - class PollAdmin(admin.ModelAdmin): - # ... - list_display = ('question', 'pub_date', 'was_published_today') - -Now the poll change list page looks like this: - -.. image:: _images/admin13t.png - :alt: Polls change list page, updated - -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 -an arbitrary method is not supported. Also note that the column header for -``was_published_today`` is, by default, the name of the method (with -underscores replaced with spaces). But you can change that by giving that -method (in ``models.py``) a ``short_description`` attribute:: - - def was_published_today(self): - return self.pub_date.date() == datetime.date.today() - was_published_today.short_description = 'Published today?' - -Edit your admin.py file again and add an improvement to the Poll change list page: Filters. Add the -following line to ``PollAdmin``:: - - list_filter = ['pub_date'] - -That adds a "Filter" sidebar that lets people filter the change list by the -``pub_date`` field: - -.. image:: _images/admin14t.png - :alt: Polls change list page, updated - -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 -filter options for DateTimeFields: "Any date," "Today," "Past 7 days," -"This month," "This year." - -This is shaping up well. Let's add some search capability:: - - search_fields = ['question'] - -That adds a search box at the top of the change list. When somebody enters -search terms, Django will search the ``question`` field. You can use as many -fields as you'd like -- although because it uses a ``LIKE`` query behind the -scenes, keep it reasonable, to keep your database happy. - -Finally, because Poll objects have dates, it'd be convenient to be able to -drill down by date. Add this line:: - - date_hierarchy = 'pub_date' - -That adds hierarchical navigation, by date, to the top of the change list page. -At top level, it displays all available years. Then it drills down to months -and, ultimately, days. - -Now's also a good time to note that change lists give you free pagination. The -default is to display 50 items per page. Change-list pagination, search boxes, -filters, date-hierarchies and column-header-ordering all work together like you -think they should. - -Customize the admin look and feel -================================= - -Clearly, having "Django administration" at the top of each admin page is -ridiculous. It's just placeholder text. - -That's easy to change, though, using Django's template system. The Django admin -is powered by Django itself, and its interfaces use Django's own template -system. - -Open your settings file (``mysite/settings.py``, remember) and look at the -: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, :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. - ) - -Now copy the template ``admin/base_site.html`` from within the default Django -admin template directory in the source code of Django itself -(``django/contrib/admin/templates``) into an ``admin`` 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. - -Then, just edit the file and replace the generic Django text with your own -site's name as you see fit. - -This template file contains lots of text like ``{% block branding %}`` -and ``{{ title }}``. The ``{%`` and ``{{`` tags are part of Django's -template language. When Django renders ``admin/base_site.html``, this -template language will be evaluated to produce the final HTML page. -Don't worry if you can't make any sense of the template right now -- -we'll delve into Django's templating language in Tutorial 3. - -Note that any of Django's default admin templates can be overridden. To -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 :setting:`TEMPLATE_DIRS` was empty by default, -how was Django finding the default admin templates? The answer is that, by -default, Django automatically looks for a ``templates/`` subdirectory within -each app package, for use as a fallback. See the :ref:`template loader -documentation <template-loaders>` for full information. - -Customize the admin index page -============================== - -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 :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 -directory to your custom template directory.) Edit the file, and you'll see it -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. Again, -don't worry if you can't understand the template language -- we'll cover that -in more detail in Tutorial 3. - -When you're comfortable with the admin site, read :doc:`part 3 of this tutorial -</intro/tutorial03>` to start working on public poll views. diff --git a/parts/django/docs/intro/tutorial03.txt b/parts/django/docs/intro/tutorial03.txt deleted file mode 100644 index 0843d9e..0000000 --- a/parts/django/docs/intro/tutorial03.txt +++ /dev/null @@ -1,546 +0,0 @@ -===================================== -Writing your first Django app, part 3 -===================================== - -This tutorial begins where :doc:`Tutorial 2 </intro/tutorial02>` left off. We're -continuing the Web-poll application and will focus on creating the public -interface -- "views." - -Philosophy -========== - -A view is a "type" of Web page in your Django application that generally serves -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. - -In Django, each view is represented by a simple Python function. - -Design your URLs -================ - -The first step of writing views is to design your URL structure. You do this by -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 -: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]) - -Django starts at the first regular expression and makes its way down the list, -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 -: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 :class:`~django.http.HttpRequest` objects, see the -:doc:`/ref/request-response`. For more details on URLconfs, see the -:doc:`/topics/http/urls`. - -When you ran ``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 :setting:`ROOT_URLCONF` setting (in ``settings.py``) to -point at that file:: - - ROOT_URLCONF = 'mysite.urls' - -Time for an example. Edit ``mysite/urls.py`` so it looks like this:: - - from django.conf.urls.defaults import * - - from django.contrib import admin - admin.autodiscover() - - urlpatterns = patterns('', - (r'^polls/$', 'polls.views.index'), - (r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'), - (r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'), - (r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'), - (r'^admin/', include(admin.site.urls)), - ) - -This is worth a review. When somebody requests a page from your Web site -- say, -"/polls/23/", Django will load this Python module, because it's pointed to by -the :setting:`ROOT_URLCONF` setting. It finds the variable named ``urlpatterns`` -and traverses the regular expressions in order. When it finds a regular -expression that matches -- ``r'^polls/(?P<poll_id>\d+)/$'`` -- it loads the -function ``detail()`` from ``polls/views.py``. Finally, it calls that -``detail()`` function like so:: - - detail(request=<HttpRequest object>, poll_id='23') - -The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parentheses -around a pattern "captures" the text matched by that pattern and sends it as an -argument to the view function; the ``?P<poll_id>`` defines the name that will be -used to identify the matched pattern; and ``\d+`` is a regular expression to -match a sequence of digits (i.e., a number). - -Because the URL patterns are regular expressions, there really is no limit on -what you can do with them. And there's no need to add URL cruft such as ``.php`` --- unless you have a sick sense of humor, in which case you can do something -like this:: - - (r'^polls/latest\.php$', 'polls.views.index'), - -But, don't do that. It's silly. - -Note that these regular expressions do not search GET and POST parameters, or -the domain name. For example, in a request to ``http://www.example.com/myapp/``, -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. - -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://docs.python.org/library/re.html - -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: - -.. code-block:: bash - - python manage.py runserver - -Now go to "http://localhost:8000/polls/" on your domain in your Web browser. -You should get a pleasantly-colored error page with the following message:: - - ViewDoesNotExist at /polls/ - - Tried index in module polls.views. Error was: 'module' - object has no attribute 'index' - -This error happened because you haven't written a function ``index()`` in the -module ``polls/views.py``. - -Try "/polls/23/", "/polls/23/results/" and "/polls/23/vote/". The error -messages tell you which view Django tried (and failed to find, because you -haven't written any views yet). - -Time to write the first view. Open the file ``polls/views.py`` -and put the following Python code in it:: - - from django.http import HttpResponse - - def index(request): - return HttpResponse("Hello, world. You're at the poll index.") - -This is the simplest view possible. Go to "/polls/" in your browser, and you -should see your text. - -Now lets add a few more views. These views are slightly different, because -they take an argument (which, remember, is passed in from whatever was -captured by the regular expression in the URLconf):: - - def detail(request, poll_id): - return HttpResponse("You're looking at poll %s." % poll_id) - - def results(request, poll_id): - return HttpResponse("You're looking at the results of poll %s." % poll_id) - - def vote(request, poll_id): - return HttpResponse("You're voting on poll %s." % poll_id) - -Take a look in your browser, at "/polls/34/". It'll run the `detail()` method -and display whatever ID you provide in the URL. Try "/polls/34/results/" and -"/polls/34/vote/" too -- these will display the placeholder results and voting -pages. - -Write views that actually do something -====================================== - -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 :class:`~django.http.HttpResponse`. Or an exception. - -Because it's convenient, let's use Django's own database API, which we covered -in :doc:`Tutorial 1 </intro/tutorial01>`. Here's one stab at the ``index()`` -view, which displays the latest 5 poll questions in the system, separated by -commas, according to publication date:: - - from polls.models import Poll - from django.http import HttpResponse - - def index(request): - latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5] - output = ', '.join([p.question for p in latest_poll_list]) - return HttpResponse(output) - -There's a problem here, though: The page's design is hard-coded in the view. If -you want to change the way the page looks, you'll have to edit this Python code. -So let's use Django's template system to separate the design from Python:: - - from django.template import Context, loader - from polls.models import Poll - from django.http import HttpResponse - - def index(request): - latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5] - t = loader.get_template('polls/index.html') - c = Context({ - 'latest_poll_list': latest_poll_list, - }) - 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. - -Reload the page. Now you'll see an error:: - - TemplateDoesNotExist at /polls/ - 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 :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: - -.. code-block:: html+django - - {% if latest_poll_list %} - <ul> - {% for poll in latest_poll_list %} - <li><a href="/polls/{{ poll.id }}/">{{ poll.question }}</a></li> - {% endfor %} - </ul> - {% else %} - <p>No polls are available.</p> - {% endif %} - -Load the page in your Web browser, and you should see a bulleted-list -containing the "What's up" poll from Tutorial 1. The link points to the poll's -detail page. - -A shortcut: render_to_response() --------------------------------- - -It's a very common idiom to load a template, fill a context and return an -: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 polls.models import Poll - - def index(request): - 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 -:mod:`~django.template.loader`, :class:`~django.template.Context` and -:class:`~django.http.HttpResponse`. - -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 -=========== - -Now, let's tackle the poll detail view -- the page that displays the question -for a given poll. Here's the view:: - - from django.http import Http404 - # ... - def detail(request, poll_id): - try: - p = Poll.objects.get(pk=poll_id) - except Poll.DoesNotExist: - raise Http404 - return render_to_response('polls/detail.html', {'poll': p}) - -The new concept here: The view raises the :exc:`~django.http.Http404` exception -if a poll with the requested ID doesn't exist. - -We'll discuss what you could put in that ``polls/detail.html`` template a bit -later, but if you'd like to quickly get the above example working, just:: - - {{ poll }} - -will get you started for now. - -A shortcut: get_object_or_404() -------------------------------- - -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 - # ... - def detail(request, poll_id): - p = get_object_or_404(Poll, pk=poll_id) - return render_to_response('polls/detail.html', {'poll': p}) - -The :func:`~django.shortcuts.get_object_or_404` function takes a Django model -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 :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 :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 :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:: - - from django.conf.urls.defaults import * - -That takes care of setting ``handler404`` in the current module. As you can see -in ``django/conf/urls/defaults.py``, ``handler404`` is set to -:func:`django.views.defaults.page_not_found` by default. - -Four more things to note about 404 views: - - * If :setting:`DEBUG` is set to ``True`` (in your settings module) then your - 404 view will never be used (and thus the ``404.html`` template will never - be rendered) because the traceback will be displayed instead. - - * 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 :setting:`DEBUG` is set to ``False`` (in your settings module) and if - you didn't create a ``404.html`` file, an ``Http500`` is raised instead. - So remember to create a ``404.html``. - -Write a 500 (server error) view -=============================== - -Similarly, URLconfs may define a ``handler500``, which points to a view to call -in case of server errors. Server errors happen when you have runtime errors in -view code. - -Use the template system -======================= - -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: - -.. code-block:: html+django - - <h1>{{ poll.question }}</h1> - <ul> - {% for choice in poll.choice_set.all %} - <li>{{ choice.choice }}</li> - {% endfor %} - </ul> - -The template system uses dot-lookup syntax to access variable attributes. In -the example of ``{{ poll.question }}``, first Django does a dictionary lookup -on the object ``poll``. Failing that, it tries attribute lookup -- which works, -in this case. If attribute lookup had failed, it would've tried calling the -method ``question()`` on the poll object. - -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 :doc:`template guide </topics/templates>` for more about templates. - -Simplifying the URLconfs -======================== - -Take some time to play around with the views and template system. As you edit -the URLconf, you may notice there's a fair bit of redundancy in it:: - - urlpatterns = patterns('', - (r'^polls/$', 'polls.views.index'), - (r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'), - (r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'), - (r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'), - ) - -Namely, ``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 :func:`~django.conf.urls.defaults.patterns`, like so:: - - urlpatterns = patterns('polls.views', - (r'^polls/$', 'index'), - (r'^polls/(?P<poll_id>\d+)/$', 'detail'), - (r'^polls/(?P<poll_id>\d+)/results/$', 'results'), - (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'), - ) - -This is functionally identical to the previous formatting. It's just a bit -tidier. - -Since you generally don't want the prefix for one app to be applied to every -callback in your URLconf, you can concatenate multiple -:func:`~django.conf.urls.defaults.patterns`. Your full ``mysite/urls.py`` might -now look like this:: - - from django.conf.urls.defaults import * - - from django.contrib import admin - admin.autodiscover() - - urlpatterns = patterns('polls.views', - (r'^polls/$', 'index'), - (r'^polls/(?P<poll_id>\d+)/$', 'detail'), - (r'^polls/(?P<poll_id>\d+)/results/$', 'results'), - (r'^polls/(?P<poll_id>\d+)/vote/$', 'vote'), - ) - - urlpatterns += patterns('', - (r'^admin/', include(admin.site.urls)), - ) - -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 transferable to another Django installation -with minimal fuss. - -Our poll app is pretty decoupled at this point, thanks to the strict directory -structure that ``python manage.py startapp`` created, but one part of it is -coupled to the Django settings: The URLconf. - -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 ``polls/urls.py``. Then, change -``mysite/urls.py`` to remove the poll-specific URLs and insert an -:func:`~django.conf.urls.defaults.include`, leaving you with:: - - # This also imports the include function - from django.conf.urls.defaults import * - - from django.contrib import admin - admin.autodiscover() - - urlpatterns = patterns('', - (r'^polls/', include('polls.urls')), - (r'^admin/', include(admin.site.urls)), - ) - -: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/'`` - - * Then, Django will strip off the matching text (``"polls/"``) and send the - remaining text -- ``"34/"`` -- to the 'polls.urls' URLconf for - further processing. - -Now that we've decoupled that, we need to decouple the ``polls.urls`` -URLconf by removing the leading "polls/" from each line, and removing the -lines registering the admin site. Your ``polls.urls`` file should now look like -this:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('polls.views', - (r'^$', 'index'), - (r'^(?P<poll_id>\d+)/$', 'detail'), - (r'^(?P<poll_id>\d+)/results/$', 'results'), - (r'^(?P<poll_id>\d+)/vote/$', 'vote'), - ) - -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 path root, and the app will still work. - -All the poll app cares about is its relative path, not its absolute path. - -When you're comfortable with writing views, read :doc:`part 4 of this tutorial -</intro/tutorial04>` to learn about simple form processing and generic views. diff --git a/parts/django/docs/intro/tutorial04.txt b/parts/django/docs/intro/tutorial04.txt deleted file mode 100644 index dfbd82d..0000000 --- a/parts/django/docs/intro/tutorial04.txt +++ /dev/null @@ -1,346 +0,0 @@ -===================================== -Writing your first Django app, part 4 -===================================== - -This tutorial begins where :doc:`Tutorial 3 </intro/tutorial03>` left off. We're -continuing the Web-poll application and will focus on simple form processing and -cutting down our code. - -Write a simple form -=================== - -Let's update our poll detail template ("polls/detail.html") from the last -tutorial, so that the template contains an HTML ``<form>`` element: - -.. code-block:: html+django - - <h1>{{ poll.question }}</h1> - - {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} - - <form action="/polls/{{ poll.id }}/vote/" method="post"> - {% csrf_token %} - {% for choice in poll.choice_set.all %} - <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /> - <label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br /> - {% endfor %} - <input type="submit" value="Vote" /> - </form> - -A quick rundown: - - * The above template displays a radio button for each poll choice. The - ``value`` of each radio button is the associated poll choice's ID. The - ``name`` of each radio button is ``"choice"``. That means, when somebody - selects one of the radio buttons and submits the form, it'll send the - POST data ``choice=3``. This is HTML Forms 101. - - * We set the form's ``action`` to ``/polls/{{ poll.id }}/vote/``, and we - set ``method="post"``. Using ``method="post"`` (as opposed to - ``method="get"``) is very important, because the act of submitting this - form will alter data server-side. Whenever you create a form that alters - 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 :ttag:`for` tag has gone - through its loop - - * Since we're creating a POST form (which can have the effect of modifying - data), we need to worry about Cross Site Request Forgeries. - Thankfully, you don't have to worry too hard, because Django comes with - a very easy-to-use system for protecting against it. In short, all POST - forms that are targeted at internal URLs should use the ``{% csrf_token %}`` - template tag. - -The ``{% csrf_token %}`` tag requires information from the request object, which -is not normally accessible from within the template context. To fix this, a -small adjustment needs to be made to the ``detail`` view, so that it looks like -the following:: - - from django.template import RequestContext - # ... - def detail(request, poll_id): - p = get_object_or_404(Poll, pk=poll_id) - return render_to_response('polls/detail.html', {'poll': p}, - context_instance=RequestContext(request)) - -The details of how this works are explained in the documentation for -:ref:`RequestContext <subclassing-context-requestcontext>`. - -Now, let's create a Django view that handles the submitted data and does -something with it. Remember, in :doc:`Tutorial 3 </intro/tutorial03>`, we -created a URLconf for the polls application that includes this line:: - - (r'^(?P<poll_id>\d+)/vote/$', 'vote'), - -We also created a dummy implementation of the ``vote()`` function. Let's -create a real version. Add the following to ``polls/views.py``:: - - from django.shortcuts import get_object_or_404, render_to_response - from django.http import HttpResponseRedirect, HttpResponse - from django.core.urlresolvers import reverse - from django.template import RequestContext - from polls.models import Choice, Poll - # ... - def vote(request, poll_id): - p = get_object_or_404(Poll, pk=poll_id) - try: - selected_choice = p.choice_set.get(pk=request.POST['choice']) - except (KeyError, Choice.DoesNotExist): - # Redisplay the poll voting form. - return render_to_response('polls/detail.html', { - 'poll': p, - 'error_message': "You didn't select a choice.", - }, context_instance=RequestContext(request)) - else: - selected_choice.votes += 1 - selected_choice.save() - # Always return an HttpResponseRedirect after successfully dealing - # with POST data. This prevents data from being posted twice if a - # user hits the Back button. - return HttpResponseRedirect(reverse('polls.views.results', args=(p.id,))) - -This code includes a few things we haven't covered yet in this tutorial: - - * :attr:`request.POST <django.http.HttpRequest.POST>` is a dictionary-like - object that lets you access submitted data by key name. In this case, - ``request.POST['choice']`` returns the ID of the selected choice, as a - string. :attr:`request.POST <django.http.HttpRequest.POST>` values are - always strings. - - Note that Django also provides :attr:`request.GET - <django.http.HttpRequest.GET>` for accessing GET data in the same way -- - but we're explicitly using :attr:`request.POST - <django.http.HttpRequest.POST>` in our code, to ensure that data is only - altered via a POST call. - - * ``request.POST['choice']`` will raise :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 - :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 - :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 :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). - -As mentioned in Tutorial 3, ``request`` is a :class:`~django.http.HttpRequest` -object. For more on :class:`~django.http.HttpRequest` objects, see the -:doc:`request and response documentation </ref/request-response>`. - -After somebody votes in a poll, the ``vote()`` view redirects to the results -page for the poll. Let's write that view:: - - def results(request, poll_id): - 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 :doc:`Tutorial 3 -</intro/tutorial03>`. The only difference is the template name. We'll fix this -redundancy later. - -Now, create a ``results.html`` template: - -.. code-block:: html+django - - <h1>{{ poll.question }}</h1> - - <ul> - {% for choice in poll.choice_set.all %} - <li>{{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li> - {% endfor %} - </ul> - - <a href="/polls/{{ poll.id }}/">Vote again?</a> - -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. - -Use generic views: Less code is better -====================================== - -The ``detail()`` (from :doc:`Tutorial 3 </intro/tutorial03>`) and ``results()`` -views are stupidly simple -- and, as mentioned above, redundant. The ``index()`` -view (also from Tutorial 3), which displays a list of polls, is similar. - -These views represent a common case of basic Web development: getting data from -the database according to a parameter passed in the URL, loading a template and -returning the rendered template. Because this is so common, Django provides a -shortcut, called the "generic views" system. - -Generic views abstract common patterns to the point where you don't even need -to write Python code to write an app. - -Let's convert our poll app to use the generic views system, so we can delete a -bunch of our own code. We'll just have to take a few steps to make the -conversion. We will: - - 1. Convert the URLconf. - - 2. Rename a few templates. - - 3. Delete some of the old, unneeded views. - - 4. Fix up URL handling for the new views. - -Read on for details. - -.. admonition:: Why the code-shuffle? - - Generally, when writing a Django app, you'll evaluate whether generic views - are a good fit for your problem, and you'll use them from the beginning, - rather than refactoring your code halfway through. But this tutorial - intentionally has focused on writing the views "the hard way" until now, to - focus on core concepts. - - 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 -tutorial so far:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('polls.views', - (r'^$', 'index'), - (r'^(?P<poll_id>\d+)/$', 'detail'), - (r'^(?P<poll_id>\d+)/results/$', 'results'), - (r'^(?P<poll_id>\d+)/vote/$', 'vote'), - ) - -Change it like so:: - - from django.conf.urls.defaults import * - from polls.models import Poll - - info_dict = { - 'queryset': Poll.objects.all(), - } - - urlpatterns = patterns('', - (r'^$', 'django.views.generic.list_detail.object_list', info_dict), - (r'^(?P<object_id>\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict), - url(r'^(?P<object_id>\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html'), 'poll_results'), - (r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote'), - ) - -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 :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 - :ref:`naming URL patterns <naming-url-patterns>` for information). We're - also using the :func:`~django.conf.urls.default.url` function from - :mod:`django.conf.urls.defaults` here. It's a good habit to use - :func:`~django.conf.urls.defaults.url` when you are providing a pattern - name like this. - -By default, the :func:`~django.views.generic.list_detail.object_detail` generic -view uses a template called ``<app name>/<model name>_detail.html``. In our -case, it'll use the template ``"polls/poll_detail.html"``. Thus, rename your -``polls/detail.html`` template to ``polls/poll_detail.html``, and change the -:func:`~django.shortcuts.render_to_response` line in ``vote()``. - -Similarly, the :func:`~django.views.generic.list_detail.object_list` generic -view uses a template called ``<app name>/<model name>_list.html``. Thus, rename -``polls/index.html`` to ``polls/poll_list.html``. - -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:: :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 - :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 :ref:`explains the lazy nature of QuerySet objects - <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``. - -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 :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 -: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 :doc:`generic views documentation -</topics/http/generic-views>`. - -Coming soon -=========== - -The tutorial ends here for the time being. Future installments of the tutorial -will cover: - - * Advanced form processing - * Using the RSS framework - * Using the cache framework - * Using the comments framework - * Advanced admin features: Permissions - * Advanced admin features: Custom JavaScript - -In the meantime, you might want to check out some pointers on :doc:`where to go -from here </intro/whatsnext>` diff --git a/parts/django/docs/intro/whatsnext.txt b/parts/django/docs/intro/whatsnext.txt deleted file mode 100644 index 00c1654..0000000 --- a/parts/django/docs/intro/whatsnext.txt +++ /dev/null @@ -1,231 +0,0 @@ -================= -What to read next -================= - -So you've read all the :doc:`introductory material </intro/index>` and have -decided you'd like to keep using Django. We've only just scratched the surface -with this intro (in fact, if you've read every single word you've still read -less than 10% of the overall documentation). - -So what's next? - -Well, we've always been big fans of learning by doing. At this point you should -know enough to start a project of your own and start fooling around. As you need -to learn new tricks, come back to the documentation. - -We've put a lot of effort into making Django's documentation useful, easy to -read and as complete as possible. The rest of this document explains more about -how the documentation works so that you can get the most out of it. - -(Yes, this is documentation about documentation. Rest assured we have no plans -to write a document about how to read the document about documentation.) - -Finding documentation -===================== - -Django's got a *lot* of documentation -- almost 200,000 words -- so finding what -you need can sometimes be tricky. A few good places to start are 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 :doc:`introductory material </intro/index>` is designed for people new - to Django -- or to Web development in general. It doesn't cover anything - in depth, but instead gives a high-level overview of how developing in - Django "feels". - - * The :doc:`topic guides </topics/index>`, on the other hand, dive deep into - individual parts of Django. There are complete guides to Django's - :doc:`model system </topics/db/index>`, :doc:`template engine - </topics/templates>`, :doc:`forms framework </topics/forms/index>`, and much - more. - - This is probably where you'll want to spend 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 :doc:`how-to guides </howto/index>` that answer - common "How do I ...?" questions. Here you'll find information about - :doc:`generating PDFs with Django </howto/outputting-pdf>`, :doc:`writing - custom template tags </howto/custom-template-tags>`, and more. - - Answers to really common questions can also be found in the :doc:`FAQ - </faq/index>`. - - * The guides and how-to's don't cover every single class, function, and - method available in Django -- that would be overwhelming when you're - trying to learn. Instead, details about individual classes, functions, - methods, and modules are kept in the :doc:`reference </ref/index>`. This is - where you'll turn to find the details of a particular function or - whathaveyou. - - * Finally, there's some "specialized" documentation not usually relevant to - most developers. This includes the :doc:`release notes </releases/index>`, - :doc:`documentation of obsolete features </obsolete/index>`, - :doc:`internals documentation </internals/index>` for those who want to add - code to Django itself, and a :doc:`few other things that simply don't fit - elsewhere </misc/index>`. - - -How documentation is updated -============================ - -Just as the Django code base is developed and improved on a daily basis, our -documentation is consistently improving. We improve documentation for several -reasons: - - * To make content fixes, such as grammar/typo corrections. - - * To add information and/or examples to existing sections that need to be - expanded. - - * To document Django features that aren't yet documented. (The list of - such features is shrinking but exists nonetheless.) - - * To add documentation for new features as new features get added, or as - Django APIs or behaviors change. - -Django's documentation is kept in the same source control system as its code. It -lives in the `django/trunk/docs`_ directory of our Subversion repository. Each -document online is a separate text file in the repository. - -.. _django/trunk/docs: http://code.djangoproject.com/browser/django/trunk/docs - -Where to get it -=============== - -You can read Django documentation in several ways. They are, in order of -preference: - -On the Web ----------- - -The most recent version of the Django documentation lives at -http://docs.djangoproject.com/en/dev/. 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 "max_length" in any -Django document: - -.. code-block:: bash - - $ grep -r max_length /path/to/django/docs/ - -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 Web site, 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``. - -.. note:: - - Generation of the Django documentation will work with Sphinx version 0.6 - or newer, but we recommend going straight to Sphinx 1.0.2 or newer. - -__ 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 version X.Y", being X.Y the next release version (hence, the one - being developed). - - * 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://docs.djangoproject.com/en/dev/ diff --git a/parts/django/docs/man/daily_cleanup.1 b/parts/django/docs/man/daily_cleanup.1 deleted file mode 100644 index dfcde1d..0000000 --- a/parts/django/docs/man/daily_cleanup.1 +++ /dev/null @@ -1,34 +0,0 @@ -.TH "daily_cleanup.py" "1" "August 2007" "Django Project" "" -.SH "NAME" -daily_cleanup.py \- Database clean-up for the Django Web framework -.SH "SYNOPSIS" -.B daily_cleanup.py - -.SH "DESCRIPTION" -Removes stale session data from a Django database. This means, any session data -which has an expiry date prior to the date the script is run. -.sp -The script can be run manually or can be scheduled to run at regular -intervals as a -.BI cron -job. - -.SH "ENVIRONMENT" -.TP -.I DJANGO_SETTINGS_MODULE -This environment variable defines the settings module to be read. -It should be in Python-import form, e.g. "myproject.settings". - -.SH "SEE ALSO" -The sessions documentation: -.sp -.I http://docs.djangoproject.com/en/dev/topics/http/sessions/ - -.SH "AUTHORS/CREDITS" -Originally developed at World Online in Lawrence, Kansas, USA. Refer to the -AUTHORS file in the Django distribution for contributors. - -.SH "LICENSE" -New BSD license. For the full license text refer to the LICENSE file in the -Django distribution. - diff --git a/parts/django/docs/man/django-admin.1 b/parts/django/docs/man/django-admin.1 deleted file mode 100644 index 016c80f..0000000 --- a/parts/django/docs/man/django-admin.1 +++ /dev/null @@ -1,226 +0,0 @@ -.TH "django-admin.py" "1" "March 2008" "Django Project" "" -.SH "NAME" -django\-admin.py \- Utility script for the Django Web framework -.SH "SYNOPSIS" -.B django\-admin.py -.I <action> -.B [options] -.sp -.SH "DESCRIPTION" -This utility script provides commands for creation and maintenance of Django -projects and apps. -.sp -With the exception of -.BI startproject, -all commands listed below can also be performed with the -.BI manage.py -script found at the top level of each Django project directory. -.sp -.SH "ACTIONS" -.TP -.BI cleanup -Cleans out old data from the database (only expired sessions at the moment). -.TP -.BI "compilemessages [" "\-\-locale=LOCALE" "]" -Compiles .po files to .mo files for use with builtin gettext support. -.TP -.BI "createcachetable [" "tablename" "]" -Creates the table needed to use the SQL cache backend -.TP -.BI "createsuperuser [" "\-\-username=USERNAME" "] [" "\-\-email=EMAIL" "]" -Creates a superuser account (a user who has all permissions). -.TP -.B dbshell -Runs the command\-line client for the specified -.BI database ENGINE. -.TP -.B diffsettings -Displays differences between the current -.B settings.py -and Django's default settings. Settings that don't appear in the defaults are -followed by "###". -.TP -.BI "dumpdata [" "\-\-all" "] [" "\-\-format=FMT" "] [" "\-\-indent=NUM" "] [" "\-\-natural=NATURAL" "] [" "appname appname appname.Model ..." "]" -Outputs to standard output all data in the database associated with the named -application(s). -.TP -.BI flush -Returns the database to the state it was in immediately after syncdb was -executed. -.TP -.B inspectdb -Introspects the database tables in the database specified in settings.py and outputs a Django -model module. -.TP -.BI "loaddata [" "fixture fixture ..." "]" -Searches for and loads the contents of the named fixture into the database. -.TP -.BI "install [" "appname ..." "]" -Executes -.B sqlall -for the given app(s) in the current database. -.TP -.BI "makemessages [" "\-\-locale=LOCALE" "] [" "\-\-domain=DOMAIN" "] [" "\-\-extension=EXTENSION" "] [" "\-\-all" "] [" "\-\-symlinks" "] [" "\-\-ignore=PATTERN" "] [" "\-\-no\-default\-ignore" "]" -Runs over the entire source tree of the current directory and pulls out all -strings marked for translation. It creates (or updates) a message file in the -conf/locale (in the django tree) or locale (for project and application) directory. -.TP -.BI "reset [" "appname ..." "]" -Executes -.B sqlreset -for the given app(s) in the current database. -.TP -.BI "runfcgi [" "KEY=val" "] [" "KEY=val" "] " "..." -Runs this project as a FastCGI application. Requires flup. Use -.B runfcgi help -for help on the KEY=val pairs. -.TP -.BI "runserver [" "\-\-noreload" "] [" "\-\-adminmedia=ADMIN_MEDIA_PATH" "] [" "port|ipaddr:port" "]" -Starts a lightweight Web server for development. -.TP -.BI "shell [" "\-\-plain" "]" -Runs a Python interactive interpreter. Tries to use IPython, if it's available. -The -.BI \-\-plain -option forces the use of the standard Python interpreter even when IPython is -installed. -.TP -.BI "sql [" "appname ..." "]" -Prints the CREATE TABLE SQL statements for the given app name(s). -.TP -.BI "sqlall [" "appname ..." "]" -Prints the CREATE TABLE, initial\-data and CREATE INDEX SQL statements for the -given model module name(s). -.TP -.BI "sqlclear [" "appname ..." "]" -Prints the DROP TABLE SQL statements for the given app name(s). -.TP -.BI "sqlcustom [" "appname ..." "]" -Prints the custom SQL statements for the given app name(s). -.TP -.BI "sqlflush [" "appname ..." "]" -Prints the SQL statements that would be executed for the "flush" -command. -.TP -.BI "sqlindexes [" "appname ..." "]" -Prints the CREATE INDEX SQL statements for the given model module name(s). -.TP -.BI "sqlinitialdata [" "appname ..." "]" -Prints the initial INSERT SQL statements for the given app name(s). -.TP -.BI "sqlreset [" "appname ..." "]" -Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app -name(s). -.TP -.BI "sqlsequencereset [" "appname ..." "]" -Prints the SQL statements for resetting PostgreSQL sequences for the -given app name(s). -.TP -.BI "startapp [" "appname" "]" -Creates a Django app directory structure for the given app name in -the current directory. -.TP -.BI "startproject [" "projectname" "]" -Creates a Django project directory structure for the given project name -in the current directory. -.TP -.BI syncdb -Creates the database tables for all apps in INSTALLED_APPS whose tables -haven't already been created. -.TP -.BI "test [" "\-\-verbosity" "] [" "\-\-failfast" "] [" "appname ..." "]" -Runs the test suite for the specified applications, or the entire project if -no apps are specified -.TP -.BI "testserver [" "\-\-addrport=ipaddr|port" "] [" "fixture fixture ..." "]" -Runs the test suite for the specified applications, or the entire project if -no apps are specified -.TP -.BI validate -Validates all installed models. -.SH "OPTIONS" -.TP -.I \-\-version -Show program's version number and exit. -.TP -.I \-h, \-\-help -Show this help message and exit. -.TP -.I \-\-settings=SETTINGS -Python path to settings module, e.g. "myproject.settings.main". If -this isn't provided, the DJANGO_SETTINGS_MODULE environment variable -will be used. -.TP -.I \-\-pythonpath=PYTHONPATH -Lets you manually add a directory the Python path, -e.g. "/home/djangoprojects/myproject". -.TP -.I \-\-plain -Use plain Python, not IPython, for the "shell" command. -.TP -.I \-\-noinput -Do not prompt the user for input. -.TP -.I \-\-noreload -Disable the development server's auto\-reloader. -.TP -.I \-\-verbosity=VERBOSITY -Verbosity level: 0=minimal output, 1=normal output, 2=all output. -.TP -.I \-\-adminmedia=ADMIN_MEDIA_PATH -Specifies the directory from which to serve admin media when using the development server. -.TP -.I \-\-traceback -By default, django-admin.py will show a simple error message whenever an -error occurs. If you specify this option, django-admin.py will -output a full stack trace whenever an exception is raised. -.TP -.I \-l, \-\-locale=LOCALE -The locale to process when using makemessages or compilemessages. -.TP -.I \-d, \-\-domain=DOMAIN -The domain of the message files (default: "django") when using makemessages. -.TP -.I \-e, \-\-extension=EXTENSION -The file extension(s) to examine (default: ".html", separate multiple -extensions with commas, or use -e multiple times). -.TP -.I \-s, \-\-symlinks -Follows symlinks to directories when examining source code and templates for -translation strings. -.TP -.I \-i, \-\-ignore=PATTERN -Ignore files or directories matching this glob-style pattern. Use multiple -times to ignore more. -.TP -.I \-\-no\-default\-ignore -Don't ignore the common private glob-style patterns 'CVS', '.*' and '*~'. -.TP -.I \-a, \-\-all -Process all available locales when using makemessages..SH "ENVIRONMENT" -.TP -.I DJANGO_SETTINGS_MODULE -In the absence of the -.BI \-\-settings -option, this environment variable defines the settings module to be read. -It should be in Python-import form, e.g. "myproject.settings". -.I \-\-database=DB -Used to specify the database on which a command will operate. If not -specified, this option will default to an alias of "default". -.TP - -.SH "SEE ALSO" -Full descriptions of all these options, with examples, as well as documentation -for the rest of the Django framework, can be found on the Django site: -.sp -.I http://docs.djangoproject.com/en/dev/ -.sp -or in the distributed documentation. -.SH "AUTHORS/CREDITS" -Originally developed at World Online in Lawrence, Kansas, USA. Refer to the -AUTHORS file in the Django distribution for contributors. -.sp -.SH "LICENSE" -New BSD license. For the full license text refer to the LICENSE file in the -Django distribution. - diff --git a/parts/django/docs/man/gather_profile_stats.1 b/parts/django/docs/man/gather_profile_stats.1 deleted file mode 100644 index fc56ee2..0000000 --- a/parts/django/docs/man/gather_profile_stats.1 +++ /dev/null @@ -1,26 +0,0 @@ -.TH "gather_profile_stats.py" "1" "August 2007" "Django Project" "" -.SH "NAME" -gather_profile_stats.py \- Performance analysis tool for the Django Web -framework -.SH "SYNOPSIS" -.B python gather_profile_stats.py -.I <path> - -.SH "DESCRIPTION" -This utility script aggregates profiling logs generated using Python's -hotshot profiler. The sole command-line argument is the full path to the -directory containing the profiling logfiles. - -.SH "SEE ALSO" -Discussion of profiling Django applications on the Django project's wiki: -.sp -.I http://www.djangoproject.com/wiki/ProfilingDjango - -.SH "AUTHORS/CREDITS" -Originally developed at World Online in Lawrence, Kansas, USA. Refer to the -AUTHORS file in the Django distribution for contributors. - -.SH "LICENSE" -New BSD license. For the full license text refer to the LICENSE file in the -Django distribution. - diff --git a/parts/django/docs/misc/api-stability.txt b/parts/django/docs/misc/api-stability.txt deleted file mode 100644 index 456d84b..0000000 --- a/parts/django/docs/misc/api-stability.txt +++ /dev/null @@ -1,152 +0,0 @@ -============= -API stability -============= - -:doc:`The release of Django 1.0 </releases/1.0>` comes with a promise of API -stability and forwards-compatibility. In a nutshell, this means that code you -develop against Django 1.0 will continue to work against 1.1 unchanged, and you -should need to make only minor changes for any 1.X release. - -What "stable" means -=================== - -In this context, stable means: - - - All the public APIs -- everything documented in the linked documents below, - 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 for at least two - minor version releases. Warnings will be issued when the deprecated method - is called. - - See :ref:`official-releases` for more details on how Django's version - numbering scheme works, and how features will be deprecated. - - - We'll only break backwards compatibility of these APIs if a bug or - security hole makes it completely unavoidable. - -Stable APIs -=========== - -In general, everything covered in the documentation -- with the exception of -anything in the :doc:`internals area </internals/index>` is considered stable as -of 1.0. This includes these APIs: - - - :doc:`Authorization </topics/auth>` - - - :doc:`Caching </topics/cache>`. - - - :doc:`Model definition, managers, querying and transactions - </topics/db/index>` - - - :doc:`Sending e-mail </topics/email>`. - - - :doc:`File handling and storage </topics/files>` - - - :doc:`Forms </topics/forms/index>` - - - :doc:`HTTP request/response handling </topics/http/index>`, including file - uploads, middleware, sessions, URL resolution, view, and shortcut APIs. - - - :doc:`Generic views </topics/http/generic-views>`. - - - :doc:`Internationalization </topics/i18n/index>`. - - - :doc:`Pagination </topics/pagination>` - - - :doc:`Serialization </topics/serialization>` - - - :doc:`Signals </topics/signals>` - - - :doc:`Templates </topics/templates>`, including the language, Python-level - :doc:`template APIs </ref/templates/index>`, and :doc:`custom template tags - and libraries </howto/custom-template-tags>`. We may add new template - tags in the future and the names may inadvertently clash with - external template tags. Before adding any such tags, we'll ensure that - Django raises an error if it tries to load tags with duplicate names. - - - :doc:`Testing </topics/testing>` - - - :doc:`django-admin utility </ref/django-admin>`. - - - :doc:`Built-in middleware </ref/middleware>` - - - :doc:`Request/response objects </ref/request-response>`. - - - :doc:`Settings </ref/settings>`. Note, though that while the :doc:`list of - built-in settings </ref/settings>` can be considered complete we may -- and - probably will -- add new settings in future versions. This is one of those - places where "'stable' does not mean 'complete.'" - - - :doc:`Built-in signals </ref/signals>`. Like settings, we'll probably add - new signals in the future, but the existing ones won't break. - - - :doc:`Unicode handling </ref/unicode>`. - - - Everything covered by the :doc:`HOWTO guides </howto/index>`. - -``django.utils`` ----------------- - -Most of the modules in ``django.utils`` are designed for internal use. Only -the following parts of :doc:`django.utils </ref/utils>` can be considered stable: - - - ``django.utils.cache`` - - ``django.utils.datastructures.SortedDict`` -- only this single class; the - rest of the module is for internal use. - - ``django.utils.encoding`` - - ``django.utils.feedgenerator`` - - ``django.utils.http`` - - ``django.utils.safestring`` - - ``django.utils.translation`` - - ``django.utils.tzinfo`` - -Exceptions -========== - -There are a few exceptions to this stability and backwards-compatibility -promise. - -Security fixes --------------- - -If we become aware of a security problem -- hopefully by someone following our -:ref:`security reporting policy <reporting-security-issues>` -- we'll do -everything necessary to fix it. This might mean breaking backwards compatibility; security trumps the compatibility guarantee. - -Contributed applications (``django.contrib``) ---------------------------------------------- - -While we'll make every effort to keep these APIs stable -- and have no plans to -break any contrib apps -- this is an area that will have more flux between -releases. As the Web evolves, Django must evolve with it. - -However, any changes to contrib apps will come with an important guarantee: -we'll make sure it's always possible to use an older version of a contrib app if -we need to make changes. Thus, if Django 1.5 ships with a backwards-incompatible -``django.contrib.flatpages``, we'll make sure you can still use the Django 1.4 -version alongside Django 1.5. This will continue to allow for easy upgrades. - -Historically, apps in ``django.contrib`` have been more stable than the core, so -in practice we probably won't have to ever make this exception. However, it's -worth noting if you're building apps that depend on ``django.contrib``. - -APIs marked as internal ------------------------ - -Certain APIs are explicitly marked as "internal" in a couple of ways: - - - Some documentation refers to internals and mentions them as such. If the - documentation says that something is internal, we reserve the right to - change it. - - - Functions, methods, and other objects prefixed by a leading underscore - (``_``). This is the standard Python way of indicating that something is - private; if any method starts with a single ``_``, it's an internal API. - diff --git a/parts/django/docs/misc/design-philosophies.txt b/parts/django/docs/misc/design-philosophies.txt deleted file mode 100644 index 631097a..0000000 --- a/parts/django/docs/misc/design-philosophies.txt +++ /dev/null @@ -1,314 +0,0 @@ -=================== -Design philosophies -=================== - -This document explains some of the fundamental philosophies Django's developers -have used in creating the framework. Its goal is to explain the past and guide -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. - -For example, the template system knows nothing about Web requests, the database -layer knows nothing about data display and the view system doesn't care which -template system a programmer uses. - -Although Django comes with a full stack for convenience, the pieces of the -stack are independent of another wherever possible. - -.. _`loose coupling and tight cohesion`: http://c2.com/cgi/wiki?CouplingAndCohesion - -.. _less-code: - -Less code ---------- - -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 ------------------ - -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 --------------------------------- - -This, a `core Python principle`_, means Django shouldn't do too much "magic." -Magic shouldn't happen unless there's a really good reason for it. Magic is -worth using only if it creates a huge convenience unattainable in other ways, -and it isn't implemented in a way that confuses developers who are trying to -learn how to use the feature. - -.. _`core Python principle`: http://www.python.org/dev/peps/pep-0020/ - -.. _consistency: - -Consistency ------------ - -The framework should be consistent at all levels. Consistency applies to -everything from low-level (the Python coding style used) to high-level (the -"experience" of using Django). - -Models -====== - -Explicit is better than implicit --------------------------------- - -Fields shouldn't assume certain behaviors based solely on the name of the -field. This requires too much knowledge of the system and is prone to errors. -Instead, behaviors should be based on keyword arguments and, in some cases, on -the type of the field. - -Include all relevant domain logic ---------------------------------- - -Models should encapsulate every aspect of an "object," following Martin -Fowler's `Active Record`_ design pattern. - -This is why both the data represented by a model and information about -it (its human-readable name, options like default ordering, etc.) are -defined in the model class; all the information needed to understand a -given model should be stored *in* the model. - -.. _`Active Record`: http://www.martinfowler.com/eaaCatalog/activeRecord.html - -Database API -============ - -The core goals of the database API are: - -SQL efficiency --------------- - -It should execute SQL statements as few times as possible, and it should -optimize statements internally. - -This is why developers need to call ``save()`` explicitly, rather than the -framework saving things behind the scenes silently. - -This is also why the ``select_related()`` ``QuerySet`` method exists. It's an -optional performance booster for the common case of selecting "every related -object." - -Terse, powerful syntax ----------------------- - -The database API should allow rich, expressive statements in as little syntax -as possible. It should not rely on importing other modules or helper objects. - -Joins should be performed automatically, behind the scenes, when necessary. - -Every object should be able to access every related object, systemwide. This -access should work both ways. - -Option to drop into raw SQL easily, when needed ------------------------------------------------ - -The database API should realize it's a shortcut but not necessarily an -end-all-be-all. The framework should make it easy to write custom SQL -- entire -statements, or just custom ``WHERE`` clauses as custom parameters to API calls. - -URL design -========== - -Loose coupling --------------- - -URLs in a Django app should not be coupled to the underlying Python code. Tying -URLs to Python function names is a Bad And Ugly Thing. - -Along these lines, the Django URL system should allow URLs for the same app to -be different in different contexts. For example, one site may put stories at -``/stories/``, while another may use ``/news/``. - -Infinite flexibility --------------------- - -URLs should be as flexible as possible. Any conceivable URL design should be -allowed. - -Encourage best practices ------------------------- - -The framework should make it just as easy (or even easier) for a developer to -design pretty URLs than ugly ones. - -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 :setting:`APPEND_SLASH` setting. - -Template system -=============== - -.. _separation-of-logic-and-presentation: - -Separate logic from presentation --------------------------------- - -We see a template system as a tool that controls presentation and -presentation-related logic -- and that's it. The template system shouldn't -support functionality that goes beyond this basic goal. - -If we wanted to put everything in templates, we'd be using PHP. Been there, -done that, wised up. - -Discourage redundancy ---------------------- - -The majority of dynamic Web sites use some sort of common sitewide design -- -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 :ref:`template inheritance -<template-inheritance>`. - -Be decoupled from HTML ----------------------- - -The template system shouldn't be designed so that it only outputs HTML. It -should be equally good at generating other text-based formats, or just plain -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. - -Assume designer competence --------------------------- - -The template system shouldn't be designed so that templates necessarily are -displayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of -a limitation and wouldn't allow the syntax to be as nice as it is. Django -expects template authors are comfortable editing HTML directly. - -Treat whitespace obviously --------------------------- - -The template system shouldn't do magic things with whitespace. If a template -includes whitespace, the system should treat the whitespace as it treats text --- just display it. Any whitespace that's not in a template tag should be -displayed. - -Don't invent a programming language ------------------------------------ - -The template system intentionally doesn't allow the following: - - * Assignment to variables - * Advanced logic - -The goal is not to invent a programming language. The goal is to offer just -enough programming-esque functionality, such as branching and looping, that is -essential for making presentation-related decisions. - -The Django template system recognizes that templates are most often written by -*designers*, not *programmers*, and therefore should not assume Python -knowledge. - -Safety and security -------------------- - -The template system, out of the box, should forbid the inclusion of malicious -code -- such as commands that delete database records. - -This is another reason the template system doesn't allow arbitrary Python code. - -Extensibility -------------- - -The template system should recognize that advanced template authors may want -to extend its technology. - -This is the philosophy behind custom template tags and filters. - -Views -===== - -Simplicity ----------- - -Writing a view should be as simple as writing a Python function. Developers -shouldn't have to instantiate a class when a function will do. - -Use request objects -------------------- - -Views should have access to a request object -- an object that stores metadata -about the current request. The object should be passed directly to a view -function, rather than the view function having to access the request data from -a global variable. This makes it light, clean and easy to test views by passing -in "fake" request objects. - -Loose coupling --------------- - -A view shouldn't care about which template system the developer uses -- or even -whether a template system is used at all. - -Differentiate between GET and POST ----------------------------------- - -GET and POST are distinct; developers should explicitly use one or the other. -The framework should make it easy to distinguish between GET and POST data. diff --git a/parts/django/docs/misc/distributions.txt b/parts/django/docs/misc/distributions.txt deleted file mode 100644 index d9281ad..0000000 --- a/parts/django/docs/misc/distributions.txt +++ /dev/null @@ -1,36 +0,0 @@ -=================================== -Third-party distributions of Django -=================================== - -Many third-party distributors are now providing versions of Django integrated -with their package-management systems. These can make installation and upgrading -much easier for users of Django since the integration includes the ability to -automatically install dependencies (like database adapters) that Django -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 :ref:`installing the development version -<installing-development-version>` from our Subversion repository. - -If you're using Linux or a Unix installation, such as OpenSolaris, -check with your distributor to see if they already package Django. If -you're using a Linux distro and don't know how to find out if a package -is available, then now is a good time to learn. The Django Wiki contains -a list of `Third Party Distributions`_ to help you out. - -.. _`Third Party Distributions`: http://code.djangoproject.com/wiki/Distributions - - -For distributors -================ - -If you'd like to package Django for distribution, we'd be happy to help out! -Please join the `django-developers mailing list`_ and introduce yourself. - -We also encourage all distributors to subscribe to the `django-announce mailing -list`_, which is a (very) low-traffic list for announcing new releases of Django -and important bugfixes. - -.. _django-developers mailing list: http://groups.google.com/group/django-developers/ -.. _django-announce mailing list: http://groups.google.com/group/django-announce/ diff --git a/parts/django/docs/misc/index.txt b/parts/django/docs/misc/index.txt deleted file mode 100644 index b42baeb..0000000 --- a/parts/django/docs/misc/index.txt +++ /dev/null @@ -1,12 +0,0 @@ -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/parts/django/docs/obsolete/_images/formrow.png b/parts/django/docs/obsolete/_images/formrow.png Binary files differdeleted file mode 100644 index 164dd26..0000000 --- a/parts/django/docs/obsolete/_images/formrow.png +++ /dev/null diff --git a/parts/django/docs/obsolete/_images/module.png b/parts/django/docs/obsolete/_images/module.png Binary files differdeleted file mode 100644 index 6acda97..0000000 --- a/parts/django/docs/obsolete/_images/module.png +++ /dev/null diff --git a/parts/django/docs/obsolete/_images/objecttools_01.png b/parts/django/docs/obsolete/_images/objecttools_01.png Binary files differdeleted file mode 100644 index 0aba816..0000000 --- a/parts/django/docs/obsolete/_images/objecttools_01.png +++ /dev/null diff --git a/parts/django/docs/obsolete/_images/objecttools_02.png b/parts/django/docs/obsolete/_images/objecttools_02.png Binary files differdeleted file mode 100644 index 06a8540..0000000 --- a/parts/django/docs/obsolete/_images/objecttools_02.png +++ /dev/null diff --git a/parts/django/docs/obsolete/admin-css.txt b/parts/django/docs/obsolete/admin-css.txt deleted file mode 100644 index f4cca54..0000000 --- a/parts/django/docs/obsolete/admin-css.txt +++ /dev/null @@ -1,186 +0,0 @@ -====================================== -Customizing the Django admin interface -====================================== - -.. warning:: - - The design of the admin has changed somewhat since this document was - written, and parts may not apply any more. This document is no longer - maintained since an official API for customizing the Django admin interface - is in development. - -Django's dynamic admin interface gives you a fully-functional admin for free -with no hand-coding required. The dynamic admin is designed to be -production-ready, not just a starting point, so you can use it as-is on a real -site. While the underlying format of the admin pages is built in to Django, you -can customize the look and feel by editing the admin stylesheet and images. - -Here's a quick and dirty overview some of the main styles and classes used in -the Django admin CSS. - -Modules -======= - -The ``.module`` class is a basic building block for grouping content in the -admin. It's generally applied to a ``div`` or a ``fieldset``. It wraps the content -group in a box and applies certain styles to the elements within. An ``h2`` -within a ``div.module`` will align to the top of the ``div`` as a header for the -whole group. - -.. image:: _images/module.png - :alt: Example use of module class on admin homepage - -Column Types -============ - -.. note:: - - All admin pages (except the dashboard) are fluid-width. All fixed-width - classes from previous Django versions have been removed. - -The base template for each admin page has a block that defines the column -structure for the page. This sets a class on the page content area -(``div#content``) so everything on the page knows how wide it should be. There -are three column types available. - -colM - This is the default column setting for all pages. The "M" stands for "main". - Assumes that all content on the page is in one main column - (``div#content-main``). -colMS - This is for pages with one main column and a sidebar on the right. The "S" - stands for "sidebar". Assumes that main content is in ``div#content-main`` - and sidebar content is in ``div#content-related``. This is used on the main - admin page. -colSM - Same as above, with the sidebar on the left. The source order of the columns - doesn't matter. - -For instance, you could stick this in a template to make a two-column page with -the sidebar on the right: - -.. code-block:: html+django - - {% block coltype %}colMS{% endblock %} - -Text Styles -=========== - -Font Sizes ----------- - -Most HTML elements (headers, lists, etc.) have base font sizes in the stylesheet -based on context. There are three classes are available for forcing text to a -certain size in any context. - -small - 11px -tiny - 10px -mini - 9px (use sparingly) - -Font Styles and Alignment -------------------------- - -There are also a few styles for styling text. - -.quiet - Sets font color to light gray. Good for side notes in instructions. Combine - with ``.small`` or ``.tiny`` for sheer excitement. -.help - This is a custom class for blocks of inline help text explaining the - function of form elements. It makes text smaller and gray, and when applied - to ``p`` elements within ``.form-row`` elements (see Form Styles below), - it will offset the text to align with the form field. Use this for help - text, instead of ``small quiet``. It works on other elements, but try to - put the class on a ``p`` whenever you can. -.align-left - It aligns the text left. Only works on block elements containing inline - elements. -.align-right - Are you paying attention? -.nowrap - Keeps text and inline objects from wrapping. Comes in handy for table - headers you want to stay on one line. - -Floats and Clears ------------------ - -float-left - floats left -float-right - floats right -clear - clears all - -Object Tools -============ - -Certain actions which apply directly to an object are used in form and -changelist pages. These appear in a "toolbar" row above the form or changelist, -to the right of the page. The tools are wrapped in a ``ul`` with the class -``object-tools``. There are two custom tool types which can be defined with an -additional class on the ``a`` for that tool. These are ``.addlink`` and -``.viewsitelink``. - -Example from a changelist page: - -.. code-block:: html+django - - <ul class="object-tools"> - <li><a href="/stories/add/" class="addlink">Add redirect</a></li> - </ul> - -.. image:: _images/objecttools_01.png - :alt: Object tools on a changelist page - -and from a form page: - -.. code-block:: html+django - - <ul class="object-tools"> - <li><a href="/history/303/152383/">History</a></li> - <li><a href="/r/303/152383/" class="viewsitelink">View on site</a></li> - </ul> - -.. image:: _images/objecttools_02.png - :alt: Object tools on a form page - -Form Styles -=========== - -Fieldsets ---------- - -Admin forms are broken up into groups by ``fieldset`` elements. Each form fieldset -should have a class ``.module``. Each fieldset should have a header ``h2`` within the -fieldset at the top (except the first group in the form, and in some cases where the -group of fields doesn't have a logical label). - -Each fieldset can also take extra classes in addition to ``.module`` to apply -appropriate formatting to the group of fields. - -.aligned - This will align the labels and inputs side by side on the same line. -.wide - Used in combination with ``.aligned`` to widen the space available for the - labels. - -Form Rows ---------- - -Each row of the form (within the ``fieldset``) should be enclosed in a ``div`` -with class ``form-row``. If the field in the row is required, a class of -``required`` should also be added to the ``div.form-row``. - -.. image:: _images/formrow.png - :alt: Example use of form-row class - -Labels ------- - -Form labels should always precede the field, except in the case -of checkboxes and radio buttons, where the ``input`` should come first. Any -explanation or help text should follow the ``label`` in a ``p`` with class -``.help``. diff --git a/parts/django/docs/obsolete/index.txt b/parts/django/docs/obsolete/index.txt deleted file mode 100644 index ddc8623..0000000 --- a/parts/django/docs/obsolete/index.txt +++ /dev/null @@ -1,12 +0,0 @@ -Deprecated/obsolete documentation -================================= - -These documents cover features that have been deprecated or that have been -replaced in newer versions of Django. They're preserved here for folks using old -versions of Django or those still using deprecated APIs. No new code based on -these APIs should be written. - -.. toctree:: - :maxdepth: 1 - - admin-css
\ No newline at end of file diff --git a/parts/django/docs/ref/authbackends.txt b/parts/django/docs/ref/authbackends.txt deleted file mode 100644 index a50b414..0000000 --- a/parts/django/docs/ref/authbackends.txt +++ /dev/null @@ -1,35 +0,0 @@ -======================= -Authentication backends -======================= - -.. module:: django.contrib.auth.backends - :synopsis: Django's built-in authentication backend classes. - -This document details the authentication backends that come with Django. For -information on how to use them and how to write your own authentication -backends, see the :ref:`Other authentication sources section -<authentication-backends>` of the :doc:`User authentication guide -</topics/auth>`. - - -Available authentication backends -================================= - -The following backends are available in :mod:`django.contrib.auth.backends`: - -.. class:: ModelBackend - - This is the default authentication backend used by Django. It - authenticates using usernames and passwords stored in the - :class:`~django.contrib.auth.models.User` model. - - -.. class:: RemoteUserBackend - - .. versionadded:: 1.1 - - Use this backend to take advantage of external-to-Django-handled - authentication. It authenticates using usernames passed in - :attr:`request.META['REMOTE_USER'] <django.http.HttpRequest.META>`. See - the :doc:`Authenticating against REMOTE_USER </howto/auth-remote-user>` - documentation. diff --git a/parts/django/docs/ref/contrib/admin/_images/article_actions.png b/parts/django/docs/ref/contrib/admin/_images/article_actions.png Binary files differdeleted file mode 100644 index 78a78ae..0000000 --- a/parts/django/docs/ref/contrib/admin/_images/article_actions.png +++ /dev/null diff --git a/parts/django/docs/ref/contrib/admin/_images/article_actions_message.png b/parts/django/docs/ref/contrib/admin/_images/article_actions_message.png Binary files differdeleted file mode 100644 index 6ea9439..0000000 --- a/parts/django/docs/ref/contrib/admin/_images/article_actions_message.png +++ /dev/null diff --git a/parts/django/docs/ref/contrib/admin/_images/flatfiles_admin.png b/parts/django/docs/ref/contrib/admin/_images/flatfiles_admin.png Binary files differdeleted file mode 100644 index 391a629..0000000 --- a/parts/django/docs/ref/contrib/admin/_images/flatfiles_admin.png +++ /dev/null diff --git a/parts/django/docs/ref/contrib/admin/_images/user_actions.png b/parts/django/docs/ref/contrib/admin/_images/user_actions.png Binary files differdeleted file mode 100644 index fdbe2ad..0000000 --- a/parts/django/docs/ref/contrib/admin/_images/user_actions.png +++ /dev/null diff --git a/parts/django/docs/ref/contrib/admin/_images/users_changelist.png b/parts/django/docs/ref/contrib/admin/_images/users_changelist.png Binary files differdeleted file mode 100644 index d5f9c01..0000000 --- a/parts/django/docs/ref/contrib/admin/_images/users_changelist.png +++ /dev/null diff --git a/parts/django/docs/ref/contrib/admin/actions.txt b/parts/django/docs/ref/contrib/admin/actions.txt deleted file mode 100644 index 0fab59e..0000000 --- a/parts/django/docs/ref/contrib/admin/actions.txt +++ /dev/null @@ -1,351 +0,0 @@ -============= -Admin actions -============= - -.. versionadded:: 1.1 - -.. currentmodule:: django.contrib.admin - -The basic workflow of Django's admin is, in a nutshell, "select an object, -then change it." This works well for a majority of use cases. However, if you -need to make the same change to many objects at once, this workflow can be -quite tedious. - -In these cases, Django's admin lets you write and register "actions" -- simple -functions that get called with a list of objects selected on the change list -page. - -If you look at any change list in the admin, you'll see this feature in -action; Django ships with a "delete selected objects" action available to all -models. For example, here's the user module from Django's built-in -:mod:`django.contrib.auth` app: - -.. image:: _images/user_actions.png - -.. warning:: - - The "delete selected objects" action uses :meth:`QuerySet.delete() - <django.db.models.QuerySet.delete>` for efficiency reasons, which has an - important caveat: your model's ``delete()`` method will not be called. - - If you wish to override this behavior, simply write a custom action which - accomplishes deletion in your preferred manner -- for example, by calling - ``Model.delete()`` for each of the selected items. - - For more background on bulk deletion, see the documentation on :ref:`object - deletion <topics-db-queries-delete>`. - -Read on to find out how to add your own actions to this list. - -Writing actions -=============== - -The easiest way to explain actions is by example, so let's dive in. - -A common use case for admin actions is the bulk updating of a model. Imagine a -simple news application with an ``Article`` model:: - - from django.db import models - - STATUS_CHOICES = ( - ('d', 'Draft'), - ('p', 'Published'), - ('w', 'Withdrawn'), - ) - - class Article(models.Model): - title = models.CharField(max_length=100) - body = models.TextField() - status = models.CharField(max_length=1, choices=STATUS_CHOICES) - - def __unicode__(self): - return self.title - -A common task we might perform with a model like this is to update an -article's status from "draft" to "published". We could easily do this in the -admin one article at a time, but if we wanted to bulk-publish a group of -articles, it'd be tedious. So, let's write an action that lets us change an -article's status to "published." - -Writing action functions ------------------------- - -First, we'll need to write a function that gets called when the action is -trigged from the admin. Action functions are just regular functions that take -three arguments: - - * The current :class:`ModelAdmin` - * An :class:`~django.http.HttpRequest` representing the current request, - * A :class:`~django.db.models.QuerySet` containing the set of objects - selected by the user. - -Our publish-these-articles function won't need the :class:`ModelAdmin` or the -request object, but we will use the queryset:: - - def make_published(modeladmin, request, queryset): - queryset.update(status='p') - -.. note:: - - For the best performance, we're using the queryset's :ref:`update method - <topics-db-queries-update>`. Other types of actions might need to deal - with each object individually; in these cases we'd just iterate over the - queryset:: - - for obj in queryset: - do_something_with(obj) - -That's actually all there is to writing an action! However, we'll take one -more optional-but-useful step and give the action a "nice" title in the admin. -By default, this action would appear in the action list as "Make published" -- -the function name, with underscores replaced by spaces. That's fine, but we -can provide a better, more human-friendly name by giving the -``make_published`` function a ``short_description`` attribute:: - - def make_published(modeladmin, request, queryset): - queryset.update(status='p') - make_published.short_description = "Mark selected stories as published" - -.. note:: - - This might look familiar; the admin's ``list_display`` option uses the - same technique to provide human-readable descriptions for callback - functions registered there, too. - -Adding actions to the :class:`ModelAdmin` ------------------------------------------ - -Next, we'll need to inform our :class:`ModelAdmin` of the action. This works -just like any other configuration option. So, the complete ``admin.py`` with -the action and its registration would look like:: - - from django.contrib import admin - from myapp.models import Article - - def make_published(modeladmin, request, queryset): - queryset.update(status='p') - make_published.short_description = "Mark selected stories as published" - - class ArticleAdmin(admin.ModelAdmin): - list_display = ['title', 'status'] - ordering = ['title'] - actions = [make_published] - - admin.site.register(Article, ArticleAdmin) - -That code will give us an admin change list that looks something like this: - -.. image:: _images/article_actions.png - -That's really all there is to it! If you're itching to write your own actions, -you now know enough to get started. The rest of this document just covers more -advanced techniques. - -Advanced action techniques -========================== - -There's a couple of extra options and possibilities you can exploit for more -advanced options. - -Actions as :class:`ModelAdmin` methods --------------------------------------- - -The example above shows the ``make_published`` action defined as a simple -function. That's perfectly fine, but it's not perfect from a code design point -of view: since the action is tightly coupled to the ``Article`` object, it -makes sense to hook the action to the ``ArticleAdmin`` object itself. - -That's easy enough to do:: - - class ArticleAdmin(admin.ModelAdmin): - ... - - actions = ['make_published'] - - def make_published(self, request, queryset): - queryset.update(status='p') - make_published.short_description = "Mark selected stories as published" - -Notice first that we've moved ``make_published`` into a method and renamed the -`modeladmin` parameter to `self`, and second that we've now put the string -``'make_published'`` in ``actions`` instead of a direct function reference. This -tells the :class:`ModelAdmin` to look up the action as a method. - -Defining actions as methods gives the action more straightforward, idiomatic -access to the :class:`ModelAdmin` itself, allowing the action to call any of the -methods provided by the admin. - -.. _custom-admin-action: - -For example, we can use ``self`` to flash a message to the user informing her -that the action was successful:: - - class ArticleAdmin(admin.ModelAdmin): - ... - - def make_published(self, request, queryset): - rows_updated = queryset.update(status='p') - if rows_updated == 1: - message_bit = "1 story was" - else: - message_bit = "%s stories were" % rows_updated - self.message_user(request, "%s successfully marked as published." % message_bit) - -This make the action match what the admin itself does after successfully -performing an action: - -.. image:: _images/article_actions_message.png - -Actions that provide intermediate pages ---------------------------------------- - -By default, after an action is performed the user is simply redirected back -to the original change list page. However, some actions, especially more -complex ones, will need to return intermediate pages. For example, the -built-in delete action asks for confirmation before deleting the selected -objects. - -To provide an intermediary page, simply return an -:class:`~django.http.HttpResponse` (or subclass) from your action. For -example, you might write a simple export function that uses Django's -:doc:`serialization functions </topics/serialization>` to dump some selected -objects as JSON:: - - from django.http import HttpResponse - from django.core import serializers - - def export_as_json(modeladmin, request, queryset): - response = HttpResponse(mimetype="text/javascript") - serializers.serialize("json", queryset, stream=response) - return response - -Generally, something like the above isn't considered a great idea. Most of the -time, the best practice will be to return an -:class:`~django.http.HttpResponseRedirect` and redirect the user to a view -you've written, passing the list of selected objects in the GET query string. -This allows you to provide complex interaction logic on the intermediary -pages. For example, if you wanted to provide a more complete export function, -you'd want to let the user choose a format, and possibly a list of fields to -include in the export. The best thing to do would be to write a small action -that simply redirects to your custom export view:: - - from django.contrib import admin - from django.contrib.contenttypes.models import ContentType - from django.http import HttpResponseRedirect - - def export_selected_objects(modeladmin, request, queryset): - selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME) - ct = ContentType.objects.get_for_model(queryset.model) - return HttpResponseRedirect("/export/?ct=%s&ids=%s" % (ct.pk, ",".join(selected))) - -As you can see, the action is the simple part; all the complex logic would -belong in your export view. This would need to deal with objects of any type, -hence the business with the ``ContentType``. - -Writing this view is left as an exercise to the reader. - -.. _adminsite-actions: - -Making actions available site-wide ----------------------------------- - -.. method:: AdminSite.add_action(action[, name]) - - Some actions are best if they're made available to *any* object in the admin - site -- the export action defined above would be a good candidate. You can - make an action globally available using :meth:`AdminSite.add_action()`. For - example:: - - from django.contrib import admin - - admin.site.add_action(export_selected_objects) - - This makes the `export_selected_objects` action globally available as an - action named `"export_selected_objects"`. You can explicitly give the action - a name -- good if you later want to programatically :ref:`remove the action - <disabling-admin-actions>` -- by passing a second argument to - :meth:`AdminSite.add_action()`:: - - admin.site.add_action(export_selected_objects, 'export_selected') - -.. _disabling-admin-actions: - -Disabling actions ------------------ - -Sometimes you need to disable certain actions -- especially those -:ref:`registered site-wide <adminsite-actions>` -- for particular objects. -There's a few ways you can disable actions: - -Disabling a site-wide action -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: AdminSite.disable_action(name) - - If you need to disable a :ref:`site-wide action <adminsite-actions>` you can - call :meth:`AdminSite.disable_action()`. - - For example, you can use this method to remove the built-in "delete selected - objects" action:: - - admin.site.disable_action('delete_selected') - - Once you've done the above, that action will no longer be available - site-wide. - - If, however, you need to re-enable a globally-disabled action for one - particular model, simply list it explicitly in your ``ModelAdmin.actions`` - list:: - - # Globally disable delete selected - admin.site.disable_action('delete_selected') - - # This ModelAdmin will not have delete_selected available - class SomeModelAdmin(admin.ModelAdmin): - actions = ['some_other_action'] - ... - - # This one will - class AnotherModelAdmin(admin.ModelAdmin): - actions = ['delete_selected', 'a_third_action'] - ... - - -Disabling all actions for a particular :class:`ModelAdmin` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you want *no* bulk actions available for a given :class:`ModelAdmin`, simply -set :attr:`ModelAdmin.actions` to ``None``:: - - class MyModelAdmin(admin.ModelAdmin): - actions = None - -This tells the :class:`ModelAdmin` to not display or allow any actions, -including any :ref:`site-wide actions <adminsite-actions>`. - -Conditionally enabling or disabling actions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. method:: ModelAdmin.get_actions(request) - - Finally, you can conditionally enable or disable actions on a per-request - (and hence per-user basis) by overriding :meth:`ModelAdmin.get_actions`. - - This returns a dictionary of actions allowed. The keys are action names, and - the values are ``(function, name, short_description)`` tuples. - - Most of the time you'll use this method to conditionally remove actions from - the list gathered by the superclass. For example, if I only wanted users - whose names begin with 'J' to be able to delete objects in bulk, I could do - the following:: - - class MyModelAdmin(admin.ModelAdmin): - ... - - def get_actions(self, request): - actions = super(MyModelAdmin, self).get_actions(request) - if request.user.username[0].upper() != 'J': - del actions['delete_selected'] - return actions - - diff --git a/parts/django/docs/ref/contrib/admin/admindocs.txt b/parts/django/docs/ref/contrib/admin/admindocs.txt deleted file mode 100644 index 6743921..0000000 --- a/parts/django/docs/ref/contrib/admin/admindocs.txt +++ /dev/null @@ -1,161 +0,0 @@ -========================================
-The Django admin documentation generator
-========================================
-
-.. module:: django.contrib.admindocs
- :synopsis: Django's admin documentation generator.
-
-.. currentmodule:: django.contrib.admindocs
-
-Django's :mod:`~django.contrib.admindocs` app pulls documentation from the
-docstrings of models, views, template tags, and template filters for any app in
-:setting:`INSTALLED_APPS` and makes that documentation available from the
-:mod:`Django admin <django.contrib.admin>`.
-
-In addition to providing offline documentation for all template tags and
-template filters that ship with Django, you may utilize admindocs to quickly
-document your own code.
-
-Overview
-========
-
-To activate the :mod:`~django.contrib.admindocs`, you will need to do
-the following:
-
- * Add :mod:`django.contrib.admindocs` to your :setting:`INSTALLED_APPS`.
- * Add ``(r'^admin/doc/', include('django.contrib.admindocs.urls'))`` to
- your :data:`urlpatterns`. Make sure it's included *before* the
- ``r'^admin/'`` entry, so that requests to ``/admin/doc/`` don't get
- handled by the latter entry.
- * Install the docutils Python module (http://docutils.sf.net/).
- * **Optional:** Linking to templates requires the :setting:`ADMIN_FOR`
- setting to be configured.
- * **Optional:** Using the admindocs bookmarklets requires the
- :mod:`XViewMiddleware<django.middleware.doc>` to be installed.
-
-Once those steps are complete, you can start browsing the documentation by
-going to your admin interface and clicking the "Documentation" link in the
-upper right of the page.
-
-Documentation helpers
-=====================
-
-The following special markup can be used in your docstrings to easily create
-hyperlinks to other components:
-
-================= =======================
-Django Component reStructuredText roles
-================= =======================
-Models ``:model:`appname.ModelName```
-Views ``:view:`appname.view_name```
-Template tags ``:tag:`tagname```
-Template filters ``:filter:`filtername```
-Templates ``:template:`path/to/template.html```
-================= =======================
-
-Model reference
-===============
-
-The **models** section of the ``admindocs`` page describes each model in the
-system along with all the fields and methods available on it. Relationships to
-other models appear as hyperlinks. Descriptions are pulled from ``help_text``
-attributes on fields or from docstrings on model methods.
-
-A model with useful documentation might look like this::
-
- class BlogEntry(models.Model):
- """
- Stores a single blog entry, related to :model:`blog.Blog` and
- :model:`auth.User`.
-
- """
- slug = models.SlugField(help_text="A short label, generally used in URLs.")
- author = models.ForeignKey(User)
- blog = models.ForeignKey(Blog)
- ...
-
- def publish(self):
- """Makes the blog entry live on the site."""
- ...
-
-View reference
-==============
-
-Each URL in your site has a separate entry in the ``admindocs`` page, and
-clicking on a given URL will show you the corresponding view. Helpful things
-you can document in your view function docstrings include:
-
- * A short description of what the view does.
- * The **context**, or a list of variables available in the view's template.
- * The name of the template or templates that are used for that view.
-
-For example::
-
- from myapp.models import MyModel
-
- def my_view(request, slug):
- """
- Display an individual :model:`myapp.MyModel`.
-
- **Context**
-
- ``RequestContext``
-
- ``mymodel``
- An instance of :model:`myapp.MyModel`.
-
- **Template:**
-
- :template:`myapp/my_template.html`
-
- """
- return render_to_response('myapp/my_template.html', {
- 'mymodel': MyModel.objects.get(slug=slug)
- }, context_instance=RequestContext(request))
-
-
-Template tags and filters reference
-===================================
-
-The **tags** and **filters** ``admindocs`` sections describe all the tags and
-filters that come with Django (in fact, the :ref:`built-in tag reference
-<ref-templates-builtins-tags>` and :ref:`built-in filter reference
-<ref-templates-builtins-filters>` documentation come directly from those
-pages). Any tags or filters that you create or are added by a third-party app
-will show up in these sections as well.
-
-
-Template reference
-==================
-
-While ``admindocs`` does not include a place to document templates by
-themselves, if you use the ``:template:`path/to/template.html``` syntax in a
-docstring the resulting page will verify the path of that template with
-Django's :ref:`template loaders <template-loaders>`. This can be a handy way to
-check if the specified template exists and to show where on the filesystem that
-template is stored.
-
-
-Included Bookmarklets
-=====================
-
-Several useful bookmarklets are available from the ``admindocs`` page:
-
- Documentation for this page
- Jumps you from any page to the documentation for the view that generates
- that page.
-
- Show object ID
- Shows the content-type and unique ID for pages that represent a single
- object.
-
- Edit this object
- Jumps to the admin page for pages that represent a single object.
-
-Using these bookmarklets requires that you are either logged into the
-:mod:`Django admin <django.contrib.admin>` as a
-:class:`~django.contrib.auth.models.User` with
-:attr:`~django.contrib.auth.models.User.is_staff` set to `True`, or
-that the :mod:`django.middleware.doc` middleware and
-:mod:`XViewMiddleware <django.middleware.doc>` are installed and you
-are accessing the site from an IP address listed in :setting:`INTERNAL_IPS`.
diff --git a/parts/django/docs/ref/contrib/admin/index.txt b/parts/django/docs/ref/contrib/admin/index.txt deleted file mode 100644 index b99cfdc..0000000 --- a/parts/django/docs/ref/contrib/admin/index.txt +++ /dev/null @@ -1,1613 +0,0 @@ -===================== -The Django admin site -===================== - -.. module:: django.contrib.admin - :synopsis: Django's admin site. - -One of the most powerful parts of Django is the automatic admin interface. It -reads metadata in your model to provide a powerful and production-ready -interface that content producers can immediately use to start adding content to -the site. In this document, we discuss how to activate, use and customize -Django's admin interface. - -.. admonition:: Note - - The admin site has been refactored significantly since Django 0.96. This - document describes the newest version of the admin site, which allows for - much richer customization. If you follow the development of Django itself, - you may have heard this described as "newforms-admin." - -Overview -======== - -There are six steps in activating the Django admin site: - - 1. Add ``'django.contrib.admin'`` to your :setting:`INSTALLED_APPS` - setting. - - 2. Admin has two dependencies - ``django.contrib.auth`` and - ``django.contrib.contenttypes``. If these applications are not - in your :setting:`INSTALLED_APPS` list, add them. - - 3. Determine which of your application's models should be editable in the - admin interface. - - 4. For each of those models, optionally create a ``ModelAdmin`` class that - encapsulates the customized admin functionality and options for that - particular model. - - 5. Instantiate an ``AdminSite`` and tell it about each of your models and - ``ModelAdmin`` classes. - - 6. Hook the ``AdminSite`` instance into your URLconf. - -Other topics ------------- - -.. toctree:: - :maxdepth: 1 - - actions - admindocs - -.. seealso:: - - For information about serving the media files (images, JavaScript, and CSS) - associated with the admin in production, see :ref:`serving-media-files`. - -``ModelAdmin`` objects -====================== - -.. class:: ModelAdmin - -The ``ModelAdmin`` class is the representation of a model in the admin -interface. These are stored in a file named ``admin.py`` in your application. -Let's take a look at a very simple example of the ``ModelAdmin``:: - - from django.contrib import admin - from myproject.myapp.models import Author - - class AuthorAdmin(admin.ModelAdmin): - pass - admin.site.register(Author, AuthorAdmin) - -.. admonition:: Do you need a ``ModelAdmin`` object at all? - - In the preceding example, the ``ModelAdmin`` class doesn't define any - custom values (yet). As a result, the default admin interface will be - provided. If you are happy with the default admin interface, you don't - need to define a ``ModelAdmin`` object at all -- you can register the - model class without providing a ``ModelAdmin`` description. The - preceding example could be simplified to:: - - from django.contrib import admin - from myproject.myapp.models import Author - - admin.site.register(Author) - -``ModelAdmin`` Options ----------------------- - -The ``ModelAdmin`` is very flexible. It has several options for dealing with -customizing the interface. All options are defined on the ``ModelAdmin`` -subclass:: - - class AuthorAdmin(admin.ModelAdmin): - date_hierarchy = 'pub_date' - -.. attribute:: ModelAdmin.date_hierarchy - -Set ``date_hierarchy`` to the name of a ``DateField`` or ``DateTimeField`` in -your model, and the change list page will include a date-based drilldown -navigation by that field. - -Example:: - - date_hierarchy = 'pub_date' - -.. attribute:: ModelAdmin.form - -By default a ``ModelForm`` is dynamically created for your model. It is used -to create the form presented on both the add/change pages. You can easily -provide your own ``ModelForm`` to override any default form behavior on the -add/change pages. - -For an example see the section `Adding custom validation to the admin`_. - -.. attribute:: ModelAdmin.fieldsets - -Set ``fieldsets`` to control the layout of admin "add" and "change" pages. - -``fieldsets`` is a list of two-tuples, in which each two-tuple represents a -``<fieldset>`` on the admin form page. (A ``<fieldset>`` is a "section" of the -form.) - -The two-tuples are in the format ``(name, field_options)``, where ``name`` is a -string representing the title of the fieldset and ``field_options`` is a -dictionary of information about the fieldset, including a list of fields to be -displayed in it. - -A full example, taken from the ``django.contrib.flatpages.FlatPage`` model:: - - class FlatPageAdmin(admin.ModelAdmin): - fieldsets = ( - (None, { - 'fields': ('url', 'title', 'content', 'sites') - }), - ('Advanced options', { - 'classes': ('collapse',), - 'fields': ('enable_comments', 'registration_required', 'template_name') - }), - ) - -This results in an admin page that looks like: - - .. image:: _images/flatfiles_admin.png - -If ``fieldsets`` isn't given, Django will default to displaying each field -that isn't an ``AutoField`` and has ``editable=True``, in a single fieldset, -in the same order as the fields are defined in the model. - -The ``field_options`` dictionary can have the following keys: - - * ``fields`` - A tuple of field names to display in this fieldset. This key is - required. - - Example:: - - { - 'fields': ('first_name', 'last_name', 'address', 'city', 'state'), - } - - To display multiple fields on the same line, wrap those fields in - their own tuple. In this example, the ``first_name`` and ``last_name`` - fields will display on the same line:: - - { - 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'), - } - - .. versionadded:: 1.2 - - ``fields`` can contain values defined in - :attr:`ModelAdmin.readonly_fields` to be displayed as read-only. - - * ``classes`` - A list containing extra CSS classes to apply to the fieldset. - - Example:: - - { - 'classes': ['wide', 'extrapretty'], - } - - Two useful classes defined by the default admin site stylesheet are - ``collapse`` and ``wide``. Fieldsets with the ``collapse`` style will - be initially collapsed in the admin and replaced with a small - "click to expand" link. Fieldsets with the ``wide`` style will be - given extra horizontal space. - - * ``description`` - A string of optional extra text to be displayed at the top of each - fieldset, under the heading of the fieldset. - - Note that this value is *not* HTML-escaped when it's displayed in - the admin interface. This lets you include HTML if you so desire. - Alternatively you can use plain text and - ``django.utils.html.escape()`` to escape any HTML special - characters. - -.. attribute:: ModelAdmin.fields - -Use this option as an alternative to ``fieldsets`` if the layout does not -matter and if you want to only show a subset of the available fields in the -form. For example, you could define a simpler version of the admin form for -the ``django.contrib.flatpages.FlatPage`` model as follows:: - - class FlatPageAdmin(admin.ModelAdmin): - fields = ('url', 'title', 'content') - -In the above example, only the fields 'url', 'title' and 'content' will be -displayed, sequentially, in the form. - -.. versionadded:: 1.2 - -``fields`` can contain values defined in :attr:`ModelAdmin.readonly_fields` -to be displayed as read-only. - -.. admonition:: Note - - This ``fields`` option should not be confused with the ``fields`` - dictionary key that is within the ``fieldsets`` option, as described in - the previous section. - -.. attribute:: ModelAdmin.exclude - -This attribute, if given, should be a list of field names to exclude from the -form. - -For example, let's consider the following model:: - - class Author(models.Model): - name = models.CharField(max_length=100) - title = models.CharField(max_length=3) - birth_date = models.DateField(blank=True, null=True) - -If you want a form for the ``Author`` model that includes only the ``name`` -and ``title`` fields, you would specify ``fields`` or ``exclude`` like this:: - - class AuthorAdmin(admin.ModelAdmin): - fields = ('name', 'title') - - class AuthorAdmin(admin.ModelAdmin): - exclude = ('birth_date',) - -Since the Author model only has three fields, ``name``, ``title``, and -``birth_date``, the forms resulting from the above declarations will contain -exactly the same fields. - -.. attribute:: ModelAdmin.filter_horizontal - -Use a nifty unobtrusive JavaScript "filter" interface instead of the -usability-challenged ``<select multiple>`` in the admin form. The value is a -list of fields that should be displayed as a horizontal filter interface. See -``filter_vertical`` to use a vertical interface. - -.. attribute:: ModelAdmin.filter_vertical - -Same as ``filter_horizontal``, but is a vertical display of the filter -interface. - -.. attribute:: ModelAdmin.list_display - -Set ``list_display`` to control which fields are displayed on the change list -page of the admin. - -Example:: - - list_display = ('first_name', 'last_name') - -If you don't set ``list_display``, the admin site will display a single column -that displays the ``__unicode__()`` representation of each object. - -You have four possible values that can be used in ``list_display``: - - * A field of the model. For example:: - - class PersonAdmin(admin.ModelAdmin): - list_display = ('first_name', 'last_name') - - * A callable that accepts one parameter for the model instance. For - example:: - - def upper_case_name(obj): - return ("%s %s" % (obj.first_name, obj.last_name)).upper() - upper_case_name.short_description = 'Name' - - class PersonAdmin(admin.ModelAdmin): - list_display = (upper_case_name,) - - * A string representing an attribute on the ``ModelAdmin``. This behaves - same as the callable. For example:: - - class PersonAdmin(admin.ModelAdmin): - list_display = ('upper_case_name',) - - def upper_case_name(self, obj): - return ("%s %s" % (obj.first_name, obj.last_name)).upper() - upper_case_name.short_description = 'Name' - - * A string representing an attribute on the model. This behaves almost - the same as the callable, but ``self`` in this context is the model - instance. Here's a full model example:: - - class Person(models.Model): - name = models.CharField(max_length=50) - birthday = models.DateField() - - def decade_born_in(self): - return self.birthday.strftime('%Y')[:3] + "0's" - decade_born_in.short_description = 'Birth decade' - - class PersonAdmin(admin.ModelAdmin): - list_display = ('name', 'decade_born_in') - -A few special cases to note about ``list_display``: - - * If the field is a ``ForeignKey``, Django will display the - ``__unicode__()`` of the related object. - - * ``ManyToManyField`` fields aren't supported, because that would entail - executing a separate SQL statement for each row in the table. If you - want to do this nonetheless, give your model a custom method, and add - that method's name to ``list_display``. (See below for more on custom - methods in ``list_display``.) - - * If the field is a ``BooleanField`` or ``NullBooleanField``, Django will - display a pretty "on" or "off" icon instead of ``True`` or ``False``. - - * If the string given is a method of the model, ``ModelAdmin`` or a - callable, Django will HTML-escape the output by default. If you'd rather - not escape the output of the method, give the method an ``allow_tags`` - attribute whose value is ``True``. - - Here's a full example model:: - - class Person(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - color_code = models.CharField(max_length=6) - - def colored_name(self): - return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name) - colored_name.allow_tags = True - - class PersonAdmin(admin.ModelAdmin): - list_display = ('first_name', 'last_name', 'colored_name') - - * If the string given is a method of the model, ``ModelAdmin`` or a - callable that returns True or False Django will display a pretty "on" or - "off" icon if you give the method a ``boolean`` attribute whose value is - ``True``. - - Here's a full example model:: - - class Person(models.Model): - first_name = models.CharField(max_length=50) - birthday = models.DateField() - - def born_in_fifties(self): - return self.birthday.strftime('%Y')[:3] == '195' - born_in_fifties.boolean = True - - class PersonAdmin(admin.ModelAdmin): - list_display = ('name', 'born_in_fifties') - - - * The ``__str__()`` and ``__unicode__()`` methods are just as valid in - ``list_display`` as any other model method, so it's perfectly OK to do - this:: - - list_display = ('__unicode__', 'some_other_field') - - * Usually, elements of ``list_display`` that aren't actual database fields - can't be used in sorting (because Django does all the sorting at the - database level). - - However, if an element of ``list_display`` represents a certain database - field, you can indicate this fact by setting the ``admin_order_field`` - attribute of the item. - - For example:: - - class Person(models.Model): - first_name = models.CharField(max_length=50) - color_code = models.CharField(max_length=6) - - def colored_first_name(self): - return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name) - colored_first_name.allow_tags = True - colored_first_name.admin_order_field = 'first_name' - - class PersonAdmin(admin.ModelAdmin): - list_display = ('first_name', 'colored_first_name') - - The above will tell Django to order by the ``first_name`` field when - trying to sort by ``colored_first_name`` in the admin. - -.. attribute:: ModelAdmin.list_display_links - -Set ``list_display_links`` to control which fields in ``list_display`` should -be linked to the "change" page for an object. - -By default, the change list page will link the first column -- the first field -specified in ``list_display`` -- to the change page for each item. But -``list_display_links`` lets you change which columns are linked. Set -``list_display_links`` to a list or tuple of field names (in the same format as -``list_display``) to link. - -``list_display_links`` can specify one or many field names. As long as the -field names appear in ``list_display``, Django doesn't care how many (or how -few) fields are linked. The only requirement is: If you want to use -``list_display_links``, you must define ``list_display``. - -In this example, the ``first_name`` and ``last_name`` fields will be linked on -the change list page:: - - class PersonAdmin(admin.ModelAdmin): - list_display = ('first_name', 'last_name', 'birthday') - list_display_links = ('first_name', 'last_name') - -.. _admin-list-editable: - -.. attribute:: ModelAdmin.list_editable - -.. versionadded:: 1.1 - -Set ``list_editable`` to a list of field names on the model which will allow -editing on the change list page. That is, fields listed in ``list_editable`` -will be displayed as form widgets on the change list page, allowing users to -edit and save multiple rows at once. - -.. note:: - - ``list_editable`` interacts with a couple of other options in particular - ways; you should note the following rules: - - * Any field in ``list_editable`` must also be in ``list_display``. You - can't edit a field that's not displayed! - - * The same field can't be listed in both ``list_editable`` and - ``list_display_links`` -- a field can't be both a form and a link. - - You'll get a validation error if either of these rules are broken. - -.. attribute:: ModelAdmin.list_filter - -Set ``list_filter`` to activate filters in the right sidebar of the change list -page of the admin. This should be a list of field names, and each specified -field should be either a ``BooleanField``, ``CharField``, ``DateField``, -``DateTimeField``, ``IntegerField`` or ``ForeignKey``. - -This example, taken from the ``django.contrib.auth.models.User`` model, shows -how both ``list_display`` and ``list_filter`` work:: - - class UserAdmin(admin.ModelAdmin): - list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff') - list_filter = ('is_staff', 'is_superuser') - -The above code results in an admin change list page that looks like this: - - .. image:: _images/users_changelist.png - -(This example also has ``search_fields`` defined. See below.) - -.. attribute:: ModelAdmin.list_per_page - -Set ``list_per_page`` to control how many items appear on each paginated admin -change list page. By default, this is set to ``100``. - -.. attribute:: ModelAdmin.list_select_related - -Set ``list_select_related`` to tell Django to use -:meth:`~django.db.models.QuerySet.select_related` in retrieving the list of -objects on the admin change list page. This can save you a bunch of database -queries. - -The value should be either ``True`` or ``False``. Default is ``False``. - -Note that Django will use :meth:`~django.db.models.QuerySet.select_related`, -regardless of this setting, if one of the ``list_display`` fields is a -``ForeignKey``. - -.. attribute:: ModelAdmin.inlines - -See ``InlineModelAdmin`` objects below. - -.. attribute:: ModelAdmin.ordering - -Set ``ordering`` to specify how objects on the admin change list page should be -ordered. This should be a list or tuple in the same format as a model's -``ordering`` parameter. - -If this isn't provided, the Django admin will use the model's default ordering. - -.. admonition:: Note - - Django will only honor the first element in the list/tuple; any others - will be ignored. - -.. attribute:: ModelAdmin.prepopulated_fields - -Set ``prepopulated_fields`` to a dictionary mapping field names to the fields -it should prepopulate from:: - - class ArticleAdmin(admin.ModelAdmin): - prepopulated_fields = {"slug": ("title",)} - -When set, the given fields will use a bit of JavaScript to populate from the -fields assigned. The main use for this functionality is to automatically -generate the value for ``SlugField`` fields from one or more other fields. The -generated value is produced by concatenating the values of the source fields, -and then by transforming that result into a valid slug (e.g. substituting -dashes for spaces). - -``prepopulated_fields`` doesn't accept ``DateTimeField``, ``ForeignKey``, nor -``ManyToManyField`` fields. - -.. attribute:: ModelAdmin.radio_fields - -By default, Django's admin uses a select-box interface (<select>) for -fields that are ``ForeignKey`` or have ``choices`` set. If a field is present -in ``radio_fields``, Django will use a radio-button interface instead. -Assuming ``group`` is a ``ForeignKey`` on the ``Person`` model:: - - class PersonAdmin(admin.ModelAdmin): - radio_fields = {"group": admin.VERTICAL} - -You have the choice of using ``HORIZONTAL`` or ``VERTICAL`` from the -``django.contrib.admin`` module. - -Don't include a field in ``radio_fields`` unless it's a ``ForeignKey`` or has -``choices`` set. - -.. attribute:: ModelAdmin.raw_id_fields - -By default, Django's admin uses a select-box interface (<select>) for -fields that are ``ForeignKey``. Sometimes you don't want to incur the -overhead of having to select all the related instances to display in the -drop-down. - -``raw_id_fields`` is a list of fields you would like to change -into a ``Input`` widget for either a ``ForeignKey`` or ``ManyToManyField``:: - - class ArticleAdmin(admin.ModelAdmin): - raw_id_fields = ("newspaper",) - -.. attribute:: ModelAdmin.readonly_fields - -.. versionadded:: 1.2 - -By default the admin shows all fields as editable. Any fields in this option -(which should be a ``list`` or ``tuple``) will display its data as-is and -non-editable. This option behaves nearly identical to :attr:`ModelAdmin.list_display`. -Usage is the same, however, when you specify :attr:`ModelAdmin.fields` or -:attr:`ModelAdmin.fieldsets` the read-only fields must be present to be shown -(they are ignored otherwise). - -If ``readonly_fields`` is used without defining explicit ordering through -:attr:`ModelAdmin.fields` or :attr:`ModelAdmin.fieldsets` they will be added -last after all editable fields. - -.. attribute:: ModelAdmin.save_as - -Set ``save_as`` to enable a "save as" feature on admin change forms. - -Normally, objects have three save options: "Save", "Save and continue editing" -and "Save and add another". If ``save_as`` is ``True``, "Save and add another" -will be replaced by a "Save as" button. - -"Save as" means the object will be saved as a new object (with a new ID), -rather than the old object. - -By default, ``save_as`` is set to ``False``. - -.. attribute:: ModelAdmin.save_on_top - -Set ``save_on_top`` to add save buttons across the top of your admin change -forms. - -Normally, the save buttons appear only at the bottom of the forms. If you set -``save_on_top``, the buttons will appear both on the top and the bottom. - -By default, ``save_on_top`` is set to ``False``. - -.. attribute:: ModelAdmin.search_fields - -Set ``search_fields`` to enable a search box on the admin change list page. -This should be set to a list of field names that will be searched whenever -somebody submits a search query in that text box. - -These fields should be some kind of text field, such as ``CharField`` or -``TextField``. You can also perform a related lookup on a ``ForeignKey`` or -``ManyToManyField`` with the lookup API "follow" notation:: - - search_fields = ['foreign_key__related_fieldname'] - -For example, if you have a blog entry with an author, the following definition -would enable search blog entries by the email address of the author:: - - search_fields = ['user__email'] - -When somebody does a search in the admin search box, Django splits the search -query into words and returns all objects that contain each of the words, case -insensitive, where each word must be in at least one of ``search_fields``. For -example, if ``search_fields`` is set to ``['first_name', 'last_name']`` and a -user searches for ``john lennon``, Django will do the equivalent of this SQL -``WHERE`` clause:: - - WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') - AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%') - -For faster and/or more restrictive searches, prefix the field name -with an operator: - -``^`` - Matches the beginning of the field. For example, if ``search_fields`` is - set to ``['^first_name', '^last_name']`` and a user searches for - ``john lennon``, Django will do the equivalent of this SQL ``WHERE`` - clause:: - - WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%') - AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%') - - This query is more efficient than the normal ``'%john%'`` query, because - the database only needs to check the beginning of a column's data, rather - than seeking through the entire column's data. Plus, if the column has an - index on it, some databases may be able to use the index for this query, - even though it's a ``LIKE`` query. - -``=`` - Matches exactly, case-insensitive. For example, if - ``search_fields`` is set to ``['=first_name', '=last_name']`` and - a user searches for ``john lennon``, Django will do the equivalent - of this SQL ``WHERE`` clause:: - - WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john') - AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon') - - Note that the query input is split by spaces, so, following this example, - it's currently not possible to search for all records in which - ``first_name`` is exactly ``'john winston'`` (containing a space). - -``@`` - Performs a full-text match. This is like the default search method but uses - an index. Currently this is only available for MySQL. - -.. attribute:: ModelAdmin.formfield_overrides - -.. versionadded:: 1.1 - -This provides a quick-and-dirty way to override some of the -:class:`~django.forms.Field` options for use in the admin. -``formfield_overrides`` is a dictionary mapping a field class to a dict of -arguments to pass to the field at construction time. - -Since that's a bit abstract, let's look at a concrete example. The most common -use of ``formfield_overrides`` is to add a custom widget for a certain type of -field. So, imagine we've written a ``RichTextEditorWidget`` that we'd like to -use for large text fields instead of the default ``<textarea>``. Here's how we'd -do that:: - - from django.db import models - from django.contrib import admin - - # Import our custom widget and our model from where they're defined - from myapp.widgets import RichTextEditorWidget - from myapp.models import MyModel - - class MyModelAdmin(admin.ModelAdmin): - formfield_overrides = { - models.TextField: {'widget': RichTextEditorWidget}, - } - -Note that the key in the dictionary is the actual field class, *not* a string. -The value is another dictionary; these arguments will be passed to -:meth:`~django.forms.Field.__init__`. See :doc:`/ref/forms/api` for details. - -.. warning:: - - If you want to use a custom widget with a relation field (i.e. - :class:`~django.db.models.ForeignKey` or - :class:`~django.db.models.ManyToManyField`), make sure you haven't included - that field's name in ``raw_id_fields`` or ``radio_fields``. - - ``formfield_overrides`` won't let you change the widget on relation fields - that have ``raw_id_fields`` or ``radio_fields`` set. That's because - ``raw_id_fields`` and ``radio_fields`` imply custom widgets of their own. - -.. attribute:: ModelAdmin.actions - -.. versionadded:: 1.1 - -A list of actions to make available on the change list page. See -:doc:`/ref/contrib/admin/actions` for details. - -.. attribute:: ModelAdmin.actions_on_top -.. attribute:: ModelAdmin.actions_on_bottom - -.. versionadded:: 1.1 - -Controls where on the page the actions bar appears. By default, the admin -changelist displays actions at the top of the page (``actions_on_top = True; -actions_on_bottom = False``). - -.. attribute:: ModelAdmin.actions_selection_counter - -.. versionadded:: 1.2 - -Controls whether a selection counter is display next to the action dropdown. -By default, the admin changelist will display it -(``actions_selection_counter = True``). - -Custom template options -~~~~~~~~~~~~~~~~~~~~~~~ - -The `Overriding Admin Templates`_ section describes how to override or extend -the default admin templates. Use the following options to override the default -templates used by the :class:`ModelAdmin` views: - -.. attribute:: ModelAdmin.add_form_template - - .. versionadded:: 1.2 - - Path to a custom template, used by :meth:`add_view`. - -.. attribute:: ModelAdmin.change_form_template - - Path to a custom template, used by :meth:`change_view`. - -.. attribute:: ModelAdmin.change_list_template - - Path to a custom template, used by :meth:`changelist_view`. - -.. attribute:: ModelAdmin.delete_confirmation_template - - Path to a custom template, used by :meth:`delete_view` for displaying a - confirmation page when deleting one or more objects. - -.. attribute:: ModelAdmin.delete_selected_confirmation_template - - .. versionadded:: 1.2 - - Path to a custom template, used by the :meth:`delete_selected` - action method for displaying a confirmation page when deleting one - or more objects. See the :doc:`actions - documentation</ref/contrib/admin/actions>`. - -.. attribute:: ModelAdmin.object_history_template - - Path to a custom template, used by :meth:`history_view`. - - -.. _model-admin-methods: - -``ModelAdmin`` methods ----------------------- - -.. method:: ModelAdmin.save_model(self, request, obj, form, change) - -The ``save_model`` method is given the ``HttpRequest``, a model instance, -a ``ModelForm`` instance and a boolean value based on whether it is adding or -changing the object. Here you can do any pre- or post-save operations. - -For example to attach ``request.user`` to the object prior to saving:: - - class ArticleAdmin(admin.ModelAdmin): - def save_model(self, request, obj, form, change): - obj.user = request.user - obj.save() - -.. method:: ModelAdmin.save_formset(self, request, form, formset, change) - -The ``save_formset`` method is given the ``HttpRequest``, the parent -``ModelForm`` instance and a boolean value based on whether it is adding or -changing the parent object. - -For example to attach ``request.user`` to each changed formset -model instance:: - - class ArticleAdmin(admin.ModelAdmin): - def save_formset(self, request, form, formset, change): - instances = formset.save(commit=False) - for instance in instances: - instance.user = request.user - instance.save() - formset.save_m2m() - -.. method:: ModelAdmin.get_readonly_fields(self, request, obj=None) - -.. versionadded:: 1.2 - -The ``get_readonly_fields`` method is given the ``HttpRequest`` and the -``obj`` being edited (or ``None`` on an add form) and is expected to return a -``list`` or ``tuple`` of field names that will be displayed as read-only, as -described above in the :attr:`ModelAdmin.readonly_fields` section. - -.. method:: ModelAdmin.get_urls(self) - -.. versionadded:: 1.1 - -The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for -that ModelAdmin in the same way as a URLconf. Therefore you can extend them as -documented in :doc:`/topics/http/urls`:: - - class MyModelAdmin(admin.ModelAdmin): - def get_urls(self): - urls = super(MyModelAdmin, self).get_urls() - my_urls = patterns('', - (r'^my_view/$', self.my_view) - ) - return my_urls + urls - -.. note:: - - Notice that the custom patterns are included *before* the regular admin - URLs: the admin URL patterns are very permissive and will match nearly - anything, so you'll usually want to prepend your custom URLs to the built-in - ones. - -However, the ``self.my_view`` function registered above suffers from two -problems: - - * It will *not* perform any permission checks, so it will be accessible to - the general public. - * It will *not* provide any header details to prevent caching. This means if - the page retrieves data from the database, and caching middleware is - active, the page could show outdated information. - -Since this is usually not what you want, Django provides a convenience wrapper -to check permissions and mark the view as non-cacheable. This wrapper is -:meth:`AdminSite.admin_view` (i.e. ``self.admin_site.admin_view`` inside a -``ModelAdmin`` instance); use it like so:: - - class MyModelAdmin(admin.ModelAdmin): - def get_urls(self): - urls = super(MyModelAdmin, self).get_urls() - my_urls = patterns('', - (r'^my_view/$', self.admin_site.admin_view(self.my_view)) - ) - return my_urls + urls - -Notice the wrapped view in the fifth line above:: - - (r'^my_view/$', self.admin_site.admin_view(self.my_view)) - -This wrapping will protect ``self.my_view`` from unauthorized access and will -apply the ``django.views.decorators.cache.never_cache`` decorator to make sure -it is not cached if the cache middleware is active. - -If the page is cacheable, but you still want the permission check to be performed, -you can pass a ``cacheable=True`` argument to :meth:`AdminSite.admin_view`:: - - (r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True)) - -.. method:: ModelAdmin.formfield_for_foreignkey(self, db_field, request, **kwargs) - -.. versionadded:: 1.1 - -The ``formfield_for_foreignkey`` method on a ``ModelAdmin`` allows you to -override the default formfield for a foreign key field. For example, to -return a subset of objects for this foreign key field based on the user:: - - class MyModelAdmin(admin.ModelAdmin): - def formfield_for_foreignkey(self, db_field, request, **kwargs): - if db_field.name == "car": - kwargs["queryset"] = Car.objects.filter(owner=request.user) - return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) - -This uses the ``HttpRequest`` instance to filter the ``Car`` foreign key field -to only display the cars owned by the ``User`` instance. - -.. method:: ModelAdmin.formfield_for_manytomany(self, db_field, request, **kwargs) - -.. versionadded:: 1.1 - -Like the ``formfield_for_foreignkey`` method, the ``formfield_for_manytomany`` -method can be overridden to change the default formfield for a many to many -field. For example, if an owner can own multiple cars and cars can belong -to multiple owners -- a many to many relationship -- you could filter the -``Car`` foreign key field to only display the cars owned by the ``User``:: - - class MyModelAdmin(admin.ModelAdmin): - def formfield_for_manytomany(self, db_field, request, **kwargs): - if db_field.name == "cars": - kwargs["queryset"] = Car.objects.filter(owner=request.user) - return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs) - -.. method:: ModelAdmin.queryset(self, request) - -The ``queryset`` method on a ``ModelAdmin`` returns a -:class:`~django.db.models.QuerySet` of all model instances that can be -edited by the admin site. One use case for overriding this method is -to show objects owned by the logged-in user:: - - class MyModelAdmin(admin.ModelAdmin): - def queryset(self, request): - qs = super(MyModelAdmin, self).queryset(request) - if request.user.is_superuser: - return qs - return qs.filter(author=request.user) - -.. method:: ModelAdmin.message_user(request, message) - - Sends a message to the user. The default implementation creates a message - using the :mod:`django.contrib.messages` backend. See the - :ref:`custom ModelAdmin example <custom-admin-action>`. - -Other methods -~~~~~~~~~~~~~ - -.. method:: ModelAdmin.add_view(self, request, form_url='', extra_context=None) - -Django view for the model instance addition page. See note below. - -.. method:: ModelAdmin.change_view(self, request, object_id, extra_context=None) - -Django view for the model instance edition page. See note below. - -.. method:: ModelAdmin.changelist_view(self, request, extra_context=None) - -Django view for the model instances change list/actions page. See note below. - -.. method:: ModelAdmin.delete_view(self, request, object_id, extra_context=None) - -Django view for the model instance(s) deletion confirmation page. See note below. - -.. method:: ModelAdmin.history_view(self, request, object_id, extra_context=None) - -Django view for the page that shows the modification history for a given model -instance. - -Unlike the hook-type ``ModelAdmin`` methods detailed in the previous section, -these five methods are in reality designed to be invoked as Django views from -the admin application URL dispatching handler to render the pages that deal -with model instances CRUD operations. As a result, completely overriding these -methods will significantly change the behavior of the admin application. - -One common reason for overriding these methods is to augment the context data -that is provided to the template that renders the view. In the following -example, the change view is overridden so that the rendered template is -provided some extra mapping data that would not otherwise be available:: - - class MyModelAdmin(admin.ModelAdmin): - - # A template for a very customized change view: - change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html' - - def get_osm_info(self): - # ... - - def change_view(self, request, object_id, extra_context=None): - my_context = { - 'osm_data': self.get_osm_info(), - } - return super(MyModelAdmin, self).change_view(request, object_id, - extra_context=my_context) - -``ModelAdmin`` media definitions --------------------------------- - -There are times where you would like add a bit of CSS and/or JavaScript to -the add/change views. This can be accomplished by using a Media inner class -on your ``ModelAdmin``:: - - class ArticleAdmin(admin.ModelAdmin): - class Media: - css = { - "all": ("my_styles.css",) - } - js = ("my_code.js",) - -Keep in mind that this will be prepended with ``MEDIA_URL``. The same rules -apply as :doc:`regular media definitions on forms </topics/forms/media>`. - -Django admin Javascript makes use of the `jQuery`_ library. To avoid -conflict with user scripts, Django's jQuery is namespaced as -``django.jQuery``. If you want to use jQuery in your own admin -JavaScript without including a second copy, you can use the -``django.jQuery`` object on changelist and add/edit views. - -.. _jQuery: http://jquery.com - -Adding custom validation to the admin -------------------------------------- - -Adding custom validation of data in the admin is quite easy. The automatic admin -interface reuses :mod:`django.forms`, and the ``ModelAdmin`` class gives you -the ability define your own form:: - - class ArticleAdmin(admin.ModelAdmin): - form = MyArticleAdminForm - -``MyArticleAdminForm`` can be defined anywhere as long as you import where -needed. Now within your form you can add your own custom validation for -any field:: - - class MyArticleAdminForm(forms.ModelForm): - class Meta: - model = Article - - def clean_name(self): - # do something that validates your data - return self.cleaned_data["name"] - -It is important you use a ``ModelForm`` here otherwise things can break. See the -:doc:`forms </ref/forms/index>` documentation on :doc:`custom validation -</ref/forms/validation>` and, more specifically, the -:ref:`model form validation notes <overriding-modelform-clean-method>` for more -information. - -.. _admin-inlines: - -``InlineModelAdmin`` objects -============================ - -.. class:: InlineModelAdmin - -The admin interface has the ability to edit models on the same page as a -parent model. These are called inlines. Suppose you have these two models:: - - class Author(models.Model): - name = models.CharField(max_length=100) - - class Book(models.Model): - author = models.ForeignKey(Author) - title = models.CharField(max_length=100) - -You can edit the books authored by an author on the author page. You add -inlines to a model by specifying them in a ``ModelAdmin.inlines``:: - - class BookInline(admin.TabularInline): - model = Book - - class AuthorAdmin(admin.ModelAdmin): - inlines = [ - BookInline, - ] - -Django provides two subclasses of ``InlineModelAdmin`` and they are: - - * ``TabularInline`` - * ``StackedInline`` - -The difference between these two is merely the template used to render them. - -``InlineModelAdmin`` options ------------------------------ - -The ``InlineModelAdmin`` class is a subclass of ``ModelAdmin`` so it inherits -all the same functionality as well as some of its own: - -.. attribute:: InlineModelAdmin.model - - The model in which the inline is using. This is required. - -.. attribute:: InlineModelAdmin.fk_name - - The name of the foreign key on the model. In most cases this will be dealt - with automatically, but ``fk_name`` must be specified explicitly if there - are more than one foreign key to the same parent model. - -.. attribute:: InlineModelAdmin.formset - - This defaults to ``BaseInlineFormSet``. Using your own formset can give you - many possibilities of customization. Inlines are built around - :ref:`model formsets <model-formsets>`. - -.. attribute:: InlineModelAdmin.form - - The value for ``form`` defaults to ``ModelForm``. This is what is passed - through to ``inlineformset_factory`` when creating the formset for this - inline. - -.. _ref-contrib-admin-inline-extra: - -.. attribute:: InlineModelAdmin.extra - - - This controls the number of extra forms the formset will display in addition - to the initial forms. See the - :doc:`formsets documentation </topics/forms/formsets>` for more information. - - .. versionadded:: 1.2 - - For users with JavaScript-enabled browsers, an "Add another" link is - provided to enable any number of additional inlines to be added in addition - to those provided as a result of the ``extra`` argument. - - The dynamic link will not appear if the number of currently displayed forms - exceeds ``max_num``, or if the user does not have JavaScript enabled. - -.. _ref-contrib-admin-inline-max-num: - -.. attribute:: InlineModelAdmin.max_num - - This controls the maximum number of forms to show in the inline. This - doesn't directly correlate to the number of objects, but can if the value - is small enough. See :ref:`model-formsets-max-num` for more information. - -.. attribute:: InlineModelAdmin.raw_id_fields - - By default, Django's admin uses a select-box interface (<select>) for - fields that are ``ForeignKey``. Sometimes you don't want to incur the - overhead of having to select all the related instances to display in the - drop-down. - - ``raw_id_fields`` is a list of fields you would like to change into a - ``Input`` widget for either a ``ForeignKey`` or ``ManyToManyField``:: - - class BookInline(admin.TabularInline): - model = Book - raw_id_fields = ("pages",) - - -.. attribute:: InlineModelAdmin.template - - The template used to render the inline on the page. - -.. attribute:: InlineModelAdmin.verbose_name - - An override to the ``verbose_name`` found in the model's inner ``Meta`` - class. - -.. attribute:: InlineModelAdmin.verbose_name_plural - - An override to the ``verbose_name_plural`` found in the model's inner - ``Meta`` class. - -.. attribute:: InlineModelAdmin.can_delete - - Specifies whether or not inline objects can be deleted in the inline. - Defaults to ``True``. - - -Working with a model with two or more foreign keys to the same parent model ---------------------------------------------------------------------------- - -It is sometimes possible to have more than one foreign key to the same model. -Take this model for instance:: - - class Friendship(models.Model): - to_person = models.ForeignKey(Person, related_name="friends") - from_person = models.ForeignKey(Person, related_name="from_friends") - -If you wanted to display an inline on the ``Person`` admin add/change pages -you need to explicitly define the foreign key since it is unable to do so -automatically:: - - class FriendshipInline(admin.TabularInline): - model = Friendship - fk_name = "to_person" - - class PersonAdmin(admin.ModelAdmin): - inlines = [ - FriendshipInline, - ] - -Working with Many-to-Many Models --------------------------------- - -.. versionadded:: 1.2 - -By default, admin widgets for many-to-many relations will be displayed -on whichever model contains the actual reference to the ``ManyToManyField``. -Depending on your ``ModelAdmin`` definition, each many-to-many field in your -model will be represented by a standard HTML ``<select multiple>``, a -horizontal or vertical filter, or a ``raw_id_admin`` widget. However, it is -also possible to to replace these widgets with inlines. - -Suppose we have the following models:: - - class Person(models.Model): - name = models.CharField(max_length=128) - - class Group(models.Model): - name = models.CharField(max_length=128) - members = models.ManyToManyField(Person, related_name='groups') - -If you want to display many-to-many relations using an inline, you can do -so by defining an ``InlineModelAdmin`` object for the relationship:: - - class MembershipInline(admin.TabularInline): - model = Group.members.through - - class PersonAdmin(admin.ModelAdmin): - inlines = [ - MembershipInline, - ] - - class GroupAdmin(admin.ModelAdmin): - inlines = [ - MembershipInline, - ] - exclude = ('members',) - -There are two features worth noting in this example. - -Firstly - the ``MembershipInline`` class references ``Group.members.through``. -The ``through`` attribute is a reference to the model that manages the -many-to-many relation. This model is automatically created by Django when you -define a many-to-many field. - -Secondly, the ``GroupAdmin`` must manually exclude the ``members`` field. -Django displays an admin widget for a many-to-many field on the model that -defines the relation (in this case, ``Group``). If you want to use an inline -model to represent the many-to-many relationship, you must tell Django's admin -to *not* display this widget - otherwise you will end up with two widgets on -your admin page for managing the relation. - -In all other respects, the ``InlineModelAdmin`` is exactly the same as any -other. You can customize the appearance using any of the normal -``ModelAdmin`` properties. - -Working with Many-to-Many Intermediary Models ----------------------------------------------- - -When you specify an intermediary model using the ``through`` argument to a -``ManyToManyField``, the admin will not display a widget by default. This is -because each instance of that intermediary model requires more information -than could be displayed in a single widget, and the layout required for -multiple widgets will vary depending on the intermediate model. - -However, we still want to be able to edit that information inline. Fortunately, -this is easy to do with inline admin models. Suppose we have the following -models:: - - class Person(models.Model): - name = models.CharField(max_length=128) - - class Group(models.Model): - name = models.CharField(max_length=128) - members = models.ManyToManyField(Person, through='Membership') - - class Membership(models.Model): - person = models.ForeignKey(Person) - group = models.ForeignKey(Group) - date_joined = models.DateField() - invite_reason = models.CharField(max_length=64) - -The first step in displaying this intermediate model in the admin is to -define an inline class for the ``Membership`` model:: - - class MembershipInline(admin.TabularInline): - model = Membership - extra = 1 - -This simple example uses the default ``InlineModelAdmin`` values for the -``Membership`` model, and limits the extra add forms to one. This could be -customized using any of the options available to ``InlineModelAdmin`` classes. - -Now create admin views for the ``Person`` and ``Group`` models:: - - class PersonAdmin(admin.ModelAdmin): - inlines = (MembershipInline,) - - class GroupAdmin(admin.ModelAdmin): - inlines = (MembershipInline,) - -Finally, register your ``Person`` and ``Group`` models with the admin site:: - - admin.site.register(Person, PersonAdmin) - admin.site.register(Group, GroupAdmin) - -Now your admin site is set up to edit ``Membership`` objects inline from -either the ``Person`` or the ``Group`` detail pages. - -Using generic relations as an inline ------------------------------------- - -It is possible to use an inline with generically related objects. Let's say -you have the following models:: - - class Image(models.Model): - image = models.ImageField(upload_to="images") - content_type = models.ForeignKey(ContentType) - object_id = models.PositiveIntegerField() - content_object = generic.GenericForeignKey("content_type", "object_id") - - class Product(models.Model): - name = models.CharField(max_length=100) - -If you want to allow editing and creating ``Image`` instance on the ``Product`` -add/change views you can simply use ``GenericInlineModelAdmin`` provided by -``django.contrib.contenttypes.generic``. In your ``admin.py`` for this -example app:: - - from django.contrib import admin - from django.contrib.contenttypes import generic - - from myproject.myapp.models import Image, Product - - class ImageInline(generic.GenericTabularInline): - model = Image - - class ProductAdmin(admin.ModelAdmin): - inlines = [ - ImageInline, - ] - - admin.site.register(Product, ProductAdmin) - -``django.contrib.contenttypes.generic`` provides both a ``GenericTabularInline`` -and ``GenericStackedInline`` and behave just like any other inline. See the -:doc:`contenttypes documentation </ref/contrib/contenttypes>` for more specific -information. - -Overriding Admin Templates -========================== - -It is relatively easy to override many of the templates which the admin module -uses to generate the various pages of an admin site. You can even override a few -of these templates for a specific app, or a specific model. - -Set up your projects admin template directories ------------------------------------------------ - -The admin template files are located in the ``contrib/admin/templates/admin`` -directory. - -In order to override one or more of them, first create an ``admin`` directory in -your project's ``templates`` directory. This can be any of the directories you -specified in ``TEMPLATE_DIRS``. - -Within this ``admin`` directory, create sub-directories named after your app. -Within these app subdirectories create sub-directories named after your models. -Note, that the admin app will lowercase the model name when looking for the -directory, so make sure you name the directory in all lowercase if you are going -to run your app on a case-sensitive filesystem. - -To override an admin template for a specific app, copy and edit the template -from the ``django/contrib/admin/templates/admin`` directory, and save it to one -of the directories you just created. - -For example, if we wanted to add a tool to the change list view for all the -models in an app named ``my_app``, we would copy -``contrib/admin/templates/admin/change_list.html`` to the -``templates/admin/my_app/`` directory of our project, and make any necessary -changes. - -If we wanted to add a tool to the change list view for only a specific model -named 'Page', we would copy that same file to the -``templates/admin/my_app/page`` directory of our project. - -Overriding vs. replacing an admin template ------------------------------------------- - -Because of the modular design of the admin templates, it is usually neither -necessary nor advisable to replace an entire template. It is almost always -better to override only the section of the template which you need to change. - -To continue the example above, we want to add a new link next to the ``History`` -tool for the ``Page`` model. After looking at ``change_form.html`` we determine -that we only need to override the ``object-tools`` block. Therefore here is our -new ``change_form.html`` : - -.. code-block:: html+django - - {% extends "admin/change_form.html" %} - {% load i18n %} - {% block object-tools %} - {% if change %}{% if not is_popup %} - <ul class="object-tools"> - <li><a href="history/" class="historylink">{% trans "History" %}</a></li> - <li><a href="mylink/" class="historylink">My Link</a></li> - {% if has_absolute_url %} - <li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink"> - {% trans "View on site" %}</a> - </li> - {% endif%} - </ul> - {% endif %}{% endif %} - {% endblock %} - -And that's it! If we placed this file in the ``templates/admin/my_app`` -directory, our link would appear on every model's change form. - -Templates which may be overridden per app or model --------------------------------------------------- - -Not every template in ``contrib/admin/templates/admin`` may be overridden per -app or per model. The following can: - - * ``app_index.html`` - * ``change_form.html`` - * ``change_list.html`` - * ``delete_confirmation.html`` - * ``object_history.html`` - -For those templates that cannot be overridden in this way, you may still -override them for your entire project. Just place the new version in your -``templates/admin`` directory. This is particularly useful to create custom 404 -and 500 pages. - -.. note:: - - Some of the admin templates, such as ``change_list_request.html`` are used - to render custom inclusion tags. These may be overridden, but in such cases - you are probably better off creating your own version of the tag in question - and giving it a different name. That way you can use it selectively. - -Root and login templates ------------------------- - -If you wish to change the index, login or logout templates, you are better off -creating your own ``AdminSite`` instance (see below), and changing the -:attr:`AdminSite.index_template` , :attr:`AdminSite.login_template` or -:attr:`AdminSite.logout_template` properties. - -``AdminSite`` objects -===================== - -.. class:: AdminSite(name=None) - -A Django administrative site is represented by an instance of -``django.contrib.admin.sites.AdminSite``; by default, an instance of -this class is created as ``django.contrib.admin.site`` and you can -register your models and ``ModelAdmin`` instances with it. - -If you'd like to set up your own administrative site with custom -behavior, however, you're free to subclass ``AdminSite`` and override -or add anything you like. Then, simply create an instance of your -``AdminSite`` subclass (the same way you'd instantiate any other -Python class), and register your models and ``ModelAdmin`` subclasses -with it instead of using the default. - -.. versionadded:: 1.1 - -When constructing an instance of an ``AdminSite``, you are able to provide -a unique instance name using the ``name`` argument to the constructor. This -instance name is used to identify the instance, especially when -:ref:`reversing admin URLs <admin-reverse-urls>`. If no instance name is -provided, a default instance name of ``admin`` will be used. - -``AdminSite`` attributes ------------------------- - -Templates can override or extend base admin templates as described in -`Overriding Admin Templates`_. - -.. attribute:: AdminSite.index_template - -Path to a custom template that will be used by the admin site main index view. - -.. attribute:: AdminSite.login_template - -Path to a custom template that will be used by the admin site login view. - -.. attribute:: AdminSite.logout_template - -.. versionadded:: 1.2 - -Path to a custom template that will be used by the admin site logout view. - -.. attribute:: AdminSite.password_change_template - -.. versionadded:: 1.2 - -Path to a custom template that will be used by the admin site password change -view. - -.. attribute:: AdminSite.password_change_done_template - -.. versionadded:: 1.2 - -Path to a custom template that will be used by the admin site password change -done view. - -Hooking ``AdminSite`` instances into your URLconf -------------------------------------------------- - -The last step in setting up the Django admin is to hook your ``AdminSite`` -instance into your URLconf. Do this by pointing a given URL at the -``AdminSite.urls`` method. - -In this example, we register the default ``AdminSite`` instance -``django.contrib.admin.site`` at the URL ``/admin/`` :: - - # urls.py - from django.conf.urls.defaults import * - from django.contrib import admin - - admin.autodiscover() - - urlpatterns = patterns('', - (r'^admin/', include(admin.site.urls)), - ) - -Above we used ``admin.autodiscover()`` to automatically load the -``INSTALLED_APPS`` admin.py modules. - -In this example, we register the ``AdminSite`` instance -``myproject.admin.admin_site`` at the URL ``/myadmin/`` :: - - # urls.py - from django.conf.urls.defaults import * - from myproject.admin import admin_site - - urlpatterns = patterns('', - (r'^myadmin/', include(admin_site.urls)), - ) - -There is really no need to use autodiscover when using your own ``AdminSite`` -instance since you will likely be importing all the per-app admin.py modules -in your ``myproject.admin`` module. - -Multiple admin sites in the same URLconf ----------------------------------------- - -It's easy to create multiple instances of the admin site on the same -Django-powered Web site. Just create multiple instances of ``AdminSite`` and -root each one at a different URL. - -.. versionchanged:: 1.1 - The method for hooking ``AdminSite`` instances into urls has changed in - Django 1.1. - -In this example, the URLs ``/basic-admin/`` and ``/advanced-admin/`` feature -separate versions of the admin site -- using the ``AdminSite`` instances -``myproject.admin.basic_site`` and ``myproject.admin.advanced_site``, -respectively:: - - # urls.py - from django.conf.urls.defaults import * - from myproject.admin import basic_site, advanced_site - - urlpatterns = patterns('', - (r'^basic-admin/', include(basic_site.urls)), - (r'^advanced-admin/', include(advanced_site.urls)), - ) - -``AdminSite`` instances take a single argument to their constructor, their -name, which can be anything you like. This argument becomes the prefix to the -URL names for the purposes of :ref:`reversing them<admin-reverse-urls>`. This -is only necessary if you are using more than one ``AdminSite``. - -Adding views to admin sites ---------------------------- - -.. versionadded:: 1.1 - -Just like :class:`ModelAdmin`, :class:`AdminSite` provides a -:meth:`~django.contrib.admin.ModelAdmin.get_urls()` method -that can be overridden to define additional views for the site. To add -a new view to your admin site, extend the base -:meth:`~django.contrib.admin.ModelAdmin.get_urls()` method to include -a pattern for your new view. - -.. note:: - Any view you render that uses the admin templates, or extends the base - admin template, should provide the ``current_app`` argument to - ``RequestContext`` or ``Context`` when rendering the template. It should - be set to either ``self.name`` if your view is on an ``AdminSite`` or - ``self.admin_site.name`` if your view is on a ``ModelAdmin``. - -.. _admin-reverse-urls: - -Reversing Admin URLs -==================== - -.. versionadded:: 1.1 - -When an :class:`AdminSite` is deployed, the views provided by that site are -accessible using Django's :ref:`URL reversing system <naming-url-patterns>`. - -The :class:`AdminSite` provides the following named URL patterns: - - ====================== ======================== ============= - Page URL name Parameters - ====================== ======================== ============= - Index ``index`` - Logout ``logout`` - Password change ``password_change`` - Password change done ``password_change_done`` - i18n javascript ``jsi18n`` - Application index page ``app_list`` ``app_label`` - ====================== ======================== ============= - -Each :class:`ModelAdmin` instance provides an additional set of named URLs: - - ====================== =============================================== ============= - Page URL name Parameters - ====================== =============================================== ============= - Changelist ``{{ app_label }}_{{ model_name }}_changelist`` - Add ``{{ app_label }}_{{ model_name }}_add`` - History ``{{ app_label }}_{{ model_name }}_history`` ``object_id`` - Delete ``{{ app_label }}_{{ model_name }}_delete`` ``object_id`` - Change ``{{ app_label }}_{{ model_name }}_change`` ``object_id`` - ====================== =============================================== ============= - -These named URLs are registered with the application namespace ``admin``, and -with an instance namespace corresponding to the name of the Site instance. - -So - if you wanted to get a reference to the Change view for a particular -``Choice`` object (from the polls application) in the default admin, you would -call:: - - >>> from django.core import urlresolvers - >>> c = Choice.objects.get(...) - >>> change_url = urlresolvers.reverse('admin:polls_choice_change', args=(c.id,)) - -This will find the first registered instance of the admin application (whatever the instance -name), and resolve to the view for changing ``poll.Choice`` instances in that instance. - -If you want to find a URL in a specific admin instance, provide the name of that instance -as a ``current_app`` hint to the reverse call. For example, if you specifically wanted -the admin view from the admin instance named ``custom``, you would need to call:: - - >>> change_url = urlresolvers.reverse('custom:polls_choice_change', args=(c.id,)) - -For more details, see the documentation on :ref:`reversing namespaced URLs -<topics-http-reversing-url-namespaces>`. diff --git a/parts/django/docs/ref/contrib/auth.txt b/parts/django/docs/ref/contrib/auth.txt deleted file mode 100644 index 619b38e..0000000 --- a/parts/django/docs/ref/contrib/auth.txt +++ /dev/null @@ -1,4 +0,0 @@ -``django.contrib.auth`` -======================= - -See :doc:`/topics/auth`. diff --git a/parts/django/docs/ref/contrib/comments/custom.txt b/parts/django/docs/ref/contrib/comments/custom.txt deleted file mode 100644 index 5411d9c..0000000 --- a/parts/django/docs/ref/contrib/comments/custom.txt +++ /dev/null @@ -1,202 +0,0 @@ -================================== -Customizing the comments framework -================================== - -.. currentmodule:: django.contrib.comments - -If the built-in comment framework doesn't quite fit your needs, you can extend -the comment app's behavior to add custom data and logic. The comments framework -lets you extend the built-in comment model, the built-in comment form, and the -various comment views. - -The :setting:`COMMENTS_APP` setting is where this customization begins. Set -:setting:`COMMENTS_APP` to the name of the app you'd like to use to provide -custom behavior. You'll use the same syntax as you'd use for -:setting:`INSTALLED_APPS`, and the app given must also be in the -:setting:`INSTALLED_APPS` list. - -For example, if you wanted to use an app named ``my_comment_app``, your -settings file would contain:: - - INSTALLED_APPS = [ - ... - 'my_comment_app', - ... - ] - - COMMENTS_APP = 'my_comment_app' - -The app named in :setting:`COMMENTS_APP` provides its custom behavior by -defining some module-level functions in the app's ``__init__.py``. The -:ref:`complete list of these functions <custom-comment-app-api>` can be found -below, but first let's look at a quick example. - -An example custom comments app -============================== - -One of the most common types of customization is modifying the set of fields -provided on the built-in comment model. For example, some sites that allow -comments want the commentator to provide a title for their comment; the built-in -comment model has no field for that title. - -To make this kind of customization, we'll need to do three things: - - #. Create a custom comment :class:`~django.db.models.Model` that adds on the - "title" field. - - #. Create a custom comment :class:`~django.forms.Form` that also adds this - "title" field. - - #. Inform Django of these objects by defining a few functions in a - custom :setting:`COMMENTS_APP`. - -So, carrying on the example above, we're dealing with a typical app structure in -the ``my_custom_app`` directory:: - - my_custom_app/ - __init__.py - models.py - forms.py - -In the ``models.py`` we'll define a ``CommentWithTitle`` model:: - - from django.db import models - from django.contrib.comments.models import Comment - - class CommentWithTitle(Comment): - title = models.CharField(max_length=300) - -Most custom comment models will subclass the :class:`Comment` model. However, -if you want to substantially remove or change the fields available in the -:class:`Comment` model, but don't want to rewrite the templates, you could -try subclassing from :class:`BaseCommentAbstractModel`. - -Next, we'll define a custom comment form in ``forms.py``. This is a little more -tricky: we have to both create a form and override -:meth:`CommentForm.get_comment_model` and -:meth:`CommentForm.get_comment_create_data` to return deal with our custom title -field:: - - from django import forms - from django.contrib.comments.forms import CommentForm - from my_comment_app.models import CommentWithTitle - - class CommentFormWithTitle(CommentForm): - title = forms.CharField(max_length=300) - - def get_comment_model(self): - # Use our custom comment model instead of the built-in one. - return CommentWithTitle - - def get_comment_create_data(self): - # Use the data of the superclass, and add in the title field - data = super(CommentFormWithTitle, self).get_comment_create_data() - data['title'] = self.cleaned_data['title'] - return data - -Django provides a couple of "helper" classes to make writing certain types of -custom comment forms easier; see :mod:`django.contrib.comments.forms` for -more. - -Finally, we'll define a couple of methods in ``my_custom_app/__init__.py`` to -point Django at these classes we've created:: - - from my_comments_app.models import CommentWithTitle - from my_comments_app.forms import CommentFormWithTitle - - def get_model(): - return CommentWithTitle - - def get_form(): - return CommentFormWithTitle - - -.. warning:: - - Be careful not to create cyclic imports in your custom comments app. - If you feel your comment configuration isn't being used as defined -- - for example, if your comment moderation policy isn't being applied -- - you may have a cyclic import problem. - - If you are having unexplained problems with comments behavior, check - if your custom comments application imports (even indirectly) - any module that itself imports Django's comments module. - -The above process should take care of most common situations. For more -advanced usage, there are additional methods you can define. Those are -explained in the next section. - -.. _custom-comment-app-api: - -Custom comment app API -====================== - -The :mod:`django.contrib.comments` app defines the following methods; any -custom comment app must define at least one of them. All are optional, -however. - -.. function:: get_model() - - Return the :class:`~django.db.models.Model` class to use for comments. This - model should inherit from - :class:`django.contrib.comments.models.BaseCommentAbstractModel`, which - defines necessary core fields. - - The default implementation returns - :class:`django.contrib.comments.models.Comment`. - -.. function:: get_form() - - Return the :class:`~django.forms.Form` class you want to use for - creating, validating, and saving your comment model. Your custom - comment form should accept an additional first argument, - ``target_object``, which is the object the comment will be - attached to. - - The default implementation returns - :class:`django.contrib.comments.forms.CommentForm`. - - .. note:: - - The default comment form also includes a number of unobtrusive - spam-prevention features (see - :ref:`notes-on-the-comment-form`). If replacing it with your - own form, you may want to look at the source code for the - built-in form and consider incorporating similar features. - -.. function:: get_form_target() - - Return the URL for POSTing comments. This will be the ``<form action>`` - attribute when rendering your comment form. - - The default implementation returns a reverse-resolved URL pointing - to the :func:`post_comment` view. - - .. note:: - - If you provide a custom comment model and/or form, but you - want to use the default :func:`post_comment` view, you will - need to be aware that it requires the model and form to have - certain additional attributes and methods: see the - :func:`post_comment` view documentation for details. - -.. function:: get_flag_url() - - Return the URL for the "flag this comment" view. - - The default implementation returns a reverse-resolved URL pointing - to the :func:`django.contrib.comments.views.moderation.flag` view. - -.. function:: get_delete_url() - - Return the URL for the "delete this comment" view. - - The default implementation returns a reverse-resolved URL pointing - to the :func:`django.contrib.comments.views.moderation.delete` view. - -.. function:: get_approve_url() - - Return the URL for the "approve this comment from moderation" view. - - The default implementation returns a reverse-resolved URL pointing - to the :func:`django.contrib.comments.views.moderation.approve` view. diff --git a/parts/django/docs/ref/contrib/comments/example.txt b/parts/django/docs/ref/contrib/comments/example.txt deleted file mode 100644 index 424bdb1..0000000 --- a/parts/django/docs/ref/contrib/comments/example.txt +++ /dev/null @@ -1,208 +0,0 @@ -.. highlightlang:: html+django - -=========================================== -Example of using the in-built comments app -=========================================== - -Follow the first three steps of the quick start guide in the -:doc:`documentation </ref/contrib/comments/index>`. - -Now suppose, you have an app (``blog``) with a model (``Post``) -to which you want to attach comments. Let us also suppose that -you have a template called ``blog_detail.html`` where you want -to display the comments list and comment form. - -Template -======== - -First, we should load the ``comment`` template tags in the -``blog_detail.html`` so that we can use it's functionality. So -just like all other custom template tag libraries:: - - {% load comments %} - -Next, let us add the number of comments attached to the particular -model instance of ``Post``. For this we assume that a context -variable ``object_pk`` is present which gives the ``id`` of the -instance of ``Post``. - -The usage of the :ttag:`get_comment_count` tag is like below:: - - {% get_comment_count for blog.post object_pk as comment_count %} - <p>{{ comment_count }} comments have been posted.</p> - -If you have the instance (say ``entry``) of the model (``Post``) -available in the context, then you can refer to it directly:: - - {% get_comment_count for entry as comment_count %} - <p>{{ comment_count }} comments have been posted.</p> - -.. versionadded:: 1.2 - -Next, we can use the :ttag:`render_comment_list` tag, to render all comments -to the given instance (``entry``) by using the ``comments/list.html`` template. - - {% render_comment_list for entry %} - -Django will will look for the ``list.html`` under the following directories -(for our example):: - - comments/blog/post/list.html - comments/blog/list.html - comments/list.html - -To get a list of comments, we make use of the :ttag:`get_comment_list` tag. -This tag's usage is very similar to the :ttag:`get_comment_count` tag. We -need to remember that the :ttag:`get_comment_list` returns a list of comments -and hence we will have to iterate through them to display them:: - - {% get_comment_list for blog.post object_pk as comment_list %} - {% for comment in comment_list %} - <p>Posted by: {{ comment.user_name }} on {{ comment.submit_date }}</p> - ... - <p>Comment: {{ comment.comment }}</p> - ... - {% endfor %} - -Finally, we display the comment form, enabling users to enter their -comments. There are two ways of doing so. The first is when you want to -display the comments template available under your ``comments/form.html``. -The other method gives you a chance to customize the form. - -The first method makes use of the :ttag:`render_comment_form` tag. It's usage -too is similar to the other three tags we have discussed above:: - - {% render_comment_form for entry %} - -It looks for the ``form.html`` under the following directories -(for our example):: - - comments/blog/post/form.html - comments/blog/form.html - comments/form.html - -Since we customize the form in the second method, we make use of another -tag called :ttag:`comment_form_target`. This tag on rendering gives the URL -where the comment form is posted. Without any :doc:`customization -</ref/contrib/comments/custom>`, :ttag:`comment_form_target` evaluates to -``/comments/post/``. We use this tag in the form's ``action`` attribute. - -The :ttag:`get_comment_form` tag renders a ``form`` for a model instance by -creating a context variable. One can iterate over the ``form`` object to -get individual fields. This gives you fine-grain control over the form:: - - {% for field in form %} - {% ifequal field.name "comment" %} - <!-- Customize the "comment" field, say, make CSS changes --> - ... - {% endfor %} - -But let's look at a simple example:: - - {% get_comment_form for entry as form %} - <!-- A context variable called form is created with the necessary hidden - fields, timestamps and security hashes --> - <table> - <form action="{% comment_form_target %}" method="post"> - {{ form }} - <tr> - <td></td> - <td><input type="submit" name="preview" class="submit-post" value="Preview"></td> - </tr> - </form> - </table> - -Flagging -======== - -If you want your users to be able to flag comments (say for profanity), you -can just direct them (by placing a link in your comment list) to ``/flag/{{ -comment.id }}/``. Similarly, a user with requisite permissions (``"Can -moderate comments"``) can approve and delete comments. This can also be -done through the ``admin`` as you'll see later. You might also want to -customize the following templates: - - * ``flag.html`` - * ``flagged.html`` - * ``approve.html`` - * ``approved.html`` - * ``delete.html`` - * ``deleted.html`` - -found under the directory structure we saw for ``form.html``. - -Feeds -===== - -Suppose you want to export a :doc:`feed </ref/contrib/syndication>` of the -latest comments, you can use the in-built :class:`LatestCommentFeed`. Just -enable it in your project's ``urls.py``: - -.. code-block:: python - - from django.conf.urls.defaults import * - from django.contrib.comments.feeds import LatestCommentFeed - - feeds = { - 'latest': LatestCommentFeed, - } - - urlpatterns = patterns('', - # ... - (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', - {'feed_dict': feeds}), - # ... - ) - -Now you should have the latest comment feeds being served off ``/feeds/latest/``. - -Moderation -========== - -Now that we have the comments framework working, we might want to have some -moderation setup to administer the comments. The comments framework comes -in-built with :doc:`generic comment moderation -</ref/contrib/comments/moderation>`. The comment moderation has the following -features (all of which or only certain can be enabled): - - * Enable comments for a particular model instance. - * Close comments after a particular (user-defined) number of days. - * Email new comments to the site-staff. - -To enable comment moderation, we subclass the :class:`CommentModerator` and -register it with the moderation features we want. Let us suppose we want to -close comments after 7 days of posting and also send out an email to the -site staff. In ``blog/models.py``, we register a comment moderator in the -following way: - -.. code-block:: python - - from django.contrib.comments.moderation import CommentModerator, moderator - from django.db import models - - class Post(models.Model): - title = models.CharField(max_length = 255) - content = models.TextField() - posted_date = models.DateTimeField() - - class PostModerator(CommentModerator): - email_notification = True - auto_close_field = 'posted_date' - # Close the comments after 7 days. - close_after = 7 - - moderator.register(Post, PostModerator) - -The generic comment moderation also has the facility to remove comments. -These comments can then be moderated by any user who has access to the -``admin`` site and the ``Can moderate comments`` permission (can be set -under the ``Users`` page in the ``admin``). - -The moderator can ``Flag``, ``Approve`` or ``Remove`` comments using the -``Action`` drop-down in the ``admin`` under the ``Comments`` page. - -.. note:: - - Only a super-user will be able to delete comments from the database. - ``Remove Comments`` only sets the ``is_public`` attribute to - ``False``. diff --git a/parts/django/docs/ref/contrib/comments/forms.txt b/parts/django/docs/ref/contrib/comments/forms.txt deleted file mode 100644 index c21a27b..0000000 --- a/parts/django/docs/ref/contrib/comments/forms.txt +++ /dev/null @@ -1,46 +0,0 @@ -==================== -Comment form classes -==================== - -.. module:: django.contrib.comments.forms - :synopsis: Forms for dealing with the built-in comment model. - -The ``django.contrib.comments.forms`` module contains a handful of forms -you'll use when writing custom views dealing with comments, or when writing -:doc:`custom comment apps </ref/contrib/comments/custom>`. - -.. class:: CommentForm - - The main comment form representing the standard, built-in way of handling - submitted comments. This is the class used by all the views - :mod:`django.contrib.comments` to handle submitted comments. - - If you want to build custom views that are similar to Django's built-in - comment handling views, you'll probably want to use this form. - -Abstract comment forms for custom comment apps ----------------------------------------------- - -If you're building a :doc:`custom comment app </ref/contrib/comments/custom>`, -you might want to replace *some* of the form logic but still rely on parts of -the existing form. - -:class:`CommentForm` is actually composed of a couple of abstract base class -forms that you can subclass to reuse pieces of the form handling logic: - -.. class:: CommentSecurityForm - - Handles the anti-spoofing protection aspects of the comment form handling. - - This class contains the ``content_type`` and ``object_pk`` fields pointing - to the object the comment is attached to, along with a ``timestamp`` and a - ``security_hash`` of all the form data. Together, the timestamp and the - security hash ensure that spammers can't "replay" form submissions and - flood you with comments. - -.. class:: CommentDetailsForm - - Handles the details of the comment itself. - - This class contains the ``name``, ``email``, ``url``, and the ``comment`` - field itself, along with the associated validation logic.
\ No newline at end of file diff --git a/parts/django/docs/ref/contrib/comments/index.txt b/parts/django/docs/ref/contrib/comments/index.txt deleted file mode 100644 index 817871e..0000000 --- a/parts/django/docs/ref/contrib/comments/index.txt +++ /dev/null @@ -1,302 +0,0 @@ -=========================== -Django's comments framework -=========================== - -.. module:: django.contrib.comments - :synopsis: Django's comment framework - -.. highlightlang:: html+django - -Django includes a simple, yet customizable comments framework. The built-in -comments framework can be used to attach comments to any model, so you can use -it for comments on blog entries, photos, book chapters, or anything else. - -.. note:: - - If you used to use Django's older (undocumented) comments framework, you'll - need to upgrade. See the :doc:`upgrade guide </ref/contrib/comments/upgrade>` - for instructions. - -Quick start guide -================= - -To get started using the ``comments`` app, follow these steps: - - #. Install the comments framework by adding ``'django.contrib.comments'`` to - :setting:`INSTALLED_APPS`. - - #. Run ``manage.py syncdb`` so that Django will create the comment tables. - - #. Add the comment app's URLs to your project's ``urls.py``: - - .. code-block:: python - - urlpatterns = patterns('', - ... - (r'^comments/', include('django.contrib.comments.urls')), - ... - ) - - #. Use the `comment template tags`_ below to embed comments in your - templates. - -You might also want to examine :doc:`/ref/contrib/comments/settings`. - -Comment template tags -===================== - -You'll primarily interact with the comment system through a series of template -tags that let you embed comments and generate forms for your users to post them. - -Like all custom template tag libraries, you'll need to :ref:`load the custom -tags <loading-custom-template-libraries>` before you can use them:: - - {% load comments %} - -Once loaded you can use the template tags below. - -Specifying which object comments are attached to ------------------------------------------------- - -Django's comments are all "attached" to some parent object. This can be any -instance of a Django model. Each of the tags below gives you a couple of -different ways you can specify which object to attach to: - - #. Refer to the object directly -- the more common method. Most of the - time, you'll have some object in the template's context you want - to attach the comment to; you can simply use that object. - - For example, in a blog entry page that has a variable named ``entry``, - you could use the following to load the number of comments:: - - {% get_comment_count for entry as comment_count %}. - - #. Refer to the object by content-type and object id. You'd use this method - if you, for some reason, don't actually have direct access to the object. - - Following the above example, if you knew the object ID was ``14`` but - didn't have access to the actual object, you could do something like:: - - {% get_comment_count for blog.entry 14 as comment_count %} - - In the above, ``blog.entry`` is the app label and (lower-cased) model - name of the model class. - -Displaying comments -------------------- - -To display a list of comments, you can use the template tags -:ttag:`render_comment_list` or :ttag:`get_comment_list`. - -.. templatetag:: render_comment_list - -Quickly rendering a comment list -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The easiest way to display a list of comments for some object is by using -:ttag:`render_comment_list`:: - - {% render_comment_list for [object] %} - -For example:: - - {% render_comment_list for event %} - -This will render comments using a template named ``comments/list.html``, a -default version of which is included with Django. - -.. templatetag:: get_comment_list - -Rendering a custom comment list -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To get the list of comments for some object, use :ttag:`get_comment_list`:: - - {% get_comment_list for [object] as [varname] %} - -For example:: - - {% get_comment_list for event as comment_list %} - {% for comment in comment_list %} - ... - {% endfor %} - -This returns a list of :class:`~django.contrib.comments.models.Comment` objects; -see :doc:`the comment model documentation </ref/contrib/comments/models>` for -details. - -.. templatetag:: get_comment_permalink - -Linking to comments -------------------- - -.. versionadded:: 1.2 - -To provide a permalink to a specific comment, use :ttag:`get_comment_permalink`:: - - {% get_comment_permalink comment_obj [format_string] %} - -By default, the named anchor that will be appended to the URL will be the letter -'c' followed by the comment id, for example 'c82'. You may specify a custom -format string if you wish to override this behavior:: - - {% get_comment_permalink comment "#c%(id)s-by-%(user_name)s"%} - -The format string is a standard python format string. Valid mapping keys -include any attributes of the comment object. - -Regardless of whether you specify a custom anchor pattern, you must supply a -matching named anchor at a suitable place in your template. - -For example:: - - {% for comment in comment_list %} - <a name="c{{ comment.id }}"></a> - <a href="{% get_comment_permalink comment %}"> - permalink for comment #{{ forloop.counter }} - </a> - ... - {% endfor %} - -.. warning:: - - There's a known bug in Safari/Webkit which causes the named anchor to be - forgotten following a redirect. The practical impact for comments is that - the Safari/webkit browsers will arrive at the correct page but will not - scroll to the named anchor. - -.. templatetag:: get_comment_count - -Counting comments ------------------ - -To count comments attached to an object, use :ttag:`get_comment_count`:: - - {% get_comment_count for [object] as [varname] %} - -For example:: - - {% get_comment_count for event as comment_count %} - - <p>This event has {{ comment_count }} comments.</p> - - -Displaying the comment post form --------------------------------- - -To show the form that users will use to post a comment, you can use -:ttag:`render_comment_form` or :ttag:`get_comment_form` - -.. templatetag:: render_comment_form - -Quickly rendering the comment form -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The easiest way to display a comment form is by using -:ttag:`render_comment_form`:: - - {% render_comment_form for [object] %} - -For example:: - - {% render_comment_form for event %} - -This will render comments using a template named ``comments/form.html``, a -default version of which is included with Django. - -.. templatetag:: get_comment_form - -Rendering a custom comment form -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you want more control over the look and feel of the comment form, you use use -:ttag:`get_comment_form` to get a :doc:`form object </topics/forms/index>` that -you can use in the template:: - - {% get_comment_form for [object] as [varname] %} - -A complete form might look like:: - - {% get_comment_form for event as form %} - <form action="{% comment_form_target %}" method="post"> - {{ form }} - <tr> - <td></td> - <td><input type="submit" name="preview" class="submit-post" value="Preview"></td> - </tr> - </form> - -Be sure to read the `notes on the comment form`_, below, for some special -considerations you'll need to make if you're using this approach. - -.. templatetag:: comment_form_target - -Getting the comment form target -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You may have noticed that the above example uses another template tag -- -:ttag:`comment_form_target` -- to actually get the ``action`` attribute of the -form. This will always return the correct URL that comments should be posted to; -you'll always want to use it like above:: - - <form action="{% comment_form_target %}" method="post"> - -Redirecting after the comment post -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To specify the URL you want to redirect to after the comment has been posted, -you can include a hidden form input called ``next`` in your comment form. For example:: - - <input type="hidden" name="next" value="{% url my_comment_was_posted %}" /> - -.. _notes-on-the-comment-form: - -Notes on the comment form -------------------------- - -The form used by the comment system has a few important anti-spam attributes you -should know about: - - * It contains a number of hidden fields that contain timestamps, information - about the object the comment should be attached to, and a "security hash" - used to validate this information. If someone tampers with this data -- - something comment spammers will try -- the comment submission will fail. - - If you're rendering a custom comment form, you'll need to make sure to - pass these values through unchanged. - - * The timestamp is used to ensure that "reply attacks" can't continue very - long. Users who wait too long between requesting the form and posting a - comment will have their submissions refused. - - * The comment form includes a "honeypot_" field. It's a trap: if any data is - entered in that field, the comment will be considered spam (spammers often - automatically fill in all fields in an attempt to make valid submissions). - - The default form hides this field with a piece of CSS and further labels - it with a warning field; if you use the comment form with a custom - template you should be sure to do the same. - -The comments app also depends on the more general :doc:`Cross Site Request -Forgery protection </ref/contrib/csrf>` that comes with Django. As described in -the documentation, it is best to use ``CsrfViewMiddleware``. However, if you -are not using that, you will need to use the ``csrf_protect`` decorator on any -views that include the comment form, in order for those views to be able to -output the CSRF token and cookie. - -.. _honeypot: http://en.wikipedia.org/wiki/Honeypot_(computing) - -More information -================ - -.. toctree:: - :maxdepth: 1 - - models - settings - signals - upgrade - custom - forms - moderation - example diff --git a/parts/django/docs/ref/contrib/comments/models.txt b/parts/django/docs/ref/contrib/comments/models.txt deleted file mode 100644 index e773790..0000000 --- a/parts/django/docs/ref/contrib/comments/models.txt +++ /dev/null @@ -1,80 +0,0 @@ -=========================== -The built-in comment models -=========================== - -.. module:: django.contrib.comments.models - :synopsis: The built-in comment models - -.. class:: Comment - - Django's built-in comment model. Has the following fields: - - .. attribute:: content_object - - A :class:`~django.contrib.contettypes.generic.GenericForeignKey` - attribute pointing to the object the comment is attached to. You can use - this to get at the related object (i.e. ``my_comment.content_object``). - - Since this field is a - :class:`~django.contrib.contettypes.generic.GenericForeignKey`, it's - actually syntactic sugar on top of two underlying attributes, described - below. - - .. attribute:: content_type - - A :class:`~django.db.models.ForeignKey` to - :class:`~django.contrib.contenttypes.models.ContentType`; this is the - type of the object the comment is attached to. - - .. attribute:: object_pk - - A :class:`~django.db.models.TextField` containing the primary - key of the object the comment is attached to. - - .. attribute:: site - - A :class:`~django.db.models.ForeignKey` to the - :class:`~django.contrib.sites.models.Site` on which the comment was - posted. - - .. attribute:: user - - A :class:`~django.db.models.ForeignKey` to the - :class:`~django.contrib.auth.models.User` who posted the comment. - May be blank if the comment was posted by an unauthenticated user. - - .. attribute:: user_name - - The name of the user who posted the comment. - - .. attribute:: user_email - - The email of the user who posted the comment. - - .. attribute:: user_url - - The URL entered by the person who posted the comment. - - .. attribute:: comment - - The actual content of the comment itself. - - .. attribute:: submit_date - - The date the comment was submitted. - - .. attribute:: ip_address - - The IP address of the user posting the comment. - - .. attribute:: is_public - - ``False`` if the comment is in moderation (see - :doc:`/ref/contrib/comments/moderation`); If ``True``, the comment will - be displayed on the site. - - .. attribute:: is_removed - - ``True`` if the comment was removed. Used to keep track of removed - comments instead of just deleting them. - diff --git a/parts/django/docs/ref/contrib/comments/moderation.txt b/parts/django/docs/ref/contrib/comments/moderation.txt deleted file mode 100644 index 519bc5e..0000000 --- a/parts/django/docs/ref/contrib/comments/moderation.txt +++ /dev/null @@ -1,230 +0,0 @@ -========================== -Generic comment moderation -========================== - -.. module:: django.contrib.comments.moderation - :synopsis: Support for automatic comment moderation. - -Django's bundled comments application is extremely useful on its own, -but the amount of comment spam circulating on the Web today -essentially makes it necessary to have some sort of automatic -moderation system in place for any application which makes use of -comments. To make this easier to handle in a consistent fashion, -``django.contrib.comments.moderation`` provides a generic, extensible -comment-moderation system which can be applied to any model or set of -models which want to make use of Django's comment system. - - -Overview -======== - -The entire system is contained within ``django.contrib.comments.moderation``, -and uses a two-step process to enable moderation for any given model: - -1. A subclass of :class:`CommentModerator` - is defined which specifies the moderation options the model wants to - enable. - -2. The model is registered with the moderation system, passing in the - model class and the class which specifies its moderation options. - -A simple example is the best illustration of this. Suppose we have the -following model, which would represent entries in a Weblog:: - - from django.db import models - - class Entry(models.Model): - title = models.CharField(maxlength=250) - body = models.TextField() - pub_date = models.DateTimeField() - enable_comments = models.BooleanField() - -Now, suppose that we want the following steps to be applied whenever a -new comment is posted on an ``Entry``: - -1. If the ``Entry``'s ``enable_comments`` field is ``False``, the - comment will simply be disallowed (i.e., immediately deleted). - -2. If the ``enable_comments`` field is ``True``, the comment will be - allowed to save. - -3. Once the comment is saved, an email should be sent to site staff - notifying them of the new comment. - -Accomplishing this is fairly straightforward and requires very little -code:: - - from django.contrib.comments.moderation import CommentModerator, moderator - - class EntryModerator(CommentModerator): - email_notification = True - enable_field = 'enable_comments' - - moderator.register(Entry, EntryModerator) - -The :class:`CommentModerator` class pre-defines a number of useful moderation -options which subclasses can enable or disable as desired, and ``moderator`` -knows how to work with them to determine whether to allow a comment, whether -to moderate a comment which will be allowed to post, and whether to email -notifications of new comments. - -Built-in moderation options ---------------------------- - -.. class:: CommentModerator - - Most common comment-moderation needs can be handled by subclassing - :class:`CommentModerator` and - changing the values of pre-defined attributes; the full range of built-in - options is as follows. - - .. attribute:: auto_close_field - - If this is set to the name of a - :class:`~django.db.models.fields.DateField` or - :class:`~django.db.models.fields.DateTimeField` on the model for which - comments are being moderated, new comments for objects of that model - will be disallowed (immediately deleted) when a certain number of days - have passed after the date specified in that field. Must be - used in conjunction with :attr:`close_after`, which specifies the - number of days past which comments should be - disallowed. Default value is ``None``. - - .. attribute:: auto_moderate_field - - Like :attr:`auto_close_field`, but instead of outright deleting - new comments when the requisite number of days have elapsed, - it will simply set the ``is_public`` field of new comments to - ``False`` before saving them. Must be used in conjunction with - :attr:`moderate_after`, which specifies the number of days past - which comments should be moderated. Default value is ``None``. - - .. attribute:: close_after - - If :attr:`auto_close_field` is used, this must specify the number - of days past the value of the field specified by - :attr:`auto_close_field` after which new comments for an object - should be disallowed. Default value is ``None``. - - .. attribute:: email_notification - - If ``True``, any new comment on an object of this model which - survives moderation (i.e., is not deleted) will generate an - email to site staff. Default value is ``False``. - - .. attribute:: enable_field - - If this is set to the name of a - :class:`~django.db.models.fields.BooleanField` on the model - for which comments are being moderated, new comments on - objects of that model will be disallowed (immediately deleted) - whenever the value of that field is ``False`` on the object - the comment would be attached to. Default value is ``None``. - - .. attribute:: moderate_after - - If :attr:`auto_moderate_field` is used, this must specify the number - of days past the value of the field specified by - :attr:`auto_moderate_field` after which new comments for an object - should be marked non-public. Default value is ``None``. - -Simply subclassing :class:`CommentModerator` and changing the values of these -options will automatically enable the various moderation methods for any -models registered using the subclass. - -Adding custom moderation methods --------------------------------- - -For situations where the built-in options listed above are not -sufficient, subclasses of :class:`CommentModerator` can also override -the methods which actually perform the moderation, and apply any logic -they desire. :class:`CommentModerator` defines three methods which -determine how moderation will take place; each method will be called -by the moderation system and passed two arguments: ``comment``, which -is the new comment being posted, ``content_object``, which is the -object the comment will be attached to, and ``request``, which is the -:class:`~django.http.HttpRequest` in which the comment is being submitted: - -.. method:: CommentModerator.allow(comment, content_object, request) - - Should return ``True`` if the comment should be allowed to - post on the content object, and ``False`` otherwise (in which - case the comment will be immediately deleted). - -.. method:: CommentModerator.email(comment, content_object, request) - - If email notification of the new comment should be sent to - site staff or moderators, this method is responsible for - sending the email. - -.. method:: CommentModerator.moderate(comment, content_object, request) - - Should return ``True`` if the comment should be moderated (in - which case its ``is_public`` field will be set to ``False`` - before saving), and ``False`` otherwise (in which case the - ``is_public`` field will not be changed). - - -Registering models for moderation ---------------------------------- - -The moderation system, represented by -``django.contrib.comments.moderation.moderator`` is an instance of the class -:class:`Moderator`, which allows registration and "unregistration" of models -via two methods: - -.. function:: moderator.register(model_or_iterable, moderation_class) - - Takes two arguments: the first should be either a model class - or list of model classes, and the second should be a subclass - of ``CommentModerator``, and register the model or models to - be moderated using the options defined in the - ``CommentModerator`` subclass. If any of the models are - already registered for moderation, the exception - :exc:`AlreadyModerated` will be raised. - -.. function:: moderator.unregister(model_or_iterable) - - Takes one argument: a model class or list of model classes, - and removes the model or models from the set of models which - are being moderated. If any of the models are not currently - being moderated, the exception - :exc:`NotModerated` will be raised. - - -Customizing the moderation system ---------------------------------- - -Most use cases will work easily with simple subclassing of -:class:`CommentModerator` and registration with the provided -:class:`Moderator` instance, but customization of global moderation behavior -can be achieved by subclassing :class:`Moderator` and instead registering -models with an instance of the subclass. - -.. class:: Moderator - - In addition to the :meth:`Moderator.register` and - :meth:`Moderator.unregister` methods detailed above, the following methods - on :class:`Moderator` can be overridden to achieve customized behavior: - - .. method:: connect - - Determines how moderation is set up globally. The base - implementation in - :class:`Moderator` does this by - attaching listeners to the :data:`~django.contrib.comments.signals.comment_will_be_posted` - and :data:`~django.contrib.comments.signals.comment_was_posted` signals from the - comment models. - - .. method:: pre_save_moderation(sender, comment, request, **kwargs) - - In the base implementation, applies all pre-save moderation - steps (such as determining whether the comment needs to be - deleted, or whether it needs to be marked as non-public or - generate an email). - - .. method:: post_save_moderation(sender, comment, request, **kwargs) - - In the base implementation, applies all post-save moderation - steps (currently this consists entirely of deleting comments - which were disallowed). diff --git a/parts/django/docs/ref/contrib/comments/settings.txt b/parts/django/docs/ref/contrib/comments/settings.txt deleted file mode 100644 index 1f1aeca..0000000 --- a/parts/django/docs/ref/contrib/comments/settings.txt +++ /dev/null @@ -1,33 +0,0 @@ -================ -Comment settings -================ - -These settings configure the behavior of the comments framework: - -.. setting:: COMMENTS_HIDE_REMOVED - -COMMENTS_HIDE_REMOVED ---------------------- - -If ``True`` (default), removed comments will be excluded from comment -lists/counts (as taken from template tags). Otherwise, the template author is -responsible for some sort of a "this comment has been removed by the site staff" -message. - -.. setting:: COMMENT_MAX_LENGTH - -COMMENT_MAX_LENGTH ------------------- - -The maximum length of the comment field, in characters. Comments longer than -this will be rejected. Defaults to 3000. - -.. setting:: COMMENTS_APP - -COMMENTS_APP ------------- - -An app which provides :doc:`customization of the comments framework -</ref/contrib/comments/custom>`. Use the same dotted-string notation -as in :setting:`INSTALLED_APPS`. Your custom :setting:`COMMENTS_APP` -must also be listed in :setting:`INSTALLED_APPS`. diff --git a/parts/django/docs/ref/contrib/comments/signals.txt b/parts/django/docs/ref/contrib/comments/signals.txt deleted file mode 100644 index 7ae34a1..0000000 --- a/parts/django/docs/ref/contrib/comments/signals.txt +++ /dev/null @@ -1,91 +0,0 @@ -================================ -Signals sent by the comments app -================================ - -.. module:: django.contrib.comments.signals - :synopsis: Signals sent by the comment module. - -The comment app sends a series of :doc:`signals </topics/signals>` to allow for -comment moderation and similar activities. See :doc:`the introduction to signals -</topics/signals>` for information about how to register for and receive these -signals. - -comment_will_be_posted -====================== - -.. data:: django.contrib.comments.signals.comment_will_be_posted - :module: - -Sent just before a comment will be saved, after it's been sanity checked and -submitted. This can be used to modify the comment (in place) with posting -details or other such actions. - -If any receiver returns ``False`` the comment will be discarded and a 403 (not -allowed) response will be returned. - -This signal is sent at more or less the same time (just before, actually) as the -``Comment`` object's :data:`~django.db.models.signals.pre_save` signal. - -Arguments sent with this signal: - - ``sender`` - The comment model. - - ``comment`` - The comment instance about to be posted. Note that it won't have been - saved into the database yet, so it won't have a primary key, and any - relations might not work correctly yet. - - ``request`` - The :class:`~django.http.HttpRequest` that posted the comment. - -comment_was_posted -================== - -.. data:: django.contrib.comments.signals.comment_was_posted - :module: - -Sent just after the comment is saved. - -Arguments sent with this signal: - - ``sender`` - The comment model. - - ``comment`` - The comment instance that was posted. Note that it will have already - been saved, so if you modify it you'll need to call - :meth:`~django.db.models.Model.save` again. - - ``request`` - The :class:`~django.http.HttpRequest` that posted the comment. - -comment_was_flagged -=================== - -.. data:: django.contrib.comments.signals.comment_was_flagged - :module: - -Sent after a comment was "flagged" in some way. Check the flag to see if this -was a user requesting removal of a comment, a moderator approving/removing a -comment, or some other custom user flag. - -Arguments sent with this signal: - - ``sender`` - The comment model. - - ``comment`` - The comment instance that was posted. Note that it will have already - been saved, so if you modify it you'll need to call - :meth:`~django.db.models.Model.save` again. - - ``flag`` - The :class:`~django.contrib.comments.models.CommentFlag` that's been - attached to the comment. - - ``created`` - ``True`` if this is a new flag; ``False`` if it's a duplicate flag. - - ``request`` - The :class:`~django.http.HttpRequest` that posted the comment. diff --git a/parts/django/docs/ref/contrib/comments/upgrade.txt b/parts/django/docs/ref/contrib/comments/upgrade.txt deleted file mode 100644 index 3d6b5af..0000000 --- a/parts/django/docs/ref/contrib/comments/upgrade.txt +++ /dev/null @@ -1,78 +0,0 @@ -=============================================== -Upgrading from Django's previous comment system -=============================================== - -Prior versions of Django included an outdated, undocumented comment system. Users who reverse-engineered this framework will need to upgrade to use the -new comment system; this guide explains how. - -The main changes from the old system are: - - * This new system is documented. - - * It uses modern Django features like :doc:`forms </topics/forms/index>` and - :doc:`modelforms </topics/forms/modelforms>`. - - * It has a single ``Comment`` model instead of separate ``FreeComment`` and - ``Comment`` models. - - * Comments have "email" and "URL" fields. - - * No ratings, photos and karma. This should only effect World Online. - - * The ``{% comment_form %}`` tag no longer exists. Instead, there's now two - functions: ``{% get_comment_form %}``, which returns a form for posting a - new comment, and ``{% render_comment_form %}``, which renders said form - using the ``comments/form.html`` template. - - * The way comments are include in your URLconf have changed; you'll need to - replace:: - - (r'^comments/', include('django.contrib.comments.urls.comments')), - - with:: - - (r'^comments/', include('django.contrib.comments.urls')), - -Upgrading data --------------- - -The data models for Django's comment system have changed, as have the -table names. Before you transfer your existing data into the new comments -system, make sure that you have installed the new comments system as -explained in the -:doc:`quick start guide </ref/contrib/comments/index>`. -This will ensure that the new tables have been properly created. - -To transfer your data into the new comments system, you'll need to directly -run the following SQL: - -.. code-block:: sql - - BEGIN; - - INSERT INTO django_comments - (content_type_id, object_pk, site_id, user_name, user_email, user_url, - comment, submit_date, ip_address, is_public, is_removed) - SELECT - content_type_id, object_id, site_id, person_name, '', '', comment, - submit_date, ip_address, is_public, not approved - FROM comments_freecomment; - - INSERT INTO django_comments - (content_type_id, object_pk, site_id, user_id, user_name, user_email, - user_url, comment, submit_date, ip_address, is_public, is_removed) - SELECT - content_type_id, object_id, site_id, user_id, '', '', '', comment, - submit_date, ip_address, is_public, is_removed - FROM comments_comment; - - UPDATE django_comments SET user_name = ( - SELECT username FROM auth_user - WHERE django_comments.user_id = auth_user.id - ) WHERE django_comments.user_id is not NULL; - UPDATE django_comments SET user_email = ( - SELECT email FROM auth_user - WHERE django_comments.user_id = auth_user.id - ) WHERE django_comments.user_id is not NULL; - - COMMIT; diff --git a/parts/django/docs/ref/contrib/contenttypes.txt b/parts/django/docs/ref/contrib/contenttypes.txt deleted file mode 100644 index b695651..0000000 --- a/parts/django/docs/ref/contrib/contenttypes.txt +++ /dev/null @@ -1,385 +0,0 @@ -========================== -The contenttypes framework -========================== - -.. module:: django.contrib.contenttypes - :synopsis: Provides generic interface to installed models. - -Django includes a :mod:`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 -:class:`~django.contrib.contenttypes.models.ContentType` model, which lives at -``django.contrib.contenttypes.models.ContentType``. Instances of -:class:`~django.contrib.contenttypes.models.ContentType` represent and store -information about the models installed in your project, and new instances of -:class:`~django.contrib.contenttypes.models.ContentType` are automatically -created whenever new models are installed. - -Instances of :class:`~django.contrib.contenttypes.models.ContentType` have -methods for returning the model classes they represent and for querying objects -from those models. :class:`~django.contrib.contenttypes.models.ContentType` -also has a :ref:`custom manager <custom-managers>` that adds methods for -working with :class:`~django.contrib.contenttypes.models.ContentType` and for -obtaining instances of :class:`~django.contrib.contenttypes.models.ContentType` -for a particular model. - -Relations between your models and -:class:`~django.contrib.contenttypes.models.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. - -Installing the contenttypes framework -===================================== - -The contenttypes framework is included in the default -:setting:`INSTALLED_APPS` list created by ``django-admin.py startproject``, -but if you've removed it or if you manually set up your -:setting:`INSTALLED_APPS` list, you can enable it by adding -``'django.contrib.contenttypes'`` to your :setting:`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 :mod:`authentication framework <django.contrib.auth>` uses it - to tie user permissions to specific models. - - * Django's comments system (:mod:`django.contrib.comments`) uses it to - "attach" comments to any installed model. - -The ``ContentType`` model -========================= - -.. class:: models.ContentType - - Each instance of :class:`~django.contrib.contenttypes.models.ContentType` - has three fields which, taken together, uniquely describe an installed model: - - .. attribute:: models.ContentType.app_label - - The name of the application the model is part of. This is taken from - the :attr:`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 :attr:`app_label` - of "contenttypes". - - .. attribute:: models.ContentType.model - - The name of the model class. - - .. attribute:: models.ContentType.name - - The human-readable name of the model. This is taken from the - :attr:`verbose_name <django.db.models.fields.Field.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 -:mod:`the sites application <django.contrib.sites>` to your -:setting:`INSTALLED_APPS` setting and run ``manage.py syncdb`` to install it, -the model :class:`django.contrib.sites.models.Site` will be installed into -your database. Along with it a new instance of -:class:`~django.contrib.contenttypes.models.ContentType` will be -created with the following values: - - * :attr:`app_label` will be set to ``'sites'`` (the last part of the Python - path "django.contrib.sites"). - - * :attr:`model` will be set to ``'site'``. - - * :attr:`name` will be set to ``'site'``. - -.. _the verbose_name attribute: ../model-api/#verbose_name - -Methods on ``ContentType`` instances -==================================== - -.. class:: models.ContentType - - Each :class:`~django.contrib.contenttypes.models.ContentType` instance has - methods that allow you to get from a - :class:`~django.contrib.contenttypes.models.ContentType` instance to the model - it represents, or to retrieve objects from that model: - -.. method:: models.ContentType.get_object_for_this_type(**kwargs) - - Takes a set of valid :ref:`lookup arguments <field-lookups-intro>` for the - model the :class:`~django.contrib.contenttypes.models.ContentType` - represents, and does :lookup:`a get() lookup <get>` on that model, - returning the corresponding object. - -.. method:: models.ContentType.model_class() - - Returns the model class represented by this - :class:`~django.contrib.contenttypes.models.ContentType` instance. - -For example, we could look up the -:class:`~django.contrib.contenttypes.models.ContentType` for the -:class:`~django.contrib.auth.models.User` model:: - - >>> from django.contrib.contenttypes.models import ContentType - >>> user_type = ContentType.objects.get(app_label="auth", model="user") - >>> user_type - <ContentType: user> - -And then use it to query for a particular ``User``, or to get access -to the ``User`` model class:: - - >>> user_type.model_class() - <class 'django.contrib.auth.models.User'> - >>> user_type.get_object_for_this_type(username='Guido') - <User: Guido> - -Together, -:meth:`~django.contrib.contenttypes.models.ContentType.get_object_for_this_type` -and :meth:`~django.contrib.contenttypes.models.ContentType.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 :class:`~django.contrib.contenttypes.models.ContentType` - lookup at runtime, and then work with the model class or retrieve objects - from it. - - 2. You can relate another model to - :class:`~django.contrib.contenttypes.models.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, -:class:`the permissions system <django.contrib.auth.models.Permission` in -Django's authentication framework uses a -:class:`~django.contrib.auth.models.Permission` model with a foreign -key to :class:`~django.contrib.contenttypes.models.ContentType`; this lets -:class:`~django.contrib.auth.models.Permission` represent concepts like -"can add blog entry" or "can delete news story". - -The ``ContentTypeManager`` --------------------------- - -.. class:: models.ContentTypeManager - - :class:`~django.contrib.contenttypes.models.ContentType` also has a custom - manager, :class:`~django.contrib.contenttypes.models.ContentTypeManager`, - which adds the following methods: - - .. method:: models.ContentTypeManager.clear_cache() - - Clears an internal cache used by - :class:`~django.contrib.contenttypes.models.ContentType` to keep track - of which models for which it has created - :class:`django.contrib.contenttypes.models.ContentType` instances. You - probably won't ever need to call this method yourself; Django will call - it automatically when it's needed. - - .. method:: models.ContentTypeManager.get_for_model(model) - - Takes either a model class or an instance of a model, and returns the - :class:`~django.contrib.contenttypes.models.ContentType` instance - representing that model. - -The :meth:`~models.ContentTypeManager.get_for_model()` method is especially useful when you know you -need to work with a :class:`ContentType <django.contrib.contenttypes.models.ContentType>` but don't want to go to the -trouble of obtaining the model's metadata to perform a manual lookup:: - - >>> from django.contrib.auth.models import User - >>> user_type = ContentType.objects.get_for_model(User) - >>> user_type - <ContentType: user> - -.. _generic-relations: - -Generic relations -================= - -Adding a foreign key from one of your own models to -:class:`~django.contrib.contenttypes.models.ContentType` allows your model to -effectively tie itself to another model class, as in the example of the -:class:`~django.contrib.auth.models.Permission` model above. But it's possible -to go one step further and use -:class:`~django.contrib.contenttypes.models.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 :class:`~django.db.models.fields.related.ForeignKey` can only "point -to" one other model, which means that if the ``TaggedItem`` model used a -:class:`~django.db.models.fields.related.ForeignKey` it would have to -choose one and only one model to store tags for. The contenttypes -application provides a special field type -- -:class:`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 -:class:`~django.contrib.contenttypes.generic.GenericForeignKey`: - - 1. Give your model a :class:`~django.db.models.fields.related.ForeignKey` - to :class:`~django.contrib.contenttypes.models.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 - :class:`~django.db.models.fields.IntegerField` or - :class:`~django.db.models.fields.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 - :class:`~django.db.models.fields.IntegerField`, you won't be able to - form a generic relation with a model that uses a - :class:`~django.db.models.fields.CharField` as a primary key. - - 3. Give your model a - :class:`~django.contrib.contenttypes.generic.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 - :class:`~django.contrib.contenttypes.generic.GenericForeignKey` will - look for. - -This will enable an API similar to the one used for a normal -:class:`~django.db.models.fields.related.ForeignKey`; -each ``TaggedItem`` will have a ``content_object`` field that returns the -object it's related to, and you can also assign to that field or use it when -creating a ``TaggedItem``:: - - >>> from django.contrib.auth.models import User - >>> guido = User.objects.get(username='Guido') - >>> t = TaggedItem(content_object=guido, tag='bdfl') - >>> t.save() - >>> t.content_object - <User: Guido> - -Due to the way :class:`~django.contrib.contenttypes.generic.GenericForeignKey` -is implemented, you cannot use such fields directly with filters (``filter()`` -and ``exclude()``, for example) via the database API. They aren't normal field -objects. These examples will *not* work:: - - # This will fail - >>> TaggedItem.objects.filter(content_object=guido) - # This will also fail - >>> TaggedItem.objects.get(content_object=guido) - -Reverse generic relations -------------------------- - -If you know which models you'll be using most often, you can also add -a "reverse" generic relationship to enable an additional API. For example:: - - class Bookmark(models.Model): - url = models.URLField() - tags = generic.GenericRelation(TaggedItem) - -``Bookmark`` instances will each have a ``tags`` attribute, which can -be used to retrieve their associated ``TaggedItems``:: - - >>> b = Bookmark(url='http://www.djangoproject.com/') - >>> b.save() - >>> t1 = TaggedItem(content_object=b, tag='django') - >>> t1.save() - >>> t2 = TaggedItem(content_object=b, tag='python') - >>> t2.save() - >>> b.tags.all() - [<TaggedItem: django>, <TaggedItem: python>] - -Just as :class:`django.contrib.contenttypes.generic.GenericForeignKey` -accepts the names of the content-type and object-ID fields as -arguments, so too does ``GenericRelation``; if the model which has the -generic foreign key is using non-default names for those fields, you -must pass the names of the fields when setting up a -``GenericRelation`` to it. For example, if the ``TaggedItem`` model -referred to above used fields named ``content_type_fk`` and -``object_primary_key`` to create its generic foreign key, then a -``GenericRelation`` back to it would need to be defined like so:: - - tags = generic.GenericRelation(TaggedItem, content_type_field='content_type_fk', object_id_field='object_primary_key') - -Of course, if you don't add the reverse relationship, you can do the -same types of lookups manually:: - - >>> b = Bookmark.objects.get(url='http://www.djangoproject.com/') - >>> bookmark_type = ContentType.objects.get_for_model(b) - >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, - ... object_id=b.id) - [<TaggedItem: django>, <TaggedItem: python>] - -Note that if the model in a -:class:`~django.contrib.contenttypes.generic.GenericRelation` uses a -non-default value for ``ct_field`` or ``fk_field`` in its -:class:`~django.contrib.contenttypes.generic.GenericForeignKey` (e.g. the -:mod:`django.contrib.comments` app uses ``ct_field="object_pk"``), -you'll need to set ``content_type_field`` and/or ``object_id_field`` in -the :class:`~django.contrib.contenttypes.generic.GenericRelation` to -match the ``ct_field`` and ``fk_field``, respectively, in the -:class:`~django.contrib.contenttypes.generic.GenericForeignKey`:: - - comments = generic.GenericRelation(Comment, object_id_field="object_pk") - -Note also, that if you delete an object that has a -:class:`~django.contrib.contenttypes.generic.GenericRelation`, any objects -which have a :class:`~django.contrib.contenttypes.generic.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 and aggregation ---------------------------------- - -:doc:`Django's database aggregation API </topics/db/aggregation>` -doesn't work with a -:class:`~django.contrib.contenttypes.generic.GenericRelation`. For example, you -might be tempted to try something like:: - - Bookmark.objects.aggregate(Count('tags')) - -This will not work correctly, however. The generic relation adds extra filters -to the queryset to ensure the correct content type, but the ``aggregate`` method -doesn't take them into account. For now, if you need aggregates on generic -relations, you'll need to calculate them without using the aggregation API. - -Generic relations in forms and admin ------------------------------------- - -:mod:`django.contrib.contenttypes.generic` provides both a -:class:`~django.contrib.contenttypes.generic.GenericInlineFormSet` -and :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin`. -This enables the use of generic relations in forms and the admin. See the -:doc:`model formset </topics/forms/modelforms>` and -:doc:`admin </ref/contrib/admin/index>` documentation for more information. - -.. class:: generic.GenericInlineModelAdmin - - The :class:`~django.contrib.contenttypes.generic.GenericInlineModelAdmin` - class inherits all properties from an - :class:`~django.contrib.admin.InlineModelAdmin` class. However, - it adds a couple of its own for working with the generic relation: - - .. attribute:: generic.GenericInlineModelAdmin.ct_field - - The name of the - :class:`~django.contrib.contenttypes.models.ContentType` foreign key - field on the model. Defaults to ``content_type``. - - .. attribute:: generic.GenericInlineModelAdmin.ct_fk_field - - The name of the integer field that represents the ID of the related - object. Defaults to ``object_id``. diff --git a/parts/django/docs/ref/contrib/csrf.txt b/parts/django/docs/ref/contrib/csrf.txt deleted file mode 100644 index c32dd73..0000000 --- a/parts/django/docs/ref/contrib/csrf.txt +++ /dev/null @@ -1,433 +0,0 @@ -===================================== -Cross Site Request Forgery protection -===================================== - -.. module:: django.middleware.csrf - :synopsis: Protects against Cross Site Request Forgeries - -The CSRF middleware and template tag provides easy-to-use protection against -`Cross Site Request Forgeries`_. This type of attack occurs when a malicious -Web site contains a link, a form button or some javascript that is intended to -perform some action on your Web site, using the credentials of a logged-in user -who visits the malicious site in their browser. A related type of attack, -'login CSRF', where an attacking site tricks a user's browser into logging into -a site with someone else's credentials, is also covered. - -The first defense against CSRF attacks is to ensure that GET requests are -side-effect free. POST requests can then be protected by following the steps -below. - -.. versionadded:: 1.2 - The 'contrib' apps, including the admin, use the functionality described - here. Because it is security related, a few things have been added to core - functionality to allow this to happen without any required upgrade steps. - -.. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF - -How to use it -============= - -.. versionchanged:: 1.2 - The template tag functionality (the recommended way to use this) was added - in version 1.2. The previous method (still available) is described under - `Legacy method`_. - -To enable CSRF protection for your views, follow these steps: - - 1. Add the middleware - ``'django.middleware.csrf.CsrfViewMiddleware'`` to your list of - middleware classes, :setting:`MIDDLEWARE_CLASSES`. (It should come - before ``CsrfResponseMiddleware`` if that is being used, and before any - view middleware that assume that CSRF attacks have been dealt with.) - - Alternatively, you can use the decorator - ``django.views.decorators.csrf.csrf_protect`` on particular views you - want to protect (see below). - - 2. In any template that uses a POST form, use the :ttag:`csrf_token` tag inside - the ``<form>`` element if the form is for an internal URL, e.g.:: - - <form action="" method="post">{% csrf_token %} - - This should not be done for POST forms that target external URLs, since - that would cause the CSRF token to be leaked, leading to a vulnerability. - - 3. In the corresponding view functions, ensure that the - ``'django.core.context_processors.csrf'`` context processor is - being used. Usually, this can be done in one of two ways: - - 1. Use RequestContext, which always uses - ``'django.core.context_processors.csrf'`` (no matter what your - TEMPLATE_CONTEXT_PROCESSORS setting). If you are using - generic views or contrib apps, you are covered already, since these - apps use RequestContext throughout. - - 2. Manually import and use the processor to generate the CSRF token and - add it to the template context. e.g.:: - - from django.core.context_processors import csrf - from django.shortcuts import render_to_response - - def my_view(request): - c = {} - c.update(csrf(request)) - # ... view code here - return render_to_response("a_template.html", c) - - You may want to write your own ``render_to_response`` wrapper that - takes care of this step for you. - -The utility script ``extras/csrf_migration_helper.py`` can help to automate the -finding of code and templates that may need to be upgraded. It contains full -help on how to use it. - -The decorator method --------------------- - -Rather than adding ``CsrfViewMiddleware`` as a blanket protection, you can use -the ``csrf_protect`` decorator, which has exactly the same functionality, on -particular views that need the protection. It must be used **both** on views -that insert the CSRF token in the output, and on those that accept the POST form -data. (These are often the same view function, but not always). It is used like -this:: - - from django.views.decorators.csrf import csrf_protect - from django.template import RequestContext - - @csrf_protect - def my_view(request): - c = {} - # ... - return render_to_response("a_template.html", c, - context_instance=RequestContext(request)) - -Use of the decorator is **not recommended** by itself, since if you forget to -use it, you will have a security hole. The 'belt and braces' strategy of using -both is fine, and will incur minimal overhead. - -Legacy method -------------- - -In Django 1.1, the template tag did not exist. Instead, a post-processing -middleware that re-wrote POST forms to include the CSRF token was used. If you -are upgrading a site from version 1.1 or earlier, please read this section and -the `Upgrading notes`_ below. The post-processing middleware is still available -as ``CsrfResponseMiddleware``, and it can be used by following these steps: - - 1. Follow step 1 above to install ``CsrfViewMiddleware``. - - 2. Add ``'django.middleware.csrf.CsrfResponseMiddleware'`` to your - :setting:`MIDDLEWARE_CLASSES` setting. - - ``CsrfResponseMiddleware`` needs to process the response before things - like compression or setting ofETags happen to the response, so it must - come after ``GZipMiddleware``, ``CommonMiddleware`` and - ``ConditionalGetMiddleware`` in the list. It also must come after - ``CsrfViewMiddleware``. - -Use of the ``CsrfResponseMiddleware`` is not recommended because of the -performance hit it imposes, and because of a potential security problem (see -below). It can be used as an interim measure until applications have been -updated to use the :ttag:`csrf_token` tag. It is deprecated and will be -removed in Django 1.4. - -Django 1.1 and earlier provided a single ``CsrfMiddleware`` class. This is also -still available for backwards compatibility. It combines the functions of the -two middleware. - -Note also that previous versions of these classes depended on the sessions -framework, but this dependency has now been removed, with backward compatibility -support so that upgrading will not produce any issues. - -Security of legacy method -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The post-processing ``CsrfResponseMiddleware`` adds the CSRF token to all POST -forms (unless the view has been decorated with ``csrf_response_exempt``). If -the POST form has an external untrusted site as its target, rather than an -internal page, that site will be sent the CSRF token when the form is submitted. -Armed with this leaked information, that site will then be able to successfully -launch a CSRF attack on your site against that user. The -``@csrf_response_exempt`` decorator can be used to fix this, but only if the -page doesn't also contain internal forms that require the token. - -.. _ref-csrf-upgrading-notes: - -Upgrading notes ---------------- - -When upgrading to version 1.2 or later, you may have applications that rely on -the old post-processing functionality for CSRF protection, or you may not have -enabled any CSRF protection. This section outlines the steps necessary for a -smooth upgrade, without having to fix all the applications to use the new -template tag method immediately. - -First of all, the location of the middleware and related functions have -changed. There are backwards compatible stub files so that old imports will -continue to work for now, but they are deprecated and will be removed in Django -1.4. The following changes have been made: - - * Middleware have been moved to ``django.middleware.csrf`` - * Decorators have been moved to ``django.views.decorators.csrf`` - -====================================================== ============================================== - Old New -====================================================== ============================================== -django.contrib.csrf.middleware.CsrfMiddleware django.middleware.csrf.CsrfMiddleware -django.contrib.csrf.middleware.CsrfViewMiddleware django.middleware.csrf.CsrfViewMiddleware -django.contrib.csrf.middleware.CsrfResponseMiddleware django.middleware.csrf.CsrfResponseMiddleware -django.contrib.csrf.middleware.csrf_exempt django.views.decorators.csrf.csrf_exempt -django.contrib.csrf.middleware.csrf_view_exempt django.views.decorators.csrf.csrf_view_exempt -django.contrib.csrf.middleware.csrf_response_exempt django.views.decorators.csrf.csrf_response_exempt -====================================================== ============================================== - -You should update any imports, and also the paths in your -:setting:`MIDDLEWARE_CLASSES`. - -If you have ``CsrfMiddleware`` in your :setting:`MIDDLEWARE_CLASSES`, you will now -have a working installation with CSRF protection. It is recommended at this -point that you replace ``CsrfMiddleware`` with its two components, -``CsrfViewMiddleware`` and ``CsrfResponseMiddleware`` (in that order). - -If you do not have any of the middleware in your :setting:`MIDDLEWARE_CLASSES`, -you will have a working installation but without any CSRF protection for your -views (just as you had before). It is strongly recommended to install -``CsrfViewMiddleware`` and ``CsrfResponseMiddleware``, as described above. - -Note that contrib apps, such as the admin, have been updated to use the -``csrf_protect`` decorator, so that they are secured even if you do not add the -``CsrfViewMiddleware`` to your settings. However, if you have supplied -customised templates to any of the view functions of contrib apps (whether -explicitly via a keyword argument, or by overriding built-in templates), **you -MUST update them** to include the :ttag:`csrf_token` template tag as described -above, or they will stop working. (If you cannot update these templates for -some reason, you will be forced to use ``CsrfResponseMiddleware`` for these -views to continue working). - -Note also, if you are using the comments app, and you are not going to add -``CsrfViewMiddleware`` to your settings (not recommended), you will need to add -the ``csrf_protect`` decorator to any views that include the comment forms and -target the comment views (usually using the :ttag:`comment_form_target` template -tag). - -Assuming you have followed the above, all views in your Django site will now be -protected by the ``CsrfViewMiddleware``. Contrib apps meet the requirements -imposed by the ``CsrfViewMiddleware`` using the template tag, and other -applications in your project will meet its requirements by virtue of the -``CsrfResponseMiddleware``. - -The next step is to update all your applications to use the template tag, as -described in `How to use it`_, steps 2-3. This can be done as soon as is -practical. Any applications that are updated will now require Django 1.1.2 or -later, since they will use the CSRF template tag which was not available in -earlier versions. (The template tag in 1.1.2 is actually a no-op that exists -solely to ease the transition to 1.2 — it allows apps to be created that have -CSRF protection under 1.2 without requiring users of the apps to upgrade to the -Django 1.2.X series). - -The utility script ``extras/csrf_migration_helper.py`` can help to automate the -finding of code and templates that may need to be upgraded. It contains full -help on how to use it. - -Finally, once all applications are upgraded, ``CsrfResponseMiddleware`` can be -removed from your settings. - -While ``CsrfResponseMiddleware`` is still in use, the ``csrf_response_exempt`` -decorator, described in `Exceptions`_, may be useful. The post-processing -middleware imposes a performance hit and a potential vulnerability, and any -views that have been upgraded to use the new template tag method no longer need -it. - -Exceptions ----------- - -.. versionadded:: 1.1 -.. versionchanged:: 1.2 - Import paths for the decorators below were changed. - -To manually exclude a view function from being handled by either of the two CSRF -middleware, you can use the ``csrf_exempt`` decorator, found in the -``django.views.decorators.csrf`` module. For example:: - - from django.views.decorators.csrf import csrf_exempt - - @csrf_exempt - def my_view(request): - return HttpResponse('Hello world') - -Like the middleware, the ``csrf_exempt`` decorator is composed of two parts: a -``csrf_view_exempt`` decorator and a ``csrf_response_exempt`` decorator, found -in the same module. These disable the view protection mechanism -(``CsrfViewMiddleware``) and the response post-processing -(``CsrfResponseMiddleware``) respectively. They can be used individually if -required. - -You don't have to worry about doing this for most AJAX views. Any request sent -with "X-Requested-With: XMLHttpRequest" is automatically exempt. (See the `How -it works`_ section.) - -Subdomains ----------- - -By default, CSRF cookies are specific to the subdomain they are set for. This -means that a form served from one subdomain (e.g. server1.example.com) will not -be able to have a target on another subdomain (e.g. server2.example.com). This -restriction can be removed by setting :setting:`CSRF_COOKIE_DOMAIN` to be -something like ``".example.com"``. - -Please note that, with or without use of this setting, this CSRF protection -mechanism is not safe against cross-subdomain attacks -- see `Limitations`_. - -Rejected requests -================= - -By default, a '403 Forbidden' response is sent to the user if an incoming -request fails the checks performed by ``CsrfViewMiddleware``. This should -usually only be seen when there is a genuine Cross Site Request Forgery, or -when, due to a programming error, the CSRF token has not been included with a -POST form. - -No logging is done, and the error message is not very friendly, so you may want -to provide your own page for handling this condition. To do this, simply set -the :setting:`CSRF_FAILURE_VIEW` setting to a dotted path to your own view -function, which should have the following signature:: - - def csrf_failure(request, reason="") - -where ``reason`` is a short message (intended for developers or logging, not for -end users) indicating the reason the request was rejected. - -How it works -============ - -The CSRF protection is based on the following things: - -1. A CSRF cookie that is set to a random value (a session independent nonce, as - it is called), which other sites will not have access to. - - This cookie is set by ``CsrfViewMiddleware``. It is meant to be permanent, - but since there is no way to set a cookie that never expires, it is sent with - every response that has called ``django.middleware.csrf.get_token()`` - (the function used internally to retrieve the CSRF token). - -2. A hidden form field with the name 'csrfmiddlewaretoken' present in all - outgoing POST forms. The value of this field is the value of the CSRF - cookie. - - This part is done by the template tag (and with the legacy method, it is done - by ``CsrfResponseMiddleware``). - -3. For all incoming POST requests, a CSRF cookie must be present, and the - 'csrfmiddlewaretoken' field must be present and correct. If it isn't, the - user will get a 403 error. - - This check is done by ``CsrfViewMiddleware``. - -4. In addition, for HTTPS requests, strict referer checking is done by - ``CsrfViewMiddleware``. This is necessary to address a Man-In-The-Middle - attack that is possible under HTTPS when using a session independent nonce, - due to the fact that HTTP 'Set-Cookie' headers are (unfortunately) accepted - by clients that are talking to a site under HTTPS. (Referer checking is not - done for HTTP requests because the presence of the Referer header is not - reliable enough under HTTP.) - -This ensures that only forms that have originated from your Web site can be used -to POST data back. - -It deliberately only targets HTTP POST requests (and the corresponding POST -forms). GET requests ought never to have any potentially dangerous side effects -(see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a CSRF attack with a GET -request ought to be harmless. - -``CsrfResponseMiddleware`` checks the Content-Type before modifying the -response, and only pages that are served as 'text/html' or -'application/xml+xhtml' are modified. - -AJAX ----- - -The middleware tries to be smart about requests that come in via AJAX. Most -modern JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP -header; these requests are detected and automatically *not* handled by this -middleware. We can do this safely because, in the context of a browser, the -header can only be added by using ``XMLHttpRequest``, and browsers already -implement a same-domain policy for ``XMLHttpRequest``. - -For the more recent browsers that relax this same-domain policy, custom headers -like "X-Requested-With" are only allowed after the browser has done a -'preflight' check to the server to see if the cross-domain request is allowed, -using a strictly 'opt in' mechanism, so the exception for AJAX is still safe—if -the developer has specifically opted in to allowing cross-site AJAX POST -requests on a specific URL, they obviously don't want the middleware to disallow -exactly that. - -.. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html - -Caching -======= - -If the :ttag:`csrf_token` template tag is used by a template (or the ``get_token`` -function is called some other way), ``CsrfViewMiddleware`` will add a cookie and -a ``Vary: Cookie`` header to the response. Similarly, -``CsrfResponseMiddleware`` will send the ``Vary: Cookie`` header if it inserted -a token. This means that these middleware will play well with the cache -middleware if it is used as instructed (``UpdateCacheMiddleware`` goes before -all other middleware). - -However, if you use cache decorators on individual views, the CSRF middleware -will not yet have been able to set the Vary header. In this case, on any views -that will require a CSRF token to be inserted you should use the -:func:`django.views.decorators.vary.vary_on_cookie` decorator first:: - - from django.views.decorators.cache import cache_page - from django.views.decorators.vary import vary_on_cookie - - @cache_page(60 * 15) - @vary_on_cookie - def my_view(request): - # ... - - -Testing -======= - -The ``CsrfViewMiddleware`` will usually be a big hindrance to testing view -functions, due to the need for the CSRF token which must be sent with every POST -request. For this reason, Django's HTTP client for tests has been modified to -set a flag on requests which relaxes the middleware and the ``csrf_protect`` -decorator so that they no longer rejects requests. In every other respect -(e.g. sending cookies etc.), they behave the same. - -If, for some reason, you *want* the test client to perform CSRF -checks, you can create an instance of the test client that enforces -CSRF checks:: - - >>> from django.test import Client - >>> csrf_client = Client(enforce_csrf_checks=True) - -Limitations -=========== - -Subdomains within a site will be able to set cookies on the client for the whole -domain. By setting the cookie and using a corresponding token, subdomains will -be able to circumvent the CSRF protection. The only way to avoid this is to -ensure that subdomains are controlled by trusted users (or, are at least unable -to set cookies). Note that even without CSRF, there are other vulnerabilities, -such as session fixation, that make giving subdomains to untrusted parties a bad -idea, and these vulnerabilities cannot easily be fixed with current browsers. - -If you are using ``CsrfResponseMiddleware`` and your app creates HTML pages and -forms in some unusual way, (e.g. it sends fragments of HTML in JavaScript -document.write statements) you might bypass the filter that adds the hidden -field to the form, in which case form submission will always fail. You should -use the template tag or :meth:`django.middleware.csrf.get_token` to get -the CSRF token and ensure it is included when your form is submitted. - -Contrib and reusable apps -========================= - -Because it is possible for the developer to turn off the ``CsrfViewMiddleware``, -all relevant views in contrib apps use the ``csrf_protect`` decorator to ensure -the security of these applications against CSRF. It is recommended that the -developers of other reusable apps that want the same guarantees also use the -``csrf_protect`` decorator on their views. diff --git a/parts/django/docs/ref/contrib/databrowse.txt b/parts/django/docs/ref/contrib/databrowse.txt deleted file mode 100644 index 33c8228..0000000 --- a/parts/django/docs/ref/contrib/databrowse.txt +++ /dev/null @@ -1,90 +0,0 @@ -========== -Databrowse -========== - -.. module:: django.contrib.databrowse - :synopsis: Databrowse is a Django application that lets you browse your data. - -Databrowse is a Django application that lets you browse your data. - -As the Django admin dynamically creates an admin interface by introspecting -your models, Databrowse dynamically creates a rich, browsable Web site by -introspecting your models. - -.. admonition:: Note - - Databrowse is **very** new and is currently under active development. It - may change substantially before the next Django release. - - With that said, it's easy to use, and it doesn't require writing any - code. So you can play around with it today, with very little investment in - time or coding. - -How to use Databrowse -===================== - - 1. Point Django at the default Databrowse templates. There are two ways to - do this: - - * Add ``'django.contrib.databrowse'`` to your :setting:`INSTALLED_APPS` - setting. This will work if your :setting:`TEMPLATE_LOADERS` setting - includes the ``app_directories`` template loader (which is the case by - default). See the :ref:`template loader docs <template-loaders>` for - more. - - * Otherwise, determine the full filesystem path to the - :file:`django/contrib/databrowse/templates` directory, and add that - directory to your :setting:`TEMPLATE_DIRS` setting. - - 2. Register a number of models with the Databrowse site:: - - from django.contrib import databrowse - from myapp.models import SomeModel, SomeOtherModel - - databrowse.site.register(SomeModel) - databrowse.site.register(SomeOtherModel) - - Note that you should register the model *classes*, not instances. - - It doesn't matter where you put this, as long as it gets executed at some - point. A good place for it is in your :doc:`URLconf file - </topics/http/urls>` (``urls.py``). - - 3. Change your URLconf to import the :mod:`~django.contrib.databrowse` module:: - - from django.contrib import databrowse - - ...and add the following line to your URLconf:: - - (r'^databrowse/(.*)', databrowse.site.root), - - The prefix doesn't matter -- you can use ``databrowse/`` or ``db/`` or - whatever you'd like. - - 4. Run the Django server and visit ``/databrowse/`` in your browser. - -Requiring user login -==================== - -You can restrict access to logged-in users with only a few extra lines of -code. Simply add the following import to your URLconf:: - - from django.contrib.auth.decorators import login_required - -Then modify the :doc:`URLconf </topics/http/urls>` so that the -:func:`databrowse.site.root` view is decorated with -:func:`django.contrib.auth.decorators.login_required`:: - - (r'^databrowse/(.*)', login_required(databrowse.site.root)), - -If you haven't already added support for user logins to your :doc:`URLconf -</topics/http/urls>`, as described in the :doc:`user authentication docs -</ref/contrib/auth>`, then you will need to do so now with the following -mapping:: - - (r'^accounts/login/$', 'django.contrib.auth.views.login'), - -The final step is to create the login form required by -:func:`django.contrib.auth.views.login`. The -:doc:`user authentication docs </ref/contrib/auth>` provide full details and a -sample template that can be used for this purpose. diff --git a/parts/django/docs/ref/contrib/flatpages.txt b/parts/django/docs/ref/contrib/flatpages.txt deleted file mode 100644 index 46b28dc..0000000 --- a/parts/django/docs/ref/contrib/flatpages.txt +++ /dev/null @@ -1,167 +0,0 @@ -================= -The flatpages app -================= - -.. module:: django.contrib.flatpages - :synopsis: A framework for managing simple ?flat? HTML content in a database. - -Django comes with an optional "flatpages" application. It lets you store simple -"flat" HTML content in a database and handles the management for you via -Django's admin interface and a Python API. - -A flatpage is a simple object with a URL, title and content. Use it for -one-off, special-case pages, such as "About" or "Privacy Policy" pages, that -you want to store in a database but for which you don't want to develop a -custom Django application. - -A flatpage can use a custom template or a default, systemwide flatpage -template. It can be associated with one, or multiple, sites. - -.. versionadded:: 1.0 - -The content field may optionally be left blank if you prefer to put your -content in a custom template. - -Here are some examples of flatpages on Django-powered sites: - - * http://www.lawrence.com/about/contact/ - * http://www2.ljworld.com/site/rules/ - -Installation -============ - -To install the flatpages app, follow these steps: - - 1. Install the :mod:`sites framework <django.contrib.sites>` by adding - ``'django.contrib.sites'`` to your :setting:`INSTALLED_APPS` setting, - if it's not already in there. - - Also make sure you've correctly set :setting:`SITE_ID` to the ID of the - site the settings file represents. This will usually be ``1`` (i.e. - ``SITE_ID = 1``, but if you're using the sites framework to manage - multiple sites, it could be the ID of a different site. - - 2. Add ``'django.contrib.flatpages'`` to your :setting:`INSTALLED_APPS` - setting. - - 3. Add ``'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'`` - to your :setting:`MIDDLEWARE_CLASSES` setting. - - 4. Run the command :djadmin:`manage.py syncdb <syncdb>`. - -How it works -============ - -``manage.py syncdb`` creates two tables in your database: ``django_flatpage`` -and ``django_flatpage_sites``. ``django_flatpage`` is a simple lookup table -that simply maps a URL to a title and bunch of text content. -``django_flatpage_sites`` associates a flatpage with a site. - -The :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` -does all of the work. Each time any Django application raises a 404 error, this -middleware checks the flatpages database for the requested URL as a last resort. -Specifically, it checks for a flatpage with the given URL with a site ID that -corresponds to the :setting:`SITE_ID` setting. - -If it finds a match, it follows this algorithm: - - * If the flatpage has a custom template, it loads that template. Otherwise, - it loads the template :file:`flatpages/default.html`. - - * It passes that template a single context variable, :data:`flatpage`, which - is the flatpage object. It uses - :class:`~django.template.context.RequestContext` in rendering the - template. - -If it doesn't find a match, the request continues to be processed as usual. - -The middleware only gets activated for 404s -- not for 500s or responses of any -other status code. - -.. admonition:: Flatpages will not apply view middleware - - Because the ``FlatpageFallbackMiddleware`` is applied only after - URL resolution has failed and produced a 404, the response it - returns will not apply any :ref:`view middleware <view-middleware>` - methods. Only requests which are successfully routed to a view via - normal URL resolution apply view middleware. - -Note that the order of :setting:`MIDDLEWARE_CLASSES` matters. Generally, you can -put :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` at -the end of the list, because it's a last resort. - -For more on middleware, read the :doc:`middleware docs -</topics/http/middleware>`. - -.. admonition:: Ensure that your 404 template works - - Note that the - :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` - only steps in once another view has successfully produced a 404 response. - If another view or middleware class attempts to produce a 404 but ends up - raising an exception instead (such as a ``TemplateDoesNotExist`` - exception if your site does not have an appropriate template to - use for HTTP 404 responses), the response will become an HTTP 500 - ("Internal Server Error") and the - :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` - will not attempt to serve a flat page. - -How to add, change and delete flatpages -======================================= - -Via the admin interface ------------------------ - -If you've activated the automatic Django admin interface, you should see a -"Flatpages" section on the admin index page. Edit flatpages as you edit any -other object in the system. - -Via the Python API ------------------- - -.. class:: models.FlatPage - - Flatpages are represented by a standard - :doc:`Django model </topics/db/models>`, - which lives in `django/contrib/flatpages/models.py`_. You can access - flatpage objects via the :doc:`Django database API </topics/db/queries>`. - -.. _django/contrib/flatpages/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/flatpages/models.py - -Flatpage templates -================== - -By default, flatpages are rendered via the template -:file:`flatpages/default.html`, but you can override that for a -particular flatpage: in the admin, a collapsed fieldset titled -"Advanced options" (clicking will expand it) contains a field for -specifying a template name. If you're creating a flat page via the -Python API you can simply set the template name as the field -``template_name`` on the ``FlatPage`` object. - -Creating the :file:`flatpages/default.html` template is your responsibility; -in your template directory, just create a :file:`flatpages` directory -containing a file :file:`default.html`. - -Flatpage templates are passed a single context variable, :data:`flatpage`, -which is the flatpage object. - -Here's a sample :file:`flatpages/default.html` template: - -.. code-block:: html+django - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" - "http://www.w3.org/TR/REC-html40/loose.dtd"> - <html> - <head> - <title>{{ flatpage.title }}</title> - </head> - <body> - {{ flatpage.content }} - </body> - </html> - -Since you're already entering raw HTML into the admin page for a flatpage, -both ``flatpage.title`` and ``flatpage.content`` are marked as **not** -requiring :ref:`automatic HTML escaping <automatic-html-escaping>` in the -template. diff --git a/parts/django/docs/ref/contrib/formtools/form-preview.txt b/parts/django/docs/ref/contrib/formtools/form-preview.txt deleted file mode 100644 index a2cbea7..0000000 --- a/parts/django/docs/ref/contrib/formtools/form-preview.txt +++ /dev/null @@ -1,121 +0,0 @@ -============ -Form preview -============ - -.. module:: django.contrib.formtools - :synopsis: Displays an HTML form, forces a preview, then does something - with the submission. - -Django comes with an optional "form preview" application that helps automate -the following workflow: - -"Display an HTML form, force a preview, then do something with the submission." - -To force a preview of a form submission, all you have to do is write a short -Python class. - -Overview -========= - -Given a :class:`django.forms.Form` subclass that you define, this -application takes care of the following workflow: - - 1. Displays the form as HTML on a Web page. - 2. Validates the form data when it's submitted via POST. - a. If it's valid, displays a preview page. - b. If it's not valid, redisplays the form with error messages. - 3. When the "confirmation" form is submitted from the preview page, calls - a hook that you define -- a - :meth:`~django.contrib.formtools.FormPreview.done()` method that gets - passed the valid data. - -The framework enforces the required preview by passing a shared-secret hash to -the preview page via hidden form fields. If somebody tweaks the form parameters -on the preview page, the form submission will fail the hash-comparison test. - -How to use ``FormPreview`` -========================== - - 1. Point Django at the default FormPreview templates. There are two ways to - do this: - - * Add ``'django.contrib.formtools'`` to your - :setting:`INSTALLED_APPS` setting. This will work if your - :setting:`TEMPLATE_LOADERS` setting includes the - ``app_directories`` template loader (which is the case by - default). See the :ref:`template loader docs <template-loaders>` - for more. - - * Otherwise, determine the full filesystem path to the - :file:`django/contrib/formtools/templates` directory, and add that - directory to your :setting:`TEMPLATE_DIRS` setting. - - 2. Create a :class:`~django.contrib.formtools.FormPreview` subclass that - overrides the :meth:`~django.contrib.formtools.FormPreview.done()` - method:: - - from django.contrib.formtools.preview import FormPreview - from myapp.models import SomeModel - - class SomeModelFormPreview(FormPreview): - - def done(self, request, cleaned_data): - # Do something with the cleaned_data, then redirect - # to a "success" page. - return HttpResponseRedirect('/form/success') - - This method takes an :class:`~django.http.HttpRequest` object and a - dictionary of the form data after it has been validated and cleaned. - It should return an :class:`~django.http.HttpResponseRedirect` that - is the end result of the form being submitted. - - 3. Change your URLconf to point to an instance of your - :class:`~django.contrib.formtools.FormPreview` subclass:: - - from myapp.preview import SomeModelFormPreview - from myapp.forms import SomeModelForm - from django import forms - - ...and add the following line to the appropriate model in your URLconf:: - - (r'^post/$', SomeModelFormPreview(SomeModelForm)), - - where ``SomeModelForm`` is a Form or ModelForm class for the model. - - 4. Run the Django server and visit :file:`/post/` in your browser. - -``FormPreview`` classes -======================= - -.. class:: FormPreview - -A :class:`~django.contrib.formtools.FormPreview` class is a simple Python class -that represents the preview workflow. -:class:`~django.contrib.formtools.FormPreview` classes must subclass -``django.contrib.formtools.preview.FormPreview`` and override the -:meth:`~django.contrib.formtools.FormPreview.done()` method. They can live -anywhere in your codebase. - -``FormPreview`` templates -========================= - -By default, the form is rendered via the template :file:`formtools/form.html`, -and the preview page is rendered via the template :file:`formtools/preview.html`. -These values can be overridden for a particular form preview by setting -:attr:`~django.contrib.formtools.FormPreview.preview_template` and -:attr:`~django.contrib.formtools.FormPreview.form_template` attributes on the -FormPreview subclass. See :file:`django/contrib/formtools/templates` for the -default templates. - -Advanced ``FormPreview`` methods -================================ - -.. versionadded:: 1.2 - -.. method:: FormPreview.process_preview - - Given a validated form, performs any extra processing before displaying the - preview page, and saves any extra data in context. - - By default, this method is empty. It is called after the form is validated, - but before the context is modified with hash information and rendered. diff --git a/parts/django/docs/ref/contrib/formtools/form-wizard.txt b/parts/django/docs/ref/contrib/formtools/form-wizard.txt deleted file mode 100644 index 390d575..0000000 --- a/parts/django/docs/ref/contrib/formtools/form-wizard.txt +++ /dev/null @@ -1,312 +0,0 @@ -=========== -Form wizard -=========== - -.. module:: django.contrib.formtools.wizard - :synopsis: Splits forms across multiple Web pages. - -.. versionadded:: 1.0 - -Django comes with an optional "form wizard" application that splits -:doc:`forms </topics/forms/index>` across multiple Web pages. It maintains -state in hashed HTML :samp:`<input type="hidden">` fields, and the data isn't -processed server-side until the final form is submitted. - -You might want to use this if you have a lengthy form that would be too -unwieldy for display on a single page. The first page might ask the user for -core information, the second page might ask for less important information, -etc. - -The term "wizard," in this context, is `explained on Wikipedia`_. - -.. _explained on Wikipedia: http://en.wikipedia.org/wiki/Wizard_%28software%29 -.. _forms: ../forms/ - -How it works -============ - -Here's the basic workflow for how a user would use a wizard: - - 1. The user visits the first page of the wizard, fills in the form and - submits it. - 2. The server validates the data. If it's invalid, the form is displayed - again, with error messages. If it's valid, the server calculates a - secure hash of the data and presents the user with the next form, - saving the validated data and hash in :samp:`<input type="hidden">` - fields. - 3. Step 1 and 2 repeat, for every subsequent form in the wizard. - 4. Once the user has submitted all the forms and all the data has been - validated, the wizard processes the data -- saving it to the database, - sending an e-mail, or whatever the application needs to do. - -Usage -===== - -This application handles as much machinery for you as possible. Generally, you -just have to do these things: - - 1. Define a number of :class:`~django.forms.Form` classes -- one per wizard - page. - - 2. Create a :class:`FormWizard` class that specifies what to do once all of - your forms have been submitted and validated. This also lets you - override some of the wizard's behavior. - - 3. Create some templates that render the forms. You can define a single, - generic template to handle every one of the forms, or you can define a - specific template for each form. - - 4. Point your URLconf at your :class:`FormWizard` class. - -Defining ``Form`` classes -========================= - -The first step in creating a form wizard is to create the -:class:`~django.forms.Form` classes. These should be standard -:class:`django.forms.Form` classes, covered in the :doc:`forms documentation -</topics/forms/index>`. These classes can live anywhere in your codebase, but -convention is to put them in a file called :file:`forms.py` in your -application. - -For example, let's write a "contact form" wizard, where the first page's form -collects the sender's e-mail address and subject, and the second page collects -the message itself. Here's what the :file:`forms.py` might look like:: - - from django import forms - - class ContactForm1(forms.Form): - subject = forms.CharField(max_length=100) - sender = forms.EmailField() - - class ContactForm2(forms.Form): - message = forms.CharField(widget=forms.Textarea) - -**Important limitation:** Because the wizard uses HTML hidden fields to store -data between pages, you may not include a :class:`~django.forms.FileField` -in any form except the last one. - -Creating a ``FormWizard`` class -=============================== - -The next step is to create a -:class:`django.contrib.formtools.wizard.FormWizard` subclass. As with your -:class:`~django.forms.Form` classes, this :class:`FormWizard` class can live -anywhere in your codebase, but convention is to put it in :file:`forms.py`. - -The only requirement on this subclass is that it implement a -:meth:`~FormWizard.done()` method. - -.. method:: FormWizard.done - - This method specifies what should happen when the data for *every* form is - submitted and validated. This method is passed two arguments: - - * ``request`` -- an :class:`~django.http.HttpRequest` object - * ``form_list`` -- a list of :class:`~django.forms.Form` classes - -In this simplistic example, rather than perform any database operation, the -method simply renders a template of the validated data:: - - from django.shortcuts import render_to_response - from django.contrib.formtools.wizard import FormWizard - - class ContactWizard(FormWizard): - def done(self, request, form_list): - return render_to_response('done.html', { - 'form_data': [form.cleaned_data for form in form_list], - }) - -Note that this method will be called via ``POST``, so it really ought to be a -good Web citizen and redirect after processing the data. Here's another -example:: - - from django.http import HttpResponseRedirect - from django.contrib.formtools.wizard import FormWizard - - class ContactWizard(FormWizard): - def done(self, request, form_list): - do_something_with_the_form_data(form_list) - return HttpResponseRedirect('/page-to-redirect-to-when-done/') - -See the section `Advanced FormWizard methods`_ below to learn about more -:class:`FormWizard` hooks. - -Creating templates for the forms -================================ - -Next, you'll need to create a template that renders the wizard's forms. By -default, every form uses a template called :file:`forms/wizard.html`. (You can -change this template name by overriding :meth:`~FormWizard.get_template()`, -which is documented below. This hook also allows you to use a different -template for each form.) - -This template expects the following context: - - * ``step_field`` -- The name of the hidden field containing the step. - * ``step0`` -- The current step (zero-based). - * ``step`` -- The current step (one-based). - * ``step_count`` -- The total number of steps. - * ``form`` -- The :class:`~django.forms.Form` instance for the current step - (either empty or with errors). - * ``previous_fields`` -- A string representing every previous data field, - plus hashes for completed forms, all in the form of hidden fields. Note - that you'll need to run this through the :tfilter:`safe` template filter, - to prevent auto-escaping, because it's raw HTML. - -You can supply extra context to this template in two ways: - - * Set the :attr:`~FormWizard.extra_context` attribute on your - :class:`FormWizard` subclass to a dictionary. - - * Pass a dictionary as a parameter named ``extra_context`` to your wizard's - URL pattern in your URLconf. See :ref:`hooking-wizard-into-urlconf`. - -Here's a full example template: - -.. code-block:: html+django - - {% extends "base.html" %} - - {% block content %} - <p>Step {{ step }} of {{ step_count }}</p> - <form action="." method="post">{% csrf_token %} - <table> - {{ form }} - </table> - <input type="hidden" name="{{ step_field }}" value="{{ step0 }}" /> - {{ previous_fields|safe }} - <input type="submit"> - </form> - {% endblock %} - -Note that ``previous_fields``, ``step_field`` and ``step0`` are all required -for the wizard to work properly. - -.. _hooking-wizard-into-urlconf: - -Hooking the wizard into a URLconf -================================= - -Finally, we need to specify which forms to use in the wizard, and then -deploy the new :class:`FormWizard` object a URL in ``urls.py``. The -wizard takes a list of your :class:`~django.forms.Form` objects as -arguments when you instantiate the Wizard:: - - from django.conf.urls.defaults import * - from testapp.forms import ContactForm1, ContactForm2, ContactWizard - - urlpatterns = patterns('', - (r'^contact/$', ContactWizard([ContactForm1, ContactForm2])), - ) - -Advanced ``FormWizard`` methods -=============================== - -.. class:: FormWizard - - Aside from the :meth:`~done()` method, :class:`FormWizard` offers a few - advanced method hooks that let you customize how your wizard works. - - Some of these methods take an argument ``step``, which is a zero-based - counter representing the current step of the wizard. (E.g., the first form - is ``0`` and the second form is ``1``.) - -.. method:: FormWizard.prefix_for_step - - Given the step, returns a form prefix to use. By default, this simply uses - the step itself. For more, see the :ref:`form prefix documentation - <form-prefix>`. - - Default implementation:: - - def prefix_for_step(self, step): - return str(step) - -.. method:: FormWizard.render_hash_failure - - Renders a template if the hash check fails. It's rare that you'd need to - override this. - - Default implementation:: - - def render_hash_failure(self, request, step): - return self.render(self.get_form(step), request, step, - context={'wizard_error': - 'We apologize, but your form has expired. Please' - ' continue filling out the form from this page.'}) - -.. method:: FormWizard.security_hash - - Calculates the security hash for the given request object and - :class:`~django.forms.Form` instance. - - By default, this uses an MD5 hash of the form data and your - :setting:`SECRET_KEY` setting. It's rare that somebody would need to - override this. - - Example:: - - def security_hash(self, request, form): - return my_hash_function(request, form) - -.. method:: FormWizard.parse_params - - A hook for saving state from the request object and ``args`` / ``kwargs`` - that were captured from the URL by your URLconf. - - By default, this does nothing. - - Example:: - - def parse_params(self, request, *args, **kwargs): - self.my_state = args[0] - -.. method:: FormWizard.get_template - - Returns the name of the template that should be used for the given step. - - By default, this returns :file:`'forms/wizard.html'`, regardless of step. - - Example:: - - def get_template(self, step): - return 'myapp/wizard_%s.html' % step - - If :meth:`~FormWizard.get_template` returns a list of strings, then the - wizard will use the template system's - :func:`~django.template.loader.select_template` function. - This means the system will use the first template that exists on the - filesystem. For example:: - - def get_template(self, step): - return ['myapp/wizard_%s.html' % step, 'myapp/wizard.html'] - -.. method:: FormWizard.render_template - - Renders the template for the given step, returning an - :class:`~django.http.HttpResponse` object. - - Override this method if you want to add a custom context, return a - different MIME type, etc. If you only need to override the template name, - use :meth:`~FormWizard.get_template` instead. - - The template will be rendered with the context documented in the - "Creating templates for the forms" section above. - -.. method:: FormWizard.process_step - - Hook for modifying the wizard's internal state, given a fully validated - :class:`~django.forms.Form` object. The Form is guaranteed to have clean, - valid data. - - This method should *not* modify any of that data. Rather, it might want to - set ``self.extra_context`` or dynamically alter ``self.form_list``, based - on previously submitted forms. - - Note that this method is called every time a page is rendered for *all* - submitted steps. - - The function signature:: - - def process_step(self, request, form, step): - # ... diff --git a/parts/django/docs/ref/contrib/formtools/index.txt b/parts/django/docs/ref/contrib/formtools/index.txt deleted file mode 100644 index f364706..0000000 --- a/parts/django/docs/ref/contrib/formtools/index.txt +++ /dev/null @@ -1,10 +0,0 @@ -django.contrib.formtools -======================== - -A set of high-level abstractions for Django forms (:mod:`django.forms`). - -.. toctree:: - :maxdepth: 1 - - form-preview - form-wizard diff --git a/parts/django/docs/ref/contrib/gis/admin.txt b/parts/django/docs/ref/contrib/gis/admin.txt deleted file mode 100644 index 011bb6b..0000000 --- a/parts/django/docs/ref/contrib/gis/admin.txt +++ /dev/null @@ -1,72 +0,0 @@ -.. _ref-gis-admin: - -====================== -GeoDjango's admin site -====================== - -.. module:: django.contrib.gis.admin - :synopsis: GeoDjango's extensions to the admin site. - - -``GeoModelAdmin`` -================= - -.. class:: GeoModelAdmin - - .. attribute:: default_lon - - The default center longitude. - - .. attribute:: default_lat - - The default center latitude. - - .. attribute:: default_zoom - - The default zoom level to use. Defaults to 18. - - .. attribute:: extra_js - - Sequence of URLs to any extra JavaScript to include. - - .. attribute:: map_template - - Override the template used to generate the JavaScript slippy map. - Default is ``'gis/admin/openlayers.html'``. - - .. attribute:: map_width - - Width of the map, in pixels. Defaults to 600. - - .. attribute:: map_height - - Height of the map, in pixels. Defaults to 400. - - .. attribute:: openlayers_url - - Link to the URL of the OpenLayers JavaScript. Defaults to - ``'http://openlayers.org/api/2.8/OpenLayers.js'``. - - - .. attribute:: modifiable - - Defaults to ``False``. When set to to ``True``, disables editing of - existing geometry fields in the admin. - - .. note:: - - This is different from adding the geometry field to - :attr:`~django.contrib.admin.ModelAdmin.readonly_fields`, - which will only display the WKT of the geometry. Setting - ``modifiable=False``, actually displays the geometry in a map, - but disables the ability to edit its vertices. - -``OSMGeoAdmin`` -=============== - -.. class:: OSMGeoAdmin - - A subclass of :class:`GeoModelAdmin` that uses a spherical mercator projection - with `OpenStreetMap <http://openstreetmap.org/>`_ street data tiles. - See the :ref:`OSMGeoAdmin introduction <osmgeoadmin-intro>` - in the tutorial for a usage example. diff --git a/parts/django/docs/ref/contrib/gis/commands.txt b/parts/django/docs/ref/contrib/gis/commands.txt deleted file mode 100644 index 3dd161c..0000000 --- a/parts/django/docs/ref/contrib/gis/commands.txt +++ /dev/null @@ -1,83 +0,0 @@ -.. ref-geodjango-admin: - -============================= -GeoDjango Management Commands -============================= - -inspectdb -========= - -.. describe:: django-admin.py inspectdb - -When :mod:`django.contrib.gis` is in your :setting:`INSTALLED_APPS`, the -:djadmin:`inspectdb` management command is overridden with one from GeoDjango. -The overridden command is spatially-aware, and places geometry fields in the -auto-generated model definition, where appropriate. - -ogrinspect <data_source> <model_name> -===================================== - -.. django-admin:: ogrinspect - -The ``ogrinpsect`` management command will inspect the given OGR-compatible -:class:`~django.contrib.gis.gdal.DataSource` (e.g., a shapefile) and will -output a GeoDjango model with the given model name. There's a detailed example -of using ``ogrinspect`` :ref:`in the tutorial <ogrinspect-intro>`. - -.. django-admin-option:: --blank <blank_field(s)> - - Use a comma separated list of OGR field names to add the ``blank=True`` - keyword option to the field definition. Set with ``true`` to apply - to all applicable fields. - -.. django-admin-option:: --decimal <decimal_field(s)> - - Use a comma separated list of OGR float fields to generate - :class:`~django.db.models.DecimalField` instead of the default - :class:`~django.db.models.FloatField`. Set to ``true`` to apply to all - OGR float fields. - -.. django-admin-option:: --geom-name <name> - - Specifies the model attribute name to use for the geometry field. - Defaults to ``'geom'``. - -.. django-admin-option:: --layer <layer> - - The key for specifying which layer in the OGR - :class:`~django.contrib.gis.gdal.DataSource` source to use. - Defaults to 0 (the first layer). May be an integer or a string identifier - for the :class:`~django.contrib.gis.gdal.Layer`. - -.. django-admin-option:: --mapping - - Automatically generate a mapping dictionary for use with - :class:`~django.contrib.gis.utils.LayerMapping`. - -.. django-admin-option:: --multi-geom - - When generating the geometry field, treat it as a geometry collection. - For example, if this setting is enabled then a - :class:`~django.contrib.gis.db.models.MultiPolygonField` will be placed - in the generated model rather than - :class:`~django.contrib.gis.db.models.PolygonField`. - -.. django-admin-option:: --name-field <name_field> - - Generates a ``__unicode__`` routine on the model that will return the - the given field name. - -.. django-admin-option:: --no-imports - - Suppresses the ``from django.contrib.gis.db import models`` import statement. - -.. django-admin-option:: --null <null_field(s)> - - Use a comma separated list of OGR field names to add the ``null=True`` - keyword option to the field definition. Set with ``true`` to apply to - all applicable fields. - -.. django-admin-option:: --srid - - The SRID to use for the geometry field. If not set, ``ogrinspect`` attempts - to automatically determine of the SRID of the data source. diff --git a/parts/django/docs/ref/contrib/gis/create_template_postgis-1.3.sh b/parts/django/docs/ref/contrib/gis/create_template_postgis-1.3.sh deleted file mode 100755 index c9ab4fc..0000000 --- a/parts/django/docs/ref/contrib/gis/create_template_postgis-1.3.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -POSTGIS_SQL_PATH=`pg_config --sharedir` -createdb -E UTF8 template_postgis # Create the template spatial database. -createlang -d template_postgis plpgsql # Adding PLPGSQL language support. -psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" -psql -d template_postgis -f $POSTGIS_SQL_PATH/lwpostgis.sql # Loading the PostGIS SQL routines -psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql -psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables. -psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" diff --git a/parts/django/docs/ref/contrib/gis/create_template_postgis-1.4.sh b/parts/django/docs/ref/contrib/gis/create_template_postgis-1.4.sh deleted file mode 100755 index 57a1373..0000000 --- a/parts/django/docs/ref/contrib/gis/create_template_postgis-1.4.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib -createdb -E UTF8 template_postgis # Create the template spatial database. -createlang -d template_postgis plpgsql # Adding PLPGSQL language support. -psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" -psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql # Loading the PostGIS SQL routines -psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql -psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables. -psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" diff --git a/parts/django/docs/ref/contrib/gis/create_template_postgis-1.5.sh b/parts/django/docs/ref/contrib/gis/create_template_postgis-1.5.sh deleted file mode 100755 index 081b5f2..0000000 --- a/parts/django/docs/ref/contrib/gis/create_template_postgis-1.5.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-1.5 -createdb -E UTF8 template_postgis # Create the template spatial database. -createlang -d template_postgis plpgsql # Adding PLPGSQL language support. -psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" -psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql # Loading the PostGIS SQL routines -psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql -psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables. -psql -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;" -psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" diff --git a/parts/django/docs/ref/contrib/gis/create_template_postgis-debian.sh b/parts/django/docs/ref/contrib/gis/create_template_postgis-debian.sh deleted file mode 100755 index 46bd074..0000000 --- a/parts/django/docs/ref/contrib/gis/create_template_postgis-debian.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash -POSTGIS_SQL_PATH=/usr/share/postgresql-8.3-postgis -createdb -E UTF8 template_postgis # Create the template spatial database. -createlang -d template_postgis plpgsql # Adding PLPGSQL language support. -psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" -psql -d template_postgis -f $POSTGIS_SQL_PATH/lwpostgis.sql # Loading the PostGIS SQL routines -psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql -psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables. -psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" diff --git a/parts/django/docs/ref/contrib/gis/db-api.txt b/parts/django/docs/ref/contrib/gis/db-api.txt deleted file mode 100644 index fbced8e..0000000 --- a/parts/django/docs/ref/contrib/gis/db-api.txt +++ /dev/null @@ -1,349 +0,0 @@ -.. _ref-gis-db-api: - -====================== -GeoDjango Database API -====================== - -.. module:: django.contrib.gis.db.models - :synopsis: GeoDjango's database API. - -.. _spatial-backends: - -Spatial Backends -================ - -.. versionadded:: 1.2 - -In Django 1.2, support for :doc:`multiple databases </topics/db/multi-db>` was -introduced. In order to support multiple databases, GeoDjango has segregated -its functionality into full-fledged spatial database backends: - -* :mod:`django.contrib.gis.db.backends.postgis` -* :mod:`django.contrib.gis.db.backends.mysql` -* :mod:`django.contrib.gis.db.backends.oracle` -* :mod:`django.contrib.gis.db.backends.spatialite` - -Database Settings Backwards-Compatibility ------------------------------------------ - -In :doc:`Django 1.2 </releases/1.2>`, the way -to :ref:`specify databases <specifying-databases>` in your settings was changed. -The old database settings format (e.g., the ``DATABASE_*`` settings) -is backwards compatible with GeoDjango, and will automatically use the -appropriate spatial backend as long as :mod:`django.contrib.gis` is in -your :setting:`INSTALLED_APPS`. For example, if you have the following in -your settings:: - - DATABASE_ENGINE='postgresql_psycopg2' - - ... - - INSTALLED_APPS = ( - ... - 'django.contrib.gis', - ... - ) - -Then, :mod:`django.contrib.gis.db.backends.postgis` is automatically used as your -spatial backend. - -.. _mysql-spatial-limitations: - -MySQL Spatial Limitations -------------------------- - -MySQL's spatial extensions only support bounding box operations -(what MySQL calls minimum bounding rectangles, or MBR). Specifically, -`MySQL does not conform to the OGC standard <http://dev.mysql.com/doc/refman/5.1/en/functions-that-test-spatial-relationships-between-geometries.html>`_: - - Currently, MySQL does not implement these functions - [``Contains``, ``Crosses``, ``Disjoint``, ``Intersects``, ``Overlaps``, - ``Touches``, ``Within``] - according to the specification. Those that are implemented return - the same result as the corresponding MBR-based functions. - -In other words, while spatial lookups such as :lookup:`contains <gis-contains>` -are available in GeoDjango when using MySQL, the results returned are really -equivalent to what would be returned when using :lookup:`bbcontains` -on a different spatial backend. - -.. warning:: - - True spatial indexes (R-trees) are only supported with - MyISAM tables on MySQL. [#fnmysqlidx]_ In other words, when using - MySQL spatial extensions you have to choose between fast spatial - lookups and the integrity of your data -- MyISAM tables do - not support transactions or foreign key constraints. - -Creating and Saving Geographic Models -===================================== -Here is an example of how to create a geometry object (assuming the ``Zipcode`` -model):: - - >>> from zipcode.models import Zipcode - >>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))') - >>> z.save() - -:class:`~django.contrib.gis.geos.GEOSGeometry` objects may also be used to save geometric models:: - - >>> from django.contrib.gis.geos import GEOSGeometry - >>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))') - >>> z = Zipcode(code=77096, poly=poly) - >>> z.save() - -Moreover, if the ``GEOSGeometry`` is in a different coordinate system (has a -different SRID value) than that of the field, then it will be implicitly -transformed into the SRID of the model's field, using the spatial database's -transform procedure:: - - >>> poly_3084 = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))', srid=3084) # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal' - >>> z = Zipcode(code=78212, poly=poly_3084) - >>> z.save() - >>> from django.db import connection - >>> print connection.queries[-1]['sql'] # printing the last SQL statement executed (requires DEBUG=True) - INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326)) - -Thus, geometry parameters may be passed in using the ``GEOSGeometry`` object, WKT -(Well Known Text [#fnwkt]_), HEXEWKB (PostGIS specific -- a WKB geometry in -hexadecimal [#fnewkb]_), and GeoJSON [#fngeojson]_ (requires GDAL). Essentially, -if the input is not a ``GEOSGeometry`` object, the geometry field will attempt to -create a ``GEOSGeometry`` instance from the input. - -For more information creating :class:`~django.contrib.gis.geos.GEOSGeometry` -objects, refer to the :ref:`GEOS tutorial <geos-tutorial>`. - -.. _spatial-lookups-intro: - -Spatial Lookups -=============== - -GeoDjango's lookup types may be used with any manager method like -``filter()``, ``exclude()``, etc. However, the lookup types unique to -GeoDjango are only available on geometry fields. -Filters on 'normal' fields (e.g. :class:`~django.db.models.CharField`) -may be chained with those on geographic fields. Thus, geographic queries -take the following general form (assuming the ``Zipcode`` model used in the -:ref:`ref-gis-model-api`):: - - >>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>) - >>> qs = Zipcode.objects.exclude(...) - -For example:: - - >>> qs = Zipcode.objects.filter(poly__contains=pnt) - -In this case, ``poly`` is the geographic field, :lookup:`contains <gis-contains>` -is the spatial lookup type, and ``pnt`` is the parameter (which may be a -:class:`~django.contrib.gis.geos.GEOSGeometry` object or a string of -GeoJSON , WKT, or HEXEWKB). - -A complete reference can be found in the :ref:`spatial lookup reference -<spatial-lookups>`. - -.. note:: - - GeoDjango constructs spatial SQL with the :class:`GeoQuerySet`, a - subclass of :class:`~django.db.models.QuerySet`. The - :class:`GeoManager` instance attached to your model is what - enables use of :class:`GeoQuerySet`. - -.. _distance-queries: - -Distance Queries -================ - -Introduction ------------- -Distance calculations with spatial data is tricky because, unfortunately, -the Earth is not flat. Some distance queries with fields in a geographic -coordinate system may have to be expressed differently because of -limitations in PostGIS. Please see the :ref:`selecting-an-srid` section -in the :ref:`ref-gis-model-api` documentation for more details. - -.. _distance-lookups-intro: - -Distance Lookups ----------------- -*Availability*: PostGIS, Oracle, SpatiaLite - -The following distance lookups are available: - -* :lookup:`distance_lt` -* :lookup:`distance_lte` -* :lookup:`distance_gt` -* :lookup:`distance_gte` -* :lookup:`dwithin` - -.. note:: - - For *measuring*, rather than querying on distances, use the - :meth:`GeoQuerySet.distance` method. - -Distance lookups take a tuple parameter comprising: - -#. A geometry to base calculations from; and -#. A number or :class:`~django.contrib.gis.measure.Distance` object containing the distance. - -If a :class:`~django.contrib.gis.measure.Distance` object is used, -it may be expressed in any units (the SQL generated will use units -converted to those of the field); otherwise, numeric parameters are assumed -to be in the units of the field. - -.. note:: - - For users of PostGIS 1.4 and below, the routine ``ST_Distance_Sphere`` - is used by default for calculating distances on geographic coordinate systems - (e.g., WGS84) -- which may only be called with point geometries [#fndistsphere14]_. - Thus, geographic distance lookups on traditional PostGIS geometry columns are - only allowed on :class:`PointField` model fields using a point for the - geometry parameter. - -.. note:: - - In PostGIS 1.5, ``ST_Distance_Sphere`` does *not* limit the geometry types - geographic distance queries are performed with. [#fndistsphere15]_ However, - these queries may take a long time, as great-circle distances must be - calculated on the fly for *every* row in the query. This is because the - spatial index on traditional geometry fields cannot be used. - - For much better performance on WGS84 distance queries, consider using - :ref:`geography columns <geography-type>` in your database instead because - they are able to use their spatial index in distance queries. - You can tell GeoDjango to use a geography column by setting ``geography=True`` - in your field definition. - -For example, let's say we have a ``SouthTexasCity`` model (from the -`GeoDjango distance tests`__ ) on a *projected* coordinate system valid for cities -in southern Texas:: - - from django.contrib.gis.db import models - - class SouthTexasCity(models.Model): - name = models.CharField(max_length=30) - # A projected coordinate system (only valid for South Texas!) - # is used, units are in meters. - point = models.PointField(srid=32140) - objects = models.GeoManager() - -Then distance queries may be performed as follows:: - - >>> from django.contrib.gis.geos import * - >>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance`` - >>> from geoapp import SouthTexasCity - # Distances will be calculated from this point, which does not have to be projected. - >>> pnt = fromstr('POINT(-96.876369 29.905320)', srid=4326) - # If numeric parameter, units of field (meters in this case) are assumed. - >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000)) - # Find all Cities within 7 km, > 20 miles away, and > 100 chains away (an obscure unit) - >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7))) - >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20))) - >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100))) - -__ http://code.djangoproject.com/browser/django/trunk/django/contrib/gis/tests/distapp/models.py - -.. _compatibility-table: - -Compatibility Tables -==================== - -.. _spatial-lookup-compatibility: - -Spatial Lookups ---------------- - -The following table provides a summary of what spatial lookups are available -for each spatial database backend. - -================================= ========= ======== ============ ========== -Lookup Type PostGIS Oracle MySQL [#]_ SpatiaLite -================================= ========= ======== ============ ========== -:lookup:`bbcontains` X X X -:lookup:`bboverlaps` X X X -:lookup:`contained` X X X -:lookup:`contains <gis-contains>` X X X X -:lookup:`contains_properly` X -:lookup:`coveredby` X X -:lookup:`covers` X X -:lookup:`crosses` X X -:lookup:`disjoint` X X X X -:lookup:`distance_gt` X X X -:lookup:`distance_gte` X X X -:lookup:`distance_lt` X X X -:lookup:`distance_lte` X X X -:lookup:`dwithin` X X -:lookup:`equals` X X X X -:lookup:`exact` X X X X -:lookup:`intersects` X X X X -:lookup:`overlaps` X X X X -:lookup:`relate` X X X -:lookup:`same_as` X X X X -:lookup:`touches` X X X X -:lookup:`within` X X X X -:lookup:`left` X -:lookup:`right` X -:lookup:`overlaps_left` X -:lookup:`overlaps_right` X -:lookup:`overlaps_above` X -:lookup:`overlaps_below` X -:lookup:`strictly_above` X -:lookup:`strictly_below` X -================================= ========= ======== ============ ========== - -.. _geoqueryset-method-compatibility: - -``GeoQuerySet`` Methods ------------------------ -The following table provides a summary of what :class:`GeoQuerySet` methods -are available on each spatial backend. Please note that MySQL does not -support any of these methods, and is thus excluded from the table. - -==================================== ======= ====== ========== -Method PostGIS Oracle SpatiaLite -==================================== ======= ====== ========== -:meth:`GeoQuerySet.area` X X X -:meth:`GeoQuerySet.centroid` X X X -:meth:`GeoQuerySet.collect` X -:meth:`GeoQuerySet.difference` X X X -:meth:`GeoQuerySet.distance` X X X -:meth:`GeoQuerySet.envelope` X X -:meth:`GeoQuerySet.extent` X X -:meth:`GeoQuerySet.extent3d` X -:meth:`GeoQuerySet.force_rhr` X -:meth:`GeoQuerySet.geohash` X -:meth:`GeoQuerySet.geojson` X -:meth:`GeoQuerySet.gml` X X -:meth:`GeoQuerySet.intersection` X X X -:meth:`GeoQuerySet.kml` X -:meth:`GeoQuerySet.length` X X X -:meth:`GeoQuerySet.make_line` X -:meth:`GeoQuerySet.mem_size` X -:meth:`GeoQuerySet.num_geom` X X X -:meth:`GeoQuerySet.num_points` X X X -:meth:`GeoQuerySet.perimeter` X X -:meth:`GeoQuerySet.point_on_surface` X X X -:meth:`GeoQuerySet.reverse_geom` X X -:meth:`GeoQuerySet.scale` X X -:meth:`GeoQuerySet.snap_to_grid` X -:meth:`GeoQuerySet.svg` X X -:meth:`GeoQuerySet.sym_difference` X X X -:meth:`GeoQuerySet.transform` X X X -:meth:`GeoQuerySet.translate` X X -:meth:`GeoQuerySet.union` X X X -:meth:`GeoQuerySet.unionagg` X X X -==================================== ======= ====== ========== - -.. rubric:: Footnotes -.. [#fnwkt] *See* Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049 (May 5, 1999), at Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry). -.. [#fnewkb] *See* `PostGIS EWKB, EWKT and Canonical Forms <http://postgis.refractions.net/documentation/manual-1.5/ch04.html#EWKB_EWKT>`_, PostGIS documentation at Ch. 4.1.2. -.. [#fngeojson] *See* Howard Butler, Martin Daly, Allan Doyle, Tim Schaub, & Christopher Schmidt, `The GeoJSON Format Specification <http://geojson.org/geojson-spec.html>`_, Revision 1.0 (June 16, 2008). -.. [#fndistsphere14] *See* `PostGIS 1.4 documentation <http://postgis.refractions.net/documentation/manual-1.4/ST_Distance_Sphere.html>`_ on ``ST_distance_sphere``. -.. [#fndistsphere15] *See* `PostGIS 1.5 documentation <http://postgis.refractions.net/documentation/manual-1.5/ST_Distance_Sphere.html>`_ on ``ST_distance_sphere``. -.. [#fnmysqlidx] *See* `Creating Spatial Indexes <http://dev.mysql.com/doc/refman/5.1/en/creating-spatial-indexes.html>`_ - in the MySQL 5.1 Reference Manual: - - For MyISAM tables, ``SPATIAL INDEX`` creates an R-tree index. For storage - engines that support nonspatial indexing of spatial columns, the engine - creates a B-tree index. A B-tree index on spatial values will be useful - for exact-value lookups, but not for range scans. - -.. [#] Refer :ref:`mysql-spatial-limitations` section for more details. diff --git a/parts/django/docs/ref/contrib/gis/deployment.txt b/parts/django/docs/ref/contrib/gis/deployment.txt deleted file mode 100644 index 035b23f..0000000 --- a/parts/django/docs/ref/contrib/gis/deployment.txt +++ /dev/null @@ -1,99 +0,0 @@ -=================== -Deploying GeoDjango -=================== - -.. warning:: - - GeoDjango uses the GDAL geospatial library which is - not thread safe at this time. Thus, it is *highly* recommended - to not use threading when deploying -- in other words, use a - an appropriate configuration of Apache or the prefork method - when using FastCGI through another Web server. - -Apache -====== -In this section there are some example ``VirtualHost`` directives for -when deploying using either ``mod_python`` or ``mod_wsgi``. At this -time, we recommend ``mod_wsgi``, as it is now officially recommended -way to deploy Django applications with Apache. Moreover, if -``mod_python`` is used, then a prefork version of Apache must also be -used. As long as ``mod_wsgi`` is configured correctly, it does not -matter whether the version of Apache is prefork or worker. - -.. note:: - - The ``Alias`` and ``Directory`` configurations in the the examples - below use an example path to a system-wide installation folder of Django. - Substitute in an appropriate location, if necessary, as it may be - different than the path on your system. - -``mod_wsgi`` ------------- - -Example:: - - <VirtualHost *:80> - WSGIDaemonProcess geodjango user=geo group=geo processes=5 threads=1 - WSGIProcessGroup geodjango - WSGIScriptAlias / /home/geo/geodjango/world.wsgi - - Alias /media/ "/usr/lib/python2.5/site-packages/django/contrib/admin/media/" - <Directory "/usr/lib/python2.5/site-packages/django/contrib/admin/media/"> - Order allow,deny - Options Indexes - Allow from all - IndexOptions FancyIndexing - </Directory> - - </VirtualHost> - -.. warning:: - - If the ``WSGIDaemonProcess`` attribute ``threads`` is not set to ``1``, then - Apache may crash when running your GeoDjango application. Increase the - number of ``processes`` instead. - -For more information, please consult Django's -:doc:`mod_wsgi documentation </howto/deployment/modwsgi>`. - -``mod_python`` --------------- - -Example:: - - <VirtualHost *:80> - - <Location "/"> - SetHandler mod_python - PythonHandler django.core.handlers.modpython - SetEnv DJANGO_SETTINGS_MODULE world.settings - PythonDebug On - PythonPath "['/var/www/apps'] + sys.path" - </Location> - - Alias /media/ "/usr/lib/python2.5/site-packages/django/contrib/admin/media/" - <Location "/media"> - SetHandler None - </Location> - - </VirtualHost> - -.. warning:: - - When using ``mod_python`` you *must* be using a prefork version of Apache, or - else your GeoDjango application may crash Apache. - -For more information, please consult Django's -:doc:`mod_python documentation </howto/deployment/modpython>`. - -Lighttpd -======== - -FastCGI -------- - -Nginx -===== - -FastCGI -------- diff --git a/parts/django/docs/ref/contrib/gis/feeds.txt b/parts/django/docs/ref/contrib/gis/feeds.txt deleted file mode 100644 index 7c3a2d0..0000000 --- a/parts/django/docs/ref/contrib/gis/feeds.txt +++ /dev/null @@ -1,95 +0,0 @@ -================ -Geographic Feeds -================ - -.. module:: django.contrib.gis.feeds - :synopsis: GeoDjango's framework for generating spatial feeds. - -GeoDjango has its own :class:`Feed` subclass that may embed location information -in RSS/Atom feeds formatted according to either the `Simple GeoRSS`__ or -`W3C Geo`_ standards. Because GeoDjango's syndication API is a superset of -Django's, please consult :doc:`Django's syndication documentation -</ref/contrib/syndication>` for details on general usage. - -.. _W3C Geo: http://www.w3.org/2003/01/geo/ - -__ http://georss.org/1.0#simple - -Example -======= - -API Reference -============= - -``Feed`` Subclass ------------------ - -.. class:: Feed - - In addition to methods provided by - the :class:`django.contrib.syndication.feeds.Feed` - base class, GeoDjango's ``Feed`` class provides - the following overrides. Note that these overrides may be done in multiple ways:: - - from django.contrib.gis.feeds import Feed - - class MyFeed(Feed): - - # First, as a class attribute. - geometry = ... - item_geometry = ... - - # Also a function with no arguments - def geometry(self): - ... - - def item_geometry(self): - ... - - # And as a function with a single argument - def geometry(self, obj): - ... - - def item_geometry(self, item): - ... - - .. method:: geometry(obj) - - Takes the object returned by ``get_object()`` and returns the *feed's* - geometry. Typically this is a ``GEOSGeometry`` instance, or can be a - tuple to represent a point or a box. For example:: - - class ZipcodeFeed(Feed): - - def geometry(self, obj): - # Can also return: `obj.poly`, and `obj.poly.centroid`. - return obj.poly.extent # tuple like: (X0, Y0, X1, Y1). - - .. method:: item_geometry(item) - - Set this to return the geometry for each *item* in the feed. This - can be a ``GEOSGeometry`` instance, or a tuple that represents a - point coordinate or bounding box. For example:: - - class ZipcodeFeed(Feed): - - def item_geometry(self, obj): - # Returns the polygon. - return obj.poly - -``SyndicationFeed`` Subclasses ------------------------------- - -The following :class:`django.utils.feedgenerator.SyndicationFeed` subclasses -are available: - -.. class:: GeoRSSFeed - -.. class:: GeoAtom1Feed - -.. class:: W3CGeoFeed - -.. note:: - - `W3C Geo`_ formatted feeds only support - :class:`~django.contrib.gis.db.models.PointField` geometries. diff --git a/parts/django/docs/ref/contrib/gis/gdal.txt b/parts/django/docs/ref/contrib/gis/gdal.txt deleted file mode 100644 index 1ce21d9..0000000 --- a/parts/django/docs/ref/contrib/gis/gdal.txt +++ /dev/null @@ -1,1114 +0,0 @@ -.. _ref-gdal: - -======== -GDAL API -======== - -.. module:: django.contrib.gis.gdal - :synopsis: GeoDjango's high-level interface to the GDAL library. - -`GDAL`__ stands for **G**\ eospatial **D**\ ata **A**\ bstraction **L**\ ibrary, -and is a veritable "swiss army knife" of GIS data functionality. A subset -of GDAL is the `OGR`__ Simple Features Library, which specializes -in reading and writing vector geographic data in a variety of standard -formats. - -GeoDjango provides a high-level Python interface for some of the -capabilities of OGR, including the reading and coordinate transformation -of vector spatial data. - -.. note:: - - Although the module is named ``gdal``, GeoDjango only supports - some of the capabilities of OGR. Thus, none of GDAL's features - with respect to raster (image) data are supported at this time. - -__ http://www.gdal.org/ -__ http://www.gdal.org/ogr/ - -Overview -======== - -Sample Data ------------ - -The GDAL/OGR tools described here are designed to help you read in -your geospatial data, in order for most of them to be useful you have -to have some data to work with. If you're starting out and don't yet -have any data of your own to use, GeoDjango comes with a number of -simple data sets that you can use for testing. This snippet will -determine where these sample files are installed on your computer:: - - >>> import os - >>> import django.contrib.gis - >>> GIS_PATH = os.path.dirname(django.contrib.gis.__file__) - >>> CITIES_PATH = os.path.join(GIS_PATH, 'tests/data/cities/cities.shp') - -Vector Data Source Objects -========================== - -``DataSource`` --------------- - -:class:`DataSource` is a wrapper for the OGR data source object that -supports reading data from a variety of OGR-supported geospatial file -formats and data sources using a simple, consistent interface. Each -data source is represented by a :class:`DataSource` object which contains -one or more layers of data. Each layer, represented by a :class:`Layer` -object, contains some number of geographic features (:class:`Feature`), -information about the type of features contained in that layer (e.g. -points, polygons, etc.), as well as the names and types of any -additional fields (:class:`Field`) of data that may be associated with -each feature in that layer. - -.. class:: DataSource(ds_input) - - The constructor for ``DataSource`` just a single parameter: the path of - the file you want to read. However, OGR - also supports a variety of more complex data sources, including - databases, that may be accessed by passing a special name string instead - of a path. For more information, see the `OGR Vector Formats`__ - documentation. The :attr:`name` property of a ``DataSource`` - instance gives the OGR name of the underlying data source that it is - using. - - Once you've created your ``DataSource``, you can find out how many - layers of data it contains by accessing the :attr:`layer_count` property, - or (equivalently) by using the ``len()`` function. For information on - accessing the layers of data themselves, see the next section:: - - >>> from django.contrib.gis.gdal import DataSource - >>> ds = DataSource(CITIES_PATH) - >>> ds.name # The exact filename may be different on your computer - '/usr/local/lib/python2.6/site-packages/django/contrib/gis/tests/data/cities/cities.shp' - >>> ds.layer_count # This file only contains one layer - 1 - - .. attribute:: layer_count - - Returns the number of layers in the data source. - - .. attribute:: name - - Returns the name of the data source. - -__ http://www.gdal.org/ogr/ogr_formats.html - -``Layer`` ---------- - -.. class:: Layer - - ``Layer`` is a wrapper for a layer of data in a ``DataSource`` object. - You never create a ``Layer`` object directly. Instead, you retrieve - them from a :class:`DataSource` object, which is essentially a standard - Python container of ``Layer`` objects. For example, you can access a - specific layer by its index (e.g. ``ds[0]`` to access the first - layer), or you can iterate over all the layers in the container in a - ``for`` loop. The ``Layer`` itself acts as a container for geometric - features. - - Typically, all the features in a given layer have the same geometry type. - The :attr:`geom_type` property of a layer is an :class:`OGRGeomType` - that identifies the feature type. We can use it to print out some basic - information about each layer in a :class:`DataSource`:: - - >>> for layer in ds: - ... print 'Layer "%s": %i %ss' % (layer.name, len(layer), layer.geom_type.name) - ... - Layer "cities": 3 Points - - The example output is from the cities data source, loaded above, which - evidently contains one layer, called ``"cities"``, which contains three - point features. For simplicity, the examples below assume that you've - stored that layer in the variable ``layer``:: - - >>> layer = ds[0] - - .. attribute:: name - - Returns the name of this layer in the data source. - - >>> layer.name - 'cities' - - .. attribute:: num_feat - - Returns the number of features in the layer. Same as ``len(layer)``:: - - >>> layer.num_feat - 3 - - .. attribute:: geom_type - - Returns the geometry type of the layer, as an :class:`OGRGeomType` - object:: - - >>> layer.geom_type.name - 'Point' - - .. attribute:: num_fields - - Returns the number of fields in the layer, i.e the number of fields of - data associated with each feature in the layer:: - - >>> layer.num_fields - 4 - - .. attribute:: fields - - Returns a list of the names of each of the fields in this layer:: - - >>> layer.fields - ['Name', 'Population', 'Density', 'Created'] - - .. attribute field_types - - Returns a list of the data types of each of the fields in this layer. - These are subclasses of ``Field``, discussed below:: - - >>> [ft.__name__ for ft in layer.field_types] - ['OFTString', 'OFTReal', 'OFTReal', 'OFTDate'] - - .. attribute:: field_widths - - Returns a list of the maximum field widths for each of the fields in - this layer:: - - >>> layer.field_widths - [80, 11, 24, 10] - - .. attribute:: field_precisions - - Returns a list of the numeric precisions for each of the fields in - this layer. This is meaningless (and set to zero) for non-numeric - fields:: - - >>> layer.field_precisions - [0, 0, 15, 0] - - .. attribute:: extent - - Returns the spatial extent of this layer, as an :class:`Envelope` - object:: - - >>> layer.extent.tuple - (-104.609252, 29.763374, -95.23506, 38.971823) - - .. attribute:: srs - - Property that returns the :class:`SpatialReference` associated - with this layer:: - - >>> print layer.srs - GEOGCS["GCS_WGS_1984", - DATUM["WGS_1984", - SPHEROID["WGS_1984",6378137,298.257223563]], - PRIMEM["Greenwich",0], - UNIT["Degree",0.017453292519943295]] - - If the :class:`Layer` has no spatial reference information associated - with it, ``None`` is returned. - - .. attribute:: spatial_filter - - .. versionadded:: 1.2 - - Property that may be used to retrieve or set a spatial filter for this - layer. A spatial filter can only be set with an :class:`OGRGeometry` - instance, a 4-tuple extent, or ``None``. When set with something - other than ``None``, only features that intersect the filter will be - returned when iterating over the layer:: - - >>> print layer.spatial_filter - None - >>> print len(layer) - 3 - >>> [feat.get('Name') for feat in layer] - ['Pueblo', 'Lawrence', 'Houston'] - >>> ks_extent = (-102.051, 36.99, -94.59, 40.00) # Extent for state of Kansas - >>> layer.spatial_filter = ks_extent - >>> len(layer) - 1 - >>> [feat.get('Name') for feat in layer] - ['Lawrence'] - >>> layer.spatial_filter = None - >>> len(layer) - 3 - - .. method:: get_fields() - - A method that returns a list of the values of a given field for each - feature in the layer:: - - >>> layer.get_fields('Name') - ['Pueblo', 'Lawrence', 'Houston'] - - .. method:: get_geoms([geos=False]) - - A method that returns a list containing the geometry of each feature - in the layer. If the optional argument ``geos`` is set to ``True`` - then the geometries are converted to :class:`~django.contrib.gis.geos.GEOSGeometry` - objects. Otherwise, they are returned as :class:`OGRGeometry` objects:: - - >>> [pt.tuple for pt in layer.get_geoms()] - [(-104.609252, 38.255001), (-95.23506, 38.971823), (-95.363151, 29.763374)] - - .. method:: test_capability(capability) - - Returns a boolean indicating whether this layer supports the - given capability (a string). Examples of valid capability strings - include: ``'RandomRead'``, ``'SequentialWrite'``, ``'RandomWrite'``, - ``'FastSpatialFilter'``, ``'FastFeatureCount'``, ``'FastGetExtent'``, - ``'CreateField'``, ``'Transactions'``, ``'DeleteFeature'``, and - ``'FastSetNextByIndex'``. - -``Feature`` ------------ - -.. class:: Feature - - - ``Feature`` wraps an OGR feature. You never create a ``Feature`` - object directly. Instead, you retrieve them from a :class:`Layer` object. - Each feature consists of a geometry and a set of fields containing - additional properties. The geometry of a field is accessible via its - ``geom`` property, which returns an :class:`OGRGeometry` object. A ``Feature`` - behaves like a standard Python container for its fields, which it returns as - :class:`Field` objects: you can access a field directly by its index or name, - or you can iterate over a feature's fields, e.g. in a ``for`` loop. - - .. attribute:: geom - - Returns the geometry for this feature, as an ``OGRGeometry`` object:: - - >>> city.geom.tuple - (-104.609252, 38.255001) - - .. attribute:: get - - A method that returns the value of the given field (specified by name) - for this feature, **not** a ``Field`` wrapper object:: - - >>> city.get('Population') - 102121 - - .. attribute:: geom_type - - Returns the type of geometry for this feature, as an :class:`OGRGeomType` - object. This will be the same for all features in a given layer, and - is equivalent to the :attr:`Layer.geom_type` property of the - :class:`Layer`` object the feature came from. - - .. attribute:: num_fields - - Returns the number of fields of data associated with the feature. - This will be the same for all features in a given layer, and is - equivalent to the :attr:`Layer.num_fields` property of the - :class:`Layer` object the feature came from. - - .. attribute:: fields - - Returns a list of the names of the fields of data associated with the - feature. This will be the same for all features in a given layer, and - is equivalent to the :attr:`Layer.fields` property of the :class:`Layer` - object the feature came from. - - .. attribute:: fid - - Returns the feature identifier within the layer:: - - >>> city.fid - 0 - - .. attribute:: layer_name - - Returns the name of the :class:`Layer` that the feature came from. - This will be the same for all features in a given layer:: - - >>> city.layer_name - 'cities' - - .. attribute:: index - - A method that returns the index of the given field name. This will be - the same for all features in a given layer:: - - >>> city.index('Population') - 1 - -``Field`` ---------- - -.. class:: Field - - .. attribute:: name - - Returns the name of this field:: - - >>> city['Name'].name - 'Name' - - .. attribute:: type - - Returns the OGR type of this field, as an integer. The - ``FIELD_CLASSES`` dictionary maps these values onto - subclasses of ``Field``:: - - >>> city['Density'].type - 2 - - .. attribute:: type_name - - Returns a string with the name of the data type of this field:: - - >>> city['Name'].type_name - 'String' - - .. attribute:: value - - Returns the value of this field. The ``Field`` class itself - returns the value as a string, but each subclass returns the - value in the most appropriate form:: - - >>> city['Population'].value - 102121 - - .. attribute:: width - - Returns the width of this field:: - - >>> city['Name'].width - 80 - - .. attribute:: precision - - Returns the numeric precision of this field. This is meaningless (and - set to zero) for non-numeric fields:: - - >>> city['Density'].precision - 15 - - .. method:: as_double() - - Returns the value of the field as a double (float):: - - >>> city['Density'].as_double() - 874.7 - - .. method:: as_int() - - Returns the value of the field as an integer:: - - >>> city['Population'].as_int() - 102121 - - .. method:: as_string() - - Returns the value of the field as a string:: - - >>> city['Name'].as_string() - 'Pueblo' - - .. method:: as_datetime() - - Returns the value of the field as a tuple of date and time components:: - - >>> city['Created'].as_datetime() - (c_long(1999), c_long(5), c_long(23), c_long(0), c_long(0), c_long(0), c_long(0)) - -``Driver`` ----------- - -.. class:: Driver(dr_input) - - The ``Driver`` class is used internally to wrap an OGR :class:`DataSource` driver. - - .. attribute:: driver_count - - Returns the number of OGR vector drivers currently registered. - - -OGR Geometries -============== - -``OGRGeometry`` ---------------- - -:class:`OGRGeometry` objects share similar functionality with -:class:`~django.contrib.gis.geos.GEOSGeometry` objects, and are thin -wrappers around OGR's internal geometry representation. Thus, -they allow for more efficient access to data when using :class:`DataSource`. -Unlike its GEOS counterpart, :class:`OGRGeometry` supports spatial reference -systems and coordinate transformation:: - - >>> from django.contrib.gis.gdal import OGRGeometry - >>> polygon = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5))') - -.. class:: OGRGeometry(geom_input[, srs=None]) - - This object is a wrapper for the `OGR Geometry`__ class. - These objects are instantiated directly from the given ``geom_input`` - parameter, which may be a string containing WKT or HEX, a ``buffer`` - containing WKB data, or an :class:`OGRGeomType` object. These objects - are also returned from the :class:`Feature.geom` attribute, when - reading vector data from :class:`Layer` (which is in turn a part of - a :class:`DataSource`). - - __ http://www.gdal.org/ogr/classOGRGeometry.html - - .. classmethod:: from_bbox(bbox) - - .. versionadded:: 1.1 - - Constructs a :class:`Polygon` from the given bounding-box (a 4-tuple). - - .. method:: __len__ - - Returns the number of points in a :class:`LineString`, the - number of rings in a :class:`Polygon`, or the number of geometries in a - :class:`GeometryCollection`. Not applicable to other geometry types. - - .. method:: __iter__ - - Iterates over the points in a :class:`LineString`, the rings in a - :class:`Polygon`, or the geometries in a :class:`GeometryCollection`. - Not applicable to other geometry types. - - .. method:: __getitem__ - - Returns the point at the specified index for a :class:`LineString`, the - interior ring at the specified index for a :class:`Polygon`, or the geometry - at the specified index in a :class:`GeometryCollection`. Not applicable to - other geometry types. - - .. attribute:: dimension - - Returns the number of coordinated dimensions of the geometry, i.e. 0 - for points, 1 for lines, and so forth:: - - >> polygon.dimension - 2 - - .. attribute:: coord_dim - - .. versionchanged:: 1.2 - - Returns or sets the coordinate dimension of this geometry. For - example, the value would be 2 for two-dimensional geometries. - - .. note:: - - Setting this property is only available in versions 1.2 and above. - - .. attribute:: geom_count - - Returns the number of elements in this geometry:: - - >>> polygon.geom_count - 1 - - .. attribute:: point_count - - Returns the number of points used to describe this geometry:: - - >>> polygon.point_count - 4 - - .. attribute:: num_points - - Alias for :attr:`point_count`. - - .. attribute:: num_coords - - Alias for :attr:`point_count`. - - .. attribute:: geom_type - - Returns the type of this geometry, as an :class:`OGRGeomType` object. - - .. attribute:: geom_name - - Returns the name of the type of this geometry:: - - >>> polygon.geom_name - 'POLYGON' - - .. attribute:: area - - Returns the area of this geometry, or 0 for geometries that do not - contain an area:: - - >>> polygon.area - 25.0 - - .. attribute:: envelope - - Returns the envelope of this geometry, as an :class:`Envelope` object. - - .. attribute:: extent - - Returns the envelope of this geometry as a 4-tuple, instead of as an - :class:`Envelope` object:: - - >>> point.extent - (0.0, 0.0, 5.0, 5.0) - - .. attribute:: srs - - This property controls the spatial reference for this geometry, or - ``None`` if no spatial reference system has been assigned to it. - If assigned, accessing this property returns a :class:`SpatialReference` - object. It may be set with another :class:`SpatialReference` object, - or any input that :class:`SpatialReference` accepts. Example:: - - >>> city.geom.srs.name - 'GCS_WGS_1984' - - .. attribute:: srid - - Returns or sets the spatial reference identifier corresponding to - :class:`SpatialReference` of this geometry. Returns ``None`` if - there is no spatial reference information associated with this - geometry, or if an SRID cannot be determined. - - .. attribute:: geos - - Returns a :class:`~django.contrib.gis.geos.GEOSGeometry` object - corresponding to this geometry. - - .. attribute:: gml - - Returns a string representation of this geometry in GML format:: - - >>> OGRGeometry('POINT(1 2)').gml - '<gml:Point><gml:coordinates>1,2</gml:coordinates></gml:Point>' - - .. attribute:: hex - - Returns a string representation of this geometry in HEX WKB format:: - - >>> OGRGeometry('POINT(1 2)').hex - '0101000000000000000000F03F0000000000000040' - - .. attribute:: json - - Returns a string representation of this geometry in JSON format:: - - >>> OGRGeometry('POINT(1 2)').json - '{ "type": "Point", "coordinates": [ 1.000000, 2.000000 ] }' - - - .. attribute:: kml - - .. versionadded:: 1.1 - - Returns a string representation of this geometry in KML format. - - .. attribute:: wkb_size - - Returns the size of the WKB buffer needed to hold a WKB representation - of this geometry:: - - >>> OGRGeometry('POINT(1 2)').wkb_size - 21 - - .. attribute:: wkb - - Returns a ``buffer`` containing a WKB representation of this geometry. - - .. attribute:: wkt - - Returns a string representation of this geometry in WKT format. - - .. attribute:: ewkt - - .. versionadded:: 1.2 - - Returns the EWKT representation of this geometry. - - .. method:: clone() - - Returns a new :class:`OGRGeometry` clone of this geometry object. - - .. method:: close_rings() - - If there are any rings within this geometry that have not been closed, - this routine will do so by adding the starting point to the end:: - - >>> triangle = OGRGeometry('LINEARRING (0 0,0 1,1 0)') - >>> triangle.close_rings() - >>> triangle.wkt - 'LINEARRING (0 0,0 1,1 0,0 0)' - - .. method:: transform(coord_trans, clone=False) - - Transforms this geometry to a different spatial reference system. May - take a :class:`CoordTransform` object, a :class:`SpatialReference` object, - or any other input accepted by :class:`SpatialReference` (including - spatial reference WKT and PROJ.4 strings, or an integer SRID). - By default nothing is returned and the geometry is transformed in-place. - However, if the `clone` keyword is set to ``True`` then a transformed clone - of this geometry is returned instead. - - .. method:: intersects(other) - - Returns ``True`` if this geometry intersects the other, otherwise returns - ``False``. - - .. method:: equals(other) - - Returns ``True`` if this geometry is equivalent to the other, otherwise returns - ``False``. - - .. method:: disjoint(other) - - Returns ``True`` if this geometry is spatially disjoint to (i.e. does - not intersect) the other, otherwise returns ``False``. - - .. method:: touches(other) - - Returns ``True`` if this geometry touches the other, otherwise returns - ``False``. - - .. method:: crosses(other) - - Returns ``True`` if this geometry crosses the other, otherwise returns - ``False``. - - .. method:: within(other) - - Returns ``True`` if this geometry is contained within the other, otherwise returns - ``False``. - - .. method:: contains(other) - - Returns ``True`` if this geometry contains the other, otherwise returns - ``False``. - - .. method:: overlaps(other) - - Returns ``True`` if this geometry overlaps the other, otherwise returns - ``False``. - - .. method:: boundary - - The boundary of this geometry, as a new :class:`OGRGeometry` object. - - .. attribute:: convex_hull - - The smallest convex polygon that contains this geometry, as a new - :class:`OGRGeometry` object. - - .. method:: difference - - Returns the region consisting of the difference of this geometry and - the other, as a new :class:`OGRGeometry` object. - - .. method:: intersection - - Returns the region consisting of the intersection of this geometry and - the other, as a new :class:`OGRGeometry` object. - - .. method:: sym_difference - - Returns the region consisting of the symmetric difference of this - geometry and the other, as a new :class:`OGRGeometry` object. - - .. method:: union - - Returns the region consisting of the union of this geometry and - the other, as a new :class:`OGRGeometry` object. - - .. attribute:: tuple - - Returns the coordinates of a point geometry as a tuple, the - coordinates of a line geometry as a tuple of tuples, and so forth:: - - >>> OGRGeometry('POINT (1 2)').tuple - (1.0, 2.0) - >>> OGRGeometry('LINESTRING (1 2,3 4)').tuple - ((1.0, 2.0), (3.0, 4.0)) - - .. attribute:: coords - - An alias for :attr:`tuple`. - -.. class:: Point - - .. attribute:: x - - Returns the X coordinate of this point:: - - >>> OGRGeometry('POINT (1 2)').x - 1.0 - - .. attribute:: y - - Returns the Y coordinate of this point:: - - >>> OGRGeometry('POINT (1 2)').y - 2.0 - - .. attribute:: z - - Returns the Z coordinate of this point, or ``None`` if the - the point does not have a Z coordinate:: - - >>> OGRGeometry('POINT (1 2 3)').z - 3.0 - -.. class:: LineString - - .. attribute:: x - - Returns a list of X coordinates in this line:: - - >>> OGRGeometry('LINESTRING (1 2,3 4)').x - [1.0, 3.0] - - .. attribute:: y - - Returns a list of Y coordinates in this line:: - - >>> OGRGeometry('LINESTRING (1 2,3 4)').y - [2.0, 4.0] - - .. attribute:: z - - Returns a list of Z coordinates in this line, or ``None`` if the - line does not have Z coordinates:: - - >>> OGRGeometry('LINESTRING (1 2 3,4 5 6)').z - [3.0, 6.0] - - -.. class:: Polygon - - .. attribute:: shell - - Returns the shell or exterior ring of this polygon, as a ``LinearRing`` - geometry. - - .. attribute:: exterior_ring - - An alias for :attr:`shell`. - - .. attribute:: centroid - - Returns a :class:`Point` representing the centroid of this polygon. - -.. class:: GeometryCollection - - .. method:: add(geom) - - Adds a geometry to this geometry collection. Not applicable to other - geometry types. - - -``OGRGeomType`` ---------------- - -.. class:: OGRGeomType(type_input) - - This class allows for the representation of an OGR geometry type - in any of several ways:: - - >>> from django.contrib.gis.gdal import OGRGeomType - >>> gt1 = OGRGeomType(3) # Using an integer for the type - >>> gt2 = OGRGeomType('Polygon') # Using a string - >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive - >>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects - True True - - .. attribute:: name - - Returns a short-hand string form of the OGR Geometry type:: - - >>> gt1.name - 'Polygon' - - .. attribute:: num - - Returns the number corresponding to the OGR geometry type:: - - >>> gt1.num - 3 - - .. attribute:: django - - Returns the Django field type (a subclass of GeometryField) to use for - storing this OGR type, or ``None`` if there is no appropriate Django - type:: - - >>> gt1.django - 'PolygonField' - -``Envelope`` ------------- - -.. class:: Envelope(*args) - - Represents an OGR Envelope structure that contains the - minimum and maximum X, Y coordinates for a rectangle bounding box. - The naming of the variables is compatible with the OGR Envelope - C structure. - - .. attribute:: min_x - - The value of the minimum X coordinate. - - .. attribute:: min_y - - The value of the maximum X coordinate. - - .. attribute:: max_x - - The value of the minimum Y coordinate. - - .. attribute:: max_y - - The value of the maximum Y coordinate. - - .. attribute:: ur - - The upper-right coordinate, as a tuple. - - .. attribute:: ll - - The lower-left coordinate, as a tuple. - - .. attribute:: tuple - - A tuple representing the envelope. - - .. attribute:: wkt - - A string representing this envelope as a polygon in WKT format. - - - .. method:: expand_to_include(self, *args) - - .. versionadded:: 1.1 - -Coordinate System Objects -========================= - -``SpatialReference`` --------------------- - -.. class:: SpatialReference(srs_input) - - Spatial reference objects are initialized on the given ``srs_input``, - which may be one of the following: - - * OGC Well Known Text (WKT) (a string) - * EPSG code (integer or string) - * PROJ.4 string - * A shorthand string for well-known standards (``'WGS84'``, ``'WGS72'``, ``'NAD27'``, ``'NAD83'``) - - Example:: - - >>> wgs84 = SpatialReference('WGS84') # shorthand string - >>> wgs84 = SpatialReference(4326) # EPSG code - >>> wgs84 = SpatialReference('EPSG:4326') # EPSG string - >>> proj4 = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ' - >>> wgs84 = SpatialReference(proj4) # PROJ.4 string - >>> wgs84 = SpatialReference("""GEOGCS["WGS 84", - DATUM["WGS_1984", - SPHEROID["WGS 84",6378137,298.257223563, - AUTHORITY["EPSG","7030"]], - AUTHORITY["EPSG","6326"]], - PRIMEM["Greenwich",0, - AUTHORITY["EPSG","8901"]], - UNIT["degree",0.01745329251994328, - AUTHORITY["EPSG","9122"]], - AUTHORITY["EPSG","4326"]]""") # OGC WKT - - .. method:: __getitem__(target) - - Returns the value of the given string attribute node, ``None`` if the node - doesn't exist. Can also take a tuple as a parameter, (target, child), - where child is the index of the attribute in the WKT. For example:: - - >>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]') - >>> srs = SpatialReference(wkt) # could also use 'WGS84', or 4326 - >>> print srs['GEOGCS'] - WGS 84 - >>> print srs['DATUM'] - WGS_1984 - >>> print srs['AUTHORITY'] - EPSG - >>> print srs['AUTHORITY', 1] # The authority value - 4326 - >>> print srs['TOWGS84', 4] # the fourth value in this wkt - 0 - >>> print srs['UNIT|AUTHORITY'] # For the units authority, have to use the pipe symbole. - EPSG - >>> print srs['UNIT|AUTHORITY', 1] # The authority value for the untis - 9122 - - .. method:: attr_value(target, index=0) - - The attribute value for the given target node (e.g. ``'PROJCS'``). - The index keyword specifies an index of the child node to return. - - .. method:: auth_name(target) - - Returns the authority name for the given string target node. - - .. method:: auth_code(target) - - Returns the authority code for the given string target node. - - .. method:: clone() - - Returns a clone of this spatial reference object. - - .. method:: identify_epsg() - - This method inspects the WKT of this SpatialReference, and will - add EPSG authority nodes where an EPSG identifier is applicable. - - .. method:: from_esri() - - Morphs this SpatialReference from ESRI's format to EPSG - - .. method:: to_esri() - - Morphs this SpatialReference to ESRI's format. - - .. method:: validate() - - Checks to see if the given spatial reference is valid, if not - an exception will be raised. - - .. method:: import_epsg(epsg) - - Import spatial reference from EPSG code. - - .. method:: import_proj(proj) - - Import spatial reference from PROJ.4 string. - - .. method:: import_user_input(user_input) - - .. versionadded:: 1.1 - - .. method:: import_wkt(wkt) - - Import spatial reference from WKT. - - .. method:: import_xml(xml) - - Import spatial reference from XML. - - .. attribute:: name - - Returns the name of this Spatial Reference. - - .. attribute:: srid - - Returns the SRID of top-level authority, or ``None`` if undefined. - - .. attribute:: linear_name - - Returns the name of the linear units. - - .. attribute:: linear_units - - Returns the value of the linear units. - - .. attribute:: angular_name - - Returns the name of the angular units." - - .. attribute:: angular_units - - Returns the value of the angular units. - - .. attribute:: units - - Returns a 2-tuple of the units value and the units name, - and will automatically determines whether to return the linear - or angular units. - - .. attribute:: ellisoid - - Returns a tuple of the ellipsoid parameters for this spatial - reference: (semimajor axis, semiminor axis, and inverse flattening) - - .. attribute:: semi_major - - Returns the semi major axis of the ellipsoid for this spatial reference. - - .. attribute:: semi_minor - - Returns the semi minor axis of the ellipsoid for this spatial reference. - - .. attribute:: inverse_flattening - - Returns the inverse flattening of the ellipsoid for this spatial reference. - - .. attribute:: geographic - - Returns ``True`` if this spatial reference is geographic - (root node is ``GEOGCS``). - - .. attribute:: local - - Returns ``True`` if this spatial reference is local - (root node is ``LOCAL_CS``). - - .. attribute:: projected - - Returns ``True`` if this spatial reference is a projected coordinate - system (root node is ``PROJCS``). - - .. attribute:: wkt - - Returns the WKT representation of this spatial reference. - - .. attribute:: pretty_wkt - - Returns the 'pretty' representation of the WKT. - - .. attribute:: proj - - Returns the PROJ.4 representation for this spatial reference. - - .. attribute:: proj4 - - Alias for :attr:`SpatialReference.proj`. - - .. attribute:: xml - - Returns the XML representation of this spatial reference. - - -``CoordTransform`` ------------------- - -.. class:: CoordTransform(source, target) - -Represents a coordinate system transform. It is initialized with two -:class:`SpatialReference`, representing the source and target coordinate -systems, respectively. These objects should be used when performing -the same coordinate transformation repeatedly on different geometries:: - - >>> ct = CoordTransform(SpatialReference('WGS84'), SpatialReference('NAD83')) - >>> for feat in layer: - ... geom = feat.geom # getting clone of feature geometry - ... geom.transform(ct) # transforming - -Settings -======== - -.. setting:: GDAL_LIBRARY_PATH - -GDAL_LIBRARY_PATH ------------------ - -A string specifying the location of the GDAL library. Typically, -this setting is only used if the GDAL library is in a non-standard -location (e.g., ``/home/john/lib/libgdal.so``). diff --git a/parts/django/docs/ref/contrib/gis/geoip.txt b/parts/django/docs/ref/contrib/gis/geoip.txt deleted file mode 100644 index 784d69e..0000000 --- a/parts/django/docs/ref/contrib/gis/geoip.txt +++ /dev/null @@ -1,223 +0,0 @@ -.. _ref-geoip: - -====================== -Geolocation with GeoIP -====================== - -.. module:: django.contrib.gis.utils.geoip - :synopsis: High-level Python interface for MaxMind's GeoIP C library. - -.. currentmodule:: django.contrib.gis.utils - -The :class:`GeoIP` object is a ctypes wrapper for the -`MaxMind GeoIP C API`__. [#]_ This interface is a BSD-licensed alternative -to the GPL-licensed `Python GeoIP`__ interface provided by MaxMind. - -In order to perform IP-based geolocation, the :class:`GeoIP` object requires -the GeoIP C libary and either the GeoIP `Country`__ or `City`__ -datasets in binary format (the CSV files will not work!). These datasets may be -`downloaded from MaxMind`__. Grab the ``GeoIP.dat.gz`` and ``GeoLiteCity.dat.gz`` -and unzip them in a directory corresponding to what you set -``GEOIP_PATH`` with in your settings. See the example and reference below -for more details. - -__ http://www.maxmind.com/app/c -__ http://www.maxmind.com/app/python -__ http://www.maxmind.com/app/country -__ http://www.maxmind.com/app/city -__ http://www.maxmind.com/download/geoip/database/ - -Example -======= - -Assuming you have the GeoIP C library installed, here is an example of its -usage:: - - >>> from django.contrib.gis.utils import GeoIP - >>> g = GeoIP() - >>> g.country('google.com') - {'country_code': 'US', 'country_name': 'United States'} - >>> g.city('72.14.207.99') - {'area_code': 650, - 'city': 'Mountain View', - 'country_code': 'US', - 'country_code3': 'USA', - 'country_name': 'United States', - 'dma_code': 807, - 'latitude': 37.419200897216797, - 'longitude': -122.05740356445312, - 'postal_code': '94043', - 'region': 'CA'} - >>> g.lat_lon('salon.com') - (37.789798736572266, -122.39420318603516) - >>> g.lon_lat('uh.edu') - (-95.415199279785156, 29.77549934387207) - >>> g.geos('24.124.1.80').wkt - 'POINT (-95.2087020874023438 39.0392990112304688)' - -``GeoIP`` Settings -================== - -.. setting:: GEOIP_PATH - -GEOIP_PATH ----------- - -A string specifying the directory where the GeoIP data files are -located. This setting is *required* unless manually specified -with ``path`` keyword when initializing the :class:`GeoIP` object. - -.. setting:: GEOIP_LIBRARY_PATH - -GEOIP_LIBRARY_PATH ------------------- - -A string specifying the location of the GeoIP C library. Typically, -this setting is only used if the GeoIP C library is in a non-standard -location (e.g., ``/home/sue/lib/libGeoIP.so``). - -.. setting:: GEOIP_COUNTRY - -GEOIP_COUNTRY -------------- - -The basename to use for the GeoIP country data file. -Defaults to ``'GeoIP.dat'``. - -.. setting:: GEOIP_CITY - -GEOIP_CITY ----------- - -The basename to use for the GeoIP city data file. -Defaults to ``'GeoLiteCity.dat'``. - -``GeoIP`` API -============= - -.. class:: GeoIP([path=None, cache=0, country=None, city=None]) - -The ``GeoIP`` object does not require any parameters to use the default -settings. However, at the very least the :setting:`GEOIP_PATH` setting -should be set with the path of the location of your GeoIP data sets. The -following intialization keywords may be used to customize any of the -defaults. - -=================== ======================================================= -Keyword Arguments Description -=================== ======================================================= -``path`` Base directory to where GeoIP data is located or the - full path to where the city or country data files - (.dat) are located. Assumes that both the city and - country data sets are located in this directory; - overrides the :setting:`GEOIP_PATH` settings attribute. - -``cache`` The cache settings when opening up the GeoIP datasets, - and may be an integer in (0, 1, 2, 4) corresponding to - the ``GEOIP_STANDARD``, ``GEOIP_MEMORY_CACHE``, - ``GEOIP_CHECK_CACHE``, and ``GEOIP_INDEX_CACHE`` - ``GeoIPOptions`` C API settings, respectively. - Defaults to 0 (``GEOIP_STANDARD``). - -``country`` The name of the GeoIP country data file. Defaults - to ``GeoIP.dat``. Setting this keyword overrides the - :setting:`GEOIP_COUNTRY` settings attribute. - -``city`` The name of the GeoIP city data file. Defaults to - ``GeoLiteCity.dat``. Setting this keyword overrides - the :setting:`GEOIP_CITY` settings attribute. -=================== ======================================================= - -``GeoIP`` Methods -================= - -Querying --------- - -All the following querying routines may take either a string IP address -or a fully qualified domain name (FQDN). For example, both -``'24.124.1.80'`` and ``'djangoproject.com'`` would be valid query -parameters. - -.. method:: GeoIP.city(query) - -Returns a dictionary of city information for the given query. Some -of the values in the dictionary may be undefined (``None``). - -.. method:: GeoIPcountry(query) - -Returns a dictionary with the country code and country for the given -query. - -.. method:: GeoIP.country_code(query) - -Returns only the country code corresponding to the query. - -.. method:: GeoIP.country_name(query) - -Returns only the country name corresponding to the query. - -Coordinate Retrieval --------------------- - -.. method:: GeoIP.coords(query) - -Returns a coordinate tuple of (longitude, latitude). - -.. method:: GeoIP.lon_lat(query) - -Returns a coordinate tuple of (longitude, latitude). - -.. method:: GeoIP.lat_lon(query) - -Returns a coordinate tuple of (latitude, longitude), - -.. method:: GeoIP.geos(query) - -Returns a :class:`django.contrib.gis.geos.Point` object corresponding to the query. - -Database Information --------------------- - -.. attribute:: GeoIP.country_info - -This property returns information about the GeoIP country database. - -.. attribute:: GeoIP.city_info - -This property returns information about the GeoIP city database. - -.. attribute:: GeoIP.info - -This property returns information about all GeoIP databases (both city -and country). - -GeoIP-Python API compatibility methods ----------------------------------------- - -These methods exist to ease compatibility with any code using MaxMind's -existing Python API. - -.. classmethod:: GeoIP.open(path, cache) - -This classmethod instantiates the GeoIP object from the given database path -and given cache setting. - -.. method:: GeoIP.region_by_addr(query) - -.. method:: GeoIP.region_by_name(query) - -.. method:: GeoIP.record_by_addr(query) - -.. method:: GeoIP.record_by_name(query) - -.. method:: GeoIP.country_code_by_addr(query) - -.. method:: GeoIP.country_code_by_name(query) - -.. method:: GeoIP.country_name_by_addr(query) - -.. method:: GeoIP.country_name_by_name(query) - -.. rubric:: Footnotes -.. [#] GeoIP(R) is a registered trademark of MaxMind, LLC of Boston, Massachusetts. diff --git a/parts/django/docs/ref/contrib/gis/geoquerysets.txt b/parts/django/docs/ref/contrib/gis/geoquerysets.txt deleted file mode 100644 index 69f0c02..0000000 --- a/parts/django/docs/ref/contrib/gis/geoquerysets.txt +++ /dev/null @@ -1,1256 +0,0 @@ -.. _ref-geoquerysets: - -========================= -GeoQuerySet API Reference -========================= - -.. currentmodule:: django.contrib.gis.db.models - -.. class:: GeoQuerySet([model=None]) - - -.. _spatial-lookups: - -Spatial Lookups -=============== - -Just like when using the the :ref:`queryset-api`, interaction -with ``GeoQuerySet`` by :ref:`chaining filters <chaining-filters>`. -Instead of the regular Django :ref:`field-lookups`, the -spatial lookups in this section are available for :class:`GeometryField`. - -For an introduction, see the :ref:`spatial lookups introduction -<spatial-lookups-intro>`. For an overview of what lookups are -compatible with a particular spatial backend, refer to the -:ref:`spatial lookup compatibility table <spatial-lookup-compatibility>`. - -.. fieldlookup:: bbcontains - -bbcontains ----------- - -*Availability*: PostGIS, MySQL, SpatiaLite - -Tests if the geometry field's bounding box completely contains the lookup -geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__bbcontains=geom) - -========== ========================== -Backend SQL Equivalent -========== ========================== -PostGIS ``poly ~ geom`` -MySQL ``MBRContains(poly, geom)`` -SpatiaLite ``MbrContains(poly, geom)`` -========== ========================== - -.. fieldlookup:: bboverlaps - -bboverlaps ----------- - -*Availability*: PostGIS, MySQL, SpatiaLite - -Tests if the geometry field's bounding box overlaps the lookup geometry's -bounding box. - -Example:: - - Zipcode.objects.filter(poly__bboverlaps=geom) - -========== ========================== -Backend SQL Equivalent -========== ========================== -PostGIS ``poly && geom`` -MySQL ``MBROverlaps(poly, geom)`` -SpatiaLite ``MbrOverlaps(poly, geom)`` -========== ========================== - -.. fieldlookup:: contained - -contained ---------- - -*Availability*: PostGIS, MySQL, SpatiaLite - -Tests if the geometry field's bounding box is completely contained by the -lookup geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__contained=geom) - -========== ========================== -Backend SQL Equivalent -========== ========================== -PostGIS ``poly @ geom`` -MySQL ``MBRWithin(poly, geom)`` -SpatiaLite ``MbrWithin(poly, geom)`` -========== ========================== - -.. fieldlookup:: gis-contains - -contains --------- - -*Availability*: PostGIS, Oracle, MySQL, SpatiaLite - -Tests if the geometry field spatially contains the lookup geometry. - -Example:: - - Zipcode.objects.filter(poly__contains=geom) - -========== ============================ -Backend SQL Equivalent -========== ============================ -PostGIS ``ST_Contains(poly, geom)`` -Oracle ``SDO_CONTAINS(poly, geom)`` -MySQL ``MBRContains(poly, geom)`` -SpatiaLite ``Contains(poly, geom)`` -========== ============================ - -.. fieldlookup:: contains_properly - -contains_properly ------------------ - -.. versionadded:: 1.2 - -*Availability*: PostGIS - -Returns true if the lookup geometry intersects the interior of the -geometry field, but not the boundary (or exterior). [#fncontainsproperly]_ - -.. note:: - - Requires PostGIS 1.4 and above. - -Example:: - - Zipcode.objects.filter(poly__contains_properly=geom) - -========== =================================== -Backend SQL Equivalent -========== =================================== -PostGIS ``ST_ContainsProperly(poly, geom)`` -========== =================================== - -.. fieldlookup:: coveredby - -coveredby ---------- - -*Availability*: PostGIS, Oracle - -Tests if no point in the geometry field is outside the lookup geometry. -[#fncovers]_ - -Example:: - - Zipcode.objects.filter(poly__coveredby=geom) - -========== ============================= -Backend SQL Equivalent -========== ============================= -PostGIS ``ST_CoveredBy(poly, geom)`` -Oracle ``SDO_COVEREDBY(poly, geom)`` -========== ============================= - -.. fieldlookup:: covers - -covers ------- - -*Availability*: PostGIS, Oracle - -Tests if no point in the lookup geometry is outside the geometry field. -[#fncovers]_ - -Example:: - - Zipcode.objects.filter(poly__covers=geom) - -========== ========================== -Backend SQL Equivalent -========== ========================== -PostGIS ``ST_Covers(poly, geom)`` -Oracle ``SDO_COVERS(poly, geom)`` -========== ========================== - -.. fieldlookup:: crosses - -crosses -------- - -*Availability*: PostGIS, SpatiaLite - -Tests if the geometry field spatially crosses the lookup geometry. - -Example:: - - Zipcode.objects.filter(poly__crosses=geom) - -========== ========================== -Backend SQL Equivalent -========== ========================== -PostGIS ``ST_Crosses(poly, geom)`` -SpatiaLite ``Crosses(poly, geom)`` -========== ========================== - -.. fieldlookup:: disjoint - -disjoint --------- - -*Availability*: PostGIS, Oracle, MySQL, SpatiaLite - -Tests if the geometry field is spatially disjoint from the lookup geometry. - -Example:: - - Zipcode.objects.filter(poly__disjoint=geom) - -========== ================================================= -Backend SQL Equivalent -========== ================================================= -PostGIS ``ST_Disjoint(poly, geom)`` -Oracle ``SDO_GEOM.RELATE(poly, 'DISJOINT', geom, 0.05)`` -MySQL ``MBRDisjoint(poly, geom)`` -SpatiaLite ``Disjoint(poly, geom)`` -========== ================================================= - -equals ------- - -*Availability*: PostGIS, Oracle, MySQL, SpatiaLite - -.. fieldlookup:: exact -.. fieldlookup:: same_as - -exact, same_as --------------- - -*Availability*: PostGIS, Oracle, MySQL, SpatiaLite - -.. fieldlookup:: intersects - -intersects ----------- - -*Availability*: PostGIS, Oracle, MySQL, SpatiaLite - -Tests if the geometry field spatially intersects the lookup geometry. - -Example:: - - Zipcode.objects.filter(poly__intersects=geom) - -========== ================================================= -Backend SQL Equivalent -========== ================================================= -PostGIS ``ST_Intersects(poly, geom)`` -Oracle ``SDO_OVERLAPBDYINTERSECT(poly, geom)`` -MySQL ``MBRIntersects(poly, geom)`` -SpatiaLite ``Intersects(poly, geom)`` -========== ================================================= - -.. fieldlookup:: overlaps - -overlaps --------- - -*Availability*: PostGIS, Oracle, MySQL, SpatiaLite - -.. fieldlookup:: relate - -relate ------- - -*Availability*: PostGIS, Oracle, SpatiaLite - -Tests if the geometry field is spatially related to the the lookup geometry by -the values given in the given pattern. This lookup requires a tuple parameter, -``(geom, pattern)``; the form of ``pattern`` will depend on the spatial backend: - -PostGIS & SpatiaLite -~~~~~~~~~~~~~~~~~~~~ -On these spatial backends the intersection pattern is a string comprising -nine characters, which define intersections between the interior, boundary, -and exterior of the geometry field and the lookup geometry. -The intersection pattern matrix may only use the following characters: -``1``, ``2``, ``T``, ``F``, or ``*``. This lookup type allows users to "fine tune" -a specific geometric relationship consistent with the DE-9IM model. [#fnde9im]_ - -Example:: - - # A tuple lookup parameter is used to specify the geometry and - # the intersection pattern (the pattern here is for 'contains'). - Zipcode.objects.filter(poly__relate(geom, 'T*T***FF*')) - -PostGIS SQL equivalent:: - - SELECT ... WHERE ST_Relate(poly, geom, 'T*T***FF*') - -SpatiaLite SQL equivalent:: - - SELECT ... WHERE Relate(poly, geom, 'T*T***FF*') - -Oracle -~~~~~~ - -Here the relation pattern is compreised at least one of the nine relation -strings: ``TOUCH``, ``OVERLAPBDYDISJOINT``, ``OVERLAPBDYINTERSECT``, -``EQUAL``, ``INSIDE``, ``COVEREDBY``, ``CONTAINS``, ``COVERS``, ``ON``, and -``ANYINTERACT``. Multiple strings may be combined with the logical Boolean -operator OR, for example, ``'inside+touch'``. [#fnsdorelate]_ The relation -strings are case-insensitive. - -Example:: - - Zipcode.objects.filter(poly__relate(geom, 'anyinteract')) - -Oracle SQL equivalent:: - - SELECT ... WHERE SDO_RELATE(poly, geom, 'anyinteract') - -.. fieldlookup:: touches - -touches -------- - -*Availability*: PostGIS, Oracle, MySQL, SpatiaLite - -Tests if the geometry field spatially touches the lookup geometry. - -Example:: - - Zipcode.objects.filter(poly__touches=geom) - -========== ========================== -Backend SQL Equivalent -========== ========================== -PostGIS ``ST_Touches(poly, geom)`` -MySQL ``MBRTouches(poly, geom)`` -Oracle ``SDO_TOUCH(poly, geom)`` -SpatiaLite ``Touches(poly, geom)`` -========== ========================== - -.. fieldlookup:: within - -within ------- - -*Availability*: PostGIS, Oracle, MySQL, SpatiaLite - -Tests if the geometry field is spatially within the lookup geometry. - -Example:: - - Zipcode.objects.filter(poly__within=geom) - -========== ========================== -Backend SQL Equivalent -========== ========================== -PostGIS ``ST_Within(poly, geom)`` -MySQL ``MBRWithin(poly, geom)`` -Oracle ``SDO_INSIDE(poly, geom)`` -SpatiaLite ``Within(poly, geom)`` -========== ========================== - -.. fieldlookup:: left - -left ----- - -*Availability*: PostGIS - -Tests if the geometry field's bounding box is strictly to the left of the -lookup geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__left=geom) - -PostGIS equivalent:: - - SELECT ... WHERE poly << geom - -.. fieldlookup:: right - -right ------ - -*Availability*: PostGIS - -Tests if the geometry field's bounding box is strictly to the right of the -lookup geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__right=geom) - -PostGIS equivalent:: - - SELECT ... WHERE poly >> geom - -.. fieldlookup:: overlaps_left - -overlaps_left -------------- - -*Availability*: PostGIS - -Tests if the geometry field's bounding box overlaps or is to the left of the lookup -geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__overlaps_left=geom) - -PostGIS equivalent:: - - SELECT ... WHERE poly &< geom - - -.. fieldlookup:: overlaps_right - -overlaps_right --------------- - -*Availability*: PostGIS - -Tests if the geometry field's bounding box overlaps or is to the right of the lookup -geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__overlaps_right=geom) - -PostGIS equivalent:: - - SELECT ... WHERE poly &> geom - -.. fieldlookup:: overlaps_above - -overlaps_above --------------- - -*Availability*: PostGIS - -Tests if the geometry field's bounding box overlaps or is above the lookup -geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__overlaps_above=geom) - -PostGIS equivalent:: - - SELECT ... WHERE poly |&> geom - -.. fieldlookup:: overlaps_below - -overlaps_below --------------- - -*Availability*: PostGIS - -Tests if the geometry field's bounding box overlaps or is below the lookup -geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__overlaps_below=geom) - -PostGIS equivalent:: - - SELECT ... WHERE poly &<| geom - -.. fieldlookup:: strictly_above - -strictly_above --------------- - -*Availability*: PostGIS - -Tests if the geometry field's bounding box is strictly above the lookup -geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__strictly_above=geom) - -PostGIS equivalent:: - - SELECT ... WHERE poly |>> geom - -.. fieldlookup:: strictly_below - -strictly_below --------------- - -*Availability*: PostGIS - -Tests if the geometry field's bounding box is strictly above the lookup -geometry's bounding box. - -Example:: - - Zipcode.objects.filter(poly__strictly_above=geom) - -PostGIS equivalent:: - - SELECT ... WHERE poly |>> geom - - -.. _distance-lookups: - -Distance Lookups -================ - -*Availability*: PostGIS, Oracle, SpatiaLite - -For an overview on performing distance queries, please refer to -the :ref:`distance queries introduction <distance-queries>`. - -Distance lookups take the following form:: - - <field>__<distance lookup>=(<geometry>, <distance value>[, 'spheroid']) - -The value passed into a distance lookup is a tuple; the first two -values are mandatory, and are the geometry to calculate distances to, -and a distance value (either a number in units of the field or a -:class:`~django.contrib.gis.measure.Distance` object). On every -distance lookup but :lookup:`dwithin`, an optional -third element, ``'spheroid'``, may be included to tell GeoDjango -to use the more accurate spheroid distance calculation functions on -fields with a geodetic coordinate system (e.g., ``ST_Distance_Spheroid`` -would be used instead of ``ST_Distance_Sphere``). - -.. fieldlookup:: distance_gt - -distance_gt ------------ - -Returns models where the distance to the geometry field from the lookup -geometry is greater than the given distance value. - -Example:: - - Zipcode.objects.filter(poly__distance_gt=(geom, D(m=5))) - -========== =============================================== -Backend SQL Equivalent -========== =============================================== -PostGIS ``ST_Distance(poly, geom) > 5`` -Oracle ``SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) > 5`` -SpatiaLite ``Distance(poly, geom) > 5`` -========== =============================================== - -.. fieldlookup:: distance_gte - -distance_gte ------------- - -Returns models where the distance to the geometry field from the lookup -geometry is greater than or equal to the given distance value. - -Example:: - - Zipcode.objects.filter(poly__distance_gte=(geom, D(m=5))) - -========== ================================================ -Backend SQL Equivalent -========== ================================================ -PostGIS ``ST_Distance(poly, geom) >= 5`` -Oracle ``SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) >= 5`` -SpatiaLite ``Distance(poly, geom) >= 5`` -========== ================================================ - -.. fieldlookup:: distance_lt - -distance_lt ------------ - -Returns models where the distance to the geometry field from the lookup -geometry is less than the given distance value. - -Example:: - - Zipcode.objects.filter(poly__distance_lt=(geom, D(m=5))) - -========== =============================================== -Backend SQL Equivalent -========== =============================================== -PostGIS ``ST_Distance(poly, geom) < 5`` -Oracle ``SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) < 5`` -SpatiaLite ``Distance(poly, geom) < 5`` -========== =============================================== - -.. fieldlookup:: distance_lte - -distance_lte ------------- - -Returns models where the distance to the geometry field from the lookup -geometry is less than or equal to the given distance value. - -Example:: - - Zipcode.objects.filter(poly__distance_lte=(geom, D(m=5))) - -========== ================================================ -Backend SQL Equivalent -========== ================================================ -PostGIS ``ST_Distance(poly, geom) <= 5`` -Oracle ``SDO_GEOM.SDO_DISTANCE(poly, geom, 0.05) <= 5`` -SpatiaLite ``Distance(poly, geom) <= 5`` -========== ================================================ - -.. fieldlookup:: dwithin - -dwithin -------- - -Returns models where the distance to the geometry field from the -lookup geometry are within the given distance from one another. - -Example:: - - Zipcode.objects.filter(poly__dwithin=(geom, D(m=5))) - -========== ====================================== -Backend SQL Equivalent -========== ====================================== -PostGIS ``ST_DWithin(poly, geom, 5)`` -Oracle ``SDO_WITHIN_DISTANCE(poly, geom, 5)`` -========== ====================================== - -.. note:: - - This lookup is not available on SpatiaLite. - -.. fieldlookup:: equals - - -``GeoQuerySet`` Methods -======================= - -``GeoQuerySet`` methods specify that a spatial operation be performed -on each patial operation on each geographic -field in the queryset and store its output in a new attribute on the model -(which is generally the name of the ``GeoQuerySet`` method). - -There are also aggregate ``GeoQuerySet`` methods which return a single value -instead of a queryset. This section will describe the API and availability -of every ``GeoQuerySet`` method available in GeoDjango. - -.. note:: - - What methods are available depend on your spatial backend. See - the :ref:`compatibility table <geoqueryset-method-compatibility>` - for more details. - -With a few exceptions, the following keyword arguments may be used with all -``GeoQuerySet`` methods: - -===================== ===================================================== -Keyword Argument Description -===================== ===================================================== -``field_name`` By default, ``GeoQuerySet`` methods use the first - geographic field encountered in the model. This - keyword should be used to specify another - geographic field (e.g., ``field_name='point2'``) - when there are multiple geographic fields in a model. - - On PostGIS, the ``field_name`` keyword may also be - used on geometry fields in models that are related - via a ``ForeignKey`` relation (e.g., - ``field_name='related__point'``). - -``model_att`` By default, ``GeoQuerySet`` methods typically attach - their output in an attribute with the same name as - the ``GeoQuerySet`` method. Setting this keyword - with the desired attribute name will override this - default behavior. For example, - ``qs = Zipcode.objects.centroid(model_att='c')`` will - attach the centroid of the ``Zipcode`` geometry field - in a ``c`` attribute on every model rather than in a - ``centroid`` attribute. - - This keyword is required if - a method name clashes with an existing - ``GeoQuerySet`` method -- if you wanted to use the - ``area()`` method on model with a ``PolygonField`` - named ``area``, for example. -===================== ===================================================== - -Measurement ------------ -*Availability*: PostGIS, Oracle, SpatiaLite - -``area`` -~~~~~~~~ - -.. method:: GeoQuerySet.area(**kwargs) - -Returns the area of the geographic field in an ``area`` attribute on -each element of this GeoQuerySet. - -``distance`` -~~~~~~~~~~~~ - -.. method:: GeoQuerySet.distance(geom, **kwargs) - -This method takes a geometry as a parameter, and attaches a ``distance`` -attribute to every model in the returned queryset that contains the -distance (as a :class:`~django.contrib.gis.measure.Distance` object) to the given geometry. - -In the following example (taken from the `GeoDjango distance tests`__), -the distance from the `Tasmanian`__ city of Hobart to every other -:class:`PointField` in the ``AustraliaCity`` queryset is calculated:: - - >>> pnt = AustraliaCity.objects.get(name='Hobart').point - >>> for city in AustraliaCity.objects.distance(pnt): print city.name, city.distance - Wollongong 990071.220408 m - Shellharbour 972804.613941 m - Thirroul 1002334.36351 m - Mittagong 975691.632637 m - Batemans Bay 834342.185561 m - Canberra 598140.268959 m - Melbourne 575337.765042 m - Sydney 1056978.87363 m - Hobart 0.0 m - Adelaide 1162031.83522 m - Hillsdale 1049200.46122 m - -.. note:: - - Because the ``distance`` attribute is a - :class:`~django.contrib.gis.measure.Distance` object, you can easily express - the value in the units of your choice. For example, ``city.distance.mi`` is - the distance value in miles and ``city.distance.km`` is the distance value - in kilometers. See the :ref:`ref-measure` for usage details and the list of - :ref:`supported_units`. - -__ http://code.djangoproject.com/browser/django/trunk/django/contrib/gis/tests/distapp/models.py -__ http://en.wikipedia.org/wiki/Tasmania - -``length`` -~~~~~~~~~~ - -.. method:: GeoQuerySet.length(**kwargs) - -Returns the length of the geometry field in a ``length`` attribute -(a :class:`~django.contrib.gis.measure.Distance` object) on each model in -the queryset. - -``perimeter`` -~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.perimeter(**kwargs) - -Returns the perimeter of the geometry field in a ``perimeter`` attribute -(a :class:`~django.contrib.gis.measure.Distance` object) on each model in -the queryset. - -Geometry Relationships ----------------------- - -The following methods take no arguments, and attach geometry objects -each element of the :class:`GeoQuerySet` that is the result of relationship -function evaluated on the the geometry field. - -``centroid`` -~~~~~~~~~~~~ - -.. method:: GeoQuerySet.centroid(**kwargs) - -*Availability*: PostGIS, Oracle, SpatiaLite - -Returns the ``centroid`` value for the geographic field in a ``centroid`` -attribute on each element of the ``GeoQuerySet``. - -``envelope`` -~~~~~~~~~~~~ - -.. method:: GeoQuerySet.envelope(**kwargs) - -*Availability*: PostGIS, SpatiaLite - -Returns a geometry representing the bounding box of the geometry field in -an ``envelope`` attribute on each element of the ``GeoQuerySet``. - -``point_on_surface`` -~~~~~~~~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.point_on_surface(**kwargs) - -*Availability*: PostGIS, Oracle, SpatiaLite - -Returns a Point geometry guaranteed to lie on the surface of the -geometry field in a ``point_on_surface`` attribute on each element -of the queryset; otherwise sets with None. - -Geometry Editors ----------------- - -``force_rhr`` -~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.force_rhr(**kwargs) - -.. versionadded:: 1.2 - -*Availability*: PostGIS - -Returns a modified version of the polygon/multipolygon in which all -of the vertices follow the Right-Hand-Rule, and attaches as a -``force_rhr`` attribute on each element of the queryset. - -``reverse_geom`` -~~~~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.reverse_geom(**kwargs) - -.. versionadded:: 1.2 - -*Availability*: PostGIS, Oracle - -Reverse the coordinate order of the geometry field, and attaches as a -``reverse`` attribute on each element of the queryset. - -``scale`` -~~~~~~~~~ - -.. method:: GeoQuerySet.scale(x, y, z=0.0, **kwargs) - -*Availability*: PostGIS, SpatiaLite - -``snap_to_grid`` -~~~~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.snap_to_grid(*args, **kwargs) - -.. versionadded:: 1.1 - -Snap all points of the input geometry to the grid. How the -geometry is snapped to the grid depends on how many numeric -(either float, integer, or long) arguments are given. - -=================== ===================================================== -Number of Arguments Description -=================== ===================================================== -1 A single size to snap bot the X and Y grids to. -2 X and Y sizes to snap the grid to. -4 X, Y sizes and the corresponding X, Y origins. -=================== ===================================================== - -``transform`` -~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.transform(srid=4326, **kwargs) - -*Availability*: PostGIS, Oracle, SpatiaLite - -The ``transform`` method transforms the geometry field of a model to the spatial -reference system specified by the ``srid`` parameter. If no ``srid`` is given, -then 4326 (WGS84) is used by default. - -.. note:: - - Unlike other ``GeoQuerySet`` methods, ``transform`` stores its output - "in-place". In other words, no new attribute for the transformed - geometry is placed on the models. - -.. note:: - - What spatial reference system an integer SRID corresponds to may depend on - the spatial database used. In other words, the SRID numbers used for Oracle - are not necessarily the same as those used by PostGIS. - -Example:: - - >>> qs = Zipcode.objects.all().transform() # Transforms to WGS84 - >>> qs = Zipcode.objects.all().transform(32140) # Transforming to "NAD83 / Texas South Central" - >>> print qs[0].poly.srid - 32140 - >>> print qs[0].poly - POLYGON ((234055.1698884720099159 4937796.9232223574072123 ... - -``translate`` -~~~~~~~~~~~~~ -.. method:: GeoQuerySet.translate(x, y, z=0.0, **kwargs) - -*Availability*: PostGIS, SpatiaLite - -Translates the geometry field to a new location using the given numeric -parameters as offsets. - -Geometry Operations -------------------- -*Availability*: PostGIS, Oracle, SpatiaLite - -The following methods all take a geometry as a parameter and attach a geometry -to each element of the ``GeoQuerySet`` that is the result of the operation. - -``difference`` -~~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.difference(geom) - -Returns the spatial difference of the geographic field with the given -geometry in a ``difference`` attribute on each element of the -``GeoQuerySet``. - - -``intersection`` -~~~~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.intersection(geom) - -Returns the spatial intersection of the geographic field with the -given geometry in an ``intersection`` attribute on each element of the -``GeoQuerySet``. - -``sym_difference`` -~~~~~~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.sym_difference(geom) - -Returns the symmetric difference of the geographic field with the -given geometry in a ``sym_difference`` attribute on each element of the -``GeoQuerySet``. - -``union`` -~~~~~~~~~ - -.. method:: GeoQuerySet.union(geom) - -Returns the union of the geographic field with the given -geometry in an ``union`` attribute on each element of the -``GeoQuerySet``. - -Geometry Output ---------------- - -The following ``GeoQuerySet`` methods will return an attribute that has the value -of the geometry field in each model converted to the requested output format. - -``geohash`` -~~~~~~~~~~~ - -.. method:: GeoQuerySet.geohash(preceision=20, **kwargs) - -.. versionadded:: 1.2 - -Attaches a ``geohash`` attribute to every model the the queryset -containing the `GeoHash`__ representation of the geometry. - -__ http://geohash.org/ - -``geojson`` -~~~~~~~~~~~ - -.. method:: GeoQuerySet.geojson(**kwargs) - -.. versionadded:: 1.1 - -*Availability*: PostGIS - -Attaches a ``geojson`` attribute to every model in the queryset that contains the -`GeoJSON`__ representation of the geometry. - -===================== ===================================================== -Keyword Argument Description -===================== ===================================================== -``precision`` It may be used to specify the number of significant - digits for the coordinates in the GeoJSON - representation -- the default value is 8. - -``crs`` Set this to ``True`` if you want the coordinate - reference system to be included in the returned - GeoJSON. - -``bbox`` Set this to ``True`` if you want the bounding box - to be included in the returned GeoJSON. -===================== ===================================================== - -__ http://geojson.org/ - -``gml`` -~~~~~~~ - -.. method:: GeoQuerySet.gml(**kwargs) - -*Availability*: PostGIS, Oracle - -Attaches a ``gml`` attribute to every model in the queryset that contains the -`Geographic Markup Language (GML)`__ representation of the geometry. - -Example:: - - >>> qs = Zipcode.objects.all().gml() - >>> print qs[0].gml - <gml:Polygon srsName="EPSG:4326"><gml:OuterBoundaryIs>-147.78711,70.245363 ... -147.78711,70.245363</gml:OuterBoundaryIs></gml:Polygon> - -===================== ===================================================== -Keyword Argument Description -===================== ===================================================== -``precision`` This keyword is for PostGIS only. It may be used - to specify the number of significant digits for the - coordinates in the GML representation -- the default - value is 8. - -``version`` This keyword is for PostGIS only. It may be used to - specify the GML version used, and may only be values - of 2 or 3. The default value is 2. -===================== ===================================================== - -__ http://en.wikipedia.org/wiki/Geography_Markup_Language - -``kml`` -~~~~~~~ - -.. method:: GeoQuerySet.kml(**kwargs) - -*Availability*: PostGIS - -Attaches a ``kml`` attribute to every model in the queryset that contains the -`Keyhole Markup Language (KML)`__ representation of the geometry fields. It -should be noted that the contents of the KML are transformed to WGS84 if -necessary. - -Example:: - - >>> qs = Zipcode.objects.all().kml() - >>> print qs[0].kml - <Polygon><outerBoundaryIs><LinearRing><coordinates>-103.04135,36.217596,0 ... -103.04135,36.217596,0</coordinates></LinearRing></outerBoundaryIs></Polygon> - -===================== ===================================================== -Keyword Argument Description -===================== ===================================================== -``precision`` This keyword may be used to specify the number of - significant digits for the coordinates in the KML - representation -- the default value is 8. -===================== ===================================================== - -__ http://code.google.com/apis/kml/documentation/ - -``svg`` -~~~~~~~ - -.. method:: GeoQuerySet.svg(**kwargs) - -*Availability*: PostGIS, SpatiaLite - -Attaches a ``svg`` attribute to every model in the queryset that contains -the `Scalable Vector Graphics (SVG)`__ path data of the geometry fields. - -===================== ===================================================== -Keyword Argument Description -===================== ===================================================== -``relative`` If set to ``True``, the path data will be implemented - in terms of relative moves. Defaults to ``False``, - meaning that absolute moves are used instead. - -``precision`` This keyword may be used to specify the number of - significant digits for the coordinates in the SVG - representation -- the default value is 8. -===================== ===================================================== - -__ http://www.w3.org/Graphics/SVG/ - -Miscellaneous -------------- - -``mem_size`` -~~~~~~~~~~~~ - -.. method:: GeoQuerySet.mem_size(**kwargs) - -*Availability*: PostGIS - -Returns the memory size (number of bytes) that the geometry field takes -in a ``mem_size`` attribute on each element of the ``GeoQuerySet``. - -``num_geom`` -~~~~~~~~~~~~ - -.. method:: GeoQuerySet.num_geom(**kwargs) - -*Availability*: PostGIS, Oracle, SpatiaLite - -Returns the number of geometries in a ``num_geom`` attribute on -each element of the ``GeoQuerySet`` if the geometry field is a -collection (e.g., a ``GEOMETRYCOLLECTION`` or ``MULTI*`` field); -otherwise sets with ``None``. - -``num_points`` -~~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.num_points(**kwargs) - -*Availability*: PostGIS, Oracle, SpatiaLite - -Returns the number of points in the first linestring in the -geometry field in a ``num_points`` attribute on each element of -the ``GeoQuerySet``; otherwise sets with ``None``. - -Spatial Aggregates -================== -.. versionadded:: 1.1 - -Aggregate Methods ------------------ - -``collect`` -~~~~~~~~~~~ - -.. method:: GeoQuerySet.collect(**kwargs) - -.. versionadded:: 1.1 - -*Availability*: PostGIS - -Returns a ``GEOMETRYCOLLECTION`` or a ``MULTI`` geometry object from the geometry -column. This is analagous to a simplified version of the :meth:`GeoQuerySet.unionagg` method, -except it can be several orders of magnitude faster than peforming a union because -it simply rolls up geometries into a collection or multi object, not caring about -dissolving boundaries. - -``extent`` -~~~~~~~~~~ - -.. method:: GeoQuerySet.extent(**kwargs) - -*Availability*: PostGIS, Oracle - -Returns the extent of the ``GeoQuerySet`` as a four-tuple, comprising the -lower left coordinate and the upper right coordinate. - -Example:: - - >>> qs = City.objects.filter(name__in=('Houston', 'Dallas')) - >>> print qs.extent() - (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820) - -``extent3d`` -~~~~~~~~~~~~ - -.. method:: GeoQuerySet.extent3d(**kwargs) - -.. versionadded:: 1.2 - -*Availability*: PostGIS - -Returns the 3D extent of the ``GeoQuerySet`` as a six-tuple, comprising -the lower left coordinate and upper right coordinate. - -Example:: - - >>> qs = City.objects.filter(name__in=('Houston', 'Dallas')) - >>> print qs.extent3d() - (-96.8016128540039, 29.7633724212646, 0, -95.3631439208984, 32.782058715820, 0) - -``make_line`` -~~~~~~~~~~~~~ - -.. method:: GeoQuerySet.make_line(**kwargs) - -*Availability*: PostGIS - -Returns a ``LineString`` constructed from the point field geometries in the -``GeoQuerySet``. Currently, ordering the queryset has no effect. - -Example:: - - >>> print City.objects.filter(name__in=('Houston', 'Dallas')).make_line() - LINESTRING (-95.3631510000000020 29.7633739999999989, -96.8016109999999941 32.7820570000000018) - -``unionagg`` -~~~~~~~~~~~~ - -.. method:: GeoQuerySet.unionagg(**kwargs) - -*Availability*: PostGIS, Oracle, SpatiaLite - -This method returns a :class:`~django.contrib.gis.geos.GEOSGeometry` object -comprising the union of every geometry in the queryset. Please note that -use of ``unionagg`` is processor intensive and may take a significant amount -of time on large querysets. - -.. note:: - - If the computation time for using this method is too expensive, - consider using :meth:`GeoQuerySet.collect` instead. - -Example:: - - >>> u = Zipcode.objects.unionagg() # This may take a long time. - >>> u = Zipcode.objects.filter(poly__within=bbox).unionagg() # A more sensible approach. - -===================== ===================================================== -Keyword Argument Description -===================== ===================================================== -``tolerance`` This keyword is for Oracle only. It is for the - tolerance value used by the ``SDOAGGRTYPE`` - procedure; the `Oracle documentation`__ has more - details. -===================== ===================================================== - -__ http://download.oracle.com/docs/html/B14255_01/sdo_intro.htm#sthref150 - -Aggregate Functions -------------------- - -Example:: - - >>> from django.contrib.gis.db.models import Extent, Union - >>> WorldBorders.objects.aggregate(Extent('mpoly'), Union('mpoly')) - -``Collect`` -~~~~~~~~~~~ - -.. class:: Collect(geo_field) - -Returns the same as the :meth:`GeoQuerySet.collect` aggregate method. - -``Extent`` -~~~~~~~~~~ -.. class:: Extent(geo_field) - - -Returns the same as the :meth:`GeoQuerySet.extent` aggregate method. - -``Extent3D`` -~~~~~~~~~~~~ - -.. class:: Extent3D(geo_field) - -.. versionadded:: 1.2 - -Returns the same as the :meth:`GeoQuerySet.extent3d` aggregate method. - -``MakeLine`` -~~~~~~~~~~~~ - -.. class:: MakeLine(geo_field) - -Returns the same as the :meth:`GeoQuerySet.make_line` aggregate method. - -``Union`` -~~~~~~~~~ - -.. class:: Union(geo_field) - -Returns the same as the :meth:`GeoQuerySet.union` aggregate method. - -.. rubric:: Footnotes -.. [#fnde9im] *See* `OpenGIS Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, at Ch. 2.1.13.2, p. 2-13 (The Dimensionally Extended Nine-Intersection Model). -.. [#fnsdorelate] *See* `SDO_RELATE documentation <http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14255/sdo_operat.htm#sthref845>`_, from Ch. 11 of the Oracle Spatial User's Guide and Manual. -.. [#fncovers] For an explanation of this routine, read `Quirks of the "Contains" Spatial Predicate <http://lin-ear-th-inking.blogspot.com/2007/06/subtleties-of-ogc-covers-spatial.html>`_ by Martin Davis (a PostGIS developer). -.. [#fncontainsproperly] Refer to the PostGIS ``ST_ContainsProperly`` `documentation <http://postgis.refractions.net/documentation/manual-1.4/ST_ContainsProperly.html>`_ for more details. diff --git a/parts/django/docs/ref/contrib/gis/geos.txt b/parts/django/docs/ref/contrib/gis/geos.txt deleted file mode 100644 index 06a88a8..0000000 --- a/parts/django/docs/ref/contrib/gis/geos.txt +++ /dev/null @@ -1,911 +0,0 @@ -.. _ref-geos: - -======== -GEOS API -======== - -.. module:: django.contrib.gis.geos - :synopsis: GeoDjango's high-level interface to the GEOS library. - -Background -========== - -What is GEOS? -------------- - -`GEOS`__ stands for **G**\ eometry **E**\ ngine - **O**\ pen **S**\ ource, -and is a C++ library, ported from the `Java Topology Suite`__. GEOS -implements the OpenGIS `Simple Features for SQL`__ spatial predicate functions -and spatial operators. GEOS, now an OSGeo project, was initially developed and -maintained by `Refractions Research`__ of Victoria, Canada. - -__ http://trac.osgeo.org/geos/ -__ http://sourceforge.net/projects/jts-topo-suite/ -__ http://www.opengeospatial.org/standards/sfs -__ http://www.refractions.net/ - -Features --------- - -GeoDjango implements a high-level Python wrapper for the GEOS library, its -features include: - -* A BSD-licensed interface to the GEOS geometry routines, implemented purely - in Python using ``ctypes``. -* Loosely-coupled to GeoDjango. For example, :class:`GEOSGeometry` objects - may be used outside of a django project/application. In other words, - no need to have ``DJANGO_SETTINGS_MODULE`` set or use a database, etc. -* Mutability: :class:`GEOSGeometry` objects may be modified. -* Cross-platform and tested; compatible with Windows, Linux, Solaris, and Mac - OS X platforms. - -.. _geos-tutorial: - -Tutorial -======== - -This section contains a brief introduction and tutorial to using -:class:`GEOSGeometry` objects. - -Creating a Geometry -------------------- - -:class:`GEOSGeometry` objects may be created in a few ways. The first is -to simply instantiate the object on some spatial input -- the following -are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON:: - - >>> from django.contrib.gis.geos import GEOSGeometry - >>> pnt = GEOSGeometry('POINT(5 23)') # WKT - >>> pnt = GEOSGeometry('010100000000000000000014400000000000003740') # HEX - >>> pnt = GEOSGeometry(buffer('\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@')) - >>> pnt = GEOSGeometry('{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }') # GeoJSON - -Another option is to use the constructor for the specific geometry type -that you wish to create. For example, a :class:`Point` object may be -created by passing in the X and Y coordinates into its constructor:: - - >>> from django.contrib.gis.geos import Point - >>> pnt = Point(5, 23) - -Finally, there are :func:`fromstr` and :func:`fromfile` factory methods, which -return a :class:`GEOSGeometry` object from an input string or a file:: - - >>> from django.contrib.gis.geos import fromstr, fromfile - >>> pnt = fromstr('POINT(5 23)') - >>> pnt = fromfile('/path/to/pnt.wkt') - >>> pnt = fromfile(open('/path/to/pnt.wkt')) - -Geometries are Pythonic ------------------------ -:class:`GEOSGeometry` objects are 'Pythonic', in other words components may -be accessed, modified, and iterated over using standard Python conventions. -For example, you can iterate over the coordinates in a :class:`Point`:: - - >>> pnt = Point(5, 23) - >>> [coord for coord in pnt] - [5.0, 23.0] - -With any geometry object, the :attr:`GEOSGeometry.coords` property -may be used to get the geometry coordinates as a Python tuple:: - - >>> pnt.coords - (5.0, 23.0) - -You can get/set geometry components using standard Python indexing -techniques. However, what is returned depends on the geometry type -of the object. For example, indexing on a :class:`LineString` -returns a coordinate tuple:: - - >>> from django.contrib.gis.geos import LineString - >>> line = LineString((0, 0), (0, 50), (50, 50), (50, 0), (0, 0)) - >>> line[0] - (0.0, 0.0) - >>> line[-2] - (50.0, 0.0) - -Whereas indexing on a :class:`Polygon` will return the ring -(a :class:`LinearRing` object) corresponding to the index:: - - >>> from django.contrib.gis.geos import Polygon - >>> poly = Polygon( ((0.0, 0.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (0.0, 0.0)) ) - >>> poly[0] - <LinearRing object at 0x1044395b0> - >>> poly[0][-2] # second-to-last coordinate of external ring - (50.0, 0.0) - -In addition, coordinates/components of the geometry may added or modified, -just like a Python list:: - - >>> line[0] = (1.0, 1.0) - >>> line.pop() - (0.0, 0.0) - >>> line.append((1.0, 1.0)) - >>> line.coords - ((1.0, 1.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (1.0, 1.0)) - -Geometry Objects -================ - -``GEOSGeometry`` ----------------- - -.. class:: GEOSGeometry(geo_input[, srid=None]) - - :param geo_input: Geometry input value - :type geo_input: string or buffer - :param srid: spatial reference identifier - :type srid: integer - -This is the base class for all GEOS geometry objects. It initializes on the -given ``geo_input`` argument, and then assumes the proper geometry subclass -(e.g., ``GEOSGeometry('POINT(1 1)')`` will create a :class:`Point` object). - -The following input formats, along with their corresponding Python types, -are accepted: - -============= ====================== -Format Input Type -============= ====================== -WKT / EWKT ``str`` or ``unicode`` -HEX / HEXEWKB ``str`` or ``unicode`` -WKB / EWKB ``buffer`` -GeoJSON ``str`` or ``unicode`` -============= ====================== - -Properties -~~~~~~~~~~ - -.. attribute:: GEOSGeometry.coords - -Returns the coordinates of the geometry as a tuple. - -.. attribute:: GEOSGeometry.empty - -Returns whether or not the set of points in the geometry is empty. - -.. attribute:: GEOSGeometry.geom_type - -Returns a string corresponding to the type of geometry. For example:: - - >>> pnt = GEOSGeometry('POINT(5 23)') - >>> pnt.geom_type - 'Point' - -.. attribute:: GEOSGeometry.geom_typeid - -Returns the GEOS geometry type identification number. The following table -shows the value for each geometry type: - -=========================== ======== -Geometry ID -=========================== ======== -:class:`Point` 0 -:class:`LineString` 1 -:class:`LinearRing` 2 -:class:`Polygon` 3 -:class:`MultiPoint` 4 -:class:`MultiLineString` 5 -:class:`MultiPolygon` 6 -:class:`GeometryCollection` 7 -=========================== ======== - -.. attribute:: GEOSGeometry.num_coords - -Returns the number of coordinates in the geometry. - -.. attribute:: GEOSGeometry.num_geom - -Returns the number of geometries in this geometry. In other words, will -return 1 on anything but geometry collections. - -.. attribute:: GEOSGeometry.hasz - -Returns a boolean indicating whether the geometry is three-dimensional. - -.. attribute:: GEOSGeometry.ring - -Returns a boolean indicating whether the geometry is a ``LinearRing``. - -.. attribute:: GEOSGeometry.simple - -Returns a boolean indicating whether the geometry is 'simple'. A geometry -is simple if and only if it does not intersect itself (except at boundary -points). For example, a :class:`LineString` object is not simple if it -intersects itself. Thus, :class:`LinearRing` and :class`Polygon` objects -are always simple because they do cannot intersect themselves, by -definition. - -.. attribute:: GEOSGeometry.valid - -Returns a boolean indicating whether the geometry is valid. - -.. attribute:: GEOSGeometry.srid - -Property that may be used to retrieve or set the SRID associated with the -geometry. For example:: - - >>> pnt = Point(5, 23) - >>> print pnt.srid - None - >>> pnt.srid = 4326 - >>> pnt.srid - 4326 - -Output Properties -~~~~~~~~~~~~~~~~~ - -The properties in this section export the :class:`GEOSGeometry` object into -a different. This output may be in the form of a string, buffer, or even -another object. - -.. attribute:: GEOSGeometry.ewkt - -Returns the "extended" Well-Known Text of the geometry. This representation -is specific to PostGIS and is a super set of the OGC WKT standard. [#fnogc]_ -Essentially the SRID is prepended to the WKT representation, for example -``SRID=4326;POINT(5 23)``. - -.. note:: - - The output from this property does not include the 3dm, 3dz, and 4d - information that PostGIS supports in its EWKT representations. - -.. attribute:: GEOSGeometry.hex - -Returns the WKB of this Geometry in hexadecimal form. Please note -that the SRID and Z values are not included in this representation -because it is not a part of the OGC specification (use the -:attr:`GEOSGeometry.hexewkb` property instead). - -.. attribute:: GEOSGeometry.hexewkb - -.. versionadded:: 1.2 - -Returns the EWKB of this Geometry in hexadecimal form. This is an -extension of the WKB specification that includes SRID and Z values -that are a part of this geometry. - -.. note:: - - GEOS 3.1 is *required* if you want valid 3D HEXEWKB. - -.. attribute:: GEOSGeometry.json - -Returns the GeoJSON representation of the geometry. - -.. note:: - - Requires GDAL. - -.. attribute:: GEOSGeometry.geojson - -Alias for :attr:`GEOSGeometry.json`. - -.. attribute:: GEOSGeometry.kml - -Returns a `KML`__ (Keyhole Markup Language) representation of the -geometry. This should only be used for geometries with an SRID of -4326 (WGS84), but this restriction is not enforced. - -.. attribute:: GEOSGeometry.ogr - -Returns an :class:`~django.contrib.gis.gdal.OGRGeometry` object -correspondg to the GEOS geometry. - -.. note:: - - Requires GDAL. - -.. _wkb: - -.. attribute:: GEOSGeometry.wkb - -Returns the WKB (Well-Known Binary) representation of this Geometry -as a Python buffer. SRID and Z values are not included, use the -:attr:`GEOSGeometry.ewkb` property instead. - -.. _ewkb: - -.. attribute:: GEOSGeometry.ewkb - -.. versionadded:: 1.2 - -Return the EWKB representation of this Geometry as a Python buffer. -This is an extension of the WKB specification that includes any SRID -and Z values that are a part of this geometry. - -.. note:: - - GEOS 3.1 is *required* if you want valid 3D EWKB. - -.. attribute:: GEOSGeometry.wkt - -Returns the Well-Known Text of the geometry (an OGC standard). - -__ http://code.google.com/apis/kml/documentation/ - -Spatial Predicate Methods -~~~~~~~~~~~~~~~~~~~~~~~~~ - -All of the following spatial predicate methods take another -:class:`GEOSGeometry` instance (``other``) as a parameter, and -return a boolean. - -.. method:: GEOSGeometry.contains(other) - -Returns ``True`` if :meth:`GEOSGeometry.within` is ``False``. - -.. method:: GEOSGeometry.crosses(other) - -Returns ``True`` if the DE-9IM intersection matrix for the two Geometries -is ``T*T******`` (for a point and a curve,a point and an area or a line -and an area) ``0********`` (for two curves). - -.. method:: GEOSGeometry.disjoint(other) - -Returns ``True`` if the DE-9IM intersection matrix for the two geometries -is ``FF*FF****``. - -.. method:: GEOSGeometry.equals(other) - -Returns ``True`` if the DE-9IM intersection matrix for the two geometries -is ``T*F**FFF*``. - -.. method:: GEOSGeometry.equals_exact(other, tolerance=0) - -Returns true if the two geometries are exactly equal, up to a -specified tolerance. The ``tolerance`` value should be a floating -point number representing the error tolerance in the comparison, e.g., -``poly1.equals_exact(poly2, 0.001)`` will compare equality to within -one thousandth of a unit. - -.. method:: GEOSGeometry.intersects(other) - -Returns ``True`` if :meth:`GEOSGeometry.disjoint` is ``False``. - -.. method:: GEOSGeometry.overlaps(other) - -Returns true if the DE-9IM intersection matrix for the two geometries -is ``T*T***T**`` (for two points or two surfaces) ``1*T***T**`` -(for two curves). - -.. method:: GEOSGeometry.relate_pattern(other, pattern) - -Returns ``True`` if the elements in the DE-9IM intersection matrix -for this geometry and the other matches the given ``pattern`` -- -a string of nine characters from the alphabet: {``T``, ``F``, ``*``, ``0``}. - -.. method:: GEOSGeometry.touches(other) - -Returns ``True`` if the DE-9IM intersection matrix for the two geometries -is ``FT*******``, ``F**T*****`` or ``F***T****``. - -.. method:: GEOSGeometry.within(other) - -Returns ``True`` if the DE-9IM intersection matrix for the two geometries -is ``T*F**F***``. - -Topological Methods -~~~~~~~~~~~~~~~~~~~ - -.. method:: GEOSGeometry.buffer(width, quadsegs=8) - -Returns a :class:`GEOSGeometry` that represents all points whose distance -from this geometry is less than or equal to the given ``width``. The optional -``quadsegs`` keyword sets the number of segments used to approximate a -quarter circle (defaults is 8). - -.. method:: GEOSGeometry.difference(other) - -Returns a :class:`GEOSGeometry` representing the points making up this -geometry that do not make up other. - -.. method:: GEOSGeometry:intersection(other) - -Returns a :class:`GEOSGeometry` representing the points shared by this -geometry and other. - -.. method:: GEOSGeometry.relate(other) - -Returns the DE-9IM intersection matrix (a string) representing the -topological relationship between this geometry and the other. - -.. method:: GEOSGeometry.simplify(tolerance=0.0, preserve_topology=False) - -Returns a new :class:`GEOSGeometry`, simplified using the Douglas-Peucker -algorithm to the specified tolerance. A higher tolerance value implies -less points in the output. If no tolerance is tolerance provided, -it defaults to 0. - -By default, this function does not preserve topology - e.g., -:class:`Polygon` objects can be split, collapsed into lines or disappear. -:class:`Polygon` holes can be created or disappear, and lines can cross. -By specifying ``preserve_topology=True``, the result will have the same -dimension and number of components as the input, however, this is -significantly slower. - -.. method:: GEOSGeometry.sym_difference(other) - -Returns a :class:`GEOSGeometry` combining the points in this geometry -not in other, and the points in other not in this geometry. - -.. method:: GEOSGeometry.union(other) - -Returns a :class:`GEOSGeometry` representing all the points in this -geometry and the other. - -Topological Properties -~~~~~~~~~~~~~~~~~~~~~~ - -.. attribute:: GEOSGeometry.boundary - -Returns the boundary as a newly allocated Geometry object. - -.. attribute:: GEOSGeometry.centroid - -Returns a :class:`Point` object representing the geometric center of -the geometry. The point is not guaranteed to be on the interior -of the geometry. - -.. attribute:: GEOSGeometry.convex_hull - -Returns the smallest :class:`Polygon` that contains all the points in -the geometry. - -.. attribute:: GEOSGeometry.envelope - -Returns a :class:`Polygon` that represents the bounding envelope of -this geometry. - -.. attribute:: GEOSGeometry.point_on_surface - -Computes and returns a :class:`Point` guaranteed to be on the interior -of this geometry. - -Other Properties & Methods -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attribute:: GEOSGeometry.area - -This property returns the area of the Geometry. - -.. attribute:: GEOSGeometry.extent - -This property returns the extent of this geometry as a 4-tuple, -consisting of (xmin, ymin, xmax, ymax). - -.. method:: GEOSGeometry.clone() - -This method returns a :class:`GEOSGeometry` that is a clone of the original. - -.. method:: GEOSGeometry.distance(geom) - -Returns the distance between the closest points on this geometry and the given -``geom`` (another :class:`GEOSGeometry` object). - -.. note:: - - GEOS distance calculations are linear -- in other words, GEOS does not - perform a spherical calculation even if the SRID specifies a geographic - coordinate system. - -.. attribute:: GEOSGeometry.length - -Returns the length of this geometry (e.g., 0 for a :class:`Point`, -the length of a :class:`LineString`, or the circumference of -a :class:`Polygon`). - -.. attribute:: GEOSGeometry.prepared - -.. versionadded:: 1.1 - -.. note:: - - Support for prepared geometries requires GEOS 3.1. - -Returns a GEOS ``PreparedGeometry`` for the contents of this geometry. -``PreparedGeometry`` objects are optimized for the contains, intersects, -and covers operations. Refer to the :ref:`prepared-geometries` documentation -for more information. - -.. attribute:: GEOSGeometry.srs - -Returns a :class:`~django.contrib.gis.gdal.SpatialReference` object -corresponding to the SRID of the geometry or ``None``. - -.. note:: - - Requires GDAL. - -.. method:: transform(ct, clone=False) - -Transforms the geometry according to the given coordinate transformation paramter -(``ct``), which may be an integer SRID, spatial reference WKT string, -a PROJ.4 string, a :class:`~django.contrib.gis.gdal.SpatialReference` object, or a -:class:`~django.contrib.gis.gdal.CoordTransform` object. By default, the geometry -is transformed in-place and nothing is returned. However if the ``clone`` keyword -is set, then the geometry is not modified and a transformed clone of the geometry -is returned instead. - -.. note:: - - Requires GDAL. - -``Point`` ---------- - -.. class:: Point(x, y, z=None, srid=None) - - ``Point`` objects are instantiated using arguments that represent - the component coordinates of the point or with a single sequence - coordinates. For example, the following are equivalent:: - - >>> pnt = Point(5, 23) - >>> pnt = Point([5, 23]) - -``LineString`` --------------- - -.. class:: LineString(*args, **kwargs) - - ``LineString`` objects are instantiated using arguments that are - either a sequence of coordinates or :class:`Point` objects. - For example, the following are equivalent:: - - >>> ls = LineString((0, 0), (1, 1)) - >>> ls = LineString(Point(0, 0), Point(1, 1)) - - In addition, ``LineString`` objects may also be created by passing - in a single sequence of coordinate or :class:`Point` objects:: - - >>> ls = LineString( ((0, 0), (1, 1)) ) - >>> ls = LineString( [Point(0, 0), Point(1, 1)] ) - -``LinearRing`` --------------- - -.. class:: LinearRing(*args, **kwargs) - - ``LinearRing`` objects are constructed in the exact same way as - :class:`LineString` objects, however the coordinates must be - *closed*, in other words, the first coordinates must be the - same as the last coordinates. For example:: - - >>> ls = LinearRing((0, 0), (0, 1), (1, 1), (0, 0)) - - Notice that ``(0, 0)`` is the first and last coordinate -- if - they were not equal, an error would be raised. - -``Polygon`` ------------ - -.. class:: Polygon(*args, **kwargs) - - ``Polygon`` objects may be instantiated by passing in one or - more parameters that represent the rings of the polygon. The - parameters must either be :class:`LinearRing` instances, or - a sequence that may be used to construct a :class:`LinearRing`:: - - >>> ext_coords = ((0, 0), (0, 1), (1, 1), (1, 0), (0, 0)) - >>> int_coords = ((0.4, 0.4), (0.4, 0.6), (0.6, 0.6), (0.6, 0.4), (0.4, 0.4)) - >>> poly = Polygon(ext_coords, int_coords) - >>> poly = Polygon(LinearRing(ext_coords), LinearRing(int_coords)) - - .. classmethod:: from_bbox(bbox) - - .. versionadded:: 1.1 - - Returns a polygon object from the given bounding-box, a 4-tuple - comprising (xmin, ymin, xmax, ymax). - - .. attribute:: num_interior_rings - - Returns the number of interior rings in this geometry. - -Geometry Collections -==================== - -``MultiPoint`` --------------- - -.. class:: MultiPoint(*args, **kwargs) - - ``MultiPoint`` objects may be instantiated by passing in one - or more :class:`Point` objects as arguments, or a single - sequence of :class:`Point` objects:: - - >>> mp = MultiPoint(Point(0, 0), Point(1, 1)) - >>> mp = MultiPoint( (Point(0, 0), Point(1, 1)) ) - -``MultiLineString`` -------------------- - -.. class:: MultiLineString(*args, **kwargs) - - ``MultiLineString`` objects may be instantiated by passing in one - or more :class:`LineString` objects as arguments, or a single - sequence of :class:`LineString` objects:: - - >>> ls1 = LineString((0, 0), (1, 1)) - >>> ls2 = LineString((2, 2), (3, 3)) - >>> mls = MultiLineString(ls1, ls2) - >>> mls = MultiLineString([ls1, ls2]) - - .. attribute:: merged - - .. versionadded:: 1.1 - - Returns a :class:`LineString` representing the line merge of - all the components in this ``MultiLineString``. - - -``MultiPolygon`` ----------------- - -.. class:: MultiPolygon(*args, **kwargs) - - ``MultiPolygon`` objects may be instantiated by passing one or - more :class:`Polygon` objects as arguments, or a single sequence - of :class:`Polygon` objects:: - - >>> p1 = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) ) - >>> p2 = Polygon( ((1, 1), (1, 2), (2, 2), (1, 1)) ) - >>> mp = MultiPolygon(p1, p2) - >>> mp = MultiPolygon([p1, p2]) - - .. attribute:: cascaded_union - - .. versionadded:: 1.1 - - Returns a :class:`Polygon` that is the union of all of the component - polygons in this collection. The algorithm employed is significantly - more efficient (faster) than trying to union the geometries together - individually. [#fncascadedunion]_ - - .. note:: - - GEOS 3.1 is *required* to peform cascaded unions. - -``GeometryCollection`` ----------------------- - -.. class:: GeometryCollection(*args, **kwargs) - - ``GeometryCollection`` objects may be instantiated by passing in - one or more other :class:`GEOSGeometry` as arguments, or a single - sequence of :class:`GEOSGeometry` objects:: - - >>> poly = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) ) - >>> gc = GeometryCollection(Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly) - >>> gc = GeometryCollection((Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly)) - -.. _prepared-geometries: - -Prepared Geometries -=================== - -.. versionadded: 1.1 - -In order to obtain a prepared geometry, just access the -:attr:`GEOSGeometry.prepared` property. Once you have a -``PreparedGeometry`` instance its spatial predicate methods, listed below, -may be used with other ``GEOSGeometry`` objects. An operation with a prepared -geometry can be orders of magnitude faster -- the more complex the geometry -that is prepared, the larger the speedup in the operation. For more information, -please consult the `GEOS wiki page on prepared geometries <http://trac.osgeo.org/geos/wiki/PreparedGeometry>`_. - -.. note:: - - GEOS 3.1 is *required* in order to use prepared geometries. - -For example:: - - >>> from django.contrib.gis.geos import Point, Polygon - >>> poly = Polygon.from_bbox((0, 0, 5, 5)) - >>> prep_poly = poly.prepared - >>> prep_poly.contains(Point(2.5, 2.5)) - True - -``PreparedGeometry`` --------------------- - -.. class:: PreparedGeometry - - All methods on ``PreparedGeometry`` take an ``other`` argument, which - must be a :class:`GEOSGeometry` instance. - - .. method:: contains(other) - - .. method:: contains_properly(other) - - .. method:: covers(other) - - .. method:: intersects(other) - -Geometry Factories -================== - -.. function:: fromfile(file_h) - - :param file_h: input file that contains spatial data - :type file_h: a Python ``file`` object or a string path to the file - :rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the file - -Example:: - - >>> from django.contrib.gis.geos import fromfile - >>> g = fromfile('/home/bob/geom.wkt') - -.. function:: fromstr(string, [,srid=None]) - - :param string: string that contains spatial data - :type string: string - :param srid: spatial reference identifier - :type srid: integer - :rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the string - -Example:: - - >>> from django.contrib.gis.geos import fromstr - >>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326) - -I/O Objects -=========== - -.. versionadded: 1.1 - -Reader Objects --------------- - -The reader I/O classes simply return a :class:`GEOSGeometry` instance from the -WKB and/or WKT input given to their ``read(geom)`` method. - -.. class:: WKBReader - -Example:: - - >>> from django.contrib.gis.geos import WKBReader - >>> wkb_r = WKBReader() - >>> wkb_r.read('0101000000000000000000F03F000000000000F03F') - <Point object at 0x103a88910> - -.. class:: WKTReader - -Example:: - - >>> from django.contrib.gis.geos import WKTReader - >>> wkt_r = WKTReader() - >>> wkt_r.read('POINT(1 1)') - <Point object at 0x103a88b50> - -Writer Objects --------------- - -All writer objects have a ``write(geom)`` method that returns either the -WKB or WKT of the given geometry. In addition, :class:`WKBWriter` objects -also have properties that may be used to change the byte order, and or -include the SRID and 3D values (in other words, EWKB). - -.. class:: WKBWriter - -``WKBWriter`` provides the most control over its output. By default it -returns OGC-compliant WKB when it's ``write`` method is called. However, -it has properties that allow for the creation of EWKB, a superset of the -WKB standard that includes additional information. - -.. method:: WKBWriter.write(geom) - -Returns the WKB of the given geometry as a Python ``buffer`` object. -Example:: - - >>> from django.contrib.gis.geos import Point, WKBWriter - >>> pnt = Point(1, 1) - >>> wkb_w = WKBWriter() - >>> wkb_w.write(pnt) - <read-only buffer for 0x103a898f0, size -1, offset 0 at 0x103a89930> - -.. method:: WKBWriter.write_hex(geom) - -Returns WKB of the geometry in hexadecimal. Example:: - - >>> from django.contrib.gis.geos import Point, WKBWriter - >>> pnt = Point(1, 1) - >>> wkb_w = WKBWriter() - >>> wkb_w.write_hex(pnt) - '0101000000000000000000F03F000000000000F03F' - -.. attribute:: WKBWriter.byteorder - -This property may be be set to change the byte-order of the geometry -representation. - -=============== ================================================= -Byteorder Value Description -=============== ================================================= -0 Big Endian (e.g., compatible with RISC systems) -1 Little Endian (e.g., compatible with x86 systems) -=============== ================================================= - -Example:: - - >>> from django.contrib.gis.geos import Point, WKBWriter - >>> wkb_w = WKBWriter() - >>> pnt = Point(1, 1) - >>> wkb_w.write_hex(pnt) - '0101000000000000000000F03F000000000000F03F' - >>> wkb_w.byteorder = 0 - '00000000013FF00000000000003FF0000000000000' - -.. attribute:: WKBWriter.outdim - -This property may be set to change the output dimension of the geometry -representation. In other words, if you have a 3D geometry then set to 3 -so that the Z value is included in the WKB. - -============ =========================== -Outdim Value Description -============ =========================== -2 The default, output 2D WKB. -3 Output 3D EWKB. -============ =========================== - -Example:: - - >>> from django.contrib.gis.geos import Point, WKBWriter - >>> wkb_w = WKBWriter() - >>> wkb_w.outdim - 2 - >>> pnt = Point(1, 1, 1) - >>> wkb_w.write_hex(pnt) # By default, no Z value included: - '0101000000000000000000F03F000000000000F03F' - >>> wkb_w.outdim = 3 # Tell writer to include Z values - >>> wkb_w.write_hex(pnt) - '0101000080000000000000F03F000000000000F03F000000000000F03F' - -.. attribute:: WKBWriter.srid - -Set this property with a boolean to indicate whether the SRID of the -geometry should be included with the WKB representation. Example:: - - >>> from django.contrib.gis.geos import Point, WKBWriter - >>> wkb_w = WKBWriter() - >>> pnt = Point(1, 1, srid=4326) - >>> wkb_w.write_hex(pnt) # By default, no SRID included: - '0101000000000000000000F03F000000000000F03F' - >>> wkb_w.srid = True # Tell writer to include SRID - >>> wkb_w.write_hex(pnt) - '0101000020E6100000000000000000F03F000000000000F03F' - -.. class:: WKTWriter - -.. method:: WKTWriter.write(geom) - -Returns the WKT of the given geometry. Example:: - - >>> from django.contrib.gis.geos import Point, WKTWriter - >>> pnt = Point(1, 1) - >>> wkt_w = WKTWriter() - >>> wkt_w.write(pnt) - 'POINT (1.0000000000000000 1.0000000000000000)' - - -.. rubric:: Footnotes -.. [#fnogc] *See* `PostGIS EWKB, EWKT and Canonical Forms <http://postgis.refractions.net/docs/ch04.html#id2591381>`_, PostGIS documentation at Ch. 4.1.2. -.. [#fncascadedunion] For more information, read Paul Ramsey's blog post about `(Much) Faster Unions in PostGIS 1.4 <http://blog.cleverelephant.ca/2009/01/must-faster-unions-in-postgis-14.html>`_ and Martin Davis' blog post on `Fast polygon merging in JTS using Cascaded Union <http://lin-ear-th-inking.blogspot.com/2007/11/fast-polygon-merging-in-jts-using.html>`_. - -Settings -======== - -.. setting:: GEOS_LIBRARY_PATH - -GEOS_LIBRARY_PATH ------------------ - -A string specifying the location of the GEOS C library. Typically, -this setting is only used if the GEOS C library is in a non-standard -location (e.g., ``/home/bob/lib/libgeos_c.so``). - -.. note:: - - The setting must be the *full* path to the **C** shared library; in - other words you want to use ``libgeos_c.so``, not ``libgeos.so``. diff --git a/parts/django/docs/ref/contrib/gis/index.txt b/parts/django/docs/ref/contrib/gis/index.txt deleted file mode 100644 index c4959e0..0000000 --- a/parts/django/docs/ref/contrib/gis/index.txt +++ /dev/null @@ -1,33 +0,0 @@ -.. _ref-contrib-gis: - -========= -GeoDjango -========= - -.. versionadded:: 1.0 - -.. module:: django.contrib.gis - :synopsis: Geographic Information System (GIS) extensions for Django - -GeoDjango intends to be a world-class geographic Web framework. Its goal is to -make it as easy as possible to build GIS Web applications and harness the power -of spatially enabled data. - -.. toctree:: - :maxdepth: 2 - - tutorial - install - model-api - db-api - geoquerysets - measure - geos - gdal - utils - commands - admin - feeds - sitemaps - testing - deployment diff --git a/parts/django/docs/ref/contrib/gis/install.txt b/parts/django/docs/ref/contrib/gis/install.txt deleted file mode 100644 index fa8e34c..0000000 --- a/parts/django/docs/ref/contrib/gis/install.txt +++ /dev/null @@ -1,1190 +0,0 @@ -.. _ref-gis-install: - -====================== -GeoDjango Installation -====================== - -Overview -======== -In general, GeoDjango installation requires: - -1. :ref:`python24` and :ref:`django` -2. :ref:`spatial_database` -3. :ref:`geospatial_libs` - -Details for each of the requirements and installation instructions -are provided in the sections below. In addition, platform-specific -instructions are available for: - -* :ref:`macosx` -* :ref:`ubuntudebian` -* :ref:`windows` - -.. admonition:: Use the Source - - Because GeoDjango takes advantage of the latest in the open source geospatial - software technology, recent versions of the libraries are necessary. - If binary packages aren't available for your platform, - :ref:`installation from source <build_from_source>` - may be required. When compiling the libraries from source, please follow the - directions closely, especially if you're a beginner. - -Requirements -============ - -.. _python24: - -Python 2.4+ ------------ - -Python 2.4 is the minimum version supported by Django, however Python 2.5+ is -recommended because the `ctypes`__ module comes included; otherwise, 2.4 users -will need to `download and install ctypes`__. - -__ http://docs.python.org/lib/module-ctypes.html -__ http://sourceforge.net/projects/ctypes/files/ - -.. _django: - -Django ------- - -Because GeoDjango is included with Django, please refer to Django's -:doc:`installation instructions </intro/install>` for details on how to install. - -.. _spatial_database: - -Spatial Database ----------------- -PostgreSQL (with PostGIS), MySQL, Oracle, and SQLite (with SpatiaLite) are -the spatial databases currently supported. - -.. note:: - - PostGIS is recommended, because it is the most mature and feature-rich - open source spatial database. - -The geospatial libraries required for a GeoDjango installation depends -on the spatial database used. The following lists the library requirements, -supported versions, and any notes for each of the supported database backends: - -================== ============================== ================== ========================================================== -Database Library Requirements Supported Versions Notes -================== ============================== ================== ========================================================== -PostgreSQL GEOS, PROJ.4, PostGIS 8.1+ Requires PostGIS. -MySQL GEOS 5.x Not OGC-compliant; limited functionality. -Oracle GEOS 10.2, 11 XE not supported; not tested with 9. -SQLite GEOS, GDAL, PROJ.4, SpatiaLite 3.6.+ Requires SpatiaLite 2.3+, pysqlite2 2.5+, and Django 1.1. -================== ============================== ================== ========================================================== - -.. _geospatial_libs: - -Geospatial Libraries --------------------- -GeoDjango uses and/or provides interfaces for the the following open source -geospatial libraries: - -======================== ==================================== ================================ ========================== -Program Description Required Supported Versions -======================== ==================================== ================================ ========================== -:ref:`GEOS <ref-geos>` Geometry Engine Open Source Yes 3.2, 3.1, 3.0 -`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 4.7, 4.6, 4.5, 4.4 -:ref:`GDAL <ref-gdal>` Geospatial Data Abstraction Library No (but, required for SQLite) 1.7, 1.6, 1.5, 1.4 -:ref:`GeoIP <ref-geoip>` IP-based geolocation library No 1.4 -`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 1.5, 1.4, 1.3 -`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 2.4, 2.3 -======================== ==================================== ================================ ========================== - -.. admonition:: Install GDAL - - While :ref:`gdalbuild` is technically not required, it is *recommended*. - Some features of GeoDjango (including the :ref:`ref-layermapping` and the geographic - admin) depend on its functionality. - -.. note:: - - The GeoDjango interfaces to GEOS, GDAL, and GeoIP may be used - independently of Django. In other words, no database or settings file - required -- just import them as normal from :mod:`django.contrib.gis`. - -.. _PROJ.4: http://trac.osgeo.org/proj/ -__ http://postgis.refractions.net/ -__ http://www.gaia-gis.it/spatialite/index.html - -.. _build_from_source: - -Building from Source -==================== - -When installing from source on UNIX and GNU/Linux systems, please follow -the installation instructions carefully, and install the libraries in the -given order. If using MySQL or Oracle as the spatial database, only GEOS -is required. - -.. note:: - - On Linux platforms, it may be necessarry to run the ``ldconfig`` - command after installing each library. For example:: - - $ sudo make install - $ sudo ldconfig - -.. note:: - - OS X users are required to install `Apple Developer Tools`_ in order - to compile software from source. This is typically included on your - OS X installation DVDs. - -.. _Apple Developer Tools: http://developer.apple.com/tools/xcode/ - -.. _geosbuild: - -GEOS ----- - -GEOS is a C++ library for performing geometric operations, and is the default -internal geometry representation used by GeoDjango (it's behind the "lazy" -geometries). Specifically, the C API library is called (e.g., ``libgeos_c.so``) -directly from Python using ctypes. - -First, download GEOS 3.2 from the refractions Web site and untar the source -archive:: - - $ wget http://download.osgeo.org/geos/geos-3.2.2.tar.bz2 - $ tar xjf geos-3.2.2.tar.bz2 - -Next, change into the directory where GEOS was unpacked, run the configure -script, compile, and install:: - - $ cd geos-3.2.2 - $ ./configure - $ make - $ sudo make install - $ cd .. - -Troubleshooting -^^^^^^^^^^^^^^^ - -Can't find GEOS Library -~~~~~~~~~~~~~~~~~~~~~~~ - -When GeoDjango can't find GEOS, this error is raised:: - - ImportError: Could not find the GEOS library (tried "geos_c"). Try setting GEOS_LIBRARY_PATH in your settings. - -The most common solution is to properly configure your :ref:`libsettings` *or* set -:ref:`geoslibrarypath` in your settings. - -If using a binary package of GEOS (e.g., on Ubuntu 8.10), you may need to :ref:`binutils`. - -.. _geoslibrarypath: - -``GEOS_LIBRARY_PATH`` -~~~~~~~~~~~~~~~~~~~~~ - -If your GEOS library is in a non-standard location, or you don't want to -modify the system's library path then the :setting:`GEOS_LIBRARY_PATH` setting -may be added to your Django settings file with the full path to the GEOS -C library. For example:: - - GEOS_LIBRARY_PATH = '/home/bob/local/lib/libgeos_c.so' - -.. note:: - - The setting must be the *full* path to the **C** shared library; in - other words you want to use ``libgeos_c.so``, not ``libgeos.so``. - -.. _proj4: - -PROJ.4 ------- - -`PROJ.4`_ is a library for converting geospatial data to different coordinate -reference systems. - -First, download the PROJ.4 source code and datum shifting files [#]_:: - - $ wget http://download.osgeo.org/proj/proj-4.7.0.tar.gz - $ wget http://download.osgeo.org/proj/proj-datumgrid-1.5.zip - -Next, untar the source code archive, and extract the datum shifting files in the -``nad`` subdirectory. This must be done *prior* to configuration:: - - $ tar xzf proj-4.7.0.tar.gz - $ cd proj-4.7.0/nad - $ unzip ../../proj-datumgrid-1.5.zip - $ cd .. - -Finally, configure, make and install PROJ.4:: - - $ ./configure - $ make - $ sudo make install - $ cd .. - -.. _postgis: - -PostGIS -------- - -`PostGIS`__ adds geographic object support to PostgreSQL, turning it -into a spatial database. :ref:`geosbuild` and :ref:`proj4` should be -installed prior to building PostGIS. - -.. note:: - - The `psycopg2`_ module is required for use as the database adaptor - when using GeoDjango with PostGIS. - -.. _psycopg2: http://initd.org/projects/psycopg2 - -First download the source archive, and extract:: - - $ wget http://postgis.refractions.net/download/postgis-1.5.2.tar.gz - $ tar xzf postgis-1.5.2.tar.gz - $ cd postgis-1.5.2 - -Next, configure, make and install PostGIS:: - - $ ./configure - -Finally, make and install:: - - $ make - $ sudo make install - $ cd .. - -.. note:: - - GeoDjango does not automatically create a spatial database. Please - consult the section on :ref:`spatialdb_template` for more information. - -__ http://postgis.refractions.net/ - -.. _gdalbuild: - -GDAL ----- - -`GDAL`__ is an excellent open source geospatial library that has support for -reading most vector and raster spatial data formats. Currently, GeoDjango only -supports :ref:`GDAL's vector data <ref-gdal>` capabilities [#]_. -:ref:`geosbuild` and :ref:`proj4` should be installed prior to building GDAL. - -First download the latest GDAL release version and untar the archive:: - - $ wget http://download.osgeo.org/gdal/gdal-1.7.2.tar.gz - $ tar xzf gdal-1.7.2.tar.gz - $ cd gdal-1.7.2 - -Configure, make and install:: - - $ ./configure - $ make # Go get some coffee, this takes a while. - $ sudo make install - $ cd .. - -.. note:: - - Because GeoDjango has it's own Python interface, the preceding instructions - do not build GDAL's own Python bindings. The bindings may be built by - adding the ``--with-python`` flag when running ``configure``. See - `GDAL/OGR In Python`__ for more information on GDAL's bindings. - -If you have any problems, please see the troubleshooting section below for -suggestions and solutions. - -__ http://trac.osgeo.org/gdal/ -__ http://trac.osgeo.org/gdal/wiki/GdalOgrInPython - -.. _gdaltrouble: - -Troubleshooting -^^^^^^^^^^^^^^^ - -Can't find GDAL Library -~~~~~~~~~~~~~~~~~~~~~~~ - -When GeoDjango can't find the GDAL library, the ``HAS_GDAL`` flag -will be false:: - - >>> from django.contrib.gis import gdal - >>> gdal.HAS_GDAL - False - -The solution is to properly configure your :ref:`libsettings` *or* set -:ref:`gdallibrarypath` in your settings. - -.. _gdallibrarypath: - -``GDAL_LIBRARY_PATH`` -~~~~~~~~~~~~~~~~~~~~~ - -If your GDAL library is in a non-standard location, or you don't want to -modify the system's library path then the :setting:`GDAL_LIBRARY_PATH` -setting may be added to your Django settings file with the full path to -the GDAL library. For example:: - - GDAL_LIBRARY_PATH = '/home/sue/local/lib/libgdal.so' - -.. _gdaldata: - -Can't find GDAL data files (``GDAL_DATA``) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When installed from source, GDAL versions 1.5.1 and below have an autoconf bug -that places data in the wrong location. [#]_ This can lead to error messages -like this:: - - ERROR 4: Unable to open EPSG support file gcs.csv. - ... - OGRException: OGR failure. - -The solution is to set the ``GDAL_DATA`` environment variable to the location of the -GDAL data files before invoking Python (typically ``/usr/local/share``; use -``gdal-config --datadir`` to find out). For example:: - - $ export GDAL_DATA=`gdal-config --datadir` - $ python manage.py shell - -If using Apache, you may need to add this environment variable to your configuration -file:: - - SetEnv GDAL_DATA /usr/local/share - -.. _spatialite: - -SpatiaLite ----------- -.. versionadded:: 1.1 - -.. note:: - - Mac OS X users should follow the instructions in the :ref:`kyngchaos` section, - as it is much easier than building from source. - -`SpatiaLite`__ adds spatial support to SQLite, turning it into a full-featured -spatial database. Because SpatiaLite has special requirements, it typically -requires SQLite and pysqlite2 (the Python SQLite DB-API adaptor) to be built from -source. :ref:`geosbuild` and :ref:`proj4` should be installed prior to building -SpatiaLite. - -After installation is complete, don't forget to read the post-installation -docs on :ref:`create_spatialite_db`. - -__ http://www.gaia-gis.it/spatialite/index.html - -.. _sqlite: - -SQLite -^^^^^^ - -Typically, SQLite packages are not compiled to include the `R*Tree module`__ -- -thus it must be compiled from source. First download the latest amalgamation -source archive from the `SQLite download page`__, and extract:: - - $ wget http://sqlite.org/sqlite-amalgamation-3.6.23.1.tar.gz - $ tar xzf sqlite-amalgamation-3.6.23.1.tar.gz - $ cd sqlite-3.6.23.1 - -Next, run the ``configure`` script -- however the ``CFLAGS`` environment variable -needs to be customized so that SQLite knows to build the R*Tree module:: - - $ CFLAGS="-DSQLITE_ENABLE_RTREE=1" ./configure - $ make - $ sudo make install - $ cd .. - -.. note:: - - If using Ubuntu, installing a newer SQLite from source can be very difficult - because it links to the existing ``libsqlite3.so`` in ``/usr/lib`` which - many other packages depend on. Unfortunately, the best solution at this time - is to overwrite the existing library by adding ``--prefix=/usr`` to the - ``configure`` command. - -__ http://www.sqlite.org/rtree.html -__ http://www.sqlite.org/download.html - -.. _spatialitebuild : - -SpatiaLite Library (``libspatialite``) and Tools (``spatialite``) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After SQLite has been built with the R*Tree module enabled, get the latest -SpatiaLite library source and tools bundle from the `download page`__:: - - $ wget http://www.gaia-gis.it/spatialite/libspatialite-amalgamation-2.3.1.tar.gz - $ wget http://www.gaia-gis.it/spatialite/spatialite-tools-2.3.1.tar.gz - $ tar xzf libspatialite-amalgamation-2.3.1.tar.gz - $ tar xzf spatialite-tools-2.3.1.tar.gz - -Prior to attempting to build, please read the important notes below to see if -customization of the ``configure`` command is necessary. If not, then run the -``configure`` script, make, and install for the SpatiaLite library:: - - $ cd libspatialite-amalgamation-2.3.1 - $ ./configure # May need to modified, see notes below. - $ make - $ sudo make install - $ cd .. - -Finally, do the same for the SpatiaLite tools:: - - $ cd spatialite-tools-2.3.1 - $ ./configure # May need to modified, see notes below. - $ make - $ sudo make install - $ cd .. - -.. note:: - - If you've installed GEOS and PROJ.4 from binary packages, you will have to specify - their paths when running the ``configure`` scripts for *both* the library and the - tools (the configure scripts look, by default, in ``/usr/local``). For example, - on Debian/Ubuntu distributions that have GEOS and PROJ.4 packages, the command would be:: - - $ ./configure --with-proj-include=/usr/include --with-proj-lib=/usr/lib --with-geos-include=/usr/include --with-geos-lib=/usr/lib - -.. note:: - - For Mac OS X users building from source, the SpatiaLite library *and* tools - need to have their ``target`` configured:: - - $ ./configure --target=macosx - -__ http://www.gaia-gis.it/spatialite/sources.html - -.. _pysqlite2: - -pysqlite2 -^^^^^^^^^ - -Because SpatiaLite must be loaded as an external extension, it requires the -``enable_load_extension`` method, which is only available in versions 2.5+. -Thus, download pysqlite2 2.6, and untar:: - - $ wget http://pysqlite.googlecode.com/files/pysqlite-2.6.0.tar.gz - $ tar xzf pysqlite-2.6.0.tar.gz - $ cd pysqlite-2.6.0 - -Next, use a text editor (e.g., ``emacs`` or ``vi``) to edit the ``setup.cfg`` file -to look like the following:: - - [build_ext] - #define= - include_dirs=/usr/local/include - library_dirs=/usr/local/lib - libraries=sqlite3 - #define=SQLITE_OMIT_LOAD_EXTENSION - -.. note:: - - The important thing here is to make sure you comment out the the - ``define=SQLITE_OMIT_LOAD_EXTENSION`` flag and that the ``include_dirs`` - and ``library_dirs`` settings are uncommented and set to the appropriate - path if the SQLite header files and libraries are not in ``/usr/include`` - and ``/usr/lib``, respectively. - -After modifying ``setup.cfg`` appropriately, then run the ``setup.py`` script -to build and install:: - - $ sudo python setup.py install - -Post-Installation -================= - -.. _spatialdb_template: - -Creating a Spatial Database Template for PostGIS ------------------------------------------------- - -Creating a spatial database with PostGIS is different than normal because -additional SQL must be loaded to enable spatial functionality. Because of -the steps in this process, it's better to create a database template that -can be reused later. - -First, you need to be able to execute the commands as a privileged database -user. For example, you can use the following to become the ``postgres`` user:: - - $ sudo su - postgres - -.. note:: - - The location *and* name of the PostGIS SQL files (e.g., from - ``POSTGIS_SQL_PATH`` below) depends on the version of PostGIS. - PostGIS versions 1.3 and below use ``<pg_sharedir>/contrib/lwpostgis.sql``; - whereas version 1.4 uses ``<sharedir>/contrib/postgis.sql`` and - version 1.5 uses ``<sharedir>/contrib/postgis-1.5/postgis.sql``. - - The example below assumes PostGIS 1.5, thus you may need to modify - ``POSTGIS_SQL_PATH`` and the name of the SQL file for the specific - version of PostGIS you are using. - -Once you're a database super user, then you may execute the following commands -to create a PostGIS spatial database template. If running Ubuntu :ref:`ibex` -or Debian :ref:`lenny`, please refer to their specific documentation for -modifications to these commands:: - - $ POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-1.5 - # Creating the template spatial database. - $ createdb -E UTF8 template_postgis - $ createlang -d template_postgis plpgsql # Adding PLPGSQL language support. - # Allows non-superusers the ability to create from this template - $ psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" - # Loading the PostGIS SQL routines - $ psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql - $ psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql - # Enabling users to alter spatial tables. - $ psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" - $ psql -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;" - $ psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;" - -These commands may be placed in a shell script for later use; for convenience -the following scripts are available: - -=============== ========================================== -PostGIS Version Shell Script -=============== ========================================== -1.3 `create_template_postgis-1.3.sh`_ -1.4 `create_template_postgis-1.4.sh`_ -1.5 `create_template_postgis-1.5.sh`_ -=============== ========================================== - -Afterwards, you may create a spatial database by simply specifying -``template_postgis`` as the template to use (via the ``-T`` option):: - - $ createdb -T template_postgis <db name> - -.. note:: - - While the ``createdb`` command does not require database super-user privileges, - it must be executed by a database user that has permissions to create databases. - You can create such a user with the following command:: - - $ createuser --createdb <user> - -.. _create_template_postgis-1.3.sh: http://geodjango.org/docs/create_template_postgis-1.3.sh -.. _create_template_postgis-1.4.sh: http://geodjango.org/docs/create_template_postgis-1.4.sh -.. _create_template_postgis-1.5.sh: http://geodjango.org/docs/create_template_postgis-1.5.sh -.. _create_template_postgis-debian.sh: http://geodjango.org/docs/create_template_postgis-debian.sh - -.. _create_spatialite_db: - -Creating a Spatial Database for SpatiaLite -------------------------------------------- - -After the SpatiaLite library and tools have been installed, it is now possible -to create spatial database for use with GeoDjango. In order to do this, download -the spatial database initialization SQL from the `SpatiaLite Resources`__ page:: - - $ wget http://www.gaia-gis.it/spatialite/init_spatialite-2.3.sql.gz - $ gunzip init_spatialite-2.3.sql.gz - -Now, the ``spatialite`` command can be used to initialize a spatial database:: - - $ spatialite geodjango.db < init_spatialite-2.3.sql - -.. note:: - - The parameter ``geodjango.db`` is the *filename* of the SQLite database - you want to use. Use the same in the :setting:`DATABASE_NAME` - inside your ``settings.py``. - - -__ http://www.gaia-gis.it/spatialite/resources.html - - -Add ``django.contrib.gis`` to ``INSTALLED_APPS`` ------------------------------------------------- - -Like other Django contrib applications, you will *only* need to add -:mod:`django.contrib.gis` to :setting:`INSTALLED_APPS` in your settings. -This is the so that ``gis`` templates can be located -- if not done, then -features such as the geographic admin or KML sitemaps will not function properly. - -.. _addgoogleprojection: - -Add Google Projection to ``spatial_ref_sys`` table --------------------------------------------------- - -.. versionchanged:: 1.2 - -.. note:: - - If running PostGIS 1.4 and above, the entry is already included in the - default ``spatial_ref_sys`` table. You can skip this step. - -In order to conduct database transformations to the so-called "Google" -projection (a spherical mercator projection used by Google Maps), -an entry must be added to your spatial database's ``spatial_ref_sys`` table. -Invoke the Django shell from your project and execute the -``add_srs_entry`` function:: - - $ python manage shell - >>> from django.contrib.gis.utils import add_srs_entry - >>> add_srs_entry(900913) - -.. note:: - - In Django 1.1 the name of this function is ``add_postgis_srs``. - -This adds an entry for the 900913 SRID to the ``spatial_ref_sys`` (or equivalent) -table, making it possible for the spatial database to transform coordinates in -this projection. You only need to execute this command *once* per spatial database. - -Troubleshooting -=============== - -If you can't find the solution to your problem here then participate in the -community! You can: - -* Join the ``#geodjango`` IRC channel on FreeNode (may be accessed on the - Web via `Mibbit`__). Please be patient and polite -- while you may not - get an immediate response, someone will attempt to answer your question - as soon as they see it. -* Ask your question on the `GeoDjango`__ mailing list. -* File a ticket on the `Django trac`__ if you think there's a bug. Make - sure to provide a complete description of the problem, versions used, - and specify the component as "GIS". - -__ http://www.mibbit.com/?server=irc.freenode.net&channel=%23geodjango -__ http://groups.google.com/group/geodjango -__ http://code.djangoproject.com/simpleticket - -.. _libsettings: - -Library Environment Settings ----------------------------- - -By far, the most common problem when installing GeoDjango is that the -external shared libraries (e.g., for GEOS and GDAL) cannot be located. [#]_ -Typically, the cause of this problem is that the operating system isn't aware -of the directory where the libraries built from source were installed. - -In general, the library path may be set on a per-user basis by setting -an environment variable, or by configuring the library path for the entire -system. - -``LD_LIBRARY_PATH`` environment variable -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -A user may set this environment variable to customize the library paths -they want to use. The typical library directory for software -built from source is ``/usr/local/lib``. Thus, ``/usr/local/lib`` needs -to be included in the ``LD_LIBRARY_PATH`` variable. For example, the user -could place the following in their bash profile:: - - export LD_LIBRARY_PATH=/usr/local/lib - -Setting System Library Path -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -On GNU/Linux systems, there is typically a file in ``/etc/ld.so.conf``, which may include -additional paths from files in another directory, such as ``/etc/ld.so.conf.d``. -As the root user, add the custom library path (like ``/usr/local/lib``) on a -new line in ``ld.so.conf``. This is *one* example of how to do so:: - - $ sudo echo /usr/local/lib >> /etc/ld.so.conf - $ sudo ldconfig - -For OpenSolaris users, the system library path may be modified using the -``crle`` utility. Run ``crle`` with no options to see the current configuration -and use ``crle -l`` to set with the new library path. Be *very* careful when -modifying the system library path:: - - # crle -l $OLD_PATH:/usr/local/lib - -.. _binutils: - -Install ``binutils`` -^^^^^^^^^^^^^^^^^^^^ - -GeoDjango uses the ``find_library`` function (from the ``ctypes.util`` Python -module) to discover libraries. The ``find_library`` routine uses a program -called ``objdump`` (part of the ``binutils`` package) to verify a shared -library on GNU/Linux systems. Thus, if ``binutils`` is not installed on your -Linux system then Python's ctypes may not be able to find your library even if -your library path is set correctly and geospatial libraries were built perfectly. - -The ``binutils`` package may be installed on Debian and Ubuntu systems using the -following command:: - - $ sudo apt-get install binutils - -Similarly, on Red Hat and CentOS systems:: - - $ sudo yum install binutils - -Platform Specific Instructions -============================== - -.. _macosx: - -Mac OS X --------- - -Because of the variety of packaging systems available for OS X, users have -several different options for installing GeoDjango. These options are: - -* :ref:`kyngchaos` -* :ref:`fink` -* :ref:`macports` -* :ref:`build_from_source` - -.. note:: - - Currently, the easiest and recommended approach for installing GeoDjango - on OS X is to use the KyngChaos packages. - -This section also includes instructions for installing an upgraded version -of :ref:`macosx_python` from packages provided by the Python Software -Foundation, however, this is not required. - -.. _macosx_python: - -Python -^^^^^^ - -Although OS X comes with Python installed, users can use framework -installers (`2.5`__ and `2.6`__ are available) provided by -the Python Software Foundation. An advantage to using the installer is -that OS X's Python will remain "pristine" for internal operating system -use. - -__ http://python.org/ftp/python/2.5.4/python-2.5.4-macosx.dmg -__ http://python.org/ftp/python/2.6.2/python-2.6.2-macosx2009-04-16.dmg - -.. note:: - - You will need to modify the ``PATH`` environment variable in your - ``.profile`` file so that the new version of Python is used when - ``python`` is entered at the command-line:: - - export PATH=/Library/Frameworks/Python.framework/Versions/Current/bin:$PATH - -.. _kyngchaos: - -KyngChaos Packages -^^^^^^^^^^^^^^^^^^ - -William Kyngesburye provides a number of `geospatial library binary packages`__ -that make it simple to get GeoDjango installed on OS X without compiling -them from source. However, the `Apple Developer Tools`_ are still necessary -for compiling the Python database adapters :ref:`psycopg2_kyngchaos` (for PostGIS) -and :ref:`pysqlite2_kyngchaos` (for SpatiaLite). - -.. note:: - - SpatiaLite users should consult the :ref:`spatialite_kyngchaos` section - after installing the packages for additional instructions. - -Download the framework packages for: - -* UnixImageIO -* PROJ -* GEOS -* SQLite3 (includes the SpatiaLite library) -* GDAL - -Install the packages in the order they are listed above, as the GDAL and SQLite -packages require the packages listed before them. Afterwards, you can also -install the KyngChaos binary packages for `PostgreSQL and PostGIS`__. - -After installing the binary packages, you'll want to add the following to -your ``.profile`` to be able to run the package programs from the command-line:: - - export PATH=/Library/Frameworks/UnixImageIO.framework/Programs:$PATH - export PATH=/Library/Frameworks/PROJ.framework/Programs:$PATH - export PATH=/Library/Frameworks/GEOS.framework/Programs:$PATH - export PATH=/Library/Frameworks/SQLite3.framework/Programs:$PATH - export PATH=/Library/Frameworks/GDAL.framework/Programs:$PATH - export PATH=/usr/local/pgsql/bin:$PATH - -__ http://www.kyngchaos.com/software/frameworks -__ http://www.kyngchaos.com/software/postgres - -.. note:: - - Use of these binaries requires Django 1.0.3 and above. If you are - using a previous version of Django (like 1.0.2), then you will have - to add the the following in your settings:: - - GEOS_LIBRARY_PATH='/Library/Frameworks/GEOS.framework/GEOS' - GDAL_LIBRARY_PATH='/Library/Frameworks/GDAL.framework/GDAL' - -.. _psycopg2_kyngchaos: - -psycopg2 -~~~~~~~~ - -After you've installed the KyngChaos binaries and modified your ``PATH``, as -described above, ``psycopg2`` may be installed using the following command:: - - $ sudo python easy_install psycopg2 - -.. note:: - - To use ``easy_install`` you'll need to install Python's `setuptools`_. - -.. _setuptools: http://pypi.python.org/pypi/setuptools - -.. _pysqlite2_kyngchaos: - -pysqlite2 -~~~~~~~~~ - -Follow the :ref:`pysqlite2` source install instructions, however, -when editing the ``setup.cfg`` use the following instead:: - - [build_ext] - #define= - include_dirs=/Library/Frameworks/SQLite3.framework/unix/include - library_dirs=/Library/Frameworks/SQLite3.framework/unix/lib - libraries=sqlite3 - #define=SQLITE_OMIT_LOAD_EXTENSION - -.. _spatialite_kyngchaos: - -SpatiaLite -~~~~~~~~~~ - -When :ref:`create_spatialite_db`, the ``spatialite`` program is required. -However, instead of attempting to compile the SpatiaLite tools from source, -download the `SpatiaLite Binaries`__ for OS X, and install ``spatialite`` in a -location available in your ``PATH``. For example:: - - $ curl -O http://www.gaia-gis.it/spatialite/spatialite-tools-osx-x86-2.3.1.tar.gz - $ tar xzf spatialite-tools-osx-x86-2.3.1.tar.gz - $ cd spatialite-tools-osx-x86-2.3.1/bin - $ sudo cp spatialite /Library/Frameworks/SQLite3.framework/Programs - -Finally, for GeoDjango to be able to find the KyngChaos SpatiaLite library, -add the following to your ``settings.py``:: - - SPATIALITE_LIBRARY_PATH='/Library/Frameworks/SQLite3.framework/SQLite3' - -__ http://www.gaia-gis.it/spatialite/binaries.html - -.. _fink: - -Fink -^^^^ - -`Kurt Schwehr`__ has been gracious enough to create GeoDjango packages for users -of the `Fink`__ package system. The following packages are available, depending -on which version of Python you want to use: - -* ``django-gis-py26`` -* ``django-gis-py25`` -* ``django-gis-py24`` - -__ http://schwehr.org/blog/ -__ http://www.finkproject.org/ - -.. _macports: - -MacPorts -^^^^^^^^ - -`MacPorts`__ may be used to install GeoDjango prerequisites on Macintosh -computers running OS X. Because MacPorts still builds the software from source, -the `Apple Developer Tools`_ are required. - -Summary:: - - $ sudo port install postgresql83-server - $ sudo port install geos - $ sudo port install proj - $ sudo port install postgis - $ sudo port install gdal - $ sudo port install libgeoip - -.. note:: - - You will also have to modify the ``PATH`` in your ``.profile`` so - that the MacPorts programs are accessible from the command-line:: - - export PATH=/opt/local/bin:/opt/local/lib/postgresql83/bin - - In addition, add the ``FALLBACK_DYLD_LIBRARY_PATH`` setting so that - the libraries can be found by Python:: - - export FALLBACK_DYLD_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql83 - -__ http://www.macports.org/ - -.. _ubuntudebian: - -Ubuntu & Debian GNU/Linux -------------------------- - -.. _ubuntu: - -Ubuntu -^^^^^^ - -.. _heron: - -8.04 and lower -~~~~~~~~~~~~~~ - -The 8.04 (and lower) versions of Ubuntu use GEOS v2.2.3 in their binary packages, -which is incompatible with GeoDjango. Thus, do *not* use the binary packages -for GEOS or PostGIS and build some prerequisites from source, per the instructions -in this document; however, it is okay to use the PostgreSQL binary packages. - -For more details, please see the Debian instructions for :ref:`etch` below. - -.. _ibex: - -8.10 -~~~~ - -Use the synaptic package manager to install the following packages:: - - $ sudo apt-get install binutils libgdal1-1.5.0 postgresql-8.3-postgis postgresql-server-dev-8.3 python-psycopg2 python-setuptools - -Afterwards, you may install Django with Python's ``easy_install`` script (the -Ubuntu package ``python-django`` uses an older version missing several -important bug fixes for GeoDjango):: - - $ sudo easy_install Django - -That's it! For the curious, the required binary prerequisites packages are: - -* ``binutils``: for ctypes to find libraries -* ``postgresql-8.3`` -* ``postgresql-server-dev-8.3``: for ``pg_config`` -* ``postgresql-8.3-postgis``: for PostGIS 1.3.3 -* ``libgeos-3.0.0``, and ``libgeos-c1``: for GEOS 3.0.0 -* ``libgdal1-1.5.0``: for GDAL 1.5.0 library -* ``proj``: for PROJ 4.6.0 -- but no datum shifting files, see note below -* ``python-psycopg2`` -* ``python-setuptools``: for ``easy_install`` - -Optional packages to consider: - -* ``libgeoip1``: for :ref:`GeoIP <ref-geoip>` support -* ``gdal-bin``: for GDAL command line programs like ``ogr2ogr`` -* ``python-gdal`` for GDAL's own Python bindings -- includes interfaces for raster manipulation - -.. note:: - - The Ubuntu ``proj`` package does not come with the datum shifting files - installed, which will cause problems with the geographic admin because - the ``null`` datum grid is not available for transforming geometries to the - spherical mercator projection. A solution is to download the - datum-shifting files, create the grid file, and install it yourself:: - - $ wget http://download.osgeo.org/proj/proj-datumgrid-1.4.tar.gz - $ mkdir nad - $ cd nad - $ tar xzf ../proj-datumgrid-1.4.tar.gz - $ nad2bin null < null.lla - $ sudo cp null /usr/share/proj - - Otherwise, the Ubuntu ``proj`` package is fine for general use as long as you - do not plan on doing any database transformation of geometries to the - Google projection (900913). - -.. note:: - - The PostGIS SQL files are not placed the PostgreSQL share directory in the - Ubuntu packages. Use the `create_template_postgis-debian.sh`_ script - instead when :ref:`spatialdb_template`. - -.. _debian: - -Debian ------- - -.. _etch: - -4.0 (Etch) -^^^^^^^^^^ -The situation here is the same as that of Ubuntu :ref:`heron` -- in other words, -some packages must be built from source to work properly with GeoDjango. - -Binary Packages -~~~~~~~~~~~~~~~ -The following command will install acceptable binary packages, as well as -the development tools necessary to build the rest of the requirements:: - - $ sudo apt-get install binutils bzip2 gcc g++ flex make postgresql-8.1 postgresql-server-dev-8.1 python-ctypes python-psycopg2 python-setuptools - -Required package information: - -* ``binutils``: for ctypes to find libraries -* ``bzip2``: for decompressing the source packages -* ``gcc``, ``g++``, ``make``: GNU developer tools used to compile the libraries -* ``flex``: required to build PostGIS -* ``postgresql-8.1`` -* ``postgresql-server-dev-8.1``: for ``pg_config`` -* ``python-ctypes``: Python 2.4 needs to have ctypes installed separately -* ``python-psycopg2`` -* ``python-setuptools``: for ``easy_install`` - -Optional packages: - -* ``libgeoip``: for :ref:`GeoIP <ref-geoip>` support - -Source Packages -~~~~~~~~~~~~~~~ -You will still have to install :ref:`geosbuild`, :ref:`proj4`, -:ref:`postgis`, and :ref:`gdalbuild` from source. Please follow the -directions carefully. - -.. _lenny: - -5.0 (Lenny) -^^^^^^^^^^^ -This version is comparable to Ubuntu :ref:`ibex`, so the command -is very similar:: - - $ sudo apt-get install binutils libgdal1-1.5.0 postgresql-8.3 postgresql-8.3-postgis postgresql-server-dev-8.3 python-psycopg2 python-setuptools - -This assumes that you are using PostgreSQL version 8.3. Else, replace ``8.3`` -in the above command with the appropriate PostgreSQL version. - -.. note:: - - Please read the note in the Ubuntu :ref:`ibex` install documentation - about the ``proj`` package -- it also applies here because the package does - not include the datum shifting files. - -.. _post_install: - -Post-installation Notes -~~~~~~~~~~~~~~~~~~~~~~~ - -If the PostgreSQL database cluster was not initiated after installing, then it -can be created (and started) with the following command:: - - $ sudo pg_createcluster --start 8.3 main - -Afterwards, the ``/etc/init.d/postgresql-8.3`` script should be used to manage -the starting and stopping of PostgreSQL. - -In addition, the SQL files for PostGIS are placed in a different location on -Debian 5.0 . Thus when :ref:`spatialdb_template` either: - -* Create a symbolic link to these files:: - - $ sudo ln -s /usr/share/postgresql-8.3-postgis/{lwpostgis,spatial_ref_sys}.sql /usr/share/postgresql/8.3 - - If not running PostgreSQL 8.3, then replace ``8.3`` in the command above with the correct version. - -* Or use the `create_template_postgis-debian.sh`_ to create the spatial database. - -.. _windows: - -Windows XP ----------- - -Python -^^^^^^ - -First, download the `Python 2.6 installer`__ from the Python Web site. Next, -execute the installer and use defaults, e.g., keep 'Install for all users' -checked and the installation path set as ``C:\Python26``. - -.. note:: - - You may already have a version of Python installed in ``C:\python`` as ESRI - products sometimes install a copy there. *You should still install a - fresh version of Python 2.6.* - -__ http://python.org/ftp/python/2.6.2/python-2.6.2.msi - -PostgreSQL -^^^^^^^^^^ - -First, select a mirror and download the latest `PostgreSQL 8.3 installer`__ from -the EnterpriseDB Web site. - -.. note:: - - PostgreSQL 8.3 is required because PostGIS is not available yet for 8.4. - -After downloading, simply click on the installer, follow the -on-screen directions, and keep the default options (e.g., keep the installation -path as ``C:\Program Files\PostgreSQL\8.3``). - -.. note:: - - This PostgreSQL installation process will create both a new windows user to be the - 'postgres service account' and a special 'postgres superuser' to own the database - cluster. You will be prompted to set a password for both users (make sure to write - them down!). To see basic details on the 'service user' account right click on - 'My Computer' and select 'Manage' or go to: Control Panel -> Administrative Tools -> - Computer Management -> System Tools -> Local Users and Groups. - -If installed successfully, the PostgreSQL server will run in the background each time -the system as started as a Windows service. When finished, the installer should launch -the Application Stack Builder (ASB) -- use this to install PostGIS, see instructions -below for more details. A 'PostgreSQL 8.3' start menu group should be created that -contains shortcuts for the ASB and 'Command Prompt', which launches a terminal window -in the PostgreSQL directory. - -__ http://www.enterprisedb.com/products/pgdownload.do#windows - -PostGIS -^^^^^^^ - -From the Application Stack Builder (Programs -> PostgreSQL 8.3), select -'PostgreSQL Database Server 8.3 on port 5432' from the drop down menu. Next, -select 'PostGIS 1.3.6 for PostgreSQL 8.3' from the 'Spatial Extensions' tree -in the list. Select only the default options during install (do not uncheck -the option to create a default PostGIS database). - -.. note:: - - You will be prompted to enter your 'postgres superuser' password in the - 'Database Connection Information' dialog. - -psycopg2 -^^^^^^^^ - -The ``psycopg2`` Python module provides the interface between Python and the -PostgreSQL database. Download the `Windows installer`__ (v2.0.10) and run -using the default settings. [#]_ - -__ http://www.stickpeople.com/projects/python/win-psycopg/psycopg2-2.0.10.win32-py2.6-pg8.3.7-release.exe - -GeoDjango Installer -^^^^^^^^^^^^^^^^^^^ - -Download the `GeoDjango Installer`__; this was created [#]_ to simplify the rest -of the process for installing GeoDjango on Windows platforms. The installer -automatically installs Django 1.1, GDAL 1.6.0, PROJ 4.6.1 (including datum grid -files), and configures the necessary environment variables. - -Once the installer has completed, log out and log back in so that the -modifications to the system environment variables take effect, and you -should be good to go. - -.. note:: - - The installer modifies the system ``Path`` environment variable to - include ``C:\Program Files\PostgreSQL\8.3\bin`` and - ``C:\Program Files\GeoDjango\bin``. This is required so that Python - may find the GEOS DLL provided by PostGIS and the GDAL DLL provided - by the installer. The installer also sets the ``GDAL_DATA`` and - ``PROJ_LIB`` environment variables. - -__ http://geodjango.org/windows/GeoDjango_Installer.exe - -.. rubric:: Footnotes -.. [#] The datum shifting files are needed for converting data to and from certain projections. - For example, the PROJ.4 string for the `Google projection (900913) <http://spatialreference.org/ref/epsg/900913/proj4>`_ - requires the ``null`` grid file only included in the extra datum shifting files. - It is easier to install the shifting files now, then to have debug a problem caused by their absence later. -.. [#] Specifically, GeoDjango provides support for the `OGR <http://gdal.org/ogr>`_ library, a component of GDAL. -.. [#] See `GDAL ticket #2382 <http://trac.osgeo.org/gdal/ticket/2382>`_. -.. [#] GeoDjango uses the `find_library <http://docs.python.org/library/ctypes.html#finding-shared-libraries>`_ - routine from ``ctypes.util`` to locate shared libraries. -.. [#] The ``psycopg2`` Windows installers are packaged and maintained by - `Jason Erickson <http://www.stickpeople.com/projects/python/win-psycopg/>`_. -.. [#] The source code for the installer is available in the `nsis_installer <http://geodjango.org/hg/nsis_installer/>`_ - GeoDjango mercurial repository. diff --git a/parts/django/docs/ref/contrib/gis/layermapping.txt b/parts/django/docs/ref/contrib/gis/layermapping.txt deleted file mode 100644 index 0b09e17..0000000 --- a/parts/django/docs/ref/contrib/gis/layermapping.txt +++ /dev/null @@ -1,220 +0,0 @@ -.. _ref-layermapping: - -==================================== -``LayerMapping`` data import utility -==================================== - -.. module:: django.contrib.gis.utils.layermapping - :synopsis: Spatial data import utility for GeoDjango models. - -.. currentmodule:: django.contrib.gis.utils - -The :class:`LayerMapping` class provides a way to map the contents of -vector spatial data files (e.g. shapefiles) intoto GeoDjango models. - -This utility grew out of the author's personal needs to eliminate -the code repetition that went into pulling geometries and fields out of -a vector layer, converting to another coordinate system (e.g. WGS84), and -then inserting into a GeoDjango model. - -.. note:: - - Use of :class:`LayerMapping` requires GDAL. - -.. warning :: - - GIS data sources, like shapefiles, may be very large. If you find - that :class:`LayerMapping` is using too much memory, set - :setting:`DEBUG` to ``False`` in your settings. When :setting:`DEBUG` - is set to ``True``, Django :ref:`automatically logs <faq-see-raw-sql-queries>` - *every* SQL query -- thus, when SQL statements contain geometries, it is - easy to consume more memory than is typical. - -Example -======= - -1. You need a GDAL-supported data source, like a shapefile (here we're using - a simple polygon shapefile, ``test_poly.shp``, with three features):: - - >>> from django.contrib.gis.gdal import DataSource - >>> ds = DataSource('test_poly.shp') - >>> layer = ds[0] - >>> print layer.fields # Exploring the fields in the layer, we only want the 'str' field. - ['float', 'int', 'str'] - >>> print len(layer) # getting the number of features in the layer (should be 3) - 3 - >>> print layer.geom_type # Should be 'Polygon' - Polygon - >>> print layer.srs # WGS84 in WKT - GEOGCS["GCS_WGS_1984", - DATUM["WGS_1984", - SPHEROID["WGS_1984",6378137,298.257223563]], - PRIMEM["Greenwich",0], - UNIT["Degree",0.017453292519943295]] - -2. Now we define our corresponding Django model (make sure to use ``syncdb``):: - - from django.contrib.gis.db import models - - class TestGeo(models.Model): - name = models.CharField(max_length=25) # corresponds to the 'str' field - poly = models.PolygonField(srid=4269) # we want our model in a different SRID - objects = models.GeoManager() - def __unicode__(self): - return 'Name: %s' % self.name - -3. Use :class:`LayerMapping` to extract all the features and place them in the - database:: - - >>> from django.contrib.gis.utils import LayerMapping - >>> from geoapp.models import TestGeo - >>> mapping = {'name' : 'str', # The 'name' model field maps to the 'str' layer field. - 'poly' : 'POLYGON', # For geometry fields use OGC name. - } # The mapping is a dictionary - >>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping) - >>> lm.save(verbose=True) # Save the layermap, imports the data. - Saved: Name: 1 - Saved: Name: 2 - Saved: Name: 3 - -Here, :class:`LayerMapping` just transformed the three geometries from the -shapefile in their original spatial reference system (WGS84) to the spatial -reference system of the GeoDjango model (NAD83). If no spatial reference -system is defined for the layer, use the ``source_srs`` keyword with a -:class:`~django.contrib.gis.gdal.SpatialReference` object to specify one. - -``LayerMapping`` API -==================== - -.. class:: LayerMapping(model, data_source, mapping[, layer=0, source_srs=None, encoding=None, transaction_mode='commit_on_success', transform=True, unique=True, using='default']) - -The following are the arguments and keywords that may be used during -instantiation of ``LayerMapping`` objects. - -================= ========================================================= -Argument Description -================= ========================================================= -``model`` The geographic model, *not* an instance. - -``data_source`` The path to the OGR-supported data source file - (e.g., a shapefile). Also accepts - :class:`django.contrib.gis.gdal.DataSource` instances. - -``mapping`` A dictionary: keys are strings corresponding to - the model field, and values correspond to - string field names for the OGR feature, or if the - model field is a geographic then it should - correspond to the OGR geometry type, - e.g., ``'POINT'``, ``'LINESTRING'``, ``'POLYGON'``. -================= ========================================================= - -===================== ===================================================== -Keyword Arguments -===================== ===================================================== -``layer`` The index of the layer to use from the Data Source - (defaults to 0) - -``source_srs`` Use this to specify the source SRS manually (for - example, some shapefiles don't come with a '.prj' - file). An integer SRID, WKT or PROJ.4 strings, and - :class:`django.contrib.gis.gdal.SpatialReference` - objects are accepted. - -``encoding`` Specifies the character set encoding of the strings - in the OGR data source. For example, ``'latin-1'``, - ``'utf-8'``, and ``'cp437'`` are all valid encoding - parameters. - -``transaction_mode`` May be ``'commit_on_success'`` (default) or - ``'autocommit'``. - -``transform`` Setting this to False will disable coordinate - transformations. In other words, geometries will - be inserted into the database unmodified from their - original state in the data source. - -``unique`` Setting this to the name, or a tuple of names, - from the given model will create models unique - only to the given name(s). Geometries will from - each feature will be added into the collection - associated with the unique model. Forces - the transaction mode to be ``'autocommit'``. - -``using`` New in version 1.2. Sets the database to use when - importing spatial data. Default is ``'default'`` -===================== ===================================================== - -``save()`` Keyword Arguments ----------------------------- - -.. method:: LayerMapping.save([verbose=False, fid_range=False, step=False, progress=False, silent=False, stream=sys.stdout, strict=False]) - -The ``save()`` method also accepts keywords. These keywords are -used for controlling output logging, error handling, and for importing -specific feature ranges. - -=========================== ================================================= -Save Keyword Arguments Description -=========================== ================================================= -``fid_range`` May be set with a slice or tuple of - (begin, end) feature ID's to map from - the data source. In other words, this - keyword enables the user to selectively - import a subset range of features in the - geographic data source. - -``progress`` When this keyword is set, status information - will be printed giving the number of features - processed and successfully saved. By default, - progress information will be printed every 1000 - features processed, however, this default may - be overridden by setting this keyword with an - integer for the desired interval. - -``silent`` By default, non-fatal error notifications are - printed to ``sys.stdout``, but this keyword may - be set to disable these notifications. - -``step`` If set with an integer, transactions will - occur at every step interval. For example, if - ``step=1000``, a commit would occur after the - 1,000th feature, the 2,000th feature etc. - - -``stream`` Status information will be written to this file - handle. Defaults to using ``sys.stdout``, but - any object with a ``write`` method is supported. - -``strict`` Execution of the model mapping will cease upon - the first error encountered. The default value - (``False``) - behavior is to attempt to continue. - -``verbose`` If set, information will be printed - subsequent to each model save - executed on the database. -=========================== ================================================= - -Troubleshooting -=============== - -Running out of memory ---------------------- - -As noted in the warning at the top of this section, Django stores all SQL -queries when ``DEBUG=True``. Set ``DEBUG=False`` in your settings, and this -should stop excessive memory use when running ``LayerMapping`` scripts. - -MySQL: ``max_allowed_packet`` error ------------------------------------ - -If you encounter the following error when using ``LayerMapping`` and MySQL:: - - OperationalError: (1153, "Got a packet bigger than 'max_allowed_packet' bytes") - -Then the solution is to increase the value of the ``max_allowed_packet`` -setting in your MySQL configuration. For example, the default value may -be something low like one megabyte -- the setting may be modified in MySQL's -configuration file (``my.cnf``) in the ``[mysqld]`` section:: - - max_allowed_packet = 10M diff --git a/parts/django/docs/ref/contrib/gis/measure.txt b/parts/django/docs/ref/contrib/gis/measure.txt deleted file mode 100644 index 6971788..0000000 --- a/parts/django/docs/ref/contrib/gis/measure.txt +++ /dev/null @@ -1,180 +0,0 @@ -.. _ref-measure: - -=================== -Measurement Objects -=================== - -.. module:: django.contrib.gis.measure - :synopsis: GeoDjango's distance and area measurment objects. - -The :mod:`django.contrib.gis.measure` module contains objects that allow -for convenient representation of distance and area units of measure. [#]_ -Specifically, it implements two objects, :class:`Distance` and -:class:`Area` -- both of which may be accessed via the -:class:`D` and :class:`A` convenience aliases, respectively. - -Example -======= - -:class:`Distance` objects may be instantiated using a keyword argument indicating the -context of the units. In the example below, two different distance objects are -instantiated in units of kilometers (``km``) and miles (``mi``):: - - >>> from django.contrib.gis.measure import Distance, D - >>> d1 = Distance(km=5) - >>> print d1 - 5.0 km - >>> d2 = D(mi=5) # `D` is an alias for `Distance` - >>> print d2 - 5.0 mi - -Conversions are easy, just access the preferred unit attribute to get a -converted distance quantity:: - - >>> print d1.mi # Converting 5 kilometers to miles - 3.10685596119 - >>> print d2.km # Converting 5 miles to kilometers - 8.04672 - -Moreover, arithmetic operations may be performed between the distance -objects:: - - >>> print d1 + d2 # Adding 5 miles to 5 kilometers - 13.04672 km - >>> print d2 - d1 # Subtracting 5 kilometers from 5 miles - 1.89314403881 mi - -Two :class:`Distance` objects multiplied together will yield an :class:`Area` -object, which uses squared units of measure:: - - >>> a = d1 * d2 # Returns an Area object. - >>> print a - 40.2336 sq_km - -To determine what the attribute abbreviation of a unit is, the ``unit_attname`` -class method may be used:: - - >>> print Distance.unit_attname('US Survey Foot') - survey_ft - >>> print Distance.unit_attname('centimeter') - cm - -.. _supported_units: - -Supported units -=============== - -================================= ======================================== -Unit Attribute Full name or alias(es) -================================= ======================================== -``km`` Kilometre, Kilometer -``mi`` Mile -``m`` Meter, Metre -``yd`` Yard -``ft`` Foot, Foot (International) -``survey_ft`` U.S. Foot, US survey foot -``inch`` Inches -``cm`` Centimeter -``mm`` Millimetre, Millimeter -``um`` Micrometer, Micrometre -``british_ft`` British foot (Sears 1922) -``british_yd`` British yard (Sears 1922) -``british_chain_sears`` British chain (Sears 1922) -``indian_yd`` Indian yard, Yard (Indian) -``sears_yd`` Yard (Sears) -``clarke_ft`` Clarke's Foot -``chain`` Chain -``chain_benoit`` Chain (Benoit) -``chain_sears`` Chain (Sears) -``british_chain_benoit`` British chain (Benoit 1895 B) -``british_chain_sears_truncated`` British chain (Sears 1922 truncated) -``gold_coast_ft`` Gold Coast foot -``link`` Link -``link_benoit`` Link (Benoit) -``link_sears`` Link (Sears) -``clarke_link`` Clarke's link -``fathom`` Fathom -``rod`` Rod -``nm`` Nautical Mile -``nm_uk`` Nautical Mile (UK) -``german_m`` German legal metre -================================= ======================================== - -.. note:: - - :class:`Area` attributes are the same as :class:`Distance` attributes, - except they are prefixed with ``sq_`` (area units are square in nature). - For example, ``Area(sq_m=2)`` creates an :class:`Area` object - representing two square meters. - -Measurement API -=============== - -``Distance`` ------------- - -.. class:: Distance(**kwargs) - - To initialize a distance object, pass in a keyword corresponding to - the desired :ref:`unit attribute name <supported_units>` set with - desired value. For example, the following creates a distance - object representing 5 miles:: - - >>> dist = Distance(mi=5) - - .. method:: __getattr__(unit_att) - - Returns the distance value in units corresponding to the given unit - attribute. For example:: - - >>> print dist.km - 8.04672 - - .. classmethod:: unit_attname(unit_name) - - Returns the distance unit attribute name for the given full unit name. - For example:: - - >>> Distance.unit_attname('Mile') - 'mi' - -.. class:: D - - Alias for :class:`Distance` class. - -``Area`` --------- - -.. class:: Area(**kwargs) - - To initialize a distance object, pass in a keyword corresponding to - the desired :ref:`unit attribute name <supported_units>` set with - desired value. For example, the following creates a distance - object representing 5 square miles:: - - >>> a = Area(sq_mi=5) - - .. method:: __getattr__(unit_att) - - Returns the area value in units corresponding to the given unit - attribute. For example:: - - >>> print a.sq_km - 12.949940551680001 - - .. classmethod:: unit_attname(unit_name) - - Returns the area unit attribute name for the given full unit name. - For example:: - - >>> Area.unit_attname('Kilometer') - 'sq_km' - -.. class:: A - - Alias for :class:`Area` class. - -.. rubric:: Footnotes -.. [#] `Robert Coup <http://koordinates.com/>`_ is the initial author of the measure objects, - and was inspired by Brian Beck's work in `geopy <http://code.google.com/p/geopy/>`_ - and Geoff Biggs' PhD work on dimensioned units for robotics. diff --git a/parts/django/docs/ref/contrib/gis/model-api.txt b/parts/django/docs/ref/contrib/gis/model-api.txt deleted file mode 100644 index 6b50cf3..0000000 --- a/parts/django/docs/ref/contrib/gis/model-api.txt +++ /dev/null @@ -1,265 +0,0 @@ -.. _ref-gis-model-api: - -=================== -GeoDjango Model API -=================== - -.. module:: django.contrib.gis.db.models - :synopsis: GeoDjango model and field API. - -This document explores the details of the GeoDjango Model API. Throughout this -section, we'll be using the following geographic model of a `ZIP code`__ as our -example:: - - from django.contrib.gis.db import models - - class Zipcode(models.Model): - code = models.CharField(max_length=5) - poly = models.PolygonField() - objects = models.GeoManager() - -__ http://en.wikipedia.org/wiki/ZIP_code - -Geometry Field Types -==================== - -Each of the following geometry field types correspond with the -OpenGIS Simple Features specification [#fnogc]_. - -``GeometryField`` ------------------ - -.. class:: GeometryField - -``PointField`` --------------- - -.. class:: PointField - -``LineStringField`` -------------------- - -.. class:: LineStringField - -``PolygonField`` ----------------- - -.. class:: PolygonField - -``MultiPointField`` -------------------- - -.. class:: MultiPointField - -``MultiLineStringField`` ------------------------- - -.. class:: MultiLineStringField - -``MultiPolygonField`` ---------------------- - -.. class:: MultiPolygonField - -``GeometryCollectionField`` ---------------------------- - -.. class:: GeometryCollectionField - -.. _geometry-field-options: - -Geometry Field Options -====================== - -In addition to the regular :ref:`common-model-field-options` available for -Django model fields, geometry fields have the following additional options. -All are optional. - -``srid`` --------- - -.. attribute:: GeometryField.srid - -Sets the SRID [#fnogcsrid]_ (Spatial Reference System Identity) of the geometry field to -the given value. Defaults to 4326 (also known as `WGS84`__, units are in degrees -of longitude and latitude). - -__ http://en.wikipedia.org/wiki/WGS84 - -.. _selecting-an-srid: - -Selecting an SRID -^^^^^^^^^^^^^^^^^ - -Choosing an appropriate SRID for your model is an important decision that the -developer should consider carefully. The SRID is an integer specifier that -corresponds to the projection system that will be used to interpret the data -in the spatial database. [#fnsrid]_ Projection systems give the context to the -coordinates that specify a location. Although the details of `geodesy`__ are -beyond the scope of this documentation, the general problem is that the earth -is spherical and representations of the earth (e.g., paper maps, Web maps) -are not. - -Most people are familiar with using latitude and longitude to reference a -location on the earth's surface. However, latitude and longitude are angles, -not distances. [#fnharvard]_ In other words, while the shortest path between two points on -a flat surface is a straight line, the shortest path between two points on a curved -surface (such as the earth) is an *arc* of a `great circle`__. [#fnthematic]_ Thus, -additional computation is required to obtain distances in planar units (e.g., -kilometers and miles). Using a geographic coordinate system may introduce -complications for the developer later on. For example, PostGIS versions 1.4 -and below do not have the capability to perform distance calculations between -non-point geometries using geographic coordinate systems, e.g., constructing a -query to find all points within 5 miles of a county boundary stored as WGS84. -[#fndist]_ - -Portions of the earth's surface may projected onto a two-dimensional, or -Cartesian, plane. Projected coordinate systems are especially convenient -for region-specific applications, e.g., if you know that your database will -only cover geometries in `North Kansas`__, then you may consider using projection -system specific to that region. Moreover, projected coordinate systems are -defined in Cartesian units (such as meters or feet), easing distance -calculations. - -.. note:: - - If you wish to peform arbitrary distance queries using non-point - geometries in WGS84, consider upgrading to PostGIS 1.5. For - better performance, enable the :attr:`GeometryField.geography` - keyword so that :ref:`geography database type <geography-type>` - is used instead. - -Additional Resources: - -* `spatialreference.org`__: A Django-powered database of spatial reference - systems. -* `The State Plane Coordinate System`__: A Web site covering the various - projection systems used in the United States. Much of the U.S. spatial - data encountered will be in one of these coordinate systems rather than - in a geographic coordinate system such as WGS84. - -__ http://en.wikipedia.org/wiki/Geodesy -__ http://en.wikipedia.org/wiki/Great_circle -__ http://www.spatialreference.org/ref/epsg/2796/ -__ http://spatialreference.org/ -__ http://welcome.warnercnr.colostate.edu/class_info/nr502/lg3/datums_coordinates/spcs.html - -``spatial_index`` ------------------ - -.. attribute:: GeometryField.spatial_index - -Defaults to ``True``. Creates a spatial index for the given geometry -field. - -.. note:: - - This is different from the ``db_index`` field option because spatial - indexes are created in a different manner than regular database - indexes. Specifically, spatial indexes are typically created using - a variant of the R-Tree, while regular database indexes typically - use B-Trees. - -``dim`` -------- - -.. versionadded:: 1.2 - -.. attribute:: GeometryField.dim - -This option may be used for customizing the coordinate dimension of the -geometry field. By default, it is set to 2, for representing two-dimensional -geometries. For spatial backends that support it, it may be set to 3 for -three-dimensonal support. - -.. note:: - - At this time 3D support requires that GEOS 3.1 be installed, and is - limited only to the PostGIS spatial backend. - -``geography`` -------------- - -.. versionadded:: 1.2 - -.. attribute:: GeometryField.geography - -If set to ``True``, this option will create a database column of -type geography, rather than geometry. Please refer to the -:ref:`geography type <geography-type>` section below for more -details. - -.. note:: - - Geography support is limited only to PostGIS 1.5+, and will - force the SRID to be 4326. - -.. _geography-type: - -Geography Type -^^^^^^^^^^^^^^ - -In PostGIS 1.5, the geography type was introduced -- it provides -provides native support for spatial features represented with geographic -coordinates (e.g., WGS84 longitude/latitude). [#fngeography]_ -Unlike the plane used by a geometry type, the geography type uses a spherical -representation of its data. Distance and measurement operations -performed on a geography column automatically employ great circle arc -calculations and return linear units. In other words, when ``ST_Distance`` -is called on two geographies, a value in meters is returned (as opposed -to degrees if called on a geometry column in WGS84). - -Because geography calculations involve more mathematics, only a subset of the -PostGIS spatial lookups are available for the geography type. Practically, -this means that in addition to the :ref:`distance lookups <distance-lookups>` -only the following additional :ref:`spatial lookups <spatial-lookups>` are -available for geography columns: - -* :lookup:`bboverlaps` -* :lookup:`coveredby` -* :lookup:`covers` -* :lookup:`intersects` - -For more information, the PostGIS documentation contains a helpful section on -determining `when to use geography data type over geometry data type -<http://postgis.refractions.net/documentation/manual-1.5/ch04.html#PostGIS_GeographyVSGeometry>`_. - -``GeoManager`` -============== - -.. currentmodule:: django.contrib.gis.db.models -.. class:: GeoManager - -In order to conduct geographic queries, each geographic model requires -a ``GeoManager`` model manager. This manager allows for the proper SQL -construction for geographic queries; thus, without it, all geographic filters -will fail. It should also be noted that ``GeoManager`` is required even if the -model does not have a geographic field itself, e.g., in the case of a -``ForeignKey`` relation to a model with a geographic field. For example, -if we had an ``Address`` model with a ``ForeignKey`` to our ``Zipcode`` -model:: - - from django.contrib.gis.db import models - from django.contrib.localflavor.us.models import USStateField - - class Address(models.Model): - num = models.IntegerField() - street = models.CharField(max_length=100) - city = models.CharField(max_length=100) - state = USStateField() - zipcode = models.ForeignKey(Zipcode) - objects = models.GeoManager() - -The geographic manager is needed to do spatial queries on related ``Zipcode`` objects, -for example:: - - qs = Address.objects.filter(zipcode__poly__contains='POINT(-104.590948 38.319914)') - -.. rubric:: Footnotes -.. [#fnogc] OpenGIS Consortium, Inc., `Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049 (May 5, 1999). -.. [#fnogcsrid] *See id.* at Ch. 2.3.8, p. 39 (Geometry Values and Spatial Reference Systems). -.. [#fnsrid] Typically, SRID integer corresponds to an EPSG (`European Petroleum Survey Group <http://www.epsg.org>`_) identifier. However, it may also be associated with custom projections defined in spatial database's spatial reference systems table. -.. [#fnharvard] Harvard Graduate School of Design, `An Overview of Geodesy and Geographic Referencing Systems <http://www.gsd.harvard.edu/gis/manual/projections/fundamentals/>`_. This is an excellent resource for an overview of principles relating to geographic and Cartesian coordinate systems. -.. [#fnthematic] Terry A. Slocum, Robert B. McMaster, Fritz C. Kessler, & Hugh H. Howard, *Thematic Cartography and Geographic Visualization* (Prentice Hall, 2nd edition), at Ch. 7.1.3. -.. [#fndist] This limitation does not apply to PostGIS 1.5. It should be noted that even in previous versions of PostGIS, this isn't impossible using GeoDjango; you could for example, take a known point in a projected coordinate system, buffer it to the appropriate radius, and then perform an intersection operation with the buffer transformed to the geographic coordinate system. -.. [#fngeography] Please refer to the `PostGIS Geography Type <http://postgis.refractions.net/documentation/manual-1.5/ch04.html#PostGIS_Geography>`_ documentation for more details. diff --git a/parts/django/docs/ref/contrib/gis/ogrinspect.txt b/parts/django/docs/ref/contrib/gis/ogrinspect.txt deleted file mode 100644 index ed285e0..0000000 --- a/parts/django/docs/ref/contrib/gis/ogrinspect.txt +++ /dev/null @@ -1,21 +0,0 @@ -.. _ref-ogrinspect: - -============== -OGR Inspection -============== - -.. module:: django.contrib.gis.utils.ogrinspect - :synopsis: Utilities for inspecting OGR data sources. - -.. currentmodule:: django.contrib.gis.utils - -``ogrinspect`` -============== - -.. function:: ogrinspect(data_source, model_name[, **kwargs]) - :noindex: - -``mapping`` -=========== - -.. function:: mapping(data_source, [geom_name='geom', layer_key=0, multi_geom=False]) diff --git a/parts/django/docs/ref/contrib/gis/sitemaps.txt b/parts/django/docs/ref/contrib/gis/sitemaps.txt deleted file mode 100644 index 75bddd3..0000000 --- a/parts/django/docs/ref/contrib/gis/sitemaps.txt +++ /dev/null @@ -1,27 +0,0 @@ -=================== -Geographic Sitemaps -=================== - -Google's sitemap protocol has been recently extended to support geospatial -content. [#]_ This includes the addition of the ``<url>`` child element -``<geo:geo>``, which tells Google that the content located at the URL is -geographic in nature. [#]_ - -Example -======= - -Reference -========= - -``KMLSitemap`` --------------- - -``KMZSitemap`` --------------- - -``GeoRSSSitemap`` ------------------ - -.. rubric:: Footnotes -.. [#] Google, Inc., `What is a Geo Sitemap? <http://www.google.com/support/webmasters/bin/answer.py?answer=94554>`_. -.. [#] Google, Inc., `Submit Your Geo Content to Google <http://code.google.com/apis/kml/documentation/kmlSearch.html>`_. diff --git a/parts/django/docs/ref/contrib/gis/testing.txt b/parts/django/docs/ref/contrib/gis/testing.txt deleted file mode 100644 index 889b43a..0000000 --- a/parts/django/docs/ref/contrib/gis/testing.txt +++ /dev/null @@ -1,268 +0,0 @@ -====================== -Testing GeoDjango Apps -====================== - -.. versionchanged:: 1.2 - -In Django 1.2, the addition of :ref:`spatial-backends` -simplified the process of testing GeoDjango applications. Specifically, testing -GeoDjango applications is now the same as :doc:`/topics/testing`. - -Included in this documentation are some additional notes and settings -for :ref:`testing-postgis` and :ref:`testing-spatialite` users. - -.. note:: - - Django 1.1 users are still required to use a custom :setting:`TEST_RUNNER`. - See the :ref:`testing-1.1` section for more details. - -.. _testing-postgis: - -PostGIS -======= - -Settings --------- - -.. note:: - - The settings below have sensible defaults, and shouldn't require manual setting. - -.. setting:: POSTGIS_TEMPLATE - -``POSTGIS_TEMPLATE`` -^^^^^^^^^^^^^^^^^^^^ - -.. versionadded:: 1.1 - -.. versionchanged:: 1.2 - -This setting may be used to customize the name of the PostGIS template -database to use. In Django versions 1.2 and above, it automatically -defaults to ``'template_postgis'`` (the same name used in the -:ref:`installation documentation <spatialdb_template>`). - -.. note:: - - Django 1.1 users will still have to define the :setting:`POSTGIS_TEMPLATE` - with a value, for example:: - - POSTGIS_TEMPLATE='template_postgis' - -.. setting:: POSTGIS_VERSION - -``POSTGIS_VERSION`` -^^^^^^^^^^^^^^^^^^^ - -.. versionadded:: 1.1 - -When GeoDjango's spatial backend initializes on PostGIS, it has to perform -a SQL query to determine the version in order to figure out what -features are available. Advanced users wishing to prevent this additional -query may set the version manually using a 3-tuple of integers specifying -the major, minor, and subminor version numbers for PostGIS. For example, -to configure for PostGIS 1.5.2 you would use:: - - POSTGIS_VERSION = (1, 5, 2) - -Obtaining Sufficient Privileges -------------------------------- - -Depending on your configuration, this section describes several methods to -configure a database user with sufficient privileges to run tests for -GeoDjango applications on PostgreSQL. If your -:ref:`spatial database template <spatialdb_template>` -was created like in the instructions, then your testing database user -only needs to have the ability to create databases. In other configurations, -you may be required to use a database superuser. - -Create Database User -^^^^^^^^^^^^^^^^^^^^ - -To make database user with the ability to create databases, use the -following command:: - - $ createuser --createdb -R -S <user_name> - -The ``-R -S`` flags indicate that we do not want the user to have the ability -to create additional users (roles) or to be a superuser, respectively. - -Alternatively, you may alter an existing user's role from the SQL shell -(assuming this is done from an existing superuser account):: - - postgres# ALTER ROLE <user_name> CREATEDB NOSUPERUSER NOCREATEROLE; - -Create Database Superuser -^^^^^^^^^^^^^^^^^^^^^^^^^ - -This may be done at the time the user is created, for example:: - - $ createuser --superuser <user_name> - -Or you may alter the user's role from the SQL shell (assuming this -is done from an existing superuser account):: - - postgres# ALTER ROLE <user_name> SUPERUSER; - - -Create Local PostgreSQL Database -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -1. Initialize database: ``initdb -D /path/to/user/db`` - -2. If there's already a Postgres instance on the machine, it will need - to use a different TCP port than 5432. Edit ``postgresql.conf`` (in - ``/path/to/user/db``) to change the database port (e.g. ``port = 5433``). - -3. Start this database ``pg_ctl -D /path/to/user/db start`` - -Windows -------- - -On Windows platforms the pgAdmin III utility may also be used as -a simple way to add superuser privileges to your database user. - -By default, the PostGIS installer on Windows includes a template -spatial database entitled ``template_postgis``. - -.. _testing-spatialite: - -SpatiaLite -========== - -.. versionadded:: 1.1 - -You will need to download the `initialization SQL`__ script for SpatiaLite:: - - $ wget http://www.gaia-gis.it/spatialite/init_spatialite-2.3.zip - $ unzip init_spatialite-2.3.zip - -If ``init_spatialite-2.3.sql`` is in the same path as your project's ``manage.py``, -then all you have to do is:: - - $ python manage.py test - -Settings --------- - -.. setting:: SPATIALITE_SQL - -``SPATIALITE_SQL`` -^^^^^^^^^^^^^^^^^^ - -.. versionadded:: 1.1 - -By default, the GeoDjango test runner looks for the SpatiaLite SQL in the -same directory where it was invoked (by default the same directory where -``manage.py`` is located). If you want to use a different location, then -you may add the following to your settings:: - - SPATIALITE_SQL='/path/to/init_spatialite-2.3.sql' - -__ http://www.gaia-gis.it/spatialite/init_spatialite-2.3.zip - -.. _testing-1.1: - -Testing GeoDjango Applications in 1.1 -===================================== - -In Django 1.1, to accommodate the extra steps required to scaffalod a -spatial database automatically, a test runner customized for GeoDjango -must be used. To use this runner, configure :setting:`TEST_RUNNER` as follows:: - - TEST_RUNNER='django.contrib.gis.tests.run_tests' - -.. note:: - - In order to create a spatial database, the :setting:`USER` setting - (or :setting:`TEST_USER`, if optionally defined on Oracle) requires - elevated privileges. When using PostGIS or MySQL, the database user - must have at least the ability to create databases. When testing on Oracle, - the user should be a superuser. - -.. _geodjango-tests: - -GeoDjango Tests -=============== - -.. versionchanged:: 1.2.4 - -GeoDjango's test suite may be run in one of two ways, either by itself or -with the rest of Django's :ref:`unit-tests`. - -.. note:: - - The :setting:`TEST_RUNNER` previously used to execute the GeoDjango - test suite,:func:`django.contrib.gis.tests.run_gis_tests`, was deprecated - in favor of the :class:`django.contrib.gis.tests.GeoDjangoTestSuiteRunner` - class. - -Run only GeoDjango tests ------------------------- - -To run *only* the tests for GeoDjango, the :setting:`TEST_RUNNER` -setting must be changed to use the -:class:`~django.contrib.gis.tests.GeoDjangoTestSuiteRunner`:: - - TEST_RUNNER = 'django.contrib.gis.tests.GeoDjangoTestSuiteRunner' - -Example -^^^^^^^ - -First, you'll need a bare-bones settings file, like below, that is -customized with your spatial database name and user:: - - TEST_RUNNER = 'django.contrib.gis.tests.GeoDjangoTestSuiteRunner' - - DATABASES = { - 'default': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': 'a_spatial_database', - 'USER': 'db_user' - } - } - -Assuming the above is in a file called ``postgis.py`` that is in the -the same directory as ``manage.py`` of your Django project, then -you may run the tests with the following command:: - - $ python manage.py test --settings=postgis - -Run with ``runtests.py`` ------------------------- - -To have the GeoDjango tests executed when -:ref:`running the Django test suite <running-unit-tests>` with ``runtests.py`` -all of the databases in the settings file must be using one of the -:ref:`spatial database backends <spatial-backends>`. - -.. warning:: - - Do not change the :setting:`TEST_RUNNER` setting - when running the GeoDjango tests with ``runtests.py``. - -Example -^^^^^^^ - -The following is an example bare-bones settings file with spatial backends -that can be used to run the entire Django test suite, including those -in :mod:`django.contrib.gis`:: - - DATABASES = { - 'default': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': 'geodjango', - 'USER': 'geodjango', - }, - 'other': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': 'other', - 'USER': 'geodjango', - } - } - -Assuming the settings above were in a ``postgis.py`` file in the same -directory as ``runtests.py``, then all Django and GeoDjango tests would -be performed when executing the command:: - - $ ./runtests.py --settings=postgis diff --git a/parts/django/docs/ref/contrib/gis/tutorial.txt b/parts/django/docs/ref/contrib/gis/tutorial.txt deleted file mode 100644 index 9deeb78..0000000 --- a/parts/django/docs/ref/contrib/gis/tutorial.txt +++ /dev/null @@ -1,758 +0,0 @@ -================== -GeoDjango Tutorial -================== - -Introduction -============ - -GeoDjango is an add-on for Django that turns it into a world-class geographic -Web framework. GeoDjango strives to make at as simple as possible to create -geographic Web applications, like location-based services. Some features include: - -* Django model fields for `OGC`_ geometries. -* Extensions to Django's ORM for the querying and manipulation of spatial data. -* Loosely-coupled, high-level Python interfaces for GIS geometry operations and - data formats. -* Editing of geometry fields inside the admin. - -This tutorial assumes a familiarity with Django; thus, if you're brand new to -Django please read through the :doc:`regular tutorial </intro/tutorial01>` to introduce -yourself with basic Django concepts. - -.. note:: - - GeoDjango has special prerequisites overwhat is required by Django -- - please consult the :ref:`installation documentation <ref-gis-install>` - for more details. - -This tutorial will guide you through the creation of a geographic Web -application for viewing the `world borders`_. [#]_ Some of the code -used in this tutorial is taken from and/or inspired by the `GeoDjango -basic apps`_ project. [#]_ - -.. note:: - - Proceed through the tutorial sections sequentially for step-by-step - instructions. - -.. _OGC: http://www.opengeospatial.org/ -.. _world borders: http://thematicmapping.org/downloads/world_borders.php -.. _GeoDjango basic apps: http://code.google.com/p/geodjango-basic-apps/ - -Setting Up -========== - -Create a Spatial Database -------------------------- - -.. note:: - - MySQL and Oracle users can skip this section because spatial types - are already built into the database. - -First, a spatial database needs to be created for our project. If using -PostgreSQL and PostGIS, then the following commands will -create the database from a :ref:`spatial database template <spatialdb_template>`:: - - $ createdb -T template_postgis geodjango - -.. note:: - - This command must be issued by a database user that has permissions to - create a database. Here is an example set of commands to create such - a user:: - - $ sudo su - postgres - $ createuser --createdb geo - $ exit - - Replace ``geo`` to correspond to the system login user name will be - connecting to the database. For example, ``johndoe`` if that is the - system user that will be running GeoDjango. - -Users of SQLite and SpatiaLite should consult the instructions on how -to create a :ref:`SpatiaLite database <create_spatialite_db>`. - -Create GeoDjango Project ------------------------- - -Use the ``django-admin.py`` script like normal to create a ``geodjango`` project:: - - $ django-admin.py startproject geodjango - -With the project initialized, now create a ``world`` Django application within -the ``geodjango`` project:: - - $ cd geodjango - $ python manage.py startapp world - -Configure ``settings.py`` -------------------------- - -The ``geodjango`` project settings are stored in the ``settings.py`` file. Edit -the database connection settings appropriately:: - - DATABASES = { - 'default': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': 'geodjango', - 'USER': 'geo', - } - } - -.. note:: - - These database settings are for Django 1.2 and above. - -In addition, modify the :setting:`INSTALLED_APPS` setting to include -:mod:`django.contrib.admin`, :mod:`django.contrib.gis`, -and ``world`` (our newly created application):: - - INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.admin', - 'django.contrib.gis', - 'world' - ) - -Geographic Data -=============== - -.. _worldborders: - -World Borders -------------- - -The world borders data is available in this `zip file`__. Create a data directory -in the ``world`` application, download the world borders data, and unzip. -On GNU/Linux platforms the following commands should do it:: - - $ mkdir world/data - $ cd world/data - $ wget http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip - $ unzip TM_WORLD_BORDERS-0.3.zip - $ cd ../.. - -The world borders ZIP file contains a set of data files collectively known as -an `ESRI Shapefile`__, one of the most popular geospatial data formats. When -unzipped the world borders data set includes files with the following extensions: - -* ``.shp``: Holds the vector data for the world borders geometries. -* ``.shx``: Spatial index file for geometries stored in the ``.shp``. -* ``.dbf``: Database file for holding non-geometric attribute data - (e.g., integer and character fields). -* ``.prj``: Contains the spatial reference information for the geographic - data stored in the shapefile. - -__ http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip -__ http://en.wikipedia.org/wiki/Shapefile - -Use ``ogrinfo`` to examine spatial data ---------------------------------------- - -The GDAL ``ogrinfo`` utility is excellent for examining metadata about -shapefiles (or other vector data sources):: - - $ ogrinfo world/data/TM_WORLD_BORDERS-0.3.shp - INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp' - using driver `ESRI Shapefile' successful. - 1: TM_WORLD_BORDERS-0.3 (Polygon) - -Here ``ogrinfo`` is telling us that the shapefile has one layer, and that -layer contains polygon data. To find out more we'll specify the layer name -and use the ``-so`` option to get only important summary information:: - - $ ogrinfo -so world/data/TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3 - INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp' - using driver `ESRI Shapefile' successful. - - Layer name: TM_WORLD_BORDERS-0.3 - Geometry: Polygon - Feature Count: 246 - Extent: (-180.000000, -90.000000) - (180.000000, 83.623596) - Layer SRS WKT: - GEOGCS["GCS_WGS_1984", - DATUM["WGS_1984", - SPHEROID["WGS_1984",6378137.0,298.257223563]], - PRIMEM["Greenwich",0.0], - UNIT["Degree",0.0174532925199433]] - FIPS: String (2.0) - ISO2: String (2.0) - ISO3: String (3.0) - UN: Integer (3.0) - NAME: String (50.0) - AREA: Integer (7.0) - POP2005: Integer (10.0) - REGION: Integer (3.0) - SUBREGION: Integer (3.0) - LON: Real (8.3) - LAT: Real (7.3) - -This detailed summary information tells us the number of features in the layer -(246), the geographical extent, the spatial reference system ("SRS WKT"), -as well as detailed information for each attribute field. For example, -``FIPS: String (2.0)`` indicates that there's a ``FIPS`` character field -with a maximum length of 2; similarly, ``LON: Real (8.3)`` is a floating-point -field that holds a maximum of 8 digits up to three decimal places. Although -this information may be found right on the `world borders`_ Web site, this shows -you how to determine this information yourself when such metadata is not -provided. - -Geographic Models -================= - -Defining a Geographic Model ---------------------------- - -Now that we've examined our world borders data set using ``ogrinfo``, we can -create a GeoDjango model to represent this data:: - - from django.contrib.gis.db import models - - class WorldBorders(models.Model): - # Regular Django fields corresponding to the attributes in the - # world borders shapefile. - name = models.CharField(max_length=50) - area = models.IntegerField() - pop2005 = models.IntegerField('Population 2005') - fips = models.CharField('FIPS Code', max_length=2) - iso2 = models.CharField('2 Digit ISO', max_length=2) - iso3 = models.CharField('3 Digit ISO', max_length=3) - un = models.IntegerField('United Nations Code') - region = models.IntegerField('Region Code') - subregion = models.IntegerField('Sub-Region Code') - lon = models.FloatField() - lat = models.FloatField() - - # GeoDjango-specific: a geometry field (MultiPolygonField), and - # overriding the default manager with a GeoManager instance. - mpoly = models.MultiPolygonField() - objects = models.GeoManager() - - # So the model is pluralized correctly in the admin. - class Meta: - verbose_name_plural = "World Borders" - - # Returns the string representation of the model. - def __unicode__(self): - return self.name - -Two important things to note: - -1. The ``models`` module is imported from :mod:`django.contrib.gis.db`. -2. The model overrides its default manager with - :class:`~django.contrib.gis.db.models.GeoManager`; this is *required* - to perform spatial queries. - -When declaring a geometry field on your model the default spatial reference system -is WGS84 (meaning the `SRID`__ is 4326) -- in other words, the field coordinates are in -longitude/latitude pairs in units of degrees. If you want the coordinate system to be -different, then SRID of the geometry field may be customized by setting the ``srid`` -with an integer corresponding to the coordinate system of your choice. - -__ http://en.wikipedia.org/wiki/SRID - -Run ``syncdb`` --------------- - -After you've defined your model, it needs to be synced with the spatial database. -First, let's look at the SQL that will generate the table for the ``WorldBorders`` -model:: - - $ python manage.py sqlall world - -This management command should produce the following output:: - - BEGIN; - CREATE TABLE "world_worldborders" ( - "id" serial NOT NULL PRIMARY KEY, - "name" varchar(50) NOT NULL, - "area" integer NOT NULL, - "pop2005" integer NOT NULL, - "fips" varchar(2) NOT NULL, - "iso2" varchar(2) NOT NULL, - "iso3" varchar(3) NOT NULL, - "un" integer NOT NULL, - "region" integer NOT NULL, - "subregion" integer NOT NULL, - "lon" double precision NOT NULL, - "lat" double precision NOT NULL - ) - ; - SELECT AddGeometryColumn('world_worldborders', 'mpoly', 4326, 'MULTIPOLYGON', 2); - ALTER TABLE "world_worldborders" ALTER "mpoly" SET NOT NULL; - CREATE INDEX "world_worldborders_mpoly_id" ON "world_worldborders" USING GIST ( "mpoly" GIST_GEOMETRY_OPS ); - COMMIT; - -If satisfied, you may then create this table in the database by running the -``syncdb`` management command:: - - $ python manage.py syncdb - Creating table world_worldborders - Installing custom SQL for world.WorldBorders model - -The ``syncdb`` command may also prompt you to create an admin user; go ahead and -do so (not required now, may be done at any point in the future using the -``createsuperuser`` management command). - -Importing Spatial Data -====================== - -This section will show you how to take the data from the world borders -shapefile and import it into GeoDjango models using the :ref:`ref-layermapping`. -There are many different different ways to import data in to a -spatial database -- besides the tools included within GeoDjango, you -may also use the following to populate your spatial database: - -* `ogr2ogr`_: Command-line utility, included with GDAL, that - supports loading a multitude of vector data formats into - the PostGIS, MySQL, and Oracle spatial databases. -* `shp2pgsql`_: This utility is included with PostGIS and only supports - ESRI shapefiles. - -.. _ogr2ogr: http://www.gdal.org/ogr2ogr.html -.. _shp2pgsql: http://postgis.refractions.net/documentation/manual-1.5/ch04.html#shp2pgsql_usage - -.. _gdalinterface: - -GDAL Interface --------------- - -Earlier we used the the ``ogrinfo`` to explore the contents of the world borders -shapefile. Included within GeoDjango is an interface to GDAL's powerful OGR -library -- in other words, you'll be able explore all the vector data sources -that OGR supports via a Pythonic API. - -First, invoke the Django shell:: - - $ python manage.py shell - -If the :ref:`worldborders` data was downloaded like earlier in the -tutorial, then we can determine the path using Python's built-in -``os`` module:: - - >>> import os - >>> from geodjango import world - >>> world_shp = os.path.abspath(os.path.join(os.path.dirname(world.__file__), - ... 'data/TM_WORLD_BORDERS-0.3.shp')) - -Now, the world borders shapefile may be opened using GeoDjango's -:class:`~django.contrib.gis.gdal.DataSource` interface:: - - >>> from django.contrib.gis.gdal import * - >>> ds = DataSource(world_shp) - >>> print ds - / ... /geodjango/world/data/TM_WORLD_BORDERS-0.3.shp (ESRI Shapefile) - -Data source objects can have different layers of geospatial features; however, -shapefiles are only allowed to have one layer:: - - >>> print len(ds) - 1 - >>> lyr = ds[0] - >>> print lyr - TM_WORLD_BORDERS-0.3 - -You can see what the geometry type of the layer is and how many features it -contains:: - - >>> print lyr.geom_type - Polygon - >>> print len(lyr) - 246 - -.. note:: - - Unfortunately the shapefile data format does not allow for greater - specificity with regards to geometry types. This shapefile, like - many others, actually includes ``MultiPolygon`` geometries in its - features. You need to watch out for this when creating your models - as a GeoDjango ``PolygonField`` will not accept a ``MultiPolygon`` - type geometry -- thus a ``MultiPolygonField`` is used in our model's - definition instead. - -The :class:`~django.contrib.gis.gdal.Layer` may also have a spatial reference -system associated with it -- if it does, the ``srs`` attribute will return a -:class:`~django.contrib.gis.gdal.SpatialReference` object:: - - >>> srs = lyr.srs - >>> print srs - GEOGCS["GCS_WGS_1984", - DATUM["WGS_1984", - SPHEROID["WGS_1984",6378137.0,298.257223563]], - PRIMEM["Greenwich",0.0], - UNIT["Degree",0.0174532925199433]] - >>> srs.proj4 # PROJ.4 representation - '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ' - -Here we've noticed that the shapefile is in the popular WGS84 spatial reference -system -- in other words, the data uses units of degrees longitude and latitude. - -In addition, shapefiles also support attribute fields that may contain -additional data. Here are the fields on the World Borders layer: - - >>> print lyr.fields - ['FIPS', 'ISO2', 'ISO3', 'UN', 'NAME', 'AREA', 'POP2005', 'REGION', 'SUBREGION', 'LON', 'LAT'] - -Here we are examining the OGR types (e.g., whether a field is an integer or -a string) associated with each of the fields: - - >>> [fld.__name__ for fld in lyr.field_types] - ['OFTString', 'OFTString', 'OFTString', 'OFTInteger', 'OFTString', 'OFTInteger', 'OFTInteger', 'OFTInteger', 'OFTInteger', 'OFTReal', 'OFTReal'] - -You can iterate over each feature in the layer and extract information from both -the feature's geometry (accessed via the ``geom`` attribute) as well as the -feature's attribute fields (whose **values** are accessed via ``get()`` -method):: - - >>> for feat in lyr: - ... print feat.get('NAME'), feat.geom.num_points - ... - Guernsey 18 - Jersey 26 - South Georgia South Sandwich Islands 338 - Taiwan 363 - -:class:`~django.contrib.gis.gdal.Layer` objects may be sliced:: - - >>> lyr[0:2] - [<django.contrib.gis.gdal.feature.Feature object at 0x2f47690>, <django.contrib.gis.gdal.feature.Feature object at 0x2f47650>] - -And individual features may be retrieved by their feature ID:: - - >>> feat = lyr[234] - >>> print feat.get('NAME') - San Marino - -Here the boundary geometry for San Marino is extracted and looking -exported to WKT and GeoJSON:: - - >>> geom = feat.geom - >>> print geom.wkt - POLYGON ((12.415798 43.957954,12.450554 ... - >>> print geom.json - { "type": "Polygon", "coordinates": [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ... - - -``LayerMapping`` ----------------- - -We're going to dive right in -- create a file called ``load.py`` inside the -``world`` application, and insert the following:: - - import os - from django.contrib.gis.utils import LayerMapping - from models import WorldBorders - - world_mapping = { - 'fips' : 'FIPS', - 'iso2' : 'ISO2', - 'iso3' : 'ISO3', - 'un' : 'UN', - 'name' : 'NAME', - 'area' : 'AREA', - 'pop2005' : 'POP2005', - 'region' : 'REGION', - 'subregion' : 'SUBREGION', - 'lon' : 'LON', - 'lat' : 'LAT', - 'mpoly' : 'MULTIPOLYGON', - } - - world_shp = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data/TM_WORLD_BORDERS-0.3.shp')) - - def run(verbose=True): - lm = LayerMapping(WorldBorders, world_shp, world_mapping, - transform=False, encoding='iso-8859-1') - - lm.save(strict=True, verbose=verbose) - -A few notes about what's going on: - -* Each key in the ``world_mapping`` dictionary corresponds to a field in the - ``WorldBorders`` model, and the value is the name of the shapefile field - that data will be loaded from. -* The key ``mpoly`` for the geometry field is ``MULTIPOLYGON``, the - geometry type we wish to import as. Even if simple polygons are encountered - in the shapefile they will automatically be converted into collections prior - to insertion into the database. -* The path to the shapefile is not absolute -- in other words, if you move the - ``world`` application (with ``data`` subdirectory) to a different location, - then the script will still work. -* The ``transform`` keyword is set to ``False`` because the data in the - shapefile does not need to be converted -- it's already in WGS84 (SRID=4326). -* The ``encoding`` keyword is set to the character encoding of string values in - the shapefile. This ensures that string values are read and saved correctly - from their original encoding system. - -Afterwards, invoke the Django shell from the ``geodjango`` project directory:: - - $ python manage.py shell - -Next, import the ``load`` module, call the ``run`` routine, and watch ``LayerMapping`` -do the work:: - - >>> from world import load - >>> load.run() - - -.. _ogrinspect-intro: - -Try ``ogrinspect`` ------------------- -Now that you've seen how to define geographic models and import data with the -:ref:`ref-layermapping`, it's possible to further automate this process with -use of the :djadmin:`ogrinspect` management command. The :djadmin:`ogrinspect` -command introspects a GDAL-supported vector data source (e.g., a shapefile) and -generates a model definition and ``LayerMapping`` dictionary automatically. - -The general usage of the command goes as follows:: - - $ python manage.py ogrinspect [options] <data_source> <model_name> [options] - -Where ``data_source`` is the path to the GDAL-supported data source and -``model_name`` is the name to use for the model. Command-line options may -be used to further define how the model is generated. - -For example, the following command nearly reproduces the ``WorldBorders`` model -and mapping dictionary created above, automatically:: - - $ python manage.py ogrinspect world/data/TM_WORLD_BORDERS-0.3.shp WorldBorders --srid=4326 --mapping --multi - -A few notes about the command-line options given above: - -* The ``--srid=4326`` option sets the SRID for the geographic field. -* The ``--mapping`` option tells ``ogrinspect`` to also generate a - mapping dictionary for use with :class:`~django.contrib.gis.utils.LayerMapping`. -* The ``--multi`` option is specified so that the geographic field is a - :class:`~django.contrib.gis.db.models.MultiPolygonField` instead of just a - :class:`~django.contrib.gis.db.models.PolygonField`. - -The command produces the following output, which may be copied -directly into the ``models.py`` of a GeoDjango application:: - - # This is an auto-generated Django model module created by ogrinspect. - from django.contrib.gis.db import models - - class WorldBorders(models.Model): - fips = models.CharField(max_length=2) - iso2 = models.CharField(max_length=2) - iso3 = models.CharField(max_length=3) - un = models.IntegerField() - name = models.CharField(max_length=50) - area = models.IntegerField() - pop2005 = models.IntegerField() - region = models.IntegerField() - subregion = models.IntegerField() - lon = models.FloatField() - lat = models.FloatField() - geom = models.MultiPolygonField(srid=4326) - objects = models.GeoManager() - - # Auto-generated `LayerMapping` dictionary for WorldBorders model - worldborders_mapping = { - 'fips' : 'FIPS', - 'iso2' : 'ISO2', - 'iso3' : 'ISO3', - 'un' : 'UN', - 'name' : 'NAME', - 'area' : 'AREA', - 'pop2005' : 'POP2005', - 'region' : 'REGION', - 'subregion' : 'SUBREGION', - 'lon' : 'LON', - 'lat' : 'LAT', - 'geom' : 'MULTIPOLYGON', - } - -Spatial Queries -=============== - -Spatial Lookups ---------------- -GeoDjango extends the Django ORM and allows the use of spatial lookups. -Let's do an example where we find the ``WorldBorder`` model that contains -a point. First, fire up the management shell:: - - $ python manage.py shell - -Now, define a point of interest [#]_:: - - >>> pnt_wkt = 'POINT(-95.3385 29.7245)' - -The ``pnt_wkt`` string represents the point at -95.3385 degrees longitude, -and 29.7245 degrees latitude. The geometry is in a format known as -Well Known Text (WKT), an open standard issued by the Open Geospatial -Consortium (OGC). [#]_ Import the ``WorldBorders`` model, and perform -a ``contains`` lookup using the ``pnt_wkt`` as the parameter:: - - >>> from world.models import WorldBorders - >>> qs = WorldBorders.objects.filter(mpoly__contains=pnt_wkt) - >>> qs - [<WorldBorders: United States>] - -Here we retrieved a ``GeoQuerySet`` that has only one model: the one -for the United States (which is what we would expect). Similarly, -a :ref:`GEOS geometry object <ref-geos>` may also be used -- here the ``intersects`` -spatial lookup is combined with the ``get`` method to retrieve -only the ``WorldBorders`` instance for San Marino instead of a queryset:: - - >>> from django.contrib.gis.geos import Point - >>> pnt = Point(12.4604, 43.9420) - >>> sm = WorldBorders.objects.get(mpoly__intersects=pnt) - >>> sm - <WorldBorders: San Marino> - -The ``contains`` and ``intersects`` lookups are just a subset of what's -available -- the :ref:`ref-gis-db-api` documentation has more. - -Automatic Spatial Transformations ---------------------------------- -When querying the spatial database GeoDjango automatically transforms -geometries if they're in a different coordinate system. In the following -example, the coordinate will be expressed in terms of `EPSG SRID 32140`__, -a coordinate system specific to south Texas **only** and in units of -**meters** and not degrees:: - - >>> from django.contrib.gis.geos import * - >>> pnt = Point(954158.1, 4215137.1, srid=32140) - -Note that ``pnt`` may also constructed with EWKT, an "extended" form of -WKT that includes the SRID:: - - >>> pnt = GEOSGeometry('SRID=32140;POINT(954158.1 4215137.1)') - -When using GeoDjango's ORM, it will automatically wrap geometry values -in transformation SQL, allowing the developer to work at a higher level -of abstraction:: - - >>> qs = WorldBorders.objects.filter(mpoly__intersects=pnt) - >>> qs.query.as_sql() # Generating the SQL - ('SELECT "world_worldborders"."id", "world_worldborders"."name", "world_worldborders"."area", - "world_worldborders"."pop2005", "world_worldborders"."fips", "world_worldborders"."iso2", - "world_worldborders"."iso3", "world_worldborders"."un", "world_worldborders"."region", - "world_worldborders"."subregion", "world_worldborders"."lon", "world_worldborders"."lat", - "world_worldborders"."mpoly" FROM "world_worldborders" - WHERE ST_Intersects("world_worldborders"."mpoly", ST_Transform(%s, 4326))', - (<django.contrib.gis.db.backend.postgis.adaptor.PostGISAdaptor object at 0x25641b0>,)) - >>> qs # printing evaluates the queryset - [<WorldBorders: United States>] - -__ http://spatialreference.org/ref/epsg/32140/ - -Lazy Geometries ---------------- -Geometries come to GeoDjango in a standardized textual representation. Upon -access of the geometry field, GeoDjango creates a `GEOS geometry object <ref-geos>`, -exposing powerful functionality, such as serialization properties for -popular geospatial formats:: - - >>> sm = WorldBorders.objects.get(name='San Marino') - >>> sm.mpoly - <MultiPolygon object at 0x24c6798> - >>> sm.mpoly.wkt # WKT - MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ... - >>> sm.mpoly.wkb # WKB (as Python binary buffer) - <read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40> - >>> sm.mpoly.geojson # GeoJSON (requires GDAL) - '{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ... - -This includes access to all of the advanced geometric operations provided by -the GEOS library:: - - >>> pnt = Point(12.4604, 43.9420) - >>> sm.mpoly.contains(pnt) - True - >>> pnt.contains(sm.mpoly) - False - -``GeoQuerySet`` Methods ------------------------ - - -Putting your data on the map -============================ - -Google ------- - -Geographic Admin ----------------- - -GeoDjango extends :doc:`Django's admin application </ref/contrib/admin/index>` -to enable support for editing geometry fields. - -Basics -^^^^^^ - -GeoDjango also supplements the Django admin by allowing users to create -and modify geometries on a JavaScript slippy map (powered by `OpenLayers`_). - -Let's dive in again -- create a file called ``admin.py`` inside the -``world`` application, and insert the following:: - - from django.contrib.gis import admin - from models import WorldBorders - - admin.site.register(WorldBorders, admin.GeoModelAdmin) - -Next, edit your ``urls.py`` in the ``geodjango`` project folder to look -as follows:: - - from django.conf.urls.defaults import * - from django.contrib.gis import admin - - admin.autodiscover() - - urlpatterns = patterns('', - (r'^admin/', include(admin.site.urls)), - ) - -Start up the Django development server:: - - $ python manage.py runserver - -Finally, browse to ``http://localhost:8000/admin/``, and log in with the admin -user created after running ``syncdb``. Browse to any of the ``WorldBorders`` -entries -- the borders may be edited by clicking on a polygon and dragging -the vertexes to the desired position. - -.. _OpenLayers: http://openlayers.org/ -.. _Open Street Map: http://openstreetmap.org/ -.. _Vector Map Level 0: http://earth-info.nga.mil/publications/vmap0.html -.. _Metacarta: http://metacarta.com - -.. _osmgeoadmin-intro: - -``OSMGeoAdmin`` -^^^^^^^^^^^^^^^ - -With the :class:`~django.contrib.gis.admin.OSMGeoAdmin`, GeoDjango uses -a `Open Street Map`_ layer in the admin. -This provides more context (including street and thoroughfare details) than -available with the :class:`~django.contrib.gis.admin.GeoModelAdmin` -(which uses the `Vector Map Level 0`_ WMS data set hosted at `Metacarta`_). - -First, there are some important requirements and limitations: - -* :class:`~django.contrib.gis.admin.OSMGeoAdmin` requires that the - :ref:`spherical mercator projection be added <addgoogleprojection>` - to the to be added to the ``spatial_ref_sys`` table (PostGIS 1.3 and - below, only). -* The PROJ.4 datum shifting files must be installed (see the - :ref:`PROJ.4 installation instructions <proj4>` for more details). - -If you meet these requirements, then just substitute in the ``OSMGeoAdmin`` -option class in your ``admin.py`` file:: - - admin.site.register(WorldBorders, admin.OSMGeoAdmin) - -.. rubric:: Footnotes - -.. [#] Special thanks to Bjørn Sandvik of `thematicmapping.org <http://thematicmapping.org>`_ for providing and maintaining this data set. -.. [#] GeoDjango basic apps was written by Dane Springmeyer, Josh Livni, and Christopher Schmidt. -.. [#] Here the point is for the `University of Houston Law Center <http://www.law.uh.edu/>`_ . -.. [#] Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049. diff --git a/parts/django/docs/ref/contrib/gis/utils.txt b/parts/django/docs/ref/contrib/gis/utils.txt deleted file mode 100644 index 9f8e518..0000000 --- a/parts/django/docs/ref/contrib/gis/utils.txt +++ /dev/null @@ -1,32 +0,0 @@ -.. _ref-gis-utils: - -=================== -GeoDjango Utilities -=================== - -.. module:: django.contrib.gis.utils - :synopsis: GeoDjango's collection of utilities. - -The :mod:`django.contrib.gis.utils` module contains various utilities that are -useful in creating geospatial Web applications. - -.. toctree:: - :maxdepth: 2 - - geoip - layermapping - ogrinspect - -GeoIP -===== - -Interface to the MaxMind GeoIP library for performing IP-based geolocation -from GeoDjango. See :ref:`GeoIP reference <ref-geoip>` documentation for -more information. - -LayerMapping -============ - -The :class:`~django.contrib.gis.utils.LayerMapping` simplifies the process -of importing spatial data and attributes into your GeoDjango models. - diff --git a/parts/django/docs/ref/contrib/humanize.txt b/parts/django/docs/ref/contrib/humanize.txt deleted file mode 100644 index b5ec518..0000000 --- a/parts/django/docs/ref/contrib/humanize.txt +++ /dev/null @@ -1,100 +0,0 @@ -======================== -django.contrib.humanize -======================== - -.. module:: django.contrib.humanize - :synopsis: A set of Django template filters useful for adding a "human - touch" to data. - -A set of Django template filters useful for adding a "human touch" to data. - -To activate these filters, add ``'django.contrib.humanize'`` to your -:setting:`INSTALLED_APPS` setting. Once you've done that, use -``{% load humanize %}`` in a template, and you'll have access to the following -filters. - -.. templatefilter:: apnumber - -apnumber --------- - -For numbers 1-9, returns the number spelled out. Otherwise, returns the -number. This follows Associated Press style. - -Examples: - - * ``1`` becomes ``one``. - * ``2`` becomes ``two``. - * ``10`` becomes ``10``. - -You can pass in either an integer or a string representation of an integer. - -.. templatefilter:: intcomma - -intcomma --------- - -Converts an integer to a string containing commas every three digits. - -Examples: - - * ``4500`` becomes ``4,500``. - * ``45000`` becomes ``45,000``. - * ``450000`` becomes ``450,000``. - * ``4500000`` becomes ``4,500,000``. - -You can pass in either an integer or a string representation of an integer. - -.. templatefilter:: intword - -intword -------- - -Converts a large integer to a friendly text representation. Works best for -numbers over 1 million. - -Examples: - - * ``1000000`` becomes ``1.0 million``. - * ``1200000`` becomes ``1.2 million``. - * ``1200000000`` becomes ``1.2 billion``. - -Values up to 1000000000000000 (one quadrillion) are supported. - -You can pass in either an integer or a string representation of an integer. - -.. templatefilter:: naturalday - -naturalday ----------- - -.. versionadded:: 1.0 - -For dates that are the current day or within one day, return "today", -"tomorrow" or "yesterday", as appropriate. Otherwise, format the date using -the passed in format string. - -**Argument:** Date formatting string as described in the :tfilter:`date` tag. - -Examples (when 'today' is 17 Feb 2007): - - * ``16 Feb 2007`` becomes ``yesterday``. - * ``17 Feb 2007`` becomes ``today``. - * ``18 Feb 2007`` becomes ``tomorrow``. - * Any other day is formatted according to given argument or the - :setting:`DATE_FORMAT` setting if no argument is given. - -.. templatefilter:: ordinal - -ordinal -------- - -Converts an integer to its ordinal as a string. - -Examples: - - * ``1`` becomes ``1st``. - * ``2`` becomes ``2nd``. - * ``3`` becomes ``3rd``. - -You can pass in either an integer or a string representation of an integer. diff --git a/parts/django/docs/ref/contrib/index.txt b/parts/django/docs/ref/contrib/index.txt deleted file mode 100644 index 90edf72..0000000 --- a/parts/django/docs/ref/contrib/index.txt +++ /dev/null @@ -1,207 +0,0 @@ -==================== -``contrib`` packages -==================== - -Django aims to follow Python's `"batteries included" philosophy`_. It ships -with a variety of extra, optional tools that solve common Web-development -problems. - -This code lives in ``django/contrib`` in the Django distribution. This document -gives a rundown of the packages in ``contrib``, along with any dependencies -those packages have. - -.. admonition:: Note - - For most of these add-ons -- specifically, the add-ons that include either - models or template tags -- you'll need to add the package name (e.g., - ``'django.contrib.admin'``) to your ``INSTALLED_APPS`` setting and re-run - ``manage.py syncdb``. - -.. _"batteries included" philosophy: http://docs.python.org/tutorial/stdlib.html#batteries-included - -.. toctree:: - :maxdepth: 1 - - admin/index - auth - comments/index - contenttypes - csrf - databrowse - flatpages - formtools/index - gis/index - humanize - localflavor - markup - messages - redirects - sitemaps - sites - syndication - webdesign - -admin -===== - -The automatic Django administrative interface. For more information, see -:doc:`Tutorial 2 </intro/tutorial02>` and the -:doc:`admin documentation </ref/contrib/admin/index>`. - -Requires the auth_ and contenttypes_ contrib packages to be installed. - -auth -==== - -Django's authentication framework. - -See :doc:`/topics/auth`. - -comments -======== - -.. versionchanged:: 1.0 - The comments application has been rewriten. See :doc:`/ref/contrib/comments/upgrade` - for information on howto upgrade. - -A simple yet flexible comments system. See :doc:`/ref/contrib/comments/index`. - -contenttypes -============ - -A light framework for hooking into "types" of content, where each installed -Django model is a separate content type. - -See the :doc:`contenttypes documentation </ref/contrib/contenttypes>`. - -csrf -==== - -A middleware for preventing Cross Site Request Forgeries - -See the :doc:`csrf documentation </ref/contrib/csrf>`. - -flatpages -========= - -A framework for managing simple "flat" HTML content in a database. - -See the :doc:`flatpages documentation </ref/contrib/flatpages>`. - -Requires the sites_ contrib package to be installed as well. - -formtools -========= - -A set of high-level abstractions for Django forms (django.forms). - -django.contrib.formtools.preview --------------------------------- - -An abstraction of the following workflow: - -"Display an HTML form, force a preview, then do something with the submission." - -See the :doc:`form preview documentation </ref/contrib/formtools/form-preview>`. - -django.contrib.formtools.wizard --------------------------------- - -Splits forms across multiple Web pages. - -See the :doc:`form wizard documentation </ref/contrib/formtools/form-wizard>`. - -gis -==== - -A world-class geospatial framework built on top of Django, that enables -storage, manipulation and display of spatial data. - -See the :doc:`/ref/contrib/gis/index` documentation for more. - -humanize -======== - -A set of Django template filters useful for adding a "human touch" to data. - -See the :doc:`humanize documentation </ref/contrib/humanize>`. - -localflavor -=========== - -A collection of various Django snippets that are useful only for a particular -country or culture. For example, ``django.contrib.localflavor.us.forms`` -contains a ``USZipCodeField`` that you can use to validate U.S. zip codes. - -See the :doc:`localflavor documentation </ref/contrib/localflavor>`. - -markup -====== - -A collection of template filters that implement common markup languages - -See the :doc:`markup documentation </ref/contrib/markup>`. - -messages -======== - -.. versionchanged:: 1.2 - The messages framework was added. - -A framework for storing and retrieving temporary cookie- or session-based -messages - -See the :doc:`messages documentation </ref/contrib/messages>`. - -redirects -========= - -A framework for managing redirects. - -See the :doc:`redirects documentation </ref/contrib/redirects>`. - -sessions -======== - -A framework for storing data in anonymous sessions. - -See the :doc:`sessions documentation </topics/http/sessions>`. - -sites -===== - -A light framework that lets you operate multiple Web sites off of the same -database and Django installation. It gives you hooks for associating objects to -one or more sites. - -See the :doc:`sites documentation </ref/contrib/sites>`. - -sitemaps -======== - -A framework for generating Google sitemap XML files. - -See the :doc:`sitemaps documentation </ref/contrib/sitemaps>`. - -syndication -=========== - -A framework for generating syndication feeds, in RSS and Atom, quite easily. - -See the :doc:`syndication documentation </ref/contrib/syndication>`. - -webdesign -========= - -Helpers and utilities targeted primarily at Web *designers* rather than -Web *developers*. - -See the :doc:`Web design helpers documentation </ref/contrib/webdesign>`. - -Other add-ons -============= - -If you have an idea for functionality to include in ``contrib``, let us know! -Code it up, and post it to the `django-users mailing list`_. - -.. _django-users mailing list: http://groups.google.com/group/django-users diff --git a/parts/django/docs/ref/contrib/localflavor.txt b/parts/django/docs/ref/contrib/localflavor.txt deleted file mode 100644 index 2eb731d..0000000 --- a/parts/django/docs/ref/contrib/localflavor.txt +++ /dev/null @@ -1,842 +0,0 @@ -========================== -The "local flavor" add-ons -========================== - -.. module:: django.contrib.localflavor - :synopsis: A collection of various Django snippets that are useful only for - a particular country or culture. - -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 -:mod:`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 :doc:`forms </topics/forms/index>` framework -- for example, a -:class:`~django.contrib.localflavor.us.forms.USStateField` that knows how to -validate U.S. state abbreviations, and a -:class:`~django.contrib.localflavor.fi.forms.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.fr.forms import FRPhoneNumberField - - class MyForm(forms.Form): - my_french_phone_no = FRPhoneNumberField() - -Supported countries -=================== - -Countries currently supported by :mod:`~django.contrib.localflavor` are: - - * Argentina_ - * Australia_ - * Austria_ - * Brazil_ - * Canada_ - * Chile_ - * Czech_ - * Finland_ - * France_ - * Germany_ - * Iceland_ - * India_ - * Indonesia_ - * Ireland_ - * Italy_ - * Japan_ - * Kuwait_ - * Mexico_ - * `The Netherlands`_ - * Norway_ - * Peru_ - * Poland_ - * Portugal_ - * Romania_ - * Slovakia_ - * `South Africa`_ - * Spain_ - * Sweden_ - * Switzerland_ - * `United Kingdom`_ - * `United States of America`_ - * Uruguay_ - -The ``django.contrib.localflavor`` package also includes a ``generic`` subpackage, -containing useful code that is not specific to one particular country or culture. -Currently, it defines date, datetime and split datetime input fields based on -those from :doc:`forms </topics/forms/index>`, 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 (ar)`_ -.. _Australia: `Australia (au)`_ -.. _Austria: `Austria (at)`_ -.. _Brazil: `Brazil (br)`_ -.. _Canada: `Canada (ca)`_ -.. _Chile: `Chile (cl)`_ -.. _Czech: `Czech (cz)`_ -.. _Finland: `Finland (fi)`_ -.. _France: `France (fr)`_ -.. _Germany: `Germany (de)`_ -.. _The Netherlands: `The Netherlands (nl)`_ -.. _Iceland: `Iceland (is\_)`_ -.. _India: `India (in\_)`_ -.. _Indonesia: `Indonesia (id)`_ -.. _Ireland: `Ireland (ie)`_ -.. _Italy: `Italy (it)`_ -.. _Japan: `Japan (jp)`_ -.. _Kuwait: `Kuwait (kw)`_ -.. _Mexico: `Mexico (mx)`_ -.. _Norway: `Norway (no)`_ -.. _Peru: `Peru (pe)`_ -.. _Poland: `Poland (pl)`_ -.. _Portugal: `Portugal (pt)`_ -.. _Romania: `Romania (ro)`_ -.. _Slovakia: `Slovakia (sk)`_ -.. _South Africa: `South Africa (za)`_ -.. _Spain: `Spain (es)`_ -.. _Sweden: `Sweden (se)`_ -.. _Switzerland: `Switzerland (ch)`_ -.. _United Kingdom: `United Kingdom (uk)`_ -.. _United States of America: `United States of America (us)`_ -.. _Uruguay: `Uruguay (uy)`_ - -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 (``ar``) -============================================= - -.. class:: ar.forms.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 - -.. class:: ar.forms.ARDNIField - - A form field that validates input as a Documento Nacional de Identidad (DNI) - number. - -.. class:: ar.forms.ARCUITField - - A form field that validates input as a Codigo Unico de Identificacion - Tributaria (CUIT) number. - -.. class:: ar.forms.ARProvinceSelect - - A ``Select`` widget that uses a list of Argentina's provinces and autonomous - cities as its choices. - -Australia (``au``) -============================================= - -.. class:: au.forms.AUPostCodeField - - A form field that validates input as an Australian postcode. - -.. class:: au.forms.AUPhoneNumberField - - A form field that validates input as an Australian phone number. Valid numbers - have ten digits. - -.. class:: au.forms.AUStateSelect - - A ``Select`` widget that uses a list of Australian states/territories as its - choices. - -Austria (``at``) -================ - -.. class:: at.forms.ATZipCodeField - - A form field that validates its input as an Austrian zip code. - -.. class:: at.forms.ATStateSelect - - A ``Select`` widget that uses a list of Austrian states as its choices. - -.. class:: at.forms.ATSocialSecurityNumberField - - A form field that validates its input as an Austrian social security number. - -Brazil (``br``) -=============== - -.. class:: br.forms.BRPhoneNumberField - - A form field that validates input as a Brazilian phone number, with the format - XX-XXXX-XXXX. - -.. class:: br.forms.BRZipCodeField - - A form field that validates input as a Brazilian zip code, with the format - XXXXX-XXX. - -.. class:: br.forms.BRStateSelect - - A ``Select`` widget that uses a list of Brazilian states/territories as its - choices. - -.. class:: br.forms.BRCPFField - - A form field that validates input as `Brazilian CPF`_. - - Input can either be of the format XXX.XXX.XXX-VD or be a group of 11 digits. - -.. _Brazilian CPF: http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas - -.. class:: br.forms.BRCNPJField - - A form field that validates input as `Brazilian CNPJ`_. - - Input can either be of the format XX.XXX.XXX/XXXX-XX or be a group of 14 - digits. - -.. _Brazilian CNPJ: http://en.wikipedia.org/wiki/National_identification_number#Brazil - -Canada (``ca``) -=============== - -.. class:: ca.forms.CAPhoneNumberField - - A form field that validates input as a Canadian phone number, with the format - XXX-XXX-XXXX. - -.. class:: ca.forms.CAPostalCodeField - - A form field that validates input as a Canadian postal code, with the format - XXX XXX. - -.. class:: ca.forms.CAProvinceField - - A form field that validates input as a Canadian province name or abbreviation. - -.. class:: ca.forms.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 - -.. class:: ca.forms.CAProvinceSelect - - A ``Select`` widget that uses a list of Canadian provinces and territories as - its choices. - -Chile (``cl``) -============== - -.. class:: cl.forms.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. - -.. class:: cl.forms.CLRegionSelect - - A ``Select`` widget that uses a list of Chilean regions (Regiones) as its - choices. - -Czech (``cz``) -============== - -.. class:: cz.forms.CZPostalCodeField - - A form field that validates input as a Czech postal code. Valid formats - are XXXXX or XXX XX, where X is a digit. - -.. class:: cz.forms.CZBirthNumberField - - A form field that validates input as a Czech Birth Number. - A valid number must be in format XXXXXX/XXXX (slash is optional). - -.. class:: cz.forms.CZICNumberField - - A form field that validates input as a Czech IC number field. - -.. class:: cz.forms.CZRegionSelect - - A ``Select`` widget that uses a list of Czech regions as its choices. - -Finland (``fi``) -================ - -.. class:: fi.forms.FISocialSecurityNumber - - A form field that validates input as a Finnish social security number. - -.. class:: fi.forms.FIZipCodeField - - A form field that validates input as a Finnish zip code. Valid codes - consist of five digits. - -.. class:: fi.forms.FIMunicipalitySelect - - A ``Select`` widget that uses a list of Finnish municipalities as its - choices. - -France (``fr``) -=============== - -.. class:: fr.forms.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. - -.. class:: fr.forms.FRZipCodeField - - A form field that validates input as a French zip code. Valid codes - consist of five digits. - -.. class:: fr.forms.FRDepartmentSelect - - A ``Select`` widget that uses a list of French departments as its choices. - -Germany (``de``) -================ - -.. class:: de.forms.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 - -.. class:: de.forms.DEZipCodeField - - A form field that validates input as a German zip code. Valid codes - consist of five digits. - -.. class:: de.forms.DEStateSelect - - A ``Select`` widget that uses a list of German states as its choices. - -The Netherlands (``nl``) -======================== - -.. class:: nl.forms.NLPhoneNumberField - - A form field that validates input as a Dutch telephone number. - -.. class:: nl.forms.NLSofiNumberField - - A form field that validates input as a Dutch social security number - (SoFI/BSN). - -.. class:: nl.forms.NLZipCodeField - - A form field that validates input as a Dutch zip code. - -.. class:: nl.forms.NLProvinceSelect - - A ``Select`` widget that uses a list of Dutch provinces as its list of - choices. - -Iceland (``is_``) -================= - -.. class:: is_.forms.ISIdNumberField - - A form field that validates input as an Icelandic identification number - (kennitala). The format is XXXXXX-XXXX. - -.. class:: is_.forms.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). - -.. class:: is_.forms.ISPostalCodeSelect - - A ``Select`` widget that uses a list of Icelandic postal codes as its - choices. - -India (``in_``) -=============== - -.. class:: in.forms.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. - -.. class:: in.forms.INZipCodeField - - A form field that validates input as an Indian zip code, with the - format XXXXXXX. - -.. class:: in.forms.INStateSelect - - A ``Select`` widget that uses a list of Indian states/territories as its - choices. - -Ireland (``ie``) -================ - -.. class:: ie.forms.IECountySelect - - A ``Select`` widget that uses a list of Irish Counties as its choices. - -Indonesia (``id``) -================== - -.. class:: id.forms.IDPostCodeField - - A form field that validates input as an Indonesian post code field. - -.. class:: id.forms.IDProvinceSelect - - A ``Select`` widget that uses a list of Indonesian provinces as its choices. - -.. class:: id.forms.IDPhoneNumberField - - A form field that validates input as an Indonesian telephone number. - -.. class:: id.forms.IDLicensePlatePrefixSelect - - A ``Select`` widget that uses a list of Indonesian license plate - prefix code as its choices. - -.. class:: id.forms.IDLicensePlateField - - A form field that validates input as an Indonesian vehicle license plate. - -.. class:: id.forms.IDNationalIdentityNumberField - - A form field that validates input as an Indonesian national identity - number (`NIK`_/KTP). The output will be in the format of - 'XX.XXXX.DDMMYY.XXXX'. Dots or spaces can be used in the input to break - down the numbers. - -.. _NIK: http://en.wikipedia.org/wiki/Indonesian_identity_card - -Italy (``it``) -============== - -.. class:: it.forms.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/NSI+Informazioni+sulla+codificazione+delle+persone+fisiche - -.. class:: it.forms.ITVatNumberField - - A form field that validates Italian VAT numbers (partita IVA). - -.. class:: it.forms.ITZipCodeField - - A form field that validates input as an Italian zip code. Valid codes - must have five digits. - -.. class:: it.forms.ITProvinceSelect - - A ``Select`` widget that uses a list of Italian provinces as its choices. - -.. class:: it.forms.ITRegionSelect - - A ``Select`` widget that uses a list of Italian regions as its choices. - -Japan (``jp``) -============== - -.. class:: jp.forms.JPPostalCodeField - - A form field that validates input as a Japanese postcode. It accepts seven - digits, with or without a hyphen. - -.. class:: jp.forms.JPPrefectureSelect - - A ``Select`` widget that uses a list of Japanese prefectures as its choices. - -Kuwait (``kw``) -=============== - -.. class:: kw.forms.KWCivilIDNumberField - - A form field that validates input as a Kuwaiti Civil ID number. A valid - Civil ID number must obey the following rules: - - * The number consist of 12 digits. - * The birthdate of the person is a valid date. - * The calculated checksum equals to the last digit of the Civil ID. - -Mexico (``mx``) -=============== - -.. class:: mx.forms.MXStateSelect - - A ``Select`` widget that uses a list of Mexican states as its choices. - -Norway (``no``) -=============== - -.. class:: no.forms.NOSocialSecurityNumber - - A form field that validates input as a Norwegian social security number - (personnummer_). - -.. _personnummer: http://no.wikipedia.org/wiki/Personnummer - -.. class:: no.forms.NOZipCodeField - - A form field that validates input as a Norwegian zip code. Valid codes - have four digits. - -.. class:: no.forms.NOMunicipalitySelect - - A ``Select`` widget that uses a list of Norwegian municipalities (fylker) as - its choices. - -Peru (``pe``) -============= - -.. class:: pe.forms.PEDNIField - - A form field that validates input as a DNI (Peruvian national identity) - number. - -.. class:: pe.forms.PERUCField - - A form field that validates input as an RUC (Registro Unico de - Contribuyentes) number. Valid RUC numbers have 11 digits. - -.. class:: pe.forms.PEDepartmentSelect - - A ``Select`` widget that uses a list of Peruvian Departments as its choices. - -Poland (``pl``) -=============== - -.. class:: pl.forms.PLPESELField - - A form field that validates input as a Polish national identification number - (PESEL_). - -.. _PESEL: http://en.wikipedia.org/wiki/PESEL - -.. class:: pl.forms.PLREGONField - - 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 - -.. class:: pl.forms.PLPostalCodeField - - A form field that validates input as a Polish postal code. The valid format - is XX-XXX, where X is a digit. - -.. class:: pl.forms.PLNIPField - - 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. - -.. class:: pl.forms.PLCountySelect - - A ``Select`` widget that uses a list of Polish administrative units as its - choices. - -.. class:: pl.forms.PLProvinceSelect - - A ``Select`` widget that uses a list of Polish voivodeships (administrative - provinces) as its choices. - -Portugal (``pt``) -================= - -.. class:: pt.forms.PTZipCodeField - - A form field that validates input as a Portuguese zip code. - -.. class:: pt.forms.PTPhoneNumberField - - A form field that validates input as a Portuguese phone number. - Valid numbers have 9 digits (may include spaces) or start by 00 - or + (international). - -Romania (``ro``) -================ - -.. class:: ro.forms.ROCIFField - - A form field that validates Romanian fiscal identification codes (CIF). The - return value strips the leading RO, if given. - -.. class:: ro.forms.ROCNPField - - A form field that validates Romanian personal numeric codes (CNP). - -.. class:: ro.forms.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. - -.. class:: ro.forms.ROCountySelect - - A ``Select`` widget that uses a list of Romanian counties (judete) as its - choices. - -.. class:: ro.forms.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. - -.. class:: ro.forms.ROPhoneNumberField - - A form field that validates Romanian phone numbers, short special numbers - excluded. - -.. class:: ro.forms.ROPostalCodeField - - A form field that validates Romanian postal codes. - -Slovakia (``sk``) -================= - -.. class:: sk.forms.SKPostalCodeField - - A form field that validates input as a Slovak postal code. Valid formats - are XXXXX or XXX XX, where X is a digit. - -.. class:: sk.forms.SKDistrictSelect - - A ``Select`` widget that uses a list of Slovak districts as its choices. - -.. class:: sk.forms.SKRegionSelect - - A ``Select`` widget that uses a list of Slovak regions as its choices. - -South Africa (``za``) -===================== - -.. class:: za.forms.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. - -.. class:: za.forms.ZAPostCodeField - - A form field that validates input as a South African postcode. Valid - postcodes must have four digits. - -Spain (``es``) -============== - -.. class:: es.forms.ESIdentityCardNumberField - - A form field that validates input as a Spanish NIF/NIE/CIF (Fiscal - Identification Number) code. - -.. class:: es.forms.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. - -.. class:: es.forms.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. - -.. class:: es.forms.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. - -.. class:: es.forms.ESProvinceSelect - - A ``Select`` widget that uses a list of Spanish provinces as its choices. - -.. class:: es.forms.ESRegionSelect - - A ``Select`` widget that uses a list of Spanish regions as its choices. - -Sweden (``se``) -=============== - -.. class:: se.forms.SECountySelect - - A Select form widget that uses a list of the Swedish counties (län) as its - choices. - - The cleaned value is the official county code -- see - http://en.wikipedia.org/wiki/Counties_of_Sweden for a list. - -.. class:: se.forms.SEOrganisationNumber - - A form field that validates input as a Swedish organisation number - (organisationsnummer). - - It accepts the same input as SEPersonalIdentityField (for sole - proprietorships (enskild firma). However, co-ordination numbers are not - accepted. - - It also accepts ordinary Swedish organisation numbers with the format - NNNNNNNNNN. - - The return value will be YYYYMMDDXXXX for sole proprietors, and NNNNNNNNNN - for other organisations. - -.. class:: se.forms.SEPersonalIdentityNumber - - A form field that validates input as a Swedish personal identity number - (personnummer). - - The correct formats are YYYYMMDD-XXXX, YYYYMMDDXXXX, YYMMDD-XXXX, - YYMMDDXXXX and YYMMDD+XXXX. - - A \+ indicates that the person is older than 100 years, which will be taken - into consideration when the date is validated. - - The checksum will be calculated and checked. The birth date is checked - to be a valid date. - - By default, co-ordination numbers (samordningsnummer) will be accepted. To - only allow real personal identity numbers, pass the keyword argument - coordination_number=False to the constructor. - - The cleaned value will always have the format YYYYMMDDXXXX. - -.. class:: se.forms.SEPostalCodeField - - A form field that validates input as a Swedish postal code (postnummer). - Valid codes consist of five digits (XXXXX). The number can optionally be - formatted with a space after the third digit (XXX XX). - - The cleaned value will never contain the space. - -Switzerland (``ch``) -==================== - -.. class:: ch.forms.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. - -.. class:: ch.forms.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. - -.. class:: ch.forms.CHZipCodeField - - A form field that validates input as a Swiss zip code. Valid codes - consist of four digits. - -.. class:: ch.forms.CHStateSelect - - A ``Select`` widget that uses a list of Swiss states as its choices. - -United Kingdom (``uk``) -======================= - -.. class:: uk.forms.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.cabinetoffice.gov.uk/media/291293/bs7666-v2-0.xml. - -.. class:: uk.forms.UKCountySelect - - A ``Select`` widget that uses a list of UK counties/regions as its choices. - -.. class:: uk.forms.UKNationSelect - - A ``Select`` widget that uses a list of UK nations as its choices. - -United States of America (``us``) -================================= - -.. class:: us.forms.USPhoneNumberField - - A form field that validates input as a U.S. phone number. - -.. class:: us.forms.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) - -.. class:: us.forms.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. - -.. class:: us.forms.USZipCodeField - - A form field that validates input as a U.S. ZIP code. Valid formats are - XXXXX or XXXXX-XXXX. - -.. class:: us.forms.USStateSelect - - A form ``Select`` widget that uses a list of U.S. states/territories as its - choices. - -.. class:: us.models.PhoneNumberField - - A :class:`CharField` that checks that the value is a valid U.S.A.-style phone - number (in the format ``XXX-XXX-XXXX``). - -.. class:: us.models.USStateField - - A model field that forms represent as a ``forms.USStateField`` field and - stores the two-letter U.S. state abbreviation in the database. - -Uruguay (``uy``) -================ - -.. class:: uy.forms.UYCIField - - A field that validates Uruguayan 'Cedula de identidad' (CI) numbers. - -.. class:: uy.forms.UYDepartamentSelect - - A ``Select`` widget that uses a list of Uruguayan departaments as its - choices. diff --git a/parts/django/docs/ref/contrib/markup.txt b/parts/django/docs/ref/contrib/markup.txt deleted file mode 100644 index 9282313..0000000 --- a/parts/django/docs/ref/contrib/markup.txt +++ /dev/null @@ -1,42 +0,0 @@ -===================== -django.contrib.markup -===================== - -.. module:: django.contrib.markup - :synopsis: A collection of template filters that implement common markup languages. - -Django provides template filters that implement the following markup -languages: - - * ``textile`` -- implements `Textile`_ -- requires `PyTextile`_ - * ``markdown`` -- implements `Markdown`_ -- requires `Python-markdown`_ - * ``restructuredtext`` -- implements `reST (reStructured Text)`_ - -- requires `doc-utils`_ - -In each case, the filter expects formatted markup as a string and -returns a string representing the marked-up text. For example, the -``textile`` filter converts text that is marked-up in Textile format -to HTML. - -To activate these filters, add ``'django.contrib.markup'`` to your -:setting:`INSTALLED_APPS` setting. Once you've done that, use -``{% load markup %}`` in a template, and you'll have access to these filters. -For more documentation, read the source code in -:file:`django/contrib/markup/templatetags/markup.py`. - -.. _Textile: http://en.wikipedia.org/wiki/Textile_%28markup_language%29 -.. _Markdown: http://en.wikipedia.org/wiki/Markdown -.. _reST (reStructured Text): http://en.wikipedia.org/wiki/ReStructuredText -.. _PyTextile: http://loopcore.com/python-textile/ -.. _Python-markdown: http://www.freewisdom.org/projects/python-markdown -.. _doc-utils: http://docutils.sf.net/ - -reStructured Text ------------------ - -When using the ``restructuredtext`` markup filter you can define a -:setting:`RESTRUCTUREDTEXT_FILTER_SETTINGS` in your django settings to -override the default writer settings. See the `restructuredtext writer -settings`_ for details on what these settings are. - -.. _restructuredtext writer settings: http://docutils.sourceforge.net/docs/user/config.html#html4css1-writer diff --git a/parts/django/docs/ref/contrib/messages.txt b/parts/django/docs/ref/contrib/messages.txt deleted file mode 100644 index 3081f27..0000000 --- a/parts/django/docs/ref/contrib/messages.txt +++ /dev/null @@ -1,411 +0,0 @@ -====================== -The messages framework -====================== - -.. module:: django.contrib.messages - :synopsis: Provides cookie- and session-based temporary message storage. - -Django provides full support for cookie- and session-based messaging, for -both anonymous and authenticated clients. The messages framework allows you -to temporarily store messages in one request and retrieve them for display -in a subsequent request (usually the next one). Every message is tagged -with a specific ``level`` that determines its priority (e.g., ``info``, -``warning``, or ``error``). - -.. versionadded:: 1.2 - The messages framework was added. - -Enabling messages -================= - -Messages are implemented through a :doc:`middleware </ref/middleware>` -class and corresponding :doc:`context processor </ref/templates/api>`. - -To enable message functionality, do the following: - - * Edit the :setting:`MIDDLEWARE_CLASSES` setting and make sure - it contains ``'django.contrib.messages.middleware.MessageMiddleware'``. - - If you are using a :ref:`storage backend <message-storage-backends>` that - relies on :doc:`sessions </topics/http/sessions>` (the default), - ``'django.contrib.sessions.middleware.SessionMiddleware'`` must be - enabled and appear before ``MessageMiddleware`` in your - :setting:`MIDDLEWARE_CLASSES`. - - * Edit the :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting and make sure - it contains ``'django.contrib.messages.context_processors.messages'``. - - * Add ``'django.contrib.messages'`` to your :setting:`INSTALLED_APPS` - setting - -The default ``settings.py`` created by ``django-admin.py startproject`` has -``MessageMiddleware`` activated and the ``django.contrib.messages`` app -installed. Also, the default value for :setting:`TEMPLATE_CONTEXT_PROCESSORS` -contains ``'django.contrib.messages.context_processors.messages'``. - -If you don't want to use messages, you can remove the -``MessageMiddleware`` line from :setting:`MIDDLEWARE_CLASSES`, the ``messages`` -context processor from :setting:`TEMPLATE_CONTEXT_PROCESSORS` and -``'django.contrib.messages'`` from your :setting:`INSTALLED_APPS`. - -Configuring the message engine -============================== - -.. _message-storage-backends: - -Storage backends ----------------- - -The messages framework can use different backends to store temporary messages. -To change which backend is being used, add a `MESSAGE_STORAGE`_ to your -settings, referencing the module and class of the storage class. For -example:: - - MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' - -The value should be the full path of the desired storage class. - -Four storage classes are included: - -``'django.contrib.messages.storage.session.SessionStorage'`` - This class stores all messages inside of the request's session. It - requires Django's ``contrib.sessions`` application. - -``'django.contrib.messages.storage.cookie.CookieStorage'`` - This class stores the message data in a cookie (signed with a secret hash - to prevent manipulation) to persist notifications across requests. Old - messages are dropped if the cookie data size would exceed 4096 bytes. - -``'django.contrib.messages.storage.fallback.FallbackStorage'`` - This class first uses CookieStorage for all messages, falling back to using - SessionStorage for the messages that could not fit in a single cookie. - - Since it is uses SessionStorage, it also requires Django's - ``contrib.session`` application. - -``'django.contrib.messages.storage.user_messages.LegacyFallbackStorage'`` - This is the default temporary storage class. - - This class extends FallbackStorage and adds compatibility methods to - to retrieve any messages stored in the user Message model by code that - has not yet been updated to use the new API. This storage is temporary - (because it makes use of code that is pending deprecation) and will be - removed in Django 1.4. At that time, the default storage will become - ``django.contrib.messages.storage.fallback.FallbackStorage``. For more - information, see `LegacyFallbackStorage`_ below. - -To write your own storage class, subclass the ``BaseStorage`` class in -``django.contrib.messages.storage.base`` and implement the ``_get`` and -``_store`` methods. - -LegacyFallbackStorage -^^^^^^^^^^^^^^^^^^^^^ - -The ``LegacyFallbackStorage`` is a temporary tool to facilitate the transition -from the deprecated ``user.message_set`` API and will be removed in Django 1.4 -according to Django's standard deprecation policy. For more information, see -the full :doc:`release process documentation </internals/release-process>`. - -In addition to the functionality in the ``FallbackStorage``, it adds a custom, -read-only storage class that retrieves messages from the user ``Message`` -model. Any messages that were stored in the ``Message`` model (e.g., by code -that has not yet been updated to use the messages framework) will be retrieved -first, followed by those stored in a cookie and in the session, if any. Since -messages stored in the ``Message`` model do not have a concept of levels, they -will be assigned the ``INFO`` level by default. - -Message levels --------------- - -The messages framework is based on a configurable level architecture similar -to that of the Python logging module. Message levels allow you to group -messages by type so they can be filtered or displayed differently in views and -templates. - -The built-in levels (which can be imported from ``django.contrib.messages`` -directly) are: - -=========== ======== -Constant Purpose -=========== ======== -``DEBUG`` Development-related messages that will be ignored (or removed) in a production deployment -``INFO`` Informational messages for the user -``SUCCESS`` An action was successful, e.g. "Your profile was updated successfully" -``WARNING`` A failure did not occur but may be imminent -``ERROR`` An action was **not** successful or some other failure occurred -=========== ======== - -The `MESSAGE_LEVEL`_ setting can be used to change the minimum recorded level -(or it can be `changed per request`_). Attempts to add messages of a level less -than this will be ignored. - -.. _`changed per request`: `Changing the minimum recorded level per-request`_ - -Message tags ------------- - -Message tags are a string representation of the message level plus any -extra tags that were added directly in the view (see -`Adding extra message tags`_ below for more details). Tags are stored in a -string and are separated by spaces. Typically, message tags -are used as CSS classes to customize message style based on message type. By -default, each level has a single tag that's a lowercase version of its own -constant: - -============== =========== -Level Constant Tag -============== =========== -``DEBUG`` ``debug`` -``INFO`` ``info`` -``SUCCESS`` ``success`` -``WARNING`` ``warning`` -``ERROR`` ``error`` -============== =========== - -To change the default tags for a message level (either built-in or custom), -set the `MESSAGE_TAGS`_ setting to a dictionary containing the levels -you wish to change. As this extends the default tags, you only need to provide -tags for the levels you wish to override:: - - from django.contrib.messages import constants as messages - MESSAGE_TAGS = { - messages.INFO: '', - 50: 'critical', - } - -Using messages in views and templates -===================================== - -Adding a message ----------------- - -To add a message, call:: - - from django.contrib import messages - messages.add_message(request, messages.INFO, 'Hello world.') - -Some shortcut methods provide a standard way to add messages with commonly -used tags (which are usually represented as HTML classes for the message):: - - messages.debug(request, '%s SQL statements were executed.' % count) - messages.info(request, 'Three credits remain in your account.') - messages.success(request, 'Profile details updated.') - messages.warning(request, 'Your account expires in three days.') - messages.error(request, 'Document deleted.') - -Displaying messages -------------------- - -In your template, use something like:: - - {% if messages %} - <ul class="messages"> - {% for message in messages %} - <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> - {% endfor %} - </ul> - {% endif %} - -If you're using the context processor, your template should be rendered with a -``RequestContext``. Otherwise, ensure ``messages`` is available to -the template context. - -Creating custom message levels ------------------------------- - -Messages levels are nothing more than integers, so you can define your own -level constants and use them to create more customized user feedback, e.g.:: - - CRITICAL = 50 - - def my_view(request): - messages.add_message(request, CRITICAL, 'A serious error occurred.') - -When creating custom message levels you should be careful to avoid overloading -existing levels. The values for the built-in levels are: - -.. _message-level-constants: - -============== ===== -Level Constant Value -============== ===== -``DEBUG`` 10 -``INFO`` 20 -``SUCCESS`` 25 -``WARNING`` 30 -``ERROR`` 40 -============== ===== - -If you need to identify the custom levels in your HTML or CSS, you need to -provide a mapping via the `MESSAGE_TAGS`_ setting. - -.. note:: - If you are creating a reusable application, it is recommended to use - only the built-in `message levels`_ and not rely on any custom levels. - -Changing the minimum recorded level per-request ------------------------------------------------ - -The minimum recorded level can be set per request via the ``set_level`` -method:: - - from django.contrib import messages - - # Change the messages level to ensure the debug message is added. - messages.set_level(request, messages.DEBUG) - messages.debug(request, 'Test message...') - - # In another request, record only messages with a level of WARNING and higher - messages.set_level(request, messages.WARNING) - messages.success(request, 'Your profile was updated.') # ignored - messages.warning(request, 'Your account is about to expire.') # recorded - - # Set the messages level back to default. - messages.set_level(request, None) - -Similarly, the current effective level can be retrieved with ``get_level``:: - - from django.contrib import messages - current_level = messages.get_level(request) - -For more information on how the minimum recorded level functions, see -`Message levels`_ above. - -Adding extra message tags -------------------------- - -For more direct control over message tags, you can optionally provide a string -containing extra tags to any of the add methods:: - - messages.add_message(request, messages.INFO, 'Over 9000!', - extra_tags='dragonball') - messages.error(request, 'Email box full', extra_tags='email') - -Extra tags are added before the default tag for that level and are space -separated. - -Failing silently when the message framework is disabled -------------------------------------------------------- - -If you're writing a reusable app (or other piece of code) and want to include -messaging functionality, but don't want to require your users to enable it -if they don't want to, you may pass an additional keyword argument -``fail_silently=True`` to any of the ``add_message`` family of methods. For -example:: - - messages.add_message(request, messages.SUCCESS, 'Profile details updated.', - fail_silently=True) - messages.info(request, 'Hello world.', fail_silently=True) - -Internally, Django uses this functionality in the create, update, and delete -:doc:`generic views </topics/http/generic-views>` so that they work even if the -message framework is disabled. - -.. note:: - Setting ``fail_silently=True`` only hides the ``MessageFailure`` that would - otherwise occur when the messages framework disabled and one attempts to - use one of the ``add_message`` family of methods. It does not hide failures - that may occur for other reasons. - -Expiration of messages -====================== - -The messages are marked to be cleared when the storage instance is iterated -(and cleared when the response is processed). - -To avoid the messages being cleared, you can set the messages storage to -``False`` after iterating:: - - storage = messages.get_messages(request) - for message in storage: - do_something_with(message) - storage.used = False - -Behavior of parallel requests -============================= - -Due to the way cookies (and hence sessions) work, **the behavior of any -backends that make use of cookies or sessions is undefined when the same -client makes multiple requests that set or get messages in parallel**. For -example, if a client initiates a request that creates a message in one window -(or tab) and then another that fetches any uniterated messages in another -window, before the first window redirects, the message may appear in the -second window instead of the first window where it may be expected. - -In short, when multiple simultaneous requests from the same client are -involved, messages are not guaranteed to be delivered to the same window that -created them nor, in some cases, at all. Note that this is typically not a -problem in most applications and will become a non-issue in HTML5, where each -window/tab will have its own browsing context. - -Settings -======== - -A few :doc:`Django settings </ref/settings>` give you control over message -behavior: - -MESSAGE_LEVEL -------------- - -Default: ``messages.INFO`` - -This sets the minimum message that will be saved in the message storage. See -`Message levels`_ above for more details. - -.. admonition:: Important - - If you override ``MESSAGE_LEVEL`` in your settings file and rely on any of - the built-in constants, you must import the constants module directly to - avoid the potential for circular imports, e.g.:: - - from django.contrib.messages import constants as message_constants - MESSAGE_LEVEL = message_constants.DEBUG - - If desired, you may specify the numeric values for the constants directly - according to the values in the above :ref:`constants table - <message-level-constants>`. - -MESSAGE_STORAGE ---------------- - -Default: ``'django.contrib.messages.storage.user_messages.LegacyFallbackStorage'`` - -Controls where Django stores message data. Valid values are: - - * ``'django.contrib.messages.storage.fallback.FallbackStorage'`` - * ``'django.contrib.messages.storage.session.SessionStorage'`` - * ``'django.contrib.messages.storage.cookie.CookieStorage'`` - * ``'django.contrib.messages.storage.user_messages.LegacyFallbackStorage'`` - -See `Storage backends`_ for more details. - -MESSAGE_TAGS ------------- - -Default:: - - {messages.DEBUG: 'debug', - messages.INFO: 'info', - messages.SUCCESS: 'success', - messages.WARNING: 'warning', - messages.ERROR: 'error',} - -This sets the mapping of message level to message tag, which is typically -rendered as a CSS class in HTML. If you specify a value, it will extend -the default. This means you only have to specify those values which you need -to override. See `Displaying messages`_ above for more details. - -.. admonition:: Important - - If you override ``MESSAGE_TAGS`` in your settings file and rely on any of - the built-in constants, you must import the ``constants`` module directly to - avoid the potential for circular imports, e.g.:: - - from django.contrib.messages import constants as message_constants - MESSAGE_TAGS = {message_constants.INFO: ''} - - If desired, you may specify the numeric values for the constants directly - according to the values in the above :ref:`constants table - <message-level-constants>`. - -.. _Django settings: ../settings/ diff --git a/parts/django/docs/ref/contrib/redirects.txt b/parts/django/docs/ref/contrib/redirects.txt deleted file mode 100644 index f1a58cb..0000000 --- a/parts/django/docs/ref/contrib/redirects.txt +++ /dev/null @@ -1,70 +0,0 @@ -================= -The redirects app -================= - -.. module:: django.contrib.redirects - :synopsis: A framework for managing redirects. - -Django comes with an optional redirects application. It lets you store simple -redirects in a database and handles the redirecting for you. - -Installation -============ - -To install the redirects app, follow these steps: - - 1. Add ``'django.contrib.redirects'`` to your :setting:`INSTALLED_APPS` - setting. - 2. Add ``'django.contrib.redirects.middleware.RedirectFallbackMiddleware'`` - to your :setting:`MIDDLEWARE_CLASSES` setting. - 3. Run the command :djadmin:`manage.py syncdb <syncdb>`. - -How it works -============ - -``manage.py syncdb`` creates a ``django_redirect`` table in your database. This -is a simple lookup table with ``site_id``, ``old_path`` and ``new_path`` fields. - -The ``RedirectFallbackMiddleware`` does all of the work. Each time any Django -application raises a 404 error, this middleware checks the redirects database -for the requested URL as a last resort. Specifically, it checks for a redirect -with the given ``old_path`` with a site ID that corresponds to the -:setting:`SITE_ID` setting. - - * If it finds a match, and ``new_path`` is not empty, it redirects to - ``new_path``. - * If it finds a match, and ``new_path`` is empty, it sends a 410 ("Gone") - HTTP header and empty (content-less) response. - * If it doesn't find a match, the request continues to be processed as - usual. - -The middleware only gets activated for 404s -- not for 500s or responses of any -other status code. - -Note that the order of :setting:`MIDDLEWARE_CLASSES` matters. Generally, you -can put ``RedirectFallbackMiddleware`` at the end of the list, because it's a -last resort. - -For more on middleware, read the :doc:`middleware docs -</topics/http/middleware>`. - -How to add, change and delete redirects -======================================= - -Via the admin interface ------------------------ - -If you've activated the automatic Django admin interface, you should see a -"Redirects" section on the admin index page. Edit redirects as you edit any -other object in the system. - -Via the Python API ------------------- - -.. class:: models.Redirect - - Redirects are represented by a standard :doc:`Django model </topics/db/models>`, - which lives in `django/contrib/redirects/models.py`_. You can access redirect - objects via the :doc:`Django database API </topics/db/queries>`. - -.. _django/contrib/redirects/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/redirects/models.py diff --git a/parts/django/docs/ref/contrib/sitemaps.txt b/parts/django/docs/ref/contrib/sitemaps.txt deleted file mode 100644 index eb29c6c..0000000 --- a/parts/django/docs/ref/contrib/sitemaps.txt +++ /dev/null @@ -1,351 +0,0 @@ -===================== -The sitemap framework -===================== - -.. module:: django.contrib.sitemaps - :synopsis: A framework for generating Google sitemap XML files. - -Django comes with a high-level sitemap-generating framework that makes -creating sitemap_ XML files easy. - -.. _sitemap: http://www.sitemaps.org/ - -Overview -======== - -A sitemap is an XML file on your Web site that tells search-engine indexers how -frequently your pages change and how "important" certain pages are in relation -to other pages on your site. This information helps search engines index your -site. - -The Django sitemap framework automates the creation of this XML file by letting -you express this information in Python code. - -It works much like Django's :doc:`syndication framework -</ref/contrib/syndication>`. To create a sitemap, just write a -:class:`~django.contrib.sitemaps.Sitemap` class and point to it in your -:doc:`URLconf </topics/http/urls>`. - -Installation -============ - -To install the sitemap app, follow these steps: - - 1. Add ``'django.contrib.sitemaps'`` to your :setting:`INSTALLED_APPS` - setting. - - 2. Make sure ``'django.template.loaders.app_directories.Loader'`` - is in your :setting:`TEMPLATE_LOADERS` setting. It's in there by default, - so you'll only need to change this if you've changed that setting. - - 3. Make sure you've installed the - :mod:`sites framework <django.contrib.sites>`. - -(Note: The sitemap application doesn't install any database tables. The only -reason it needs to go into :setting:`INSTALLED_APPS` is so that the -:func:`~django.template.loaders.app_directories.Loader` template -loader can find the default templates.) - -Initialization -============== - -To activate sitemap generation on your Django site, add this line to your -:doc:`URLconf </topics/http/urls>`:: - - (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) - -This tells Django to build a sitemap when a client accesses :file:`/sitemap.xml`. - -The name of the sitemap file is not important, but the location is. Search -engines will only index links in your sitemap for the current URL level and -below. For instance, if :file:`sitemap.xml` lives in your root directory, it may -reference any URL in your site. However, if your sitemap lives at -:file:`/content/sitemap.xml`, it may only reference URLs that begin with -:file:`/content/`. - -The sitemap view takes an extra, required argument: ``{'sitemaps': sitemaps}``. -``sitemaps`` should be a dictionary that maps a short section label (e.g., -``blog`` or ``news``) to its :class:`~django.contrib.sitemaps.Sitemap` class -(e.g., ``BlogSitemap`` or ``NewsSitemap``). It may also map to an *instance* of -a :class:`~django.contrib.sitemaps.Sitemap` class (e.g., -``BlogSitemap(some_var)``). - -Sitemap classes -=============== - -A :class:`~django.contrib.sitemaps.Sitemap` class is a simple Python -class that represents a "section" of entries in your sitemap. For example, -one :class:`~django.contrib.sitemaps.Sitemap` class could represent -all the entries of your Weblog, while another could represent all of the -events in your events calendar. - -In the simplest case, all these sections get lumped together into one -:file:`sitemap.xml`, but it's also possible to use the framework to generate a -sitemap index that references individual sitemap files, one per section. (See -`Creating a sitemap index`_ below.) - -:class:`~django.contrib.sitemaps.Sitemap` classes must subclass -``django.contrib.sitemaps.Sitemap``. They can live anywhere in your codebase. - -A simple example -================ - -Let's assume you have a blog system, with an ``Entry`` model, and you want your -sitemap to include all the links to your individual blog entries. Here's how -your sitemap class might look:: - - from django.contrib.sitemaps import Sitemap - from blog.models import Entry - - class BlogSitemap(Sitemap): - changefreq = "never" - priority = 0.5 - - def items(self): - return Entry.objects.filter(is_draft=False) - - def lastmod(self, obj): - return obj.pub_date - -Note: - - * :attr:`~Sitemap.changefreq` and :attr:`~Sitemap.priority` are class - attributes corresponding to ``<changefreq>`` and ``<priority>`` elements, - respectively. They can be made callable as functions, as - :attr:`~Sitemap.lastmod` was in the example. - * :attr:`~Sitemap.items()` is simply a method that returns a list of - objects. The objects returned will get passed to any callable methods - corresponding to a sitemap property (:attr:`~Sitemap.location`, - :attr:`~Sitemap.lastmod`, :attr:`~Sitemap.changefreq`, and - :attr:`~Sitemap.priority`). - * :attr:`~Sitemap.lastmod` should return a Python ``datetime`` object. - * There is no :attr:`~Sitemap.location` method in this example, but you - can provide it in order to specify the URL for your object. By default, - :attr:`~Sitemap.location()` calls ``get_absolute_url()`` on each object - and returns the result. - -Sitemap class reference -======================= - -.. class:: Sitemap - - A ``Sitemap`` class can define the following methods/attributes: - - .. attribute:: Sitemap.items - - **Required.** A method that returns a list of objects. The framework - doesn't care what *type* of objects they are; all that matters is that - these objects get passed to the :attr:`~Sitemap.location()`, - :attr:`~Sitemap.lastmod()`, :attr:`~Sitemap.changefreq()` and - :attr:`~Sitemap.priority()` methods. - - .. attribute:: Sitemap.location - - **Optional.** Either a method or attribute. - - If it's a method, it should return the absolute path for a given object - as returned by :attr:`~Sitemap.items()`. - - If it's an attribute, its value should be a string representing an - absolute path to use for *every* object returned by - :attr:`~Sitemap.items()`. - - In both cases, "absolute path" means a URL that doesn't include the - protocol or domain. Examples: - - * Good: :file:`'/foo/bar/'` - * Bad: :file:`'example.com/foo/bar/'` - * Bad: :file:`'http://example.com/foo/bar/'` - - If :attr:`~Sitemap.location` isn't provided, the framework will call - the ``get_absolute_url()`` method on each object as returned by - :attr:`~Sitemap.items()`. - - .. attribute:: Sitemap.lastmod - - **Optional.** Either a method or attribute. - - If it's a method, it should take one argument -- an object as returned by - :attr:`~Sitemap.items()` -- and return that object's last-modified date/time, as a Python - ``datetime.datetime`` object. - - If it's an attribute, its value should be a Python ``datetime.datetime`` object - representing the last-modified date/time for *every* object returned by - :attr:`~Sitemap.items()`. - - .. attribute:: Sitemap.changefreq - - **Optional.** Either a method or attribute. - - If it's a method, it should take one argument -- an object as returned by - :attr:`~Sitemap.items()` -- and return that object's change frequency, as a Python string. - - If it's an attribute, its value should be a string representing the change - frequency of *every* object returned by :attr:`~Sitemap.items()`. - - Possible values for :attr:`~Sitemap.changefreq`, whether you use a method or attribute, are: - - * ``'always'`` - * ``'hourly'`` - * ``'daily'`` - * ``'weekly'`` - * ``'monthly'`` - * ``'yearly'`` - * ``'never'`` - - .. method:: Sitemap.priority - - **Optional.** Either a method or attribute. - - If it's a method, it should take one argument -- an object as returned by - :attr:`~Sitemap.items()` -- and return that object's priority, as either a string or float. - - If it's an attribute, its value should be either a string or float representing - the priority of *every* object returned by :attr:`~Sitemap.items()`. - - Example values for :attr:`~Sitemap.priority`: ``0.4``, ``1.0``. The default priority of a - page is ``0.5``. See the `sitemaps.org documentation`_ for more. - - .. _sitemaps.org documentation: http://www.sitemaps.org/protocol.html#prioritydef - -Shortcuts -========= - -The sitemap framework provides a couple convenience classes for common cases: - -.. class:: FlatPageSitemap - - The :class:`django.contrib.sitemaps.FlatPageSitemap` class looks at all - publicly visible :mod:`flatpages <django.contrib.flatpages>` - defined for the current :setting:`SITE_ID` (see the - :mod:`sites documentation <django.contrib.sites>`) and - creates an entry in the sitemap. These entries include only the - :attr:`~Sitemap.location` attribute -- not :attr:`~Sitemap.lastmod`, - :attr:`~Sitemap.changefreq` or :attr:`~Sitemap.priority`. - -.. class:: GenericSitemap - - The :class:`django.contrib.sitemaps.GenericSitemap` class works with any - :doc:`generic views </ref/generic-views>` you already have. - To use it, create an instance, passing in the same :data:`info_dict` you pass to - the generic views. The only requirement is that the dictionary have a - :data:`queryset` entry. It may also have a :data:`date_field` entry that specifies a - date field for objects retrieved from the :data:`queryset`. This will be used for - the :attr:`~Sitemap.lastmod` attribute in the generated sitemap. You may - also pass :attr:`~Sitemap.priority` and :attr:`~Sitemap.changefreq` - keyword arguments to the :class:`~django.contrib.sitemaps.GenericSitemap` - constructor to specify these attributes for all URLs. - -Example -------- - -Here's an example of a :doc:`URLconf </topics/http/urls>` using both:: - - from django.conf.urls.defaults import * - from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap - from blog.models import Entry - - info_dict = { - 'queryset': Entry.objects.all(), - 'date_field': 'pub_date', - } - - sitemaps = { - 'flatpages': FlatPageSitemap, - 'blog': GenericSitemap(info_dict, priority=0.6), - } - - urlpatterns = patterns('', - # some generic view using info_dict - # ... - - # the sitemap - (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) - ) - -.. _URLconf: ../url_dispatch/ - -Creating a sitemap index -======================== - -The sitemap framework also has the ability to create a sitemap index that -references individual sitemap files, one per each section defined in your -:data:`sitemaps` dictionary. The only differences in usage are: - - * You use two views in your URLconf: :func:`django.contrib.sitemaps.views.index` - and :func:`django.contrib.sitemaps.views.sitemap`. - * The :func:`django.contrib.sitemaps.views.sitemap` view should take a - :data:`section` keyword argument. - -Here's what the relevant URLconf lines would look like for the example above:: - - (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}), - (r'^sitemap-(?P<section>.+)\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}), - -This will automatically generate a :file:`sitemap.xml` file that references both -:file:`sitemap-flatpages.xml` and :file:`sitemap-blog.xml`. The -:class:`~django.contrib.sitemaps.Sitemap` classes and the :data:`sitemaps` dict -don't change at all. - -You should create an index file if one of your sitemaps has more than 50,000 -URLs. In this case, Django will automatically paginate the sitemap, and the -index will reflect that. - -Pinging Google -============== - -You may want to "ping" Google when your sitemap changes, to let it know to -reindex your site. The sitemaps framework provides a function to do just -that: :func:`django.contrib.sitemaps.ping_google()`. - -.. function:: ping_google - - :func:`ping_google` takes an optional argument, :data:`sitemap_url`, - which should be the absolute path to your site's sitemap (e.g., - :file:`'/sitemap.xml'`). If this argument isn't provided, - :func:`ping_google` will attempt to figure out your - sitemap by performing a reverse looking in your URLconf. - - :func:`ping_google` raises the exception - :exc:`django.contrib.sitemaps.SitemapNotFound` if it cannot determine your - sitemap URL. - -.. admonition:: Register with Google first! - - The :func:`ping_google` command only works if you have registered your - site with `Google Webmaster Tools`_. - -.. _`Google Webmaster Tools`: http://www.google.com/webmasters/tools/ - -One useful way to call :func:`ping_google` is from a model's ``save()`` -method:: - - from django.contrib.sitemaps import ping_google - - class Entry(models.Model): - # ... - def save(self, force_insert=False, force_update=False): - super(Entry, self).save(force_insert, force_update) - try: - ping_google() - except Exception: - # Bare 'except' because we could get a variety - # of HTTP-related exceptions. - pass - -A more efficient solution, however, would be to call :func:`ping_google` from a -cron script, or some other scheduled task. The function makes an HTTP request -to Google's servers, so you may not want to introduce that network overhead -each time you call ``save()``. - -Pinging Google via `manage.py` ------------------------------- - -.. django-admin:: ping_google - -.. versionadded:: 1.0 - -Once the sitemaps application is added to your project, you may also -ping Google using the ``ping_google`` management command:: - - python manage.py ping_google [/sitemap.xml] diff --git a/parts/django/docs/ref/contrib/sites.txt b/parts/django/docs/ref/contrib/sites.txt deleted file mode 100644 index 6d795d0..0000000 --- a/parts/django/docs/ref/contrib/sites.txt +++ /dev/null @@ -1,415 +0,0 @@ -===================== -The "sites" framework -===================== - -.. module:: django.contrib.sites - :synopsis: Lets you operate multiple Web sites from the same database and - Django project - -Django comes with an optional "sites" framework. It's a hook for associating -objects and functionality to particular Web sites, and it's a holding place for -the domain names and "verbose" names of your Django-powered sites. - -Use it if your single Django installation powers more than one site and you -need to differentiate between those sites in some way. - -The whole sites framework is based on a simple model: - -.. class:: django.contrib.sites.models.Site - -This model has :attr:`~django.contrib.sites.models.Site.domain` and -:attr:`~django.contrib.sites.models.Site.name` fields. The :setting:`SITE_ID` -setting specifies the database ID of the -:class:`~django.contrib.sites.models.Site` object associated with that -particular settings file. - -How you use this is up to you, but Django uses it in a couple of ways -automatically via simple conventions. - -Example usage -============= - -Why would you use sites? It's best explained through examples. - -Associating content with multiple sites ---------------------------------------- - -The Django-powered sites LJWorld.com_ and Lawrence.com_ are operated by the -same news organization -- the Lawrence Journal-World newspaper in Lawrence, -Kansas. LJWorld.com focuses on news, while Lawrence.com focuses on local -entertainment. But sometimes editors want to publish an article on *both* -sites. - -The brain-dead way of solving the problem would be to require site producers to -publish the same story twice: once for LJWorld.com and again for Lawrence.com. -But that's inefficient for site producers, and it's redundant to store -multiple copies of the same story in the database. - -The better solution is simple: Both sites use the same article database, and an -article is associated with one or more sites. In Django model terminology, -that's represented by a :class:`~django.db.models.ManyToManyField` in the -``Article`` model:: - - from django.db import models - from django.contrib.sites.models import Site - - class Article(models.Model): - headline = models.CharField(max_length=200) - # ... - sites = models.ManyToManyField(Site) - -This accomplishes several things quite nicely: - - * It lets the site producers edit all content -- on both sites -- in a - single interface (the Django admin). - - * It means the same story doesn't have to be published twice in the - database; it only has a single record in the database. - - * It lets the site developers use the same Django view code for both sites. - The view code that displays a given story just checks to make sure the - requested story is on the current site. It looks something like this:: - - from django.conf import settings - - def article_detail(request, article_id): - try: - a = Article.objects.get(id=article_id, sites__id__exact=settings.SITE_ID) - except Article.DoesNotExist: - raise Http404 - # ... - -.. _ljworld.com: http://www.ljworld.com/ -.. _lawrence.com: http://www.lawrence.com/ - -Associating content with a single site --------------------------------------- - -Similarly, you can associate a model to the :class:`~django.contrib.sites.models.Site` -model in a many-to-one relationship, using -:class:`~django.db.models.fields.related.ForeignKey`. - -For example, if an article is only allowed on a single site, you'd use a model -like this:: - - from django.db import models - from django.contrib.sites.models import Site - - class Article(models.Model): - headline = models.CharField(max_length=200) - # ... - site = models.ForeignKey(Site) - -This has the same benefits as described in the last section. - -Hooking into the current site from views ----------------------------------------- - -You can use the sites framework in your Django views to do -particular things based on the site in which the view is being called. -For example:: - - from django.conf import settings - - def my_view(request): - if settings.SITE_ID == 3: - # Do something. - else: - # Do something else. - -Of course, it's ugly to hard-code the site IDs like that. This sort of -hard-coding is best for hackish fixes that you need done quickly. A slightly -cleaner way of accomplishing the same thing is to check the current site's -domain:: - - from django.conf import settings - from django.contrib.sites.models import Site - - def my_view(request): - current_site = Site.objects.get(id=settings.SITE_ID) - if current_site.domain == 'foo.com': - # Do something - else: - # Do something else. - -The idiom of retrieving the :class:`~django.contrib.sites.models.Site` object -for the value of :setting:`settings.SITE_ID <SITE_ID>` is quite common, so -the :class:`~django.contrib.sites.models.Site` model's manager has a -``get_current()`` method. This example is equivalent to the previous one:: - - from django.contrib.sites.models import Site - - def my_view(request): - current_site = Site.objects.get_current() - if current_site.domain == 'foo.com': - # Do something - else: - # Do something else. - -.. versionchanged:: 1.3 - -For code which relies on getting the current domain but cannot be certain -that the sites framework will be installed for any given project, there is a -utility function :func:`~django.contrib.sites.models.get_current_site` that -takes a request object as an argument and returns either a Site instance (if -the sites framework is installed) or a RequestSite instance (if it is not). -This allows loose coupling with the sites framework and provides a usable -fallback for cases where it is not installed. - -Getting the current domain for display --------------------------------------- - -LJWorld.com and Lawrence.com both have e-mail alert functionality, which lets -readers sign up to get notifications when news happens. It's pretty basic: A -reader signs up on a Web form, and he immediately gets an e-mail saying, -"Thanks for your subscription." - -It'd be inefficient and redundant to implement this signup-processing code -twice, so the sites use the same code behind the scenes. But the "thank you for -signing up" notice needs to be different for each site. By using -:class:`~django.contrib.sites.models.Site` -objects, we can abstract the "thank you" notice to use the values of the -current site's :attr:`~django.contrib.sites.models.Site.name` and -:attr:`~django.contrib.sites.models.Site.domain`. - -Here's an example of what the form-handling view looks like:: - - from django.contrib.sites.models import Site - from django.core.mail import send_mail - - def register_for_newsletter(request): - # Check form values, etc., and subscribe the user. - # ... - - current_site = Site.objects.get_current() - send_mail('Thanks for subscribing to %s alerts' % current_site.name, - 'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name, - 'editor@%s' % current_site.domain, - [user.email]) - - # ... - -On Lawrence.com, this e-mail has the subject line "Thanks for subscribing to -lawrence.com alerts." On LJWorld.com, the e-mail has the subject "Thanks for -subscribing to LJWorld.com alerts." Same goes for the e-mail's message body. - -Note that an even more flexible (but more heavyweight) way of doing this would -be to use Django's template system. Assuming Lawrence.com and LJWorld.com have -different template directories (:setting:`TEMPLATE_DIRS`), you could simply farm out -to the template system like so:: - - from django.core.mail import send_mail - from django.template import loader, Context - - def register_for_newsletter(request): - # Check form values, etc., and subscribe the user. - # ... - - subject = loader.get_template('alerts/subject.txt').render(Context({})) - message = loader.get_template('alerts/message.txt').render(Context({})) - send_mail(subject, message, 'editor@ljworld.com', [user.email]) - - # ... - -In this case, you'd have to create :file:`subject.txt` and :file:`message.txt` template -files for both the LJWorld.com and Lawrence.com template directories. That -gives you more flexibility, but it's also more complex. - -It's a good idea to exploit the :class:`~django.contrib.sites.models.Site` -objects as much as possible, to remove unneeded complexity and redundancy. - -Getting the current domain for full URLs ----------------------------------------- - -Django's ``get_absolute_url()`` convention is nice for getting your objects' -URL without the domain name, but in some cases you might want to display the -full URL -- with ``http://`` and the domain and everything -- for an object. -To do this, you can use the sites framework. A simple example:: - - >>> from django.contrib.sites.models import Site - >>> obj = MyModel.objects.get(id=3) - >>> obj.get_absolute_url() - '/mymodel/objects/3/' - >>> Site.objects.get_current().domain - 'example.com' - >>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url()) - 'http://example.com/mymodel/objects/3/' - -Caching the current ``Site`` object -=================================== - -.. versionadded:: 1.0 - -As the current site is stored in the database, each call to -``Site.objects.get_current()`` could result in a database query. But Django is a -little cleverer than that: on the first request, the current site is cached, and -any subsequent call returns the cached data instead of hitting the database. - -If for any reason you want to force a database query, you can tell Django to -clear the cache using ``Site.objects.clear_cache()``:: - - # First call; current site fetched from database. - current_site = Site.objects.get_current() - # ... - - # Second call; current site fetched from cache. - current_site = Site.objects.get_current() - # ... - - # Force a database query for the third call. - Site.objects.clear_cache() - current_site = Site.objects.get_current() - -The ``CurrentSiteManager`` -========================== - -.. class:: django.contrib.sites.managers.CurrentSiteManager - -If :class:`~django.contrib.sites.models.Site` plays a key role in your -application, consider using the helpful -:class:`~django.contrib.sites.managers.CurrentSiteManager` in your -model(s). It's a model :doc:`manager </topics/db/managers>` that -automatically filters its queries to include only objects associated -with the current :class:`~django.contrib.sites.models.Site`. - -Use :class:`~django.contrib.sites.managers.CurrentSiteManager` by adding it to -your model explicitly. For example:: - - from django.db import models - from django.contrib.sites.models import Site - from django.contrib.sites.managers import CurrentSiteManager - - class Photo(models.Model): - photo = models.FileField(upload_to='/home/photos') - photographer_name = models.CharField(max_length=100) - pub_date = models.DateField() - site = models.ForeignKey(Site) - objects = models.Manager() - on_site = CurrentSiteManager() - -With this model, ``Photo.objects.all()`` will return all ``Photo`` objects in -the database, but ``Photo.on_site.all()`` will return only the ``Photo`` objects -associated with the current site, according to the :setting:`SITE_ID` setting. - -Put another way, these two statements are equivalent:: - - Photo.objects.filter(site=settings.SITE_ID) - Photo.on_site.all() - -How did :class:`~django.contrib.sites.managers.CurrentSiteManager` -know which field of ``Photo`` was the -:class:`~django.contrib.sites.models.Site`? By default, -:class:`~django.contrib.sites.managers.CurrentSiteManager` looks for a -either a :class:`~django.db.models.fields.related.ForeignKey` called -``site`` or a -:class:`~django.db.models.fields.related.ManyToManyField` called -``sites`` to filter on. If you use a field named something other than -``site`` or ``sites`` to identify which -:class:`~django.contrib.sites.models.Site` objects your object is -related to, then you need to explicitly pass the custom field name as -a parameter to -:class:`~django.contrib.sites.managers.CurrentSiteManager` on your -model. The following model, which has a field called ``publish_on``, -demonstrates this:: - - from django.db import models - from django.contrib.sites.models import Site - from django.contrib.sites.managers import CurrentSiteManager - - class Photo(models.Model): - photo = models.FileField(upload_to='/home/photos') - photographer_name = models.CharField(max_length=100) - pub_date = models.DateField() - publish_on = models.ForeignKey(Site) - objects = models.Manager() - on_site = CurrentSiteManager('publish_on') - -If you attempt to use :class:`~django.contrib.sites.managers.CurrentSiteManager` -and pass a field name that doesn't exist, Django will raise a :exc:`ValueError`. - -Finally, note that you'll probably want to keep a normal -(non-site-specific) ``Manager`` on your model, even if you use -:class:`~django.contrib.sites.managers.CurrentSiteManager`. As -explained in the :doc:`manager documentation </topics/db/managers>`, if -you define a manager manually, then Django won't create the automatic -``objects = models.Manager()`` manager for you. Also note that certain -parts of Django -- namely, the Django admin site and generic views -- -use whichever manager is defined *first* in the model, so if you want -your admin site to have access to all objects (not just site-specific -ones), put ``objects = models.Manager()`` in your model, before you -define :class:`~django.contrib.sites.managers.CurrentSiteManager`. - -How Django uses the sites framework -=================================== - -Although it's not required that you use the sites framework, it's strongly -encouraged, because Django takes advantage of it in a few places. Even if your -Django installation is powering only a single site, you should take the two -seconds to create the site object with your ``domain`` and ``name``, and point -to its ID in your :setting:`SITE_ID` setting. - -Here's how Django uses the sites framework: - -* In the :mod:`redirects framework <django.contrib.redirects>`, each - redirect object is associated with a particular site. When Django searches - for a redirect, it takes into account the current :setting:`SITE_ID`. - -* In the comments framework, each comment is associated with a particular - site. When a comment is posted, its - :class:`~django.contrib.sites.models.Site` is set to the current - :setting:`SITE_ID`, and when comments are listed via the appropriate - template tag, only the comments for the current site are displayed. - -* In the :mod:`flatpages framework <django.contrib.flatpages>`, each - flatpage is associated with a particular site. When a flatpage is created, - you specify its :class:`~django.contrib.sites.models.Site`, and the - :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware` - checks the current :setting:`SITE_ID` in retrieving flatpages to display. - -* In the :mod:`syndication framework <django.contrib.syndication>`, the - templates for ``title`` and ``description`` automatically have access to a - variable ``{{ site }}``, which is the - :class:`~django.contrib.sites.models.Site` object representing the current - site. Also, the hook for providing item URLs will use the ``domain`` from - the current :class:`~django.contrib.sites.models.Site` object if you don't - specify a fully-qualified domain. - -* In the :mod:`authentication framework <django.contrib.auth>`, the - :func:`django.contrib.auth.views.login` view passes the current - :class:`~django.contrib.sites.models.Site` name to the template as - ``{{ site_name }}``. - -* The shortcut view (:func:`django.views.defaults.shortcut`) uses the domain - of the current :class:`~django.contrib.sites.models.Site` object when - calculating an object's URL. - -* In the admin framework, the "view on site" link uses the current - :class:`~django.contrib.sites.models.Site` to work out the domain for the - site that it will redirect to. - - -``RequestSite`` objects -======================= - -.. _requestsite-objects: - -.. versionadded:: 1.0 - -Some :doc:`django.contrib </ref/contrib/index>` applications take advantage of -the sites framework but are architected in a way that doesn't *require* the -sites framework to be installed in your database. (Some people don't want to, or -just aren't *able* to install the extra database table that the sites framework -requires.) For those cases, the framework provides a -:class:`~django.contrib.sites.models.RequestSite` class, which can be used as a -fallback when the database-backed sites framework is not available. - -A :class:`~django.contrib.sites.models.RequestSite` object has a similar -interface to a normal :class:`~django.contrib.sites.models.Site` object, except -its :meth:`~django.contrib.sites.models.RequestSite.__init__()` method takes an -:class:`~django.http.HttpRequest` object. It's able to deduce the -:attr:`~django.contrib.sites.models.RequestSite.domain` and -:attr:`~django.contrib.sites.models.RequestSite.name` by looking at the -request's domain. It has :meth:`~django.contrib.sites.models.RequestSite.save()` -and :meth:`~django.contrib.sites.models.RequestSite.delete()` methods to match -the interface of :class:`~django.contrib.sites.models.Site`, but the methods -raise :exc:`NotImplementedError`. diff --git a/parts/django/docs/ref/contrib/syndication.txt b/parts/django/docs/ref/contrib/syndication.txt deleted file mode 100644 index 04f14b5..0000000 --- a/parts/django/docs/ref/contrib/syndication.txt +++ /dev/null @@ -1,949 +0,0 @@ -============================== -The syndication feed framework -============================== - -.. module:: django.contrib.syndication - :synopsis: A framework for generating syndication feeds, in RSS and Atom, - quite easily. - -Django comes with a high-level syndication-feed-generating framework -that makes creating RSS_ and Atom_ feeds easy. - -To create any syndication feed, all you have to do is write a short -Python class. You can create as many feeds as you want. - -Django also comes with a lower-level feed-generating API. Use this if -you want to generate feeds outside of a Web context, or in some other -lower-level way. - -.. _RSS: http://www.whatisrss.com/ -.. _Atom: http://www.atomenabled.org/ - -The high-level framework -======================== - -.. versionchanged:: 1.2 - The high-level feeds framework was refactored in Django 1.2. The - pre-1.2 interface still exists, but it has been deprecated, and - will be removed in Django 1.4. If you need to maintain an old-style - Django feed, please consult the Django 1.1 documentation. For - details on updating to use the new high-level feed framework, see - the :ref:`Django 1.2 release notes <1.2-updating-feeds>`. - -Overview --------- - -The high-level feed-generating framework is supplied by the -:class:`~django.contrib.syndication.views.Feed` class. To create a -feed, write a :class:`~django.contrib.syndication.views.Feed` class -and point to an instance of it in your :doc:`URLconf -</topics/http/urls>`. - -Feed classes ------------- - -A :class:`~django.contrib.syndication.views.Feed` class is a Python -class that represents a syndication feed. A feed can be simple (e.g., -a "site news" feed, or a basic feed displaying the latest entries of a -blog) or more complex (e.g., a feed displaying all the blog entries in -a particular category, where the category is variable). - -Feed classes subclass :class:`django.contrib.syndication.views.Feed`. -They can live anywhere in your codebase. - -Instances of :class:`~django.contrib.syndication.views.Feed` classes -are views which can be used in your :doc:`URLconf </topics/http/urls>`. - -A simple example ----------------- - -This simple example, taken from `chicagocrime.org`_, describes a feed of the -latest five news items:: - - from django.contrib.syndication.views import Feed - from chicagocrime.models import NewsItem - - class LatestEntriesFeed(Feed): - title = "Chicagocrime.org site news" - link = "/sitenews/" - description = "Updates on changes and additions to chicagocrime.org." - - def items(self): - return NewsItem.objects.order_by('-pub_date')[:5] - - def item_title(self, item): - return item.title - - def item_description(self, item): - return item.description - -To connect a URL to this feed, put an instance of the Feed object in -your :doc:`URLconf </topics/http/urls>`. For example:: - - from django.conf.urls.defaults import * - from myproject.feeds import LatestEntriesFeed - - urlpatterns = patterns('', - # ... - (r'^latest/feed/$', LatestEntriesFeed()), - # ... - ) - -Note: - -* The Feed class subclasses :class:`django.contrib.syndication.views.Feed`. - -* :attr:`title`, :attr:`link` and :attr:`description` correspond to the - standard RSS ``<title>``, ``<link>`` and ``<description>`` elements, - respectively. - -* :meth:`items()` is, simply, a method that returns a list of objects that - should be included in the feed as ``<item>`` elements. Although this - example returns ``NewsItem`` objects using Django's - :doc:`object-relational mapper </ref/models/querysets>`, :meth:`items()` - doesn't have to return model instances. Although you get a few bits of - functionality "for free" by using Django models, :meth:`items()` can - return any type of object you want. - -* If you're creating an Atom feed, rather than an RSS feed, set the - :attr:`subtitle` attribute instead of the :attr:`description` attribute. - See `Publishing Atom and RSS feeds in tandem`_, later, for an example. - -One thing is left to do. In an RSS feed, each ``<item>`` has a ``<title>``, -``<link>`` and ``<description>``. We need to tell the framework what data to put -into those elements. - - * For the contents of ``<title>`` and ``<description>``, Django tries - calling the methods :meth:`item_title()` and :meth:`item_description()` on - the :class:`~django.contrib.syndication.views.Feed` class. They are passed - a single parameter, :attr:`item`, which is the object itself. These are - optional; by default, the unicode representation of the object is used for - both. - - If you want to do any special formatting for either the title or - description, :doc:`Django templates </topics/templates>` can be used - instead. Their paths can be specified with the ``title_template`` and - ``description_template`` attributes on the - :class:`~django.contrib.syndication.views.Feed` class. The templates are - rendered for each item and are passed two template context variables: - - * ``{{ obj }}`` -- The current object (one of whichever objects you - returned in :meth:`items()`). - - * ``{{ site }}`` -- A :class:`django.contrib.sites.models.Site` object - representing the current site. This is useful for ``{{ site.domain - }}`` or ``{{ site.name }}``. If you do *not* have the Django sites - framework installed, this will be set to a - :class:`django.contrib.sites.models.RequestSite` object. See the - :ref:`RequestSite section of the sites framework documentation - <requestsite-objects>` for more. - - See `a complex example`_ below that uses a description template. - - * To specify the contents of ``<link>``, you have two options. For each item - in :meth:`items()`, Django first tries calling the - :meth:`item_link()` method on the - :class:`~django.contrib.syndication.views.Feed` class. In a similar way to - the title and description, it is passed it a single parameter, - :attr:`item`. If that method doesn't exist, Django tries executing a - ``get_absolute_url()`` method on that object. Both - :meth:`get_absolute_url()` and :meth:`item_link()` should return the - item's URL as a normal Python string. As with ``get_absolute_url()``, the - result of :meth:`item_link()` will be included directly in the URL, so you - are responsible for doing all necessary URL quoting and conversion to - ASCII inside the method itself. - -.. _chicagocrime.org: http://www.chicagocrime.org/ - -A complex example ------------------ - -The framework also supports more complex feeds, via arguments. - -For example, `chicagocrime.org`_ offers an RSS feed of recent crimes for every -police beat in Chicago. It'd be silly to create a separate -:class:`~django.contrib.syndication.views.Feed` class for each police beat; that -would violate the :ref:`DRY principle <dry>` and would couple data to -programming logic. Instead, the syndication framework lets you access the -arguments passed from your :doc:`URLconf </topics/http/urls>` so feeds can output -items based on information in the feed's URL. - -On chicagocrime.org, the police-beat feeds are accessible via URLs like this: - - * :file:`/beats/613/rss/` -- Returns recent crimes for beat 613. - * :file:`/beats/1424/rss/` -- Returns recent crimes for beat 1424. - -These can be matched with a :doc:`URLconf </topics/http/urls>` line such as:: - - (r'^beats/(?P<beat_id>\d+)/rss/$', BeatFeed()), - -Like a view, the arguments in the URL are passed to the :meth:`get_object()` -method along with the request object. - -.. versionchanged:: 1.2 - Prior to version 1.2, ``get_object()`` only accepted a ``bits`` argument. - -Here's the code for these beat-specific feeds:: - - from django.contrib.syndication.views import FeedDoesNotExist - from django.shortcuts import get_object_or_404 - - class BeatFeed(Feed): - description_template = 'feeds/beat_description.html' - - def get_object(self, request, beat_id): - return get_object_or_404(Beat, pk=beat_id) - - def title(self, obj): - return "Chicagocrime.org: Crimes for beat %s" % obj.beat - - def link(self, obj): - return obj.get_absolute_url() - - def description(self, obj): - return "Crimes recently reported in police beat %s" % obj.beat - - def items(self, obj): - return Crime.objects.filter(beat=obj).order_by('-crime_date')[:30] - -To generate the feed's ``<title>``, ``<link>`` and ``<description>``, Django -uses the :meth:`title()`, :meth:`link()` and :meth:`description()` methods. In -the previous example, they were simple string class attributes, but this example -illustrates that they can be either strings *or* methods. For each of -:attr:`title`, :attr:`link` and :attr:`description`, Django follows this -algorithm: - - * First, it tries to call a method, passing the ``obj`` argument, where - ``obj`` is the object returned by :meth:`get_object()`. - - * Failing that, it tries to call a method with no arguments. - - * Failing that, it uses the class attribute. - -Also note that :meth:`items()` also follows the same algorithm -- first, it -tries :meth:`items(obj)`, then :meth:`items()`, then finally an :attr:`items` -class attribute (which should be a list). - -We are using a template for the item descriptions. It can be very simple: - -.. code-block:: html+django - - {{ obj.description }} - -However, you are free to add formatting as desired. - -The ``ExampleFeed`` class below gives full documentation on methods and -attributes of :class:`~django.contrib.syndication.views.Feed` classes. - -Specifying the type of feed ---------------------------- - -By default, feeds produced in this framework use RSS 2.0. - -To change that, add a ``feed_type`` attribute to your -:class:`~django.contrib.syndication.views.Feed` class, like so:: - - from django.utils.feedgenerator import Atom1Feed - - class MyFeed(Feed): - feed_type = Atom1Feed - -Note that you set ``feed_type`` to a class object, not an instance. - -Currently available feed types are: - - * :class:`django.utils.feedgenerator.Rss201rev2Feed` (RSS 2.01. Default.) - * :class:`django.utils.feedgenerator.RssUserland091Feed` (RSS 0.91.) - * :class:`django.utils.feedgenerator.Atom1Feed` (Atom 1.0.) - -Enclosures ----------- - -To specify enclosures, such as those used in creating podcast feeds, use the -:attr:`item_enclosure_url`, :attr:`item_enclosure_length` and -:attr:`item_enclosure_mime_type` hooks. See the ``ExampleFeed`` class below for -usage examples. - -Language --------- - -Feeds created by the syndication framework automatically include the -appropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom). This -comes directly from your :setting:`LANGUAGE_CODE` setting. - -URLs ----- - -The :attr:`link` method/attribute can return either an absolute path (e.g. -:file:`"/blog/"`) or a URL with the fully-qualified domain and protocol (e.g. -``"http://www.example.com/blog/"``). If :attr:`link` doesn't return the domain, -the syndication framework will insert the domain of the current site, according -to your :setting:`SITE_ID setting <SITE_ID>`. - -Atom feeds require a ``<link rel="self">`` that defines the feed's current -location. The syndication framework populates this automatically, using the -domain of the current site according to the :setting:`SITE_ID` setting. - -Publishing Atom and RSS feeds in tandem ---------------------------------------- - -Some developers like to make available both Atom *and* RSS versions of their -feeds. That's easy to do with Django: Just create a subclass of your -:class:`~django.contrib.syndication.views.Feed` -class and set the :attr:`feed_type` to something different. Then update your -URLconf to add the extra versions. - -Here's a full example:: - - from django.contrib.syndication.views import Feed - from chicagocrime.models import NewsItem - from django.utils.feedgenerator import Atom1Feed - - class RssSiteNewsFeed(Feed): - title = "Chicagocrime.org site news" - link = "/sitenews/" - description = "Updates on changes and additions to chicagocrime.org." - - def items(self): - return NewsItem.objects.order_by('-pub_date')[:5] - - class AtomSiteNewsFeed(RssSiteNewsFeed): - feed_type = Atom1Feed - subtitle = RssSiteNewsFeed.description - -.. Note:: - In this example, the RSS feed uses a :attr:`description` while the Atom - feed uses a :attr:`subtitle`. That's because Atom feeds don't provide for - a feed-level "description," but they *do* provide for a "subtitle." - - If you provide a :attr:`description` in your - :class:`~django.contrib.syndication.views.Feed` class, Django will *not* - automatically put that into the :attr:`subtitle` element, because a - subtitle and description are not necessarily the same thing. Instead, you - should define a :attr:`subtitle` attribute. - - In the above example, we simply set the Atom feed's :attr:`subtitle` to the - RSS feed's :attr:`description`, because it's quite short already. - -And the accompanying URLconf:: - - from django.conf.urls.defaults import * - from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed - - urlpatterns = patterns('', - # ... - (r'^sitenews/rss/$', RssSiteNewsFeed()), - (r'^sitenews/atom/$', AtomSiteNewsFeed()), - # ... - ) - -Feed class reference --------------------- - -.. class:: django.contrib.syndication.views.Feed - -This example illustrates all possible attributes and methods for a -:class:`~django.contrib.syndication.views.Feed` class:: - - from django.contrib.syndication.views import Feed - from django.utils import feedgenerator - - class ExampleFeed(Feed): - - # FEED TYPE -- Optional. This should be a class that subclasses - # django.utils.feedgenerator.SyndicationFeed. This designates - # which type of feed this should be: RSS 2.0, Atom 1.0, etc. If - # you don't specify feed_type, your feed will be RSS 2.0. This - # should be a class, not an instance of the class. - - feed_type = feedgenerator.Rss201rev2Feed - - # TEMPLATE NAMES -- Optional. These should be strings - # representing names of Django templates that the system should - # use in rendering the title and description of your feed items. - # Both are optional. If a template is not specified, the - # item_title() or item_description() methods are used instead. - - title_template = None - description_template = None - - # TITLE -- One of the following three is required. The framework - # looks for them in this order. - - def title(self, obj): - """ - Takes the object returned by get_object() and returns the - feed's title as a normal Python string. - """ - - def title(self): - """ - Returns the feed's title as a normal Python string. - """ - - title = 'foo' # Hard-coded title. - - # LINK -- One of the following three is required. The framework - # looks for them in this order. - - def link(self, obj): - """ - # Takes the object returned by get_object() and returns the feed's - # link as a normal Python string. - """ - - def link(self): - """ - Returns the feed's link as a normal Python string. - """ - - link = '/foo/bar/' # Hard-coded link. - - # GUID -- One of the following three is optional. The framework looks - # for them in this order. This property is only used for Atom feeds - # (where it is the feed-level ID element). If not provided, the feed - # link is used as the ID. - - def feed_guid(self, obj): - """ - Takes the object returned by get_object() and returns the globally - unique ID for the feed as a normal Python string. - """ - - def feed_guid(self): - """ - Returns the feed's globally unique ID as a normal Python string. - """ - - feed_guid = '/foo/bar/1234' # Hard-coded guid. - - # DESCRIPTION -- One of the following three is required. The framework - # looks for them in this order. - - def description(self, obj): - """ - Takes the object returned by get_object() and returns the feed's - description as a normal Python string. - """ - - def description(self): - """ - Returns the feed's description as a normal Python string. - """ - - description = 'Foo bar baz.' # Hard-coded description. - - # AUTHOR NAME --One of the following three is optional. The framework - # looks for them in this order. - - def author_name(self, obj): - """ - Takes the object returned by get_object() and returns the feed's - author's name as a normal Python string. - """ - - def author_name(self): - """ - Returns the feed's author's name as a normal Python string. - """ - - author_name = 'Sally Smith' # Hard-coded author name. - - # AUTHOR E-MAIL --One of the following three is optional. The framework - # looks for them in this order. - - def author_email(self, obj): - """ - Takes the object returned by get_object() and returns the feed's - author's e-mail as a normal Python string. - """ - - def author_email(self): - """ - Returns the feed's author's e-mail as a normal Python string. - """ - - author_email = 'test@example.com' # Hard-coded author e-mail. - - # AUTHOR LINK --One of the following three is optional. The framework - # looks for them in this order. In each case, the URL should include - # the "http://" and domain name. - - def author_link(self, obj): - """ - Takes the object returned by get_object() and returns the feed's - author's URL as a normal Python string. - """ - - def author_link(self): - """ - Returns the feed's author's URL as a normal Python string. - """ - - author_link = 'http://www.example.com/' # Hard-coded author URL. - - # CATEGORIES -- One of the following three is optional. The framework - # looks for them in this order. In each case, the method/attribute - # should return an iterable object that returns strings. - - def categories(self, obj): - """ - Takes the object returned by get_object() and returns the feed's - categories as iterable over strings. - """ - - def categories(self): - """ - Returns the feed's categories as iterable over strings. - """ - - categories = ("python", "django") # Hard-coded list of categories. - - # COPYRIGHT NOTICE -- One of the following three is optional. The - # framework looks for them in this order. - - def feed_copyright(self, obj): - """ - Takes the object returned by get_object() and returns the feed's - copyright notice as a normal Python string. - """ - - def feed_copyright(self): - """ - Returns the feed's copyright notice as a normal Python string. - """ - - feed_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice. - - # TTL -- One of the following three is optional. The framework looks - # for them in this order. Ignored for Atom feeds. - - def ttl(self, obj): - """ - Takes the object returned by get_object() and returns the feed's - TTL (Time To Live) as a normal Python string. - """ - - def ttl(self): - """ - Returns the feed's TTL as a normal Python string. - """ - - ttl = 600 # Hard-coded Time To Live. - - # ITEMS -- One of the following three is required. The framework looks - # for them in this order. - - def items(self, obj): - """ - Takes the object returned by get_object() and returns a list of - items to publish in this feed. - """ - - def items(self): - """ - Returns a list of items to publish in this feed. - """ - - items = ('Item 1', 'Item 2') # Hard-coded items. - - # GET_OBJECT -- This is required for feeds that publish different data - # for different URL parameters. (See "A complex example" above.) - - def get_object(self, request, *args, **kwargs): - """ - Takes the current request and the arguments from the URL, and - returns an object represented by this feed. Raises - django.core.exceptions.ObjectDoesNotExist on error. - """ - - # ITEM TITLE AND DESCRIPTION -- If title_template or - # description_template are not defined, these are used instead. Both are - # optional, by default they will use the unicode representation of the - # item. - - def item_title(self, item): - """ - Takes an item, as returned by items(), and returns the item's - title as a normal Python string. - """ - - def item_title(self): - """ - Returns the title for every item in the feed. - """ - - item_title = 'Breaking News: Nothing Happening' # Hard-coded title. - - def item_description(self, item): - """ - Takes an item, as returned by items(), and returns the item's - description as a normal Python string. - """ - - def item_description(self): - """ - Returns the description for every item in the feed. - """ - - item_description = 'A description of the item.' # Hard-coded description. - - # ITEM LINK -- One of these three is required. The framework looks for - # them in this order. - - # First, the framework tries the two methods below, in - # order. Failing that, it falls back to the get_absolute_url() - # method on each item returned by items(). - - def item_link(self, item): - """ - Takes an item, as returned by items(), and returns the item's URL. - """ - - def item_link(self): - """ - Returns the URL for every item in the feed. - """ - - # ITEM_GUID -- The following method is optional. If not provided, the - # item's link is used by default. - - def item_guid(self, obj): - """ - Takes an item, as return by items(), and returns the item's ID. - """ - - # ITEM AUTHOR NAME -- One of the following three is optional. The - # framework looks for them in this order. - - def item_author_name(self, item): - """ - Takes an item, as returned by items(), and returns the item's - author's name as a normal Python string. - """ - - def item_author_name(self): - """ - Returns the author name for every item in the feed. - """ - - item_author_name = 'Sally Smith' # Hard-coded author name. - - # ITEM AUTHOR E-MAIL --One of the following three is optional. The - # framework looks for them in this order. - # - # If you specify this, you must specify item_author_name. - - def item_author_email(self, obj): - """ - Takes an item, as returned by items(), and returns the item's - author's e-mail as a normal Python string. - """ - - def item_author_email(self): - """ - Returns the author e-mail for every item in the feed. - """ - - item_author_email = 'test@example.com' # Hard-coded author e-mail. - - # ITEM AUTHOR LINK -- One of the following three is optional. The - # framework looks for them in this order. In each case, the URL should - # include the "http://" and domain name. - # - # If you specify this, you must specify item_author_name. - - def item_author_link(self, obj): - """ - Takes an item, as returned by items(), and returns the item's - author's URL as a normal Python string. - """ - - def item_author_link(self): - """ - Returns the author URL for every item in the feed. - """ - - item_author_link = 'http://www.example.com/' # Hard-coded author URL. - - # ITEM ENCLOSURE URL -- One of these three is required if you're - # publishing enclosures. The framework looks for them in this order. - - def item_enclosure_url(self, item): - """ - Takes an item, as returned by items(), and returns the item's - enclosure URL. - """ - - def item_enclosure_url(self): - """ - Returns the enclosure URL for every item in the feed. - """ - - item_enclosure_url = "/foo/bar.mp3" # Hard-coded enclosure link. - - # ITEM ENCLOSURE LENGTH -- One of these three is required if you're - # publishing enclosures. The framework looks for them in this order. - # In each case, the returned value should be either an integer, or a - # string representation of the integer, in bytes. - - def item_enclosure_length(self, item): - """ - Takes an item, as returned by items(), and returns the item's - enclosure length. - """ - - def item_enclosure_length(self): - """ - Returns the enclosure length for every item in the feed. - """ - - item_enclosure_length = 32000 # Hard-coded enclosure length. - - # ITEM ENCLOSURE MIME TYPE -- One of these three is required if you're - # publishing enclosures. The framework looks for them in this order. - - def item_enclosure_mime_type(self, item): - """ - Takes an item, as returned by items(), and returns the item's - enclosure MIME type. - """ - - def item_enclosure_mime_type(self): - """ - Returns the enclosure MIME type for every item in the feed. - """ - - item_enclosure_mime_type = "audio/mpeg" # Hard-coded enclosure MIME type. - - # ITEM PUBDATE -- It's optional to use one of these three. This is a - # hook that specifies how to get the pubdate for a given item. - # In each case, the method/attribute should return a Python - # datetime.datetime object. - - def item_pubdate(self, item): - """ - Takes an item, as returned by items(), and returns the item's - pubdate. - """ - - def item_pubdate(self): - """ - Returns the pubdate for every item in the feed. - """ - - item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate. - - # ITEM CATEGORIES -- It's optional to use one of these three. This is - # a hook that specifies how to get the list of categories for a given - # item. In each case, the method/attribute should return an iterable - # object that returns strings. - - def item_categories(self, item): - """ - Takes an item, as returned by items(), and returns the item's - categories. - """ - - def item_categories(self): - """ - Returns the categories for every item in the feed. - """ - - item_categories = ("python", "django") # Hard-coded categories. - - # ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the - # following three is optional. The framework looks for them in this - # order. - - def item_copyright(self, obj): - """ - Takes an item, as returned by items(), and returns the item's - copyright notice as a normal Python string. - """ - - def item_copyright(self): - """ - Returns the copyright notice for every item in the feed. - """ - - item_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice. - - -The low-level framework -======================= - -Behind the scenes, the high-level RSS framework uses a lower-level framework -for generating feeds' XML. This framework lives in a single module: -`django/utils/feedgenerator.py`_. - -You use this framework on your own, for lower-level feed generation. You can -also create custom feed generator subclasses for use with the ``feed_type`` -``Feed`` option. - -``SyndicationFeed`` classes ---------------------------- - -The :mod:`~django.utils.feedgenerator` module contains a base class: - -.. class:: django.utils.feedgenerator.SyndicationFeed - -and several subclasses: - -.. class:: django.utils.feedgenerator.RssUserland091Feed -.. class:: django.utils.feedgenerator.Rss201rev2Feed -.. class:: django.utils.feedgenerator.Atom1Feed - -Each of these three classes knows how to render a certain type of feed as XML. -They share this interface: - -.. method:: SyndicationFeed.__init__(**kwargs) - - Initialize the feed with the given dictionary of metadata, which applies to - the entire feed. Required keyword arguments are: - - * ``title`` - * ``link`` - * ``description`` - - There's also a bunch of other optional keywords: - - * ``language`` - * ``author_email`` - * ``author_name`` - * ``author_link`` - * ``subtitle`` - * ``categories`` - * ``feed_url`` - * ``feed_copyright`` - * ``feed_guid`` - * ``ttl`` - - Any extra keyword arguments you pass to ``__init__`` will be stored in - ``self.feed`` for use with `custom feed generators`_. - - All parameters should be Unicode objects, except ``categories``, which - should be a sequence of Unicode objects. - -.. method:: SyndicationFeed.add_item(**kwargs) - - Add an item to the feed with the given parameters. - - Required keyword arguments are: - - * ``title`` - * ``link`` - * ``description`` - - Optional keyword arguments are: - - * ``author_email`` - * ``author_name`` - * ``author_link`` - * ``pubdate`` - * ``comments`` - * ``unique_id`` - * ``enclosure`` - * ``categories`` - * ``item_copyright`` - * ``ttl`` - - Extra keyword arguments will be stored for `custom feed generators`_. - - All parameters, if given, should be Unicode objects, except: - - * ``pubdate`` should be a `Python datetime object`_. - * ``enclosure`` should be an instance of ``feedgenerator.Enclosure``. - * ``categories`` should be a sequence of Unicode objects. - -.. method:: SyndicationFeed.write(outfile, encoding) - - Outputs the feed in the given encoding to outfile, which is a file-like object. - -.. method:: SyndicationFeed.writeString(encoding) - - Returns the feed as a string in the given encoding. - -For example, to create an Atom 1.0 feed and print it to standard output:: - - >>> from django.utils import feedgenerator - >>> from datetime import datetime - >>> f = feedgenerator.Atom1Feed( - ... title=u"My Weblog", - ... link=u"http://www.example.com/", - ... description=u"In which I write about what I ate today.", - ... language=u"en", - ... author_name=u"Myself", - ... feed_url=u"http://example.com/atom.xml") - >>> f.add_item(title=u"Hot dog today", - ... link=u"http://www.example.com/entries/1/", - ... pubdate=datetime.now(), - ... description=u"<p>Today I had a Vienna Beef hot dog. It was pink, plump and perfect.</p>") - >>> print f.writeString('UTF-8') - <?xml version="1.0" encoding="UTF-8"?> - <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"> - ... - </feed> - -.. _django/utils/feedgenerator.py: http://code.djangoproject.com/browser/django/trunk/django/utils/feedgenerator.py -.. _Python datetime object: http://docs.python.org/library/datetime.html#datetime-objects - -Custom feed generators ----------------------- - -If you need to produce a custom feed format, you've got a couple of options. - -If the feed format is totally custom, you'll want to subclass -``SyndicationFeed`` and completely replace the ``write()`` and -``writeString()`` methods. - -However, if the feed format is a spin-off of RSS or Atom (i.e. GeoRSS_, Apple's -`iTunes podcast format`_, etc.), you've got a better choice. These types of -feeds typically add extra elements and/or attributes to the underlying format, -and there are a set of methods that ``SyndicationFeed`` calls to get these extra -attributes. Thus, you can subclass the appropriate feed generator class -(``Atom1Feed`` or ``Rss201rev2Feed``) and extend these callbacks. They are: - -.. _georss: http://georss.org/ -.. _itunes podcast format: http://www.apple.com/itunes/podcasts/specs.html - -``SyndicationFeed.root_attributes(self, )`` - Return a ``dict`` of attributes to add to the root feed element - (``feed``/``channel``). - -``SyndicationFeed.add_root_elements(self, handler)`` - Callback to add elements inside the root feed element - (``feed``/``channel``). ``handler`` is an `XMLGenerator`_ from Python's - built-in SAX library; you'll call methods on it to add to the XML - document in process. - -``SyndicationFeed.item_attributes(self, item)`` - Return a ``dict`` of attributes to add to each item (``item``/``entry``) - element. The argument, ``item``, is a dictionary of all the data passed to - ``SyndicationFeed.add_item()``. - -``SyndicationFeed.add_item_elements(self, handler, item)`` - Callback to add elements to each item (``item``/``entry``) element. - ``handler`` and ``item`` are as above. - -.. warning:: - - If you override any of these methods, be sure to call the superclass methods - since they add the required elements for each feed format. - -For example, you might start implementing an iTunes RSS feed generator like so:: - - class iTunesFeed(Rss201rev2Feed): - def root_attributes(self): - attrs = super(iTunesFeed, self).root_attributes() - attrs['xmlns:itunes'] = 'http://www.itunes.com/dtds/podcast-1.0.dtd' - return attrs - - def add_root_elements(self, handler): - super(iTunesFeed, self).add_root_elements(handler) - handler.addQuickElement('itunes:explicit', 'clean') - -Obviously there's a lot more work to be done for a complete custom feed class, -but the above example should demonstrate the basic idea. - -.. _XMLGenerator: http://docs.python.org/dev/library/xml.sax.utils.html#xml.sax.saxutils.XMLGenerator diff --git a/parts/django/docs/ref/contrib/webdesign.txt b/parts/django/docs/ref/contrib/webdesign.txt deleted file mode 100644 index d355d03..0000000 --- a/parts/django/docs/ref/contrib/webdesign.txt +++ /dev/null @@ -1,56 +0,0 @@ -======================== -django.contrib.webdesign -======================== - -.. module:: django.contrib.webdesign - :synopsis: Helpers and utilities targeted primarily at Web *designers* - rather than Web *developers*. - -The ``django.contrib.webdesign`` package, part of the -:doc:`"django.contrib" add-ons </ref/contrib/index>`, provides various Django -helpers that are particularly useful to Web *designers* (as opposed to -developers). - -At present, the package contains only a single template tag. If you have ideas -for Web-designer-friendly functionality in Django, please -:doc:`suggest them </internals/contributing>`. - -Template tags -============= - -To use these template tags, add ``'django.contrib.webdesign'`` to your -:setting:`INSTALLED_APPS` setting. Once you've done that, use -``{% load webdesign %}`` in a template to give your template access to the tags. - - -lorem -===== - -Displays random "lorem ipsum" Latin text. This is useful for providing sample -data in templates. - -Usage:: - - {% lorem [count] [method] [random] %} - -The ``{% lorem %}`` tag can be used with zero, one, two or three arguments. -The arguments are: - - =========== ============================================================= - Argument Description - =========== ============================================================= - ``count`` A number (or variable) containing the number of paragraphs or - words to generate (default is 1). - ``method`` Either ``w`` for words, ``p`` for HTML paragraphs or ``b`` - for plain-text paragraph blocks (default is ``b``). - ``random`` The word ``random``, which if given, does not use the common - paragraph ("Lorem ipsum dolor sit amet...") when generating - text. - =========== ============================================================= - -Examples: - - * ``{% lorem %}`` will output the common "lorem ipsum" paragraph. - * ``{% lorem 3 p %}`` will output the common "lorem ipsum" paragraph - and two random paragraphs each wrapped in HTML ``<p>`` tags. - * ``{% lorem 2 w random %}`` will output two random Latin words. diff --git a/parts/django/docs/ref/databases.txt b/parts/django/docs/ref/databases.txt deleted file mode 100644 index c49a3fc..0000000 --- a/parts/django/docs/ref/databases.txt +++ /dev/null @@ -1,682 +0,0 @@ -========= -Databases -========= - -Django attempts to support as many features as possible on all database -backends. However, not all database backends are alike, and we've had to make -design decisions on which features to support and which assumptions we can make -safely. - -This file describes some of the features that might be relevant to Django -usage. Of course, it is not intended as a replacement for server-specific -documentation or reference manuals. - -.. _postgresql-notes: - -PostgreSQL notes -================ - -PostgreSQL 8.2 to 8.2.4 ------------------------ - -The implementation of the population statistics aggregates ``STDDEV_POP`` and -``VAR_POP`` that shipped with PostgreSQL 8.2 to 8.2.4 are `known to be -faulty`_. Users of these releases of PostgreSQL are advised to upgrade to -`Release 8.2.5`_ or later. Django will raise a ``NotImplementedError`` if you -attempt to use the ``StdDev(sample=False)`` or ``Variance(sample=False)`` -aggregate with a database backend that falls within the affected release range. - -.. _known to be faulty: http://archives.postgresql.org/pgsql-bugs/2007-07/msg00046.php -.. _Release 8.2.5: http://developer.postgresql.org/pgdocs/postgres/release-8-2-5.html - -Transaction handling ---------------------- - -:doc:`By default </topics/db/transactions>`, Django starts a transaction when a -database connection is first used and commits the result at the end of the -request/response handling. The PostgreSQL backends normally operate the same -as any other Django backend in this respect. - -Autocommit mode -~~~~~~~~~~~~~~~ - -.. versionadded:: 1.1 - -If your application is particularly read-heavy and doesn't make many -database writes, the overhead of a constantly open transaction can -sometimes be noticeable. For those situations, if you're using the -``postgresql_psycopg2`` backend, you can configure Django to use -*"autocommit"* behavior for the connection, meaning that each database -operation will normally be in its own transaction, rather than having -the transaction extend over multiple operations. In this case, you can -still manually start a transaction if you're doing something that -requires consistency across multiple database operations. The -autocommit behavior is enabled by setting the ``autocommit`` key in -the :setting:`OPTIONS` part of your database configuration in -:setting:`DATABASES`:: - - 'OPTIONS': { - 'autocommit': True, - } - -In this configuration, Django still ensures that :ref:`delete() -<topics-db-queries-delete>` and :ref:`update() <topics-db-queries-update>` -queries run inside a single transaction, so that either all the affected -objects are changed or none of them are. - -.. admonition:: This is database-level autocommit - - This functionality is not the same as the - :ref:`topics-db-transactions-autocommit` decorator. That decorator - is a Django-level implementation that commits automatically after - data changing operations. The feature enabled using the - :setting:`OPTIONS` option provides autocommit behavior at the - database adapter level. It commits after *every* operation. - -If you are using this feature and performing an operation akin to delete or -updating that requires multiple operations, you are strongly recommended to -wrap you operations in manual transaction handling to ensure data consistency. -You should also audit your existing code for any instances of this behavior -before enabling this feature. It's faster, but it provides less automatic -protection for multi-call operations. - -Indexes for ``varchar`` and ``text`` columns -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. versionadded:: 1.1.2 - -When specifying ``db_index=True`` on your model fields, Django typically -outputs a single ``CREATE INDEX`` statement. However, if the database type -for the field is either ``varchar`` or ``text`` (e.g., used by ``CharField``, -``FileField``, and ``TextField``), then Django will create -an additional index that uses an appropriate `PostgreSQL operator class`_ -for the column. The extra index is necessary to correctly perfrom -lookups that use the ``LIKE`` operator in their SQL, as is done with the -``contains`` and ``startswith`` lookup types. - -.. _PostgreSQL operator class: http://www.postgresql.org/docs/8.4/static/indexes-opclass.html - -.. _mysql-notes: - -MySQL notes -=========== - -Django expects the database to support transactions, referential integrity, and -Unicode (UTF-8 encoding). Fortunately, MySQL_ has all these features as -available as far back as 3.23. While it may be possible to use 3.23 or 4.0, -you'll probably have less trouble if you use 4.1 or 5.0. - -MySQL 4.1 ---------- - -`MySQL 4.1`_ has greatly improved support for character sets. It is possible to -set different default character sets on the database, table, and column. -Previous versions have only a server-wide character set setting. It's also the -first version where the character set can be changed on the fly. 4.1 also has -support for views, but Django currently doesn't use views. - -MySQL 5.0 ---------- - -`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed -data on all database schema. Django's ``inspectdb`` feature uses this -``information_schema`` if it's available. 5.0 also has support for stored -procedures, but Django currently doesn't use stored procedures. - -.. _MySQL: http://www.mysql.com/ -.. _MySQL 4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html -.. _MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html - -Storage engines ---------------- - -MySQL has several `storage engines`_ (previously called table types). You can -change the default storage engine in the server configuration. - -The default engine is MyISAM_ [#]_. The main drawback of MyISAM is that it -doesn't currently support transactions or foreign keys. On the plus side, it's -currently the only engine that supports full-text indexing and searching. - -The InnoDB_ engine is fully transactional and supports foreign key references. - -The BDB_ engine, like InnoDB, is also fully transactional and supports foreign -key references. However, its use seems to be deprecated. - -`Other storage engines`_, including SolidDB_ and Falcon_, are on the horizon. -For now, InnoDB is probably your best choice. - -.. _storage engines: http://dev.mysql.com/doc/refman/5.0/en/storage-engines.html -.. _MyISAM: http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html -.. _BDB: http://dev.mysql.com/doc/refman/5.0/en/bdb-storage-engine.html -.. _InnoDB: http://dev.mysql.com/doc/refman/5.0/en/innodb.html -.. _Other storage engines: http://dev.mysql.com/doc/refman/5.1/en/storage-engines-other.html -.. _SolidDB: http://forge.mysql.com/projects/project.php?id=139 -.. _Falcon: http://dev.mysql.com/doc/falcon/en/index.html - -.. [#] Unless this was changed by the packager of your MySQL package. We've - had reports that the Windows Community Server installer sets up InnoDB as - the default storage engine, for example. - -MySQLdb -------- - -`MySQLdb`_ is the Python interface to MySQL. Version 1.2.1p2 or later is -required for full MySQL support in Django. - -.. note:: - If you see ``ImportError: cannot import name ImmutableSet`` when trying to - use Django, your MySQLdb installation may contain an outdated ``sets.py`` - file that conflicts with the built-in module of the same name from Python - 2.4 and later. To fix this, verify that you have installed MySQLdb version - 1.2.1p2 or newer, then delete the ``sets.py`` file in the MySQLdb - directory that was left by an earlier version. - -.. _MySQLdb: http://sourceforge.net/projects/mysql-python - -Creating your database ----------------------- - -You can `create your database`_ using the command-line tools and this SQL:: - - CREATE DATABASE <dbname> CHARACTER SET utf8; - -This ensures all tables and columns will use UTF-8 by default. - -.. _create your database: http://dev.mysql.com/doc/refman/5.0/en/create-database.html - -.. _mysql-collation: - -Collation settings -~~~~~~~~~~~~~~~~~~ - -The collation setting for a column controls the order in which data is sorted -as well as what strings compare as equal. It can be set on a database-wide -level and also per-table and per-column. This is `documented thoroughly`_ in -the MySQL documentation. In all cases, you set the collation by directly -manipulating the database tables; Django doesn't provide a way to set this on -the model definition. - -.. _documented thoroughly: http://dev.mysql.com/doc/refman/5.0/en/charset.html - -By default, with a UTF-8 database, MySQL will use the -``utf8_general_ci_swedish`` collation. This results in all string equality -comparisons being done in a *case-insensitive* manner. That is, ``"Fred"`` and -``"freD"`` are considered equal at the database level. If you have a unique -constraint on a field, it would be illegal to try to insert both ``"aa"`` and -``"AA"`` into the same column, since they compare as equal (and, hence, -non-unique) with the default collation. - -In many cases, this default will not be a problem. However, if you really want -case-sensitive comparisons on a particular column or table, you would change -the column or table to use the ``utf8_bin`` collation. The main thing to be -aware of in this case is that if you are using MySQLdb 1.2.2, the database -backend in Django will then return bytestrings (instead of unicode strings) for -any character fields it receive from the database. This is a strong variation -from Django's normal practice of *always* returning unicode strings. It is up -to you, the developer, to handle the fact that you will receive bytestrings if -you configure your table(s) to use ``utf8_bin`` collation. Django itself should -mostly work smoothly with such columns (except for the ``contrib.sessions`` -``Session`` and ``contrib.admin`` ``LogEntry`` tables described below), but -your code must be prepared to call ``django.utils.encoding.smart_unicode()`` at -times if it really wants to work with consistent data -- Django will not do -this for you (the database backend layer and the model population layer are -separated internally so the database layer doesn't know it needs to make this -conversion in this one particular case). - -If you're using MySQLdb 1.2.1p2, Django's standard -:class:`~django.db.models.CharField` class will return unicode strings even -with ``utf8_bin`` collation. However, :class:`~django.db.models.TextField` -fields will be returned as an ``array.array`` instance (from Python's standard -``array`` module). There isn't a lot Django can do about that, since, again, -the information needed to make the necessary conversions isn't available when -the data is read in from the database. This problem was `fixed in MySQLdb -1.2.2`_, so if you want to use :class:`~django.db.models.TextField` with -``utf8_bin`` collation, upgrading to version 1.2.2 and then dealing with the -bytestrings (which shouldn't be too difficult) as described above is the -recommended solution. - -Should you decide to use ``utf8_bin`` collation for some of your tables with -MySQLdb 1.2.1p2 or 1.2.2, you should still use ``utf8_collation_ci_swedish`` -(the default) collation for the :class:`django.contrib.sessions.models.Session` -table (usually called ``django_session``) and the -:class:`django.contrib.admin.models.LogEntry` table (usually called -``django_admin_log``). Those are the two standard tables that use -:class:`~django.db.model.TextField` internally. - -.. _fixed in MySQLdb 1.2.2: http://sourceforge.net/tracker/index.php?func=detail&aid=1495765&group_id=22307&atid=374932 - -Connecting to the database --------------------------- - -Refer to the :doc:`settings documentation </ref/settings>`. - -Connection settings are used in this order: - - 1. :setting:`OPTIONS`. - 2. :setting:`NAME`, :setting:`USER`, :setting:`PASSWORD`, - :setting:`HOST`, :setting:`PORT` - 3. MySQL option files. - -In other words, if you set the name of the database in ``OPTIONS``, -this will take precedence over ``NAME``, which would override -anything in a `MySQL option file`_. - -Here's a sample configuration which uses a MySQL option file:: - - # settings.py - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.mysql', - 'OPTIONS': { - 'read_default_file': '/path/to/my.cnf', - }, - } - } - - - # my.cnf - [client] - database = NAME - user = USER - password = PASSWORD - default-character-set = utf8 - -Several other MySQLdb connection options may be useful, such as ``ssl``, -``use_unicode``, ``init_command``, and ``sql_mode``. Consult the -`MySQLdb documentation`_ for more details. - -.. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html -.. _MySQLdb documentation: http://mysql-python.sourceforge.net/ - -Creating your tables --------------------- - -When Django generates the schema, it doesn't specify a storage engine, so -tables will be created with whatever default storage engine your database -server is configured for. The easiest solution is to set your database server's -default storage engine to the desired engine. - -If you're using a hosting service and can't change your server's default -storage engine, you have a couple of options. - - * After the tables are created, execute an ``ALTER TABLE`` statement to - convert a table to a new storage engine (such as InnoDB):: - - ALTER TABLE <tablename> ENGINE=INNODB; - - This can be tedious if you have a lot of tables. - - * Another option is to use the ``init_command`` option for MySQLdb prior to - creating your tables:: - - 'OPTIONS': { - 'init_command': 'SET storage_engine=INNODB', - } - - This sets the default storage engine upon connecting to the database. - After your tables have been created, you should remove this option. - - * Another method for changing the storage engine is described in - AlterModelOnSyncDB_. - -.. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB - -Notes on specific fields ------------------------- - -Boolean fields -~~~~~~~~~~~~~~ - -.. versionchanged:: 1.2 - -In previous versions of Django when running under MySQL ``BooleanFields`` would -return their data as ``ints``, instead of true ``bools``. See the release -notes for a complete description of the change. - -Character fields -~~~~~~~~~~~~~~~~ - -Any fields that are stored with ``VARCHAR`` column types have their -``max_length`` restricted to 255 characters if you are using ``unique=True`` -for the field. This affects :class:`~django.db.models.CharField`, -:class:`~django.db.models.SlugField` and -:class:`~django.db.models.CommaSeparatedIntegerField`. - -Furthermore, if you are using a version of MySQL prior to 5.0.3, all of those -column types have a maximum length restriction of 255 characters, regardless -of whether ``unique=True`` is specified or not. - -.. _sqlite-notes: - -SQLite notes -============ - -SQLite_ provides an excellent development alternative for applications that -are predominantly read-only or require a smaller installation footprint. As -with all database servers, though, there are some differences that are -specific to SQLite that you should be aware of. - -.. _SQLite: http://www.sqlite.org/ - -.. _sqlite-string-matching: - -String matching for non-ASCII strings --------------------------------------- - -SQLite doesn't support case-insensitive matching for non-ASCII strings. Some -possible workarounds for this are `documented at sqlite.org`_, but they are -not utilised by the default SQLite backend in Django. Therefore, if you are -using the ``iexact`` lookup type in your queryset filters, be aware that it -will not work as expected for non-ASCII strings. - -.. _documented at sqlite.org: http://www.sqlite.org/faq.html#q18 - -SQLite 3.3.6 or newer strongly recommended ------------------------------------------- - -Versions of SQLite 3.3.5 and older contains the following bugs: - - * A bug when `handling`_ ``ORDER BY`` parameters. This can cause problems when - you use the ``select`` parameter for the ``extra()`` QuerySet method. The bug - can be identified by the error message ``OperationalError: ORDER BY terms - must not be non-integer constants``. - - * A bug when handling `aggregation`_ together with DateFields and - DecimalFields. - -.. _handling: http://www.sqlite.org/cvstrac/tktview?tn=1768 -.. _aggregation: http://code.djangoproject.com/ticket/10031 - -SQLite 3.3.6 was released in April 2006, so most current binary distributions -for different platforms include newer version of SQLite usable from Python -through either the ``pysqlite2`` or the ``sqlite3`` modules. - -However, some platform/Python version combinations include older versions of -SQLite (e.g. the official binary distribution of Python 2.5 for Windows, 2.5.4 -as of this writing, includes SQLite 3.3.4). There are (as of Django 1.1) even -some tests in the Django test suite that will fail when run under this setup. - -As described :ref:`below<using-newer-versions-of-pysqlite>`, this can be solved -by downloading and installing a newer version of ``pysqlite2`` -(``pysqlite-2.x.x.win32-py2.5.exe`` in the described case) that includes and -uses a newer version of SQLite. Python 2.6 for Windows ships with a version of -SQLite that is not affected by these issues. - -Version 3.5.9 -------------- - -The Ubuntu "Intrepid Ibex" (8.10) SQLite 3.5.9-3 package contains a bug that -causes problems with the evaluation of query expressions. If you are using -Ubuntu "Intrepid Ibex", you will need to update the package to version -3.5.9-3ubuntu1 or newer (recommended) or find an alternate source for SQLite -packages, or install SQLite from source. - -At one time, Debian Lenny shipped with the same malfunctioning SQLite 3.5.9-3 -package. However the Debian project has subsequently issued updated versions -of the SQLite package that correct these bugs. If you find you are getting -unexpected results under Debian, ensure you have updated your SQLite package -to 3.5.9-5 or later. - -The problem does not appear to exist with other versions of SQLite packaged -with other operating systems. - -Version 3.6.2 --------------- - -SQLite version 3.6.2 (released August 30, 2008) introduced a bug into ``SELECT -DISTINCT`` handling that is triggered by, amongst other things, Django's -``DateQuerySet`` (returned by the ``dates()`` method on a queryset). - -You should avoid using this version of SQLite with Django. Either upgrade to -3.6.3 (released September 22, 2008) or later, or downgrade to an earlier -version of SQLite. - -.. _using-newer-versions-of-pysqlite: - -Using newer versions of the SQLite DB-API 2.0 driver ----------------------------------------------------- - -.. versionadded:: 1.1 - -For versions of Python 2.5 or newer that include ``sqlite3`` in the standard -library Django will now use a ``pysqlite2`` interface in preference to -``sqlite3`` if it finds one is available. - -This provides the ability to upgrade both the DB-API 2.0 interface or SQLite 3 -itself to versions newer than the ones included with your particular Python -binary distribution, if needed. - -"Database is locked" errors ------------------------------------------------ - -SQLite is meant to be a lightweight database, and thus can't support a high -level of concurrency. ``OperationalError: database is locked`` errors indicate -that your application is experiencing more concurrency than ``sqlite`` can -handle in default configuration. This error means that one thread or process has -an exclusive lock on the database connection and another thread timed out -waiting for the lock the be released. - -Python's SQLite wrapper has -a default timeout value that determines how long the second thread is allowed to -wait on the lock before it times out and raises the ``OperationalError: database -is locked`` error. - -If you're getting this error, you can solve it by: - - * Switching to another database backend. At a certain point SQLite becomes - too "lite" for real-world applications, and these sorts of concurrency - errors indicate you've reached that point. - - * Rewriting your code to reduce concurrency and ensure that database - transactions are short-lived. - - * Increase the default timeout value by setting the ``timeout`` database - option option:: - - 'OPTIONS': { - # ... - 'timeout': 20, - # ... - } - - This will simply make SQLite wait a bit longer before throwing "database - is locked" errors; it won't really do anything to solve them. - -.. _oracle-notes: - -Oracle notes -============ - -Django supports `Oracle Database Server`_ versions 9i and -higher. Oracle version 10g or later is required to use Django's -``regex`` and ``iregex`` query operators. You will also need at least -version 4.3.1 of the `cx_Oracle`_ Python driver. - -Note that due to a Unicode-corruption bug in ``cx_Oracle`` 5.0, that -version of the driver should **not** be used with Django; -``cx_Oracle`` 5.0.1 resolved this issue, so if you'd like to use a -more recent ``cx_Oracle``, use version 5.0.1. - -``cx_Oracle`` 5.0.1 or greater can optionally be compiled with the -``WITH_UNICODE`` environment variable. This is recommended but not -required. - -.. _`Oracle Database Server`: http://www.oracle.com/ -.. _`cx_Oracle`: http://cx-oracle.sourceforge.net/ - -In order for the ``python manage.py syncdb`` command to work, your Oracle -database user must have privileges to run the following commands: - - * CREATE TABLE - * CREATE SEQUENCE - * CREATE PROCEDURE - * CREATE TRIGGER - -To run Django's test suite, the user needs these *additional* privileges: - - * CREATE USER - * DROP USER - * CREATE TABLESPACE - * DROP TABLESPACE - * CONNECT WITH ADMIN OPTION - * RESOURCE WITH ADMIN OPTION - -Connecting to the database --------------------------- - -Your Django settings.py file should look something like this for Oracle:: - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.oracle', - 'NAME': 'xe', - 'USER': 'a_user', - 'PASSWORD': 'a_password', - 'HOST': '', - 'PORT': '', - } - } - - -If you don't use a ``tnsnames.ora`` file or a similar naming method that -recognizes the SID ("xe" in this example), then fill in both -``HOST`` and ``PORT`` like so:: - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.oracle', - 'NAME': 'xe', - 'USER': 'a_user', - 'PASSWORD': 'a_password', - 'HOST': 'dbprod01ned.mycompany.com', - 'PORT': '1540', - } - } - -You should supply both ``HOST`` and ``PORT``, or leave both -as empty strings. - -Threaded option ----------------- - -If you plan to run Django in a multithreaded environment (e.g. Apache in Windows -using the default MPM module), then you **must** set the ``threaded`` option of -your Oracle database configuration to True:: - - 'OPTIONS': { - 'threaded': True, - }, - -Failure to do this may result in crashes and other odd behavior. - -Tablespace options ------------------- - -A common paradigm for optimizing performance in Oracle-based systems is the -use of `tablespaces`_ to organize disk layout. The Oracle backend supports -this use case by adding ``db_tablespace`` options to the ``Meta`` and -``Field`` classes. (When you use a backend that lacks support for tablespaces, -Django ignores these options.) - -.. _`tablespaces`: http://en.wikipedia.org/wiki/Tablespace - -A tablespace can be specified for the table(s) generated by a model by -supplying the ``db_tablespace`` option inside the model's ``class Meta``. -Additionally, you can pass the ``db_tablespace`` option to a ``Field`` -constructor to specify an alternate tablespace for the ``Field``'s column -index. If no index would be created for the column, the ``db_tablespace`` -option is ignored:: - - class TablespaceExample(models.Model): - name = models.CharField(max_length=30, db_index=True, db_tablespace="indexes") - data = models.CharField(max_length=255, db_index=True) - edges = models.ManyToManyField(to="self", db_tablespace="indexes") - - class Meta: - db_tablespace = "tables" - -In this example, the tables generated by the ``TablespaceExample`` model -(i.e., the model table and the many-to-many table) would be stored in the -``tables`` tablespace. The index for the name field and the indexes on the -many-to-many table would be stored in the ``indexes`` tablespace. The ``data`` -field would also generate an index, but no tablespace for it is specified, so -it would be stored in the model tablespace ``tables`` by default. - -.. versionadded:: 1.0 - -Use the :setting:`DEFAULT_TABLESPACE` and :setting:`DEFAULT_INDEX_TABLESPACE` -settings to specify default values for the db_tablespace options. -These are useful for setting a tablespace for the built-in Django apps and -other applications whose code you cannot control. - -Django does not create the tablespaces for you. Please refer to `Oracle's -documentation`_ for details on creating and managing tablespaces. - -.. _`Oracle's documentation`: http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_7003.htm#SQLRF01403 - -Naming issues -------------- - -Oracle imposes a name length limit of 30 characters. To accommodate this, the -backend truncates database identifiers to fit, replacing the final four -characters of the truncated name with a repeatable MD5 hash value. - -When running syncdb, an ``ORA-06552`` error may be encountered if -certain Oracle keywords are used as the name of a model field or the -value of a ``db_column`` option. Django quotes all identifiers used -in queries to prevent most such problems, but this error can still -occur when an Oracle datatype is used as a column name. In -particular, take care to avoid using the names ``date``, -``timestamp``, ``number`` or ``float`` as a field name. - -NULL and empty strings ----------------------- - -Django generally prefers to use the empty string ('') rather than -NULL, but Oracle treats both identically. To get around this, the -Oracle backend coerces the ``null=True`` option on fields that have -the empty string as a possible value. When fetching from the database, -it is assumed that a NULL value in one of these fields really means -the empty string, and the data is silently converted to reflect this -assumption. - -``TextField`` limitations -------------------------- - -The Oracle backend stores ``TextFields`` as ``NCLOB`` columns. Oracle imposes -some limitations on the usage of such LOB columns in general: - - * LOB columns may not be used as primary keys. - - * LOB columns may not be used in indexes. - - * LOB columns may not be used in a ``SELECT DISTINCT`` list. This means that - attempting to use the ``QuerySet.distinct`` method on a model that - includes ``TextField`` columns will result in an error when run against - Oracle. As a workaround, use the ``QuerySet.defer`` method in conjunction - with ``distinct()`` to prevent ``TextField`` columns from being included in - the ``SELECT DISTINCT`` list. - -.. _third-party-notes: - -Using a 3rd-party database backend -================================== - -In addition to the officially supported databases, there are backends provided -by 3rd parties that allow you to use other databases with Django: - -* `Sybase SQL Anywhere`_ -* `IBM DB2`_ -* `Microsoft SQL Server 2005`_ -* Firebird_ -* ODBC_ - -The Django versions and ORM features supported by these unofficial backends -vary considerably. Queries regarding the specific capabilities of these -unofficial backends, along with any support queries, should be directed to -the support channels provided by each 3rd party project. - -.. _Sybase SQL Anywhere: http://code.google.com/p/sqlany-django/ -.. _IBM DB2: http://code.google.com/p/ibm-db/ -.. _Microsoft SQL Server 2005: http://code.google.com/p/django-mssql/ -.. _Firebird: http://code.google.com/p/django-firebird/ -.. _ODBC: http://code.google.com/p/django-pyodbc/ diff --git a/parts/django/docs/ref/django-admin.txt b/parts/django/docs/ref/django-admin.txt deleted file mode 100644 index 70faa3c..0000000 --- a/parts/django/docs/ref/django-admin.txt +++ /dev/null @@ -1,1293 +0,0 @@ -============================= -django-admin.py and manage.py -============================= - -``django-admin.py`` is Django's command-line utility for administrative tasks. -This document outlines all it can do. - -In addition, ``manage.py`` is automatically created in each Django project. -``manage.py`` is a thin wrapper around ``django-admin.py`` that takes care of -two things for you before delegating to ``django-admin.py``: - - * It puts your project's package on ``sys.path``. - - * It sets the :envvar:`DJANGO_SETTINGS_MODULE` environment variable so that - it points to your project's ``settings.py`` file. - -The ``django-admin.py`` script should be on your system path if you installed -Django via its ``setup.py`` utility. If it's not on your path, you can find it -in ``site-packages/django/bin`` within your Python installation. Consider -symlinking it from some place on your path, such as ``/usr/local/bin``. - -For Windows users, who do not have symlinking functionality available, you can -copy ``django-admin.py`` to a location on your existing path or edit the -``PATH`` settings (under ``Settings - Control Panel - System - Advanced - -Environment...``) to point to its installed location. - -Generally, when working on a single Django project, it's easier to use -``manage.py``. Use ``django-admin.py`` with ``DJANGO_SETTINGS_MODULE``, or the -``--settings`` command line option, if you need to switch between multiple -Django settings files. - -The command-line examples throughout this document use ``django-admin.py`` to -be consistent, but any example can use ``manage.py`` just as well. - -Usage -===== - -.. code-block:: bash - - django-admin.py <command> [options] - manage.py <command> [options] - -``command`` should be one of the commands listed in this document. -``options``, which is optional, should be zero or more of the options available -for the given command. - -Getting runtime help --------------------- - -.. django-admin-option:: --help - -Run ``django-admin.py help`` to display a list of all available commands. -Run ``django-admin.py help <command>`` to display a description of the -given command and a list of its available options. - -App names ---------- - -Many commands take a list of "app names." An "app name" is the basename of -the package containing your models. For example, if your ``INSTALLED_APPS`` -contains the string ``'mysite.blog'``, the app name is ``blog``. - -Determining the version ------------------------ - -.. django-admin-option:: --version - -Run ``django-admin.py --version`` to display the current Django version. - -Examples of output:: - - 0.95 - 0.96 - 0.97-pre-SVN-6069 - -Displaying debug output ------------------------ - -Use :djadminopt:`--verbosity` to specify the amount of notification and debug information -that ``django-admin.py`` should print to the console. For more details, see the -documentation for the :djadminopt:`--verbosity` option. - -Available commands -================== - -cleanup -------- - -.. django-admin:: cleanup - -.. versionadded:: 1.0 - -Can be run as a cronjob or directly to clean out old data from the database -(only expired sessions at the moment). - -compilemessages ---------------- - -.. django-admin:: compilemessages - -.. versionchanged:: 1.0 - Before 1.0 this was the "bin/compile-messages.py" command. - -Compiles .po files created with ``makemessages`` to .mo files for use with -the builtin gettext support. See :doc:`/topics/i18n/index`. - -Use the :djadminopt:`--locale` option to specify the locale to process. -If not provided, all locales are processed. - -Example usage:: - - django-admin.py compilemessages --locale=br_PT - -createcachetable ----------------- - -.. django-admin:: createcachetable - -Creates a cache table named ``tablename`` for use with the database cache -backend. See :doc:`/topics/cache` for more information. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database -onto which the cachetable will be installed. - -dbshell -------- - -.. django-admin:: dbshell - -Runs the command-line client for the database engine specified in your -``ENGINE`` setting, with the connection parameters specified in your -``USER``, ``PASSWORD``, etc., settings. - - * For PostgreSQL, this runs the ``psql`` command-line client. - * For MySQL, this runs the ``mysql`` command-line client. - * For SQLite, this runs the ``sqlite3`` command-line client. - -This command assumes the programs are on your ``PATH`` so that a simple call to -the program name (``psql``, ``mysql``, ``sqlite3``) will find the program in -the right place. There's no way to specify the location of the program -manually. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database -onto which to open a shell. - -diffsettings ------------- - -.. django-admin:: diffsettings - -Displays differences between the current settings file and Django's default -settings. - -Settings that don't appear in the defaults are followed by ``"###"``. For -example, the default settings don't define ``ROOT_URLCONF``, so -``ROOT_URLCONF`` is followed by ``"###"`` in the output of ``diffsettings``. - -Note that Django's default settings live in ``django/conf/global_settings.py``, -if you're ever curious to see the full list of defaults. - -dumpdata <appname appname appname.Model ...> --------------------------------------------- - -.. django-admin:: dumpdata - -Outputs to standard output all data in the database associated with the named -application(s). - -If no application name is provided, all installed applications will be dumped. - -The output of ``dumpdata`` can be used as input for ``loaddata``. - -Note that ``dumpdata`` uses the default manager on the model for selecting the -records to dump. If you're using a :ref:`custom manager <custom-managers>` as -the default manager and it filters some of the available records, not all of the -objects will be dumped. - -.. django-admin-option:: --format <fmt> - -By default, ``dumpdata`` will format its output in JSON, but you can use the -``--format`` option to specify another format. Currently supported formats -are listed in :ref:`serialization-formats`. - -.. django-admin-option:: --indent <num> - -By default, ``dumpdata`` will output all data on a single line. This isn't -easy for humans to read, so you can use the ``--indent`` option to -pretty-print the output with a number of indentation spaces. - -.. versionadded:: 1.0 - -The :djadminopt:`--exclude` option may be provided to prevent specific -applications from being dumped. - -.. versionadded:: 1.1 - -In addition to specifying application names, you can provide a list of -individual models, in the form of ``appname.Model``. If you specify a model -name to ``dumpdata``, the dumped output will be restricted to that model, -rather than the entire application. You can also mix application names and -model names. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database -onto which the data will be loaded. - -.. django-admin-option:: --natural - -.. versionadded:: 1.2 - -Use :ref:`natural keys <topics-serialization-natural-keys>` to represent -any foreign key and many-to-many relationship with a model that provides -a natural key definition. If you are dumping ``contrib.auth`` ``Permission`` -objects or ``contrib.contenttypes`` ``ContentType`` objects, you should -probably be using this flag. - -flush ------ - -.. django-admin:: flush - -Returns the database to the state it was in immediately after syncdb was -executed. This means that all data will be removed from the database, any -post-synchronization handlers will be re-executed, and the ``initial_data`` -fixture will be re-installed. - -The :djadminopt:`--noinput` option may be provided to suppress all user -prompts. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option may be used to specify the database -to flush. - - -inspectdb ---------- - -.. django-admin:: inspectdb - -Introspects the database tables in the database pointed-to by the -``NAME`` setting and outputs a Django model module (a ``models.py`` -file) to standard output. - -Use this if you have a legacy database with which you'd like to use Django. -The script will inspect the database and create a model for each table within -it. - -As you might expect, the created models will have an attribute for every field -in the table. Note that ``inspectdb`` has a few special cases in its field-name -output: - - * If ``inspectdb`` cannot map a column's type to a model field type, it'll - use ``TextField`` and will insert the Python comment - ``'This field type is a guess.'`` next to the field in the generated - model. - - * If the database column name is a Python reserved word (such as - ``'pass'``, ``'class'`` or ``'for'``), ``inspectdb`` will append - ``'_field'`` to the attribute name. For example, if a table has a column - ``'for'``, the generated model will have a field ``'for_field'``, with - the ``db_column`` attribute set to ``'for'``. ``inspectdb`` will insert - the Python comment - ``'Field renamed because it was a Python reserved word.'`` next to the - field. - -This feature is meant as a shortcut, not as definitive model generation. After -you run it, you'll want to look over the generated models yourself to make -customizations. In particular, you'll need to rearrange models' order, so that -models that refer to other models are ordered properly. - -Primary keys are automatically introspected for PostgreSQL, MySQL and -SQLite, in which case Django puts in the ``primary_key=True`` where -needed. - -``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection -only works in PostgreSQL and with certain types of MySQL tables. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option may be used to specify the -database to introspect. - -loaddata <fixture fixture ...> ------------------------------- - -.. django-admin:: loaddata - -Searches for and loads the contents of the named fixture into the database. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database -onto which the data will be loaded. - -What's a "fixture"? -~~~~~~~~~~~~~~~~~~~ - -A *fixture* is a collection of files that contain the serialized contents of -the database. Each fixture has a unique name, and the files that comprise the -fixture can be distributed over multiple directories, in multiple applications. - -Django will search in three locations for fixtures: - - 1. In the ``fixtures`` directory of every installed application - 2. In any directory named in the ``FIXTURE_DIRS`` setting - 3. In the literal path named by the fixture - -Django will load any and all fixtures it finds in these locations that match -the provided fixture names. - -If the named fixture has a file extension, only fixtures of that type -will be loaded. For example:: - - django-admin.py loaddata mydata.json - -would only load JSON fixtures called ``mydata``. The fixture extension -must correspond to the registered name of a -:ref:`serializer <serialization-formats>` (e.g., ``json`` or ``xml``). - -If you omit the extensions, Django will search all available fixture types -for a matching fixture. For example:: - - django-admin.py loaddata mydata - -would look for any fixture of any fixture type called ``mydata``. If a fixture -directory contained ``mydata.json``, that fixture would be loaded -as a JSON fixture. - -The fixtures that are named can include directory components. These -directories will be included in the search path. For example:: - - django-admin.py loaddata foo/bar/mydata.json - -would search ``<appname>/fixtures/foo/bar/mydata.json`` for each installed -application, ``<dirname>/foo/bar/mydata.json`` for each directory in -``FIXTURE_DIRS``, and the literal path ``foo/bar/mydata.json``. - -When fixture files are processed, the data is saved to the database as is. -Model defined ``save`` methods and ``pre_save`` signals are not called. - -Note that the order in which fixture files are processed is undefined. However, -all fixture data is installed as a single transaction, so data in -one fixture can reference data in another fixture. If the database backend -supports row-level constraints, these constraints will be checked at the -end of the transaction. - -The ``dumpdata`` command can be used to generate input for ``loaddata``. - -Compressed fixtures -~~~~~~~~~~~~~~~~~~~ - -Fixtures may be compressed in ``zip``, ``gz``, or ``bz2`` format. For example:: - - django-admin.py loaddata mydata.json - -would look for any of ``mydata.json``, ``mydata.json.zip``, -``mydata.json.gz``, or ``mydata.json.bz2``. The first file contained within a -zip-compressed archive is used. - -Note that if two fixtures with the same name but different -fixture type are discovered (for example, if ``mydata.json`` and -``mydata.xml.gz`` were found in the same fixture directory), fixture -installation will be aborted, and any data installed in the call to -``loaddata`` will be removed from the database. - -.. admonition:: MySQL and Fixtures - - Unfortunately, MySQL isn't capable of completely supporting all the - features of Django fixtures. If you use MyISAM tables, MySQL doesn't - support transactions or constraints, so you won't get a rollback if - multiple transaction files are found, or validation of fixture data. - If you use InnoDB tables, you won't be able to have any forward - references in your data files - MySQL doesn't provide a mechanism to - defer checking of row constraints until a transaction is committed. - -Database-specific fixtures -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you are in a multi-database setup, you may have fixture data that -you want to load onto one database, but not onto another. In this -situation, you can add database identifier into . If your -:setting:`DATABASES` setting has a 'master' database defined, you can -define the fixture ``mydata.master.json`` or -``mydata.master.json.gz``. This fixture will only be loaded if you -have specified that you want to load data onto the ``master`` -database. - -makemessages ------------- - -.. django-admin:: makemessages - -.. versionchanged:: 1.0 - Before 1.0 this was the ``bin/make-messages.py`` command. - -Runs over the entire source tree of the current directory and pulls out all -strings marked for translation. It creates (or updates) a message file in the -conf/locale (in the django tree) or locale (for project and application) -directory. After making changes to the messages files you need to compile them -with ``compilemessages`` for use with the builtin gettext support. See the -:ref:`i18n documentation <how-to-create-language-files>` for details. - -.. django-admin-option:: --all - -Use the ``--all`` or ``-a`` option to update the message files for all -available languages. - -Example usage:: - - django-admin.py makemessages --all - -.. django-admin-option:: --extension - -Use the ``--extension`` or ``-e`` option to specify a list of file extensions -to examine (default: ".html"). - -Example usage:: - - django-admin.py makemessages --locale=de --extension xhtml - -Separate multiple extensions with commas or use -e or --extension multiple times:: - - django-admin.py makemessages --locale=de --extension=html,txt --extension xml - -Use the :djadminopt:`--locale` option to specify the locale to process. - -Example usage:: - - django-admin.py makemessages --locale=br_PT - -.. django-admin-option:: --domain - -Use the ``--domain`` or ``-d`` option to change the domain of the messages files. -Currently supported: - - * ``django`` for all ``*.py`` and ``*.html`` files (default) - * ``djangojs`` for ``*.js`` files - -.. django-admin-option:: --symlinks - -.. versionadded:: 1.2 - -Use the ``--symlinks`` or ``-s`` option to follow symlinks to directories when -looking for new translation strings. - -Example usage:: - - django-admin.py makemessages --locale=de --symlinks - -.. django-admin-option:: --ignore - -Use the ``--ignore`` or ``-i`` option to ignore files or directories matching -the given `glob-style pattern`_. Use multiple times to ignore more. - -These patterns are used by default: ``'CVS'``, ``'.*'``, ``'*~'`` - -Example usage:: - - django-admin.py makemessages --locale=en_US --ignore=apps/* --ignore=secret/*.html - -.. _`glob-style pattern`: http://docs.python.org/library/glob.html - -.. django-admin-option:: --no-default-ignore - -Use the ``--no-default-ignore`` option to disable the default values of -:djadminopt:`--ignore`. - -reset <appname appname ...> ---------------------------- - -.. django-admin:: reset - -Executes the equivalent of ``sqlreset`` for the given app name(s). - -The :djadminopt:`--noinput` option may be provided to suppress all user -prompts. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the alias -of the database to reset. - -runfcgi [options] ------------------ - -.. django-admin:: runfcgi - -Starts a set of FastCGI processes suitable for use with any Web server that -supports the FastCGI protocol. See the :doc:`FastCGI deployment documentation -</howto/deployment/fastcgi>` for details. Requires the Python FastCGI module from -`flup`_. - -.. _flup: http://www.saddi.com/software/flup/ - -The options accepted by this command are passed to the FastCGI library and -don't use the ``'--'`` prefix as is usual for other Django management commands. - -.. django-admin-option:: protocol - -``protocol=PROTOCOL`` - -Protocol to use. *PROTOCOL* can be ``fcgi``, ``scgi``, ``ajp``, etc. -(default is ``fcgi``) - -.. django-admin-option:: host - -``host=HOSTNAME`` - -Hostname to listen on. - -.. django-admin-option:: port - -``port=PORTNUM`` - -Port to listen on. - -.. django-admin-option:: socket - -``socket=FILE`` - -UNIX socket to listen on. - -.. django-admin-option:: method - -``method=IMPL`` - -Possible values: ``prefork`` or ``threaded`` (default ``prefork``) - -.. django-admin-option:: maxrequests - -``maxrequests=NUMBER`` - -Number of requests a child handles before it is killed and a new child is -forked (0 means no limit). - -.. django-admin-option:: maxspare - -``maxspare=NUMBER`` - -Max number of spare processes / threads. - -.. django-admin-option:: minspare - -``minspare=NUMBER`` - -Min number of spare processes / threads. - -.. django-admin-option:: maxchildren - -``maxchildren=NUMBER`` - -Hard limit number of processes / threads. - -.. django-admin-option:: daemonize - -``daemonize=BOOL`` - -Whether to detach from terminal. - -.. django-admin-option:: pidfile - -``pidfile=FILE`` - -Write the spawned process-id to file *FILE*. - -.. django-admin-option:: workdir - -``workdir=DIRECTORY`` - -Change to directory *DIRECTORY* when daemonizing. - -.. django-admin-option:: debug - -``debug=BOOL`` - -Set to true to enable flup tracebacks. - -.. django-admin-option:: outlog - -``outlog=FILE`` - -Write stdout to the *FILE* file. - -.. django-admin-option:: errlog - -``errlog=FILE`` - -Write stderr to the *FILE* file. - -.. django-admin-option:: umask - -``umask=UMASK`` - -Umask to use when daemonizing. The value is interpeted as an octal number -(default value is ``022``). - -Example usage:: - - django-admin.py runfcgi socket=/tmp/fcgi.sock method=prefork daemonize=true \ - pidfile=/var/run/django-fcgi.pid - -Run a FastCGI server as a daemon and write the spawned PID in a file. - -runserver [port or ipaddr:port] -------------------------------- - -.. django-admin:: runserver - -Starts a lightweight development Web server on the local machine. By default, -the server runs on port 8000 on the IP address 127.0.0.1. You can pass in an -IP address and port number explicitly. - -If you run this script as a user with normal privileges (recommended), you -might not have access to start a port on a low port number. Low port numbers -are reserved for the superuser (root). - -DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through -security audits or performance tests. (And that's how it's gonna stay. We're in -the business of making Web frameworks, not Web servers, so improving this -server to be able to handle a production environment is outside the scope of -Django.) - -The development server automatically reloads Python code for each request, as -needed. You don't need to restart the server for code changes to take effect. - -When you start the server, and each time you change Python code while the -server is running, the server will validate all of your installed models. (See -the ``validate`` command below.) If the validator finds errors, it will print -them to standard output, but it won't stop the server. - -You can run as many servers as you want, as long as they're on separate ports. -Just execute ``django-admin.py runserver`` more than once. - -Note that the default IP address, 127.0.0.1, is not accessible from other -machines on your network. To make your development server viewable to other -machines on the network, use its own IP address (e.g. ``192.168.2.1``) or -``0.0.0.0``. - -.. django-admin-option:: --adminmedia - -Use the ``--adminmedia`` option to tell Django where to find the various CSS -and JavaScript files for the Django admin interface. Normally, the development -server serves these files out of the Django source tree magically, but you'd -want to use this if you made any changes to those files for your own site. - -Example usage:: - - django-admin.py runserver --adminmedia=/tmp/new-admin-style/ - -.. django-admin-option:: --noreload - -Use the ``--noreload`` option to disable the use of the auto-reloader. This -means any Python code changes you make while the server is running will *not* -take effect if the particular Python modules have already been loaded into -memory. - -Example usage:: - - django-admin.py runserver --noreload - -Examples of using different ports and addresses -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Port 8000 on IP address 127.0.0.1:: - - django-admin.py runserver - -Port 8000 on IP address 1.2.3.4:: - - django-admin.py runserver 1.2.3.4:8000 - -Port 7000 on IP address 127.0.0.1:: - - django-admin.py runserver 7000 - -Port 7000 on IP address 1.2.3.4:: - - django-admin.py runserver 1.2.3.4:7000 - -Serving static files with the development server -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default, the development server doesn't serve any static files for your site -(such as CSS files, images, things under ``MEDIA_URL`` and so forth). If -you want to configure Django to serve static media, read :doc:`/howto/static-files`. - -shell ------ - -.. django-admin:: shell - -Starts the Python interactive interpreter. - -Django will use IPython_, if it's installed. If you have IPython installed and -want to force use of the "plain" Python interpreter, use the ``--plain`` -option, like so:: - - django-admin.py shell --plain - -.. _IPython: http://ipython.scipy.org/ - -sql <appname appname ...> -------------------------- - -.. django-admin:: sql - -Prints the CREATE TABLE SQL statements for the given app name(s). - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database for -which to print the SQL. - -sqlall <appname appname ...> ----------------------------- - -.. django-admin:: sqlall - -Prints the CREATE TABLE and initial-data SQL statements for the given app name(s). - -Refer to the description of ``sqlcustom`` for an explanation of how to -specify initial data. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database for -which to print the SQL. - -sqlclear <appname appname ...> ------------------------------- - -.. django-admin:: sqlclear - -Prints the DROP TABLE SQL statements for the given app name(s). - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database for -which to print the SQL. - -sqlcustom <appname appname ...> -------------------------------- - -.. django-admin:: sqlcustom - -Prints the custom SQL statements for the given app name(s). - -For each model in each specified app, this command looks for the file -``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given app name and -``<modelname>`` is the model's name in lowercase. For example, if you have an -app ``news`` that includes a ``Story`` model, ``sqlcustom`` will attempt -to read a file ``news/sql/story.sql`` and append it to the output of this -command. - -Each of the SQL files, if given, is expected to contain valid SQL. The SQL -files are piped directly into the database after all of the models' -table-creation statements have been executed. Use this SQL hook to make any -table modifications, or insert any SQL functions into the database. - -Note that the order in which the SQL files are processed is undefined. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database for -which to print the SQL. - -sqlflush --------- - -.. django-admin:: sqlflush - -Prints the SQL statements that would be executed for the :djadmin:`flush` -command. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database for -which to print the SQL. - -sqlindexes <appname appname ...> --------------------------------- - -.. django-admin:: sqlindexes - -Prints the CREATE INDEX SQL statements for the given app name(s). - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database for -which to print the SQL. - -sqlreset <appname appname ...> ------------------------------- - -.. django-admin:: sqlreset - -Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s). - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database for -which to print the SQL. - -sqlsequencereset <appname appname ...> --------------------------------------- - -.. django-admin:: sqlsequencereset - -Prints the SQL statements for resetting sequences for the given app name(s). - -Sequences are indexes used by some database engines to track the next available -number for automatically incremented fields. - -Use this command to generate SQL which will fix cases where a sequence is out -of sync with its automatically incremented field data. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database for -which to print the SQL. - -startapp <appname> ------------------- - -.. django-admin:: startapp - -Creates a Django app directory structure for the given app name in the current -directory. - -startproject <projectname> --------------------------- - -.. django-admin:: startproject - -Creates a Django project directory structure for the given project name in the -current directory. - -This command is disabled when the ``--settings`` option to -``django-admin.py`` is used, or when the environment variable -``DJANGO_SETTINGS_MODULE`` has been set. To re-enable it in these -situations, either omit the ``--settings`` option or unset -``DJANGO_SETTINGS_MODULE``. - -syncdb ------- - -.. django-admin:: syncdb - -Creates the database tables for all apps in ``INSTALLED_APPS`` whose tables -have not already been created. - -Use this command when you've added new applications to your project and want to -install them in the database. This includes any apps shipped with Django that -might be in ``INSTALLED_APPS`` by default. When you start a new project, run -this command to install the default apps. - -.. admonition:: Syncdb will not alter existing tables - - ``syncdb`` will only create tables for models which have not yet been - installed. It will *never* issue ``ALTER TABLE`` statements to match - changes made to a model class after installation. Changes to model classes - and database schemas often involve some form of ambiguity and, in those - cases, Django would have to guess at the correct changes to make. There is - a risk that critical data would be lost in the process. - - If you have made changes to a model and wish to alter the database tables - to match, use the ``sql`` command to display the new SQL structure and - compare that to your existing table schema to work out the changes. - -If you're installing the ``django.contrib.auth`` application, ``syncdb`` will -give you the option of creating a superuser immediately. - -``syncdb`` will also search for and install any fixture named ``initial_data`` -with an appropriate extension (e.g. ``json`` or ``xml``). See the -documentation for ``loaddata`` for details on the specification of fixture -data files. - ---noinput -~~~~~~~~~ -The :djadminopt:`--noinput` option may be provided to suppress all user -prompts. - -.. versionadded:: 1.2 - -The :djadminopt:`--database` option can be used to specify the database to -synchronize. - -test <app or test identifier> ------------------------------ - -.. django-admin:: test - -Runs tests for all installed models. See :doc:`/topics/testing` for more -information. - -.. versionadded:: 1.2 -.. django-admin-option:: --failfast - -Use the :djadminopt:`--failfast` option to stop running tests and report the failure -immediately after a test fails. - -testserver <fixture fixture ...> --------------------------------- - -.. django-admin:: testserver - -.. versionadded:: 1.0 - -Runs a Django development server (as in ``runserver``) using data from the -given fixture(s). - -For example, this command:: - - django-admin.py testserver mydata.json - -...would perform the following steps: - - 1. Create a test database, as described in :doc:`/topics/testing`. - 2. Populate the test database with fixture data from the given fixtures. - (For more on fixtures, see the documentation for ``loaddata`` above.) - 3. Runs the Django development server (as in ``runserver``), pointed at - this newly created test database instead of your production database. - -This is useful in a number of ways: - - * When you're writing :doc:`unit tests </topics/testing>` of how your views - act with certain fixture data, you can use ``testserver`` to interact with - the views in a Web browser, manually. - - * Let's say you're developing your Django application and have a "pristine" - copy of a database that you'd like to interact with. You can dump your - database to a fixture (using the ``dumpdata`` command, explained above), - then use ``testserver`` to run your Web application with that data. With - this arrangement, you have the flexibility of messing up your data - in any way, knowing that whatever data changes you're making are only - being made to a test database. - -Note that this server does *not* automatically detect changes to your Python -source code (as ``runserver`` does). It does, however, detect changes to -templates. - -.. django-admin-option:: --addrport [port number or ipaddr:port] - -Use ``--addrport`` to specify a different port, or IP address and port, from -the default of 127.0.0.1:8000. This value follows exactly the same format and -serves exactly the same function as the argument to the ``runserver`` command. - -Examples: - -To run the test server on port 7000 with ``fixture1`` and ``fixture2``:: - - django-admin.py testserver --addrport 7000 fixture1 fixture2 - django-admin.py testserver fixture1 fixture2 --addrport 7000 - -(The above statements are equivalent. We include both of them to demonstrate -that it doesn't matter whether the options come before or after the fixture -arguments.) - -To run on 1.2.3.4:7000 with a ``test`` fixture:: - - django-admin.py testserver --addrport 1.2.3.4:7000 test - -validate --------- - -.. django-admin:: validate - -Validates all installed models (according to the ``INSTALLED_APPS`` setting) -and prints validation errors to standard output. - -Commands provided by applications -================================= - -Some commands are only available when the ``django.contrib`` application that -:doc:`implements </howto/custom-management-commands>` them has been -:setting:`enabled <INSTALLED_APPS>`. This section describes them grouped by -their application. - -``django.contrib.auth`` ------------------------ - -changepassword -~~~~~~~~~~~~~~ - -.. django-admin:: changepassword - -.. versionadded:: 1.2 - -This command is only available if Django's :doc:`authentication system -</topics/auth>` (``django.contrib.auth``) is installed. - -Allows changing a user's password. It prompts you to enter twice the password of -the user given as parameter. If they both match, the new password will be -changed immediately. If you do not supply a user, the command will attempt to -change the password whose username matches the current user. - -Example usage:: - - django-admin.py changepassword ringo - -createsuperuser -~~~~~~~~~~~~~~~ - -.. django-admin:: createsuperuser - -.. versionadded:: 1.0 - -This command is only available if Django's :doc:`authentication system -</topics/auth>` (``django.contrib.auth``) is installed. - -Creates a superuser account (a user who has all permissions). This is -useful if you need to create an initial superuser account but did not -do so during ``syncdb``, or if you need to programmatically generate -superuser accounts for your site(s). - -When run interactively, this command will prompt for a password for -the new superuser account. When run non-interactively, no password -will be set, and the superuser account will not be able to log in until -a password has been manually set for it. - -.. django-admin-option:: --username -.. django-admin-option:: --email - -The username and e-mail address for the new account can be supplied by -using the ``--username`` and ``--email`` arguments on the command -line. If either of those is not supplied, ``createsuperuser`` will prompt for -it when running interactively. - -``django.contrib.gis`` ----------------------- - -ogrinspect -~~~~~~~~~~ - -This command is only available if :doc:`GeoDjango </ref/contrib/gis/index>` -(``django.contrib.gis``) is installed. - -Please refer to its :djadmin:`description <ogrinspect>` in the GeoDjango -documentation. - -``django.contrib.sitemaps`` ---------------------------- - -ping_google -~~~~~~~~~~~ - -This command is only available if the :doc:`Sitemaps framework -</ref/contrib/sitemaps>` (``django.contrib.sitemaps``) is installed. - -Please refer to its :djadmin:`description <ping_google>` in the Sitemaps -documentation. - -Default options -=============== - -Although some commands may allow their own custom options, every command -allows for the following options: - -.. django-admin-option:: --pythonpath - -Example usage:: - - django-admin.py syncdb --pythonpath='/home/djangoprojects/myproject' - -Adds the given filesystem path to the Python `import search path`_. If this -isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment -variable. - -Note that this option is unnecessary in ``manage.py``, because it takes care of -setting the Python path for you. - -.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html - -.. django-admin-option:: --settings - -Example usage:: - - django-admin.py syncdb --settings=mysite.settings - -Explicitly specifies the settings module to use. The settings module should be -in Python package syntax, e.g. ``mysite.settings``. If this isn't provided, -``django-admin.py`` will use the ``DJANGO_SETTINGS_MODULE`` environment -variable. - -Note that this option is unnecessary in ``manage.py``, because it uses -``settings.py`` from the current project by default. - -.. django-admin-option:: --traceback - -Example usage:: - - django-admin.py syncdb --traceback - -By default, ``django-admin.py`` will show a simple error message whenever an -error occurs. If you specify ``--traceback``, ``django-admin.py`` will -output a full stack trace whenever an exception is raised. - -.. django-admin-option:: --verbosity - -Example usage:: - - django-admin.py syncdb --verbosity 2 - -Use ``--verbosity`` to specify the amount of notification and debug information -that ``django-admin.py`` should print to the console. - - * ``0`` means no output. - * ``1`` means normal output (default). - * ``2`` means verbose output. - -Common options -============== - -The following options are not available on every commands, but they are -common to a number of commands. - -.. django-admin-option:: --database - -.. versionadded:: 1.2 - -Used to specify the database on which a command will operate. If not -specified, this option will default to an alias of ``default``. - -For example, to dump data from the database with the alias ``master``:: - - django-admin.py dumpdata --database=master - -.. django-admin-option:: --exclude - -Exclude a specific application from the applications whose contents is -output. For example, to specifically exclude the `auth` application from -the output of dumpdata, you would call:: - - django-admin.py dumpdata --exclude=auth - -If you want to exclude multiple applications, use multiple ``--exclude`` -directives:: - - django-admin.py dumpdata --exclude=auth --exclude=contenttypes - -.. django-admin-option:: --locale - -Use the ``--locale`` or ``-l`` option to specify the locale to process. -If not provided all locales are processed. - -.. django-admin-option:: --noinput - -Use the ``--noinput`` option to suppress all user prompting, such as "Are -you sure?" confirmation messages. This is useful if ``django-admin.py`` is -being executed as an unattended, automated script. - -Extra niceties -============== - -.. _syntax-coloring: - -Syntax coloring ---------------- - -The ``django-admin.py`` / ``manage.py`` commands will use pretty -color-coded output if your terminal supports ANSI-colored output. It -won't use the color codes if you're piping the command's output to -another program. - -The colors used for syntax highlighting can be customized. Django -ships with three color palettes: - - * ``dark``, suited to terminals that show white text on a black - background. This is the default palette. - - * ``light``, suited to terminals that show black text on a white - background. - - * ``nocolor``, which disables syntax highlighting. - -You select a palette by setting a ``DJANGO_COLORS`` environment -variable to specify the palette you want to use. For example, to -specify the ``light`` palette under a Unix or OS/X BASH shell, you -would run the following at a command prompt:: - - export DJANGO_COLORS="light" - -You can also customize the colors that are used. Django specifies a -number of roles in which color is used: - - * ``error`` - A major error. - * ``notice`` - A minor error. - * ``sql_field`` - The name of a model field in SQL. - * ``sql_coltype`` - The type of a model field in SQL. - * ``sql_keyword`` - A SQL keyword. - * ``sql_table`` - The name of a model in SQL. - * ``http_info`` - A 1XX HTTP Informational server response. - * ``http_success`` - A 2XX HTTP Success server response. - * ``http_not_modified`` - A 304 HTTP Not Modified server response. - * ``http_redirect`` - A 3XX HTTP Redirect server response other than 304. - * ``http_not_found`` - A 404 HTTP Not Found server response. - * ``http_bad_request`` - A 4XX HTTP Bad Request server response other than 404. - * ``http_server_error`` - A 5XX HTTP Server Error response. - -Each of these roles can be assigned a specific foreground and -background color, from the following list: - - * ``black`` - * ``red`` - * ``green`` - * ``yellow`` - * ``blue`` - * ``magenta`` - * ``cyan`` - * ``white`` - -Each of these colors can then be modified by using the following -display options: - - * ``bold`` - * ``underscore`` - * ``blink`` - * ``reverse`` - * ``conceal`` - -A color specification follows one of the the following patterns: - - * ``role=fg`` - * ``role=fg/bg`` - * ``role=fg,option,option`` - * ``role=fg/bg,option,option`` - -where ``role`` is the name of a valid color role, ``fg`` is the -foreground color, ``bg`` is the background color and each ``option`` -is one of the color modifying options. Multiple color specifications -are then separated by semicolon. For example:: - - export DJANGO_COLORS="error=yellow/blue,blink;notice=magenta" - -would specify that errors be displayed using blinking yellow on blue, -and notices displayed using magenta. All other color roles would be -left uncolored. - -Colors can also be specified by extending a base palette. If you put -a palette name in a color specification, all the colors implied by that -palette will be loaded. So:: - - export DJANGO_COLORS="light;error=yellow/blue,blink;notice=magenta" - -would specify the use of all the colors in the light color palette, -*except* for the colors for errors and notices which would be -overridden as specified. - -Bash completion ---------------- - -If you use the Bash shell, consider installing the Django bash completion -script, which lives in ``extras/django_bash_completion`` in the Django -distribution. It enables tab-completion of ``django-admin.py`` and -``manage.py`` commands, so you can, for instance... - - * Type ``django-admin.py``. - * Press [TAB] to see all available options. - * Type ``sql``, then [TAB], to see all available options whose names start - with ``sql``. - - -See :doc:`/howto/custom-management-commands` for how to add customized actions. - - -========================================== -Running management commands from your code -========================================== - -.. function:: django.core.management.call_command(name, *args, **options) - -To call a management command from code use ``call_command``. - -``name`` - the name of the command to call. - -``*args`` - a list of arguments accepted by the command. - -``**options`` - named options accepted on the command-line. - -Examples:: - - from django.core import management - management.call_command('flush', verbosity=0, interactive=False) - management.call_command('loaddata', 'test_data', verbosity=0) diff --git a/parts/django/docs/ref/exceptions.txt b/parts/django/docs/ref/exceptions.txt deleted file mode 100644 index f1246bf..0000000 --- a/parts/django/docs/ref/exceptions.txt +++ /dev/null @@ -1,128 +0,0 @@ -================= -Django Exceptions -================= - - -Django raises some Django specific exceptions as well as many standard -Python exceptions. - -Django-specific Exceptions -========================== - -.. module:: django.core.exceptions - :synopsis: Django specific exceptions - -ObjectDoesNotExist and DoesNotExist ------------------------------------ -.. exception:: DoesNotExist -.. exception:: ObjectDoesNotExist - - The :exc:`DoesNotExist` exception is raised when an object is not found - for the given parameters of a query. - - :exc:`ObjectDoesNotExist` is defined in :mod:`django.core.exceptions`. - :exc:`DoesNotExist` is a subclass of the base :exc:`ObjectDoesNotExist` - exception that is provided on every model class as a way of - identifying the specific type of object that could not be found. - - See :meth:`~django.db.models.QuerySet.get()` for further information - on :exc:`ObjectDoesNotExist` and :exc:`DoesNotExist`. - -MultipleObjectsReturned ------------------------ -.. exception:: MultipleObjectsReturned - - The :exc:`MultipleObjectsReturned` exception is raised by a query if only - one object is expected, but multiple objects are returned. A base version - of this exception is provided in :mod:`django.core.exceptions`; each model - class contains a subclassed version that can be used to identify the - specific object type that has returned multiple objects. - - See :meth:`~django.db.models.QuerySet.get()` for further information. - -SuspiciousOperation -------------------- -.. exception:: SuspiciousOperation - - The :exc:`SuspiciousOperation` exception is raised when a user has performed - an operation that should be considered suspicious from a security perspective, - such as tampering with a session cookie. - -PermissionDenied ----------------- -.. exception:: PermissionDenied - - The :exc:`PermissionDenied` exception is raised when a user does not have - permission to perform the action requested. - -ViewDoesNotExist ----------------- -.. exception:: ViewDoesNotExist - - The :exc:`ViewDoesNotExist` exception is raised by - :mod:`django.core.urlresolvers` when a requested view does not exist. - -MiddlewareNotUsed ------------------ -.. exception:: MiddlewareNotUsed - - The :exc:`MiddlewareNotUsed` exception is raised when a middleware is not - used in the server configuration. - -ImproperlyConfigured --------------------- -.. exception:: ImproperlyConfigured - - The :exc:`ImproperlyConfigured` exception is raised when Django is - somehow improperly configured -- for example, if a value in ``settings.py`` - is incorrect or unparseable. - -FieldError ----------- -.. exception:: FieldError - - The :exc:`FieldError` exception is raised when there is a problem with a - model field. This can happen for several reasons: - - - A field in a model clashes with a field of the same name from an - abstract base class - - An infinite loop is caused by ordering - - A keyword cannot be parsed from the filter parameters - - A field cannot be determined from a keyword in the query - parameters - - A join is not permitted on the specified field - - A field name is invalid - - A query contains invalid order_by arguments - -ValidationError ---------------- -.. exception:: ValidationError - - The :exc:`ValidationError` exception is raised when data fails form or - model field validation. For more information about validation, see - :doc:`Form and Field Validation </ref/forms/validation>`, - :ref:`Model Field Validation <validating-objects>` and the - :doc:`Validator Reference </ref/validators>`. - -Database Exceptions -=================== - -Django wraps the standard database exceptions :exc:`DatabaseError` and -:exc:`IntegrityError` so that your Django code has a guaranteed common -implementation of these classes. These database exceptions are -provided in :mod:`django.db`. - -The Django wrappers for database exceptions behave exactly the same as -the underlying database exceptions. See `PEP 249 - Python Database API -Specification v2.0`_ for further information. - -.. _`PEP 249 - Python Database API Specification v2.0`: http://www.python.org/dev/peps/pep-0249/ - -Python Exceptions -================= - -Django raises built-in Python exceptions when appropriate as well. See -the Python `documentation`_ for further information on the built-in -exceptions. - -.. _`documentation`: http://docs.python.org/lib/module-exceptions.html diff --git a/parts/django/docs/ref/files/file.txt b/parts/django/docs/ref/files/file.txt deleted file mode 100644 index 1374d01..0000000 --- a/parts/django/docs/ref/files/file.txt +++ /dev/null @@ -1,152 +0,0 @@ -The ``File`` object -=================== - -The :mod:`django.core.files` module and its submodules contain built-in classes -for basic file handling in Django. - -.. currentmodule:: django.core.files - -The ``File`` Class ------------------- - -.. class:: File(file_object) - - The :class:`File` is a thin wrapper around Python's built-in file object - with some Django-specific additions. Internally, Django uses this class - any time it needs to represent a file. - - :class:`File` objects have the following attributes and methods: - - .. attribute:: name - - The name of file including the relative path from - :setting:`MEDIA_ROOT`. - - .. attribute:: size - - The size of the file in bytes. - - .. attribute:: file - - The underlying Python ``file`` object passed to - :class:`~django.core.files.File`. - - .. attribute:: mode - - The read/write mode for the file. - - .. method:: open([mode=None]) - - Open or reopen the file (which by definition also does - ``File.seek(0)``). The ``mode`` argument allows the same values - as Python's standard ``open()``. - - When reopening a file, ``mode`` will override whatever mode the file - was originally opened with; ``None`` means to reopen with the original - mode. - - .. method:: read([num_bytes=None]) - - Read content from the file. The optional ``size`` is the number of - bytes to read; if not specified, the file will be read to the end. - - .. method:: __iter__() - - Iterate over the file yielding one line at a time. - - .. method:: chunks([chunk_size=None]) - - Iterate over the file yielding "chunks" of a given size. ``chunk_size`` - defaults to 64 KB. - - This is especially useful with very large files since it allows them to - be streamed off disk and avoids storing the whole file in memory. - - .. method:: multiple_chunks([chunk_size=None]) - - Returns ``True`` if the file is large enough to require multiple chunks - to access all of its content give some ``chunk_size``. - - .. method:: write([content]) - - Writes the specified content string to the file. Depending on the - storage system behind the scenes, this content might not be fully - committed until ``close()`` is called on the file. - - .. method:: close() - - Close the file. - - In addition to the listed methods, :class:`~django.core.files.File` exposes - the following attributes and methods of the underlying ``file`` object: - ``encoding``, ``fileno``, ``flush``, ``isatty``, ``newlines``, - ``read``, ``readinto``, ``readlines``, ``seek``, ``softspace``, ``tell``, - ``truncate``, ``writelines``, ``xreadlines``. - -.. currentmodule:: django.core.files.base - -The ``ContentFile`` Class -------------------------- - -.. class:: ContentFile(File) - - The ``ContentFile`` class inherits from :class:`~django.core.files.File`, - but unlike :class:`~django.core.files.File` it operates on string content, - rather than an actual file. For example:: - - from django.core.files.base import ContentFile - - f1 = ContentFile("my string content") - f2 = ContentFile(u"my unicode content encoded as UTF-8".encode('UTF-8')) - -.. currentmodule:: django.core.files.images - -The ``ImageFile`` Class ------------------------ - -.. class:: ImageFile(file_object) - - Django provides a built-in class specifically for images. - :class:`django.core.files.images.ImageFile` inherits all the attributes - and methods of :class:`~django.core.files.File`, and additionally - provides the following: - - .. attribute:: width - - Width of the image in pixels. - - .. attribute:: height - - Height of the image in pixels. - -.. currentmodule:: django.core.files - -Additional methods on files attached to objects ------------------------------------------------ - -Any :class:`File` that's associated with an object (as with ``Car.photo``, -below) will also have a couple of extra methods: - -.. method:: File.save(name, content, [save=True]) - - Saves a new file with the file name and contents provided. This will not - replace the existing file, but will create a new file and update the object - to point to it. If ``save`` is ``True``, the model's ``save()`` method will - be called once the file is saved. That is, these two lines:: - - >>> car.photo.save('myphoto.jpg', contents, save=False) - >>> car.save() - - are the same as this one line:: - - >>> car.photo.save('myphoto.jpg', contents, save=True) - - Note that the ``content`` argument must be an instance of either - :class:`File` or of a subclass of :class:`File`, such as - :class:`ContentFile`. - -.. method:: File.delete([save=True]) - - Removes the file from the model instance and deletes the underlying file. - If ``save`` is ``True``, the model's ``save()`` method will be called once - the file is deleted. diff --git a/parts/django/docs/ref/files/index.txt b/parts/django/docs/ref/files/index.txt deleted file mode 100644 index 552559d..0000000 --- a/parts/django/docs/ref/files/index.txt +++ /dev/null @@ -1,12 +0,0 @@ -============= -File handling -============= - -.. module:: django.core.files - :synopsis: File handling and storage - -.. toctree:: - :maxdepth: 2 - - file - storage diff --git a/parts/django/docs/ref/files/storage.txt b/parts/django/docs/ref/files/storage.txt deleted file mode 100644 index 84ef00c..0000000 --- a/parts/django/docs/ref/files/storage.txt +++ /dev/null @@ -1,119 +0,0 @@ -File storage API -================ - -.. module:: django.core.files.storage - -Getting the current storage class ---------------------------------- - -Django provides two convenient ways to access the current storage class: - -.. class:: DefaultStorage - - :class:`~django.core.files.storage.DefaultStorage` provides - lazy access to the current default storage system as defined by - :setting:`DEFAULT_FILE_STORAGE`. :class:`DefaultStorage` uses - :func:`~django.core.files.storage.get_storage_class` internally. - -.. function:: get_storage_class([import_path=None]) - - Returns a class or module which implements the storage API. - - When called without the ``import_path`` parameter ``get_storage_class`` - will return the current default storage system as defined by - :setting:`DEFAULT_FILE_STORAGE`. If ``import_path`` is provided, - ``get_storage_class`` will attempt to import the class or module from the - given path and will return it if successful. An exception will be - raised if the import is unsuccessful. - -The FileSystemStorage Class ---------------------------- - -.. class:: FileSystemStorage - - The :class:`~django.core.files.storage.FileSystemStorage` class implements - basic file storage on a local filesystem. It inherits from - :class:`~django.core.files.storage.Storage` and provides implementations - for all the public methods thereof. - - .. note:: - - The :class:`FileSystemStorage.delete` method will not raise - raise an exception if the given file name does not exist. - -The Storage Class ------------------ - -.. class:: Storage - - The :class:`~django.core.files.storage.Storage` class provides a - standardized API for storing files, along with a set of default - behaviors that all other storage systems can inherit or override - as necessary. - - .. method:: delete(name) - - Deletes the file referenced by ``name``. If deletion is not supported - on the targest storage system this will raise ``NotImplementedError`` - instead - - .. method:: exists(name) - - Returns ``True`` if a file referened by the given name already exists - in the storage system, or ``False`` if the name is available for a new - file. - - .. method:: get_available_name(name) - - Returns a filename based on the ``name`` parameter that's free and - available for new content to be written to on the target storage - system. - - - .. method:: get_valid_name(name) - - Returns a filename based on the ``name`` parameter that's suitable - for use on the target storage system. - - .. method:: listdir(path) - - Lists the contents of the specified path, returning a 2-tuple of lists; - the first item being directories, the second item being files. For - storage systems that aren't able to provide such a listing, this will - raise a ``NotImplementedError`` instead. - - .. method:: open(name, mode='rb') - - Opens the file given by ``name``. Note that although the returned file - is guaranteed to be a ``File`` object, it might actually be some - subclass. In the case of remote file storage this means that - reading/writing could be quite slow, so be warned. - - .. method:: path(name) - - The local filesystem path where the file can be opened using Python's - standard ``open()``. For storage systems that aren't accessible from - the local filesystem, this will raise ``NotImplementedError`` instead. - - .. method:: save(name, content) - - Saves a new file using the storage system, preferably with the name - specified. If there already exists a file with this name ``name``, the - storage system may modify the filename as necessary to get a unique - name. The actual name of the stored file will be returned. - - The ``content`` argument must be an instance of - :class:`django.core.files.File` or of a subclass of - :class:`~django.core.files.File`. - - .. method:: size(name) - - Returns the total size, in bytes, of the file referenced by ``name``. - For storage systems that aren't able to return the file size this will - raise ``NotImplementedError`` instead. - - .. method:: url(name) - - Returns the URL where the contents of the file referenced by ``name`` - can be accessed. For storage systems that don't support access by URL - this will raise ``NotImplementedError`` instead. diff --git a/parts/django/docs/ref/forms/api.txt b/parts/django/docs/ref/forms/api.txt deleted file mode 100644 index 613d754..0000000 --- a/parts/django/docs/ref/forms/api.txt +++ /dev/null @@ -1,791 +0,0 @@ -============= -The Forms API -============= - -.. module:: django.forms.forms - -.. currentmodule:: django.forms - -.. admonition:: About this document - - This document covers the gritty details of Django's forms API. You should - read the :doc:`introduction to working with forms </topics/forms/index>` - first. - -.. _ref-forms-api-bound-unbound: - -Bound and unbound forms ------------------------ - -A :class:`Form` instance is either **bound** to a set of data, or **unbound**. - - * If it's **bound** to a set of data, it's capable of validating that data - and rendering the form as HTML with the data displayed in the HTML. - - * If it's **unbound**, it cannot do validation (because there's no data to - validate!), but it can still render the blank form as HTML. - -.. class:: Form - -To create an unbound :class:`Form` instance, simply instantiate the class:: - - >>> f = ContactForm() - -To bind data to a form, pass the data as a dictionary as the first parameter to -your :class:`Form` class constructor:: - - >>> data = {'subject': 'hello', - ... 'message': 'Hi there', - ... 'sender': 'foo@example.com', - ... 'cc_myself': True} - >>> f = ContactForm(data) - -In this dictionary, the keys are the field names, which correspond to the -attributes in your :class:`Form` class. The values are the data you're trying to -validate. These will usually be strings, but there's no requirement that they be -strings; the type of data you pass depends on the :class:`Field`, as we'll see -in a moment. - -.. attribute:: Form.is_bound - -If you need to distinguish between bound and unbound form instances at runtime, -check the value of the form's :attr:`~Form.is_bound` attribute:: - - >>> f = ContactForm() - >>> f.is_bound - False - >>> f = ContactForm({'subject': 'hello'}) - >>> f.is_bound - True - -Note that passing an empty dictionary creates a *bound* form with empty data:: - - >>> f = ContactForm({}) - >>> f.is_bound - True - -If you have a bound :class:`Form` instance and want to change the data somehow, -or if you want to bind an unbound :class:`Form` instance to some data, create -another :class:`Form` instance. There is no way to change data in a -:class:`Form` instance. Once a :class:`Form` instance has been created, you -should consider its data immutable, whether it has data or not. - -Using forms to validate data ----------------------------- - -.. method:: Form.is_valid() - -The primary task of a :class:`Form` object is to validate data. With a bound -:class:`Form` instance, call the :meth:`~Form.is_valid` method to run validation -and return a boolean designating whether the data was valid:: - - >>> data = {'subject': 'hello', - ... 'message': 'Hi there', - ... 'sender': 'foo@example.com', - ... 'cc_myself': True} - >>> f = ContactForm(data) - >>> f.is_valid() - True - -Let's try with some invalid data. In this case, ``subject`` is blank (an error, -because all fields are required by default) and ``sender`` is not a valid -e-mail address:: - - >>> data = {'subject': '', - ... 'message': 'Hi there', - ... 'sender': 'invalid e-mail address', - ... 'cc_myself': True} - >>> f = ContactForm(data) - >>> f.is_valid() - False - -.. attribute:: Form.errors - -Access the :attr:`~Form.errors` attribute to get a dictionary of error -messages:: - - >>> f.errors - {'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']} - -In this dictionary, the keys are the field names, and the values are lists of -Unicode strings representing the error messages. The error messages are stored -in lists because a field can have multiple error messages. - -You can access :attr:`~Form.errors` without having to call -:meth:`~Form.is_valid` first. The form's data will be validated the first time -either you call :meth:`~Form.is_valid` or access :attr:`~Form.errors`. - -The validation routines will only get called once, regardless of how many times -you access :attr:`~Form.errors` or call :meth:`~Form.is_valid`. This means that -if validation has side effects, those side effects will only be triggered once. - -Behavior of unbound forms -~~~~~~~~~~~~~~~~~~~~~~~~~ - -It's meaningless to validate a form with no data, but, for the record, here's -what happens with unbound forms:: - - >>> f = ContactForm() - >>> f.is_valid() - False - >>> f.errors - {} - -Dynamic initial values ----------------------- - -.. attribute:: Form.initial - -Use :attr:`~Form.initial` to declare the initial value of form fields at -runtime. For example, you might want to fill in a ``username`` field with the -username of the current session. - -To accomplish this, use the :attr:`~Form.initial` argument to a :class:`Form`. -This argument, if given, should be a dictionary mapping field names to initial -values. Only include the fields for which you're specifying an initial value; -it's not necessary to include every field in your form. For example:: - - >>> f = ContactForm(initial={'subject': 'Hi there!'}) - -These values are only displayed for unbound forms, and they're not used as -fallback values if a particular value isn't provided. - -Note that if a :class:`~django.forms.fields.Field` defines -:attr:`~Form.initial` *and* you include ``initial`` when instantiating the -``Form``, then the latter ``initial`` will have precedence. In this example, -``initial`` is provided both at the field level and at the form instance level, -and the latter gets precedence:: - - >>> class CommentForm(forms.Form): - ... name = forms.CharField(initial='class') - ... url = forms.URLField() - ... comment = forms.CharField() - >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) - >>> print f - <tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr> - <tr><th>Url:</th><td><input type="text" name="url" /></td></tr> - <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> - -Accessing "clean" data ----------------------- - -.. attribute:: Form.cleaned_data - -Each field in a :class:`Form` class is responsible not only for validating -data, but also for "cleaning" it -- normalizing it to a consistent format. This -is a nice feature, because it allows data for a particular field to be input in -a variety of ways, always resulting in consistent output. - -For example, :class:`~django.forms.DateField` normalizes input into a -Python ``datetime.date`` object. Regardless of whether you pass it a string in -the format ``'1994-07-15'``, a ``datetime.date`` object, or a number of other -formats, ``DateField`` will always normalize it to a ``datetime.date`` object -as long as it's valid. - -Once you've created a :class:`~Form` instance with a set of data and validated -it, you can access the clean data via its ``cleaned_data`` attribute:: - - >>> data = {'subject': 'hello', - ... 'message': 'Hi there', - ... 'sender': 'foo@example.com', - ... 'cc_myself': True} - >>> f = ContactForm(data) - >>> f.is_valid() - True - >>> f.cleaned_data - {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} - -.. versionchanged:: 1.0 - The ``cleaned_data`` attribute was called ``clean_data`` in earlier releases. - -Note that any text-based field -- such as ``CharField`` or ``EmailField`` -- -always cleans the input into a Unicode string. We'll cover the encoding -implications later in this document. - -If your data does *not* validate, your ``Form`` instance will not have a -``cleaned_data`` attribute:: - - >>> data = {'subject': '', - ... 'message': 'Hi there', - ... 'sender': 'invalid e-mail address', - ... 'cc_myself': True} - >>> f = ContactForm(data) - >>> f.is_valid() - False - >>> f.cleaned_data - Traceback (most recent call last): - ... - AttributeError: 'ContactForm' object has no attribute 'cleaned_data' - -``cleaned_data`` will always *only* contain a key for fields defined in the -``Form``, even if you pass extra data when you define the ``Form``. In this -example, we pass a bunch of extra fields to the ``ContactForm`` constructor, -but ``cleaned_data`` contains only the form's fields:: - - >>> data = {'subject': 'hello', - ... 'message': 'Hi there', - ... 'sender': 'foo@example.com', - ... 'cc_myself': True, - ... 'extra_field_1': 'foo', - ... 'extra_field_2': 'bar', - ... 'extra_field_3': 'baz'} - >>> f = ContactForm(data) - >>> f.is_valid() - True - >>> f.cleaned_data # Doesn't contain extra_field_1, etc. - {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'} - -``cleaned_data`` will include a key and value for *all* fields defined in the -``Form``, even if the data didn't include a value for fields that are not -required. In this example, the data dictionary doesn't include a value for the -``nick_name`` field, but ``cleaned_data`` includes it, with an empty value:: - - >>> class OptionalPersonForm(Form): - ... first_name = CharField() - ... last_name = CharField() - ... nick_name = CharField(required=False) - >>> data = {'first_name': u'John', 'last_name': u'Lennon'} - >>> f = OptionalPersonForm(data) - >>> f.is_valid() - True - >>> f.cleaned_data - {'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'} - -In this above example, the ``cleaned_data`` value for ``nick_name`` is set to an -empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat -empty values as an empty string. Each field type knows what its "blank" value -is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. For -full details on each field's behavior in this case, see the "Empty value" note -for each field in the "Built-in ``Field`` classes" section below. - -You can write code to perform validation for particular form fields (based on -their name) or for the form as a whole (considering combinations of various -fields). More information about this is in :doc:`/ref/forms/validation`. - -Outputting forms as HTML ------------------------- - -The second task of a ``Form`` object is to render itself as HTML. To do so, -simply ``print`` it:: - - >>> f = ContactForm() - >>> print f - <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr> - <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr> - <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr> - <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr> - -If the form is bound to data, the HTML output will include that data -appropriately. For example, if a field is represented by an -``<input type="text">``, the data will be in the ``value`` attribute. If a -field is represented by an ``<input type="checkbox">``, then that HTML will -include ``checked="checked"`` if appropriate:: - - >>> data = {'subject': 'hello', - ... 'message': 'Hi there', - ... 'sender': 'foo@example.com', - ... 'cc_myself': True} - >>> f = ContactForm(data) - >>> print f - <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr> - <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr> - <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" value="foo@example.com" /></td></tr> - <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr> - -This default output is a two-column HTML table, with a ``<tr>`` for each field. -Notice the following: - - * For flexibility, the output does *not* include the ``<table>`` and - ``</table>`` tags, nor does it include the ``<form>`` and ``</form>`` - tags or an ``<input type="submit">`` tag. It's your job to do that. - - * Each field type has a default HTML representation. ``CharField`` and - ``EmailField`` are represented by an ``<input type="text">``. - ``BooleanField`` is represented by an ``<input type="checkbox">``. Note - these are merely sensible defaults; you can specify which HTML to use for - a given field by using widgets, which we'll explain shortly. - - * The HTML ``name`` for each tag is taken directly from its attribute name - in the ``ContactForm`` class. - - * The text label for each field -- e.g. ``'Subject:'``, ``'Message:'`` and - ``'Cc myself:'`` is generated from the field name by converting all - underscores to spaces and upper-casing the first letter. Again, note - these are merely sensible defaults; you can also specify labels manually. - - * Each text label is surrounded in an HTML ``<label>`` tag, which points - to the appropriate form field via its ``id``. Its ``id``, in turn, is - generated by prepending ``'id_'`` to the field name. The ``id`` - attributes and ``<label>`` tags are included in the output by default, to - follow best practices, but you can change that behavior. - -Although ``<table>`` output is the default output style when you ``print`` a -form, other output styles are available. Each style is available as a method on -a form object, and each rendering method returns a Unicode object. - -``as_p()`` -~~~~~~~~~~ - -.. method:: Form.as_p - - ``as_p()`` renders the form as a series of ``<p>`` tags, with each ``<p>`` - containing one field:: - - >>> f = ContactForm() - >>> f.as_p() - u'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>' - >>> print f.as_p() - <p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p> - <p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p> - <p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p> - <p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p> - -``as_ul()`` -~~~~~~~~~~~ - -.. method:: Form.as_ul - - ``as_ul()`` renders the form as a series of ``<li>`` tags, with each - ``<li>`` containing one field. It does *not* include the ``<ul>`` or - ``</ul>``, so that you can specify any HTML attributes on the ``<ul>`` for - flexibility:: - - >>> f = ContactForm() - >>> f.as_ul() - u'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>' - >>> print f.as_ul() - <li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li> - <li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li> - <li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li> - <li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li> - -``as_table()`` -~~~~~~~~~~~~~~ - -.. method:: Form.as_table - - Finally, ``as_table()`` outputs the form as an HTML ``<table>``. This is - exactly the same as ``print``. In fact, when you ``print`` a form object, - it calls its ``as_table()`` method behind the scenes:: - - >>> f = ContactForm() - >>> f.as_table() - u'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>' - >>> print f.as_table() - <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr> - <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr> - <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr> - <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr> - -Styling required or erroneous form rows -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - -It's pretty common to style form rows and fields that are required or have -errors. For example, you might want to present required form rows in bold and -highlight errors in red. - -The :class:`Form` class has a couple of hooks you can use to add ``class`` -attributes to required rows or to rows with errors: simple set the -:attr:`Form.error_css_class` and/or :attr:`Form.required_css_class` -attributes:: - - class ContactForm(Form): - error_css_class = 'error' - required_css_class = 'required' - - # ... and the rest of your fields here - -Once you've done that, rows will be given ``"error"`` and/or ``"required"`` -classes, as needed. The HTML will look something like:: - - >>> f = ContactForm(data) - >>> print f.as_table() - <tr class="required"><th><label for="id_subject">Subject:</label> ... - <tr class="required"><th><label for="id_message">Message:</label> ... - <tr class="required error"><th><label for="id_sender">Sender:</label> ... - <tr><th><label for="id_cc_myself">Cc myself:<label> ... - -.. _ref-forms-api-configuring-label: - -Configuring HTML ``<label>`` tags -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -An HTML ``<label>`` tag designates which label text is associated with which -form element. This small enhancement makes forms more usable and more accessible -to assistive devices. It's always a good idea to use ``<label>`` tags. - -By default, the form rendering methods include HTML ``id`` attributes on the -form elements and corresponding ``<label>`` tags around the labels. The ``id`` -attribute values are generated by prepending ``id_`` to the form field names. -This behavior is configurable, though, if you want to change the ``id`` -convention or remove HTML ``id`` attributes and ``<label>`` tags entirely. - -Use the ``auto_id`` argument to the ``Form`` constructor to control the label -and ``id`` behavior. This argument must be ``True``, ``False`` or a string. - -If ``auto_id`` is ``False``, then the form output will not include ``<label>`` -tags nor ``id`` attributes:: - - >>> f = ContactForm(auto_id=False) - >>> print f.as_table() - <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /></td></tr> - <tr><th>Message:</th><td><input type="text" name="message" /></td></tr> - <tr><th>Sender:</th><td><input type="text" name="sender" /></td></tr> - <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr> - >>> print f.as_ul() - <li>Subject: <input type="text" name="subject" maxlength="100" /></li> - <li>Message: <input type="text" name="message" /></li> - <li>Sender: <input type="text" name="sender" /></li> - <li>Cc myself: <input type="checkbox" name="cc_myself" /></li> - >>> print f.as_p() - <p>Subject: <input type="text" name="subject" maxlength="100" /></p> - <p>Message: <input type="text" name="message" /></p> - <p>Sender: <input type="text" name="sender" /></p> - <p>Cc myself: <input type="checkbox" name="cc_myself" /></p> - -If ``auto_id`` is set to ``True``, then the form output *will* include -``<label>`` tags and will simply use the field name as its ``id`` for each form -field:: - - >>> f = ContactForm(auto_id=True) - >>> print f.as_table() - <tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" /></td></tr> - <tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" /></td></tr> - <tr><th><label for="sender">Sender:</label></th><td><input type="text" name="sender" id="sender" /></td></tr> - <tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself" /></td></tr> - >>> print f.as_ul() - <li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></li> - <li><label for="message">Message:</label> <input type="text" name="message" id="message" /></li> - <li><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></li> - <li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></li> - >>> print f.as_p() - <p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></p> - <p><label for="message">Message:</label> <input type="text" name="message" id="message" /></p> - <p><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></p> - <p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></p> - -If ``auto_id`` is set to a string containing the format character ``'%s'``, -then the form output will include ``<label>`` tags, and will generate ``id`` -attributes based on the format string. For example, for a format string -``'field_%s'``, a field named ``subject`` will get the ``id`` value -``'field_subject'``. Continuing our example:: - - >>> f = ContactForm(auto_id='id_for_%s') - >>> print f.as_table() - <tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" /></td></tr> - <tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" /></td></tr> - <tr><th><label for="id_for_sender">Sender:</label></th><td><input type="text" name="sender" id="id_for_sender" /></td></tr> - <tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></td></tr> - >>> print f.as_ul() - <li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li> - <li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></li> - <li><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></li> - <li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li> - >>> print f.as_p() - <p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></p> - <p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></p> - <p><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></p> - <p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></p> - -If ``auto_id`` is set to any other true value -- such as a string that doesn't -include ``%s`` -- then the library will act as if ``auto_id`` is ``True``. - -By default, ``auto_id`` is set to the string ``'id_%s'``. - -Normally, a colon (``:``) will be appended after any label name when a form is -rendered. It's possible to change the colon to another character, or omit it -entirely, using the ``label_suffix`` parameter:: - - >>> f = ContactForm(auto_id='id_for_%s', label_suffix='') - >>> print f.as_ul() - <li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li> - <li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" /></li> - <li><label for="id_for_sender">Sender</label> <input type="text" name="sender" id="id_for_sender" /></li> - <li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li> - >>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->') - >>> print f.as_ul() - <li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li> - <li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" /></li> - <li><label for="id_for_sender">Sender -></label> <input type="text" name="sender" id="id_for_sender" /></li> - <li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li> - -Note that the label suffix is added only if the last character of the -label isn't a punctuation character (``.``, ``!``, ``?`` or ``:``) - -Notes on field ordering -~~~~~~~~~~~~~~~~~~~~~~~ - -In the ``as_p()``, ``as_ul()`` and ``as_table()`` shortcuts, the fields are -displayed in the order in which you define them in your form class. For -example, in the ``ContactForm`` example, the fields are defined in the order -``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML -output, just change the order in which those fields are listed in the class. - -How errors are displayed -~~~~~~~~~~~~~~~~~~~~~~~~ - -If you render a bound ``Form`` object, the act of rendering will automatically -run the form's validation if it hasn't already happened, and the HTML output -will include the validation errors as a ``<ul class="errorlist">`` near the -field. The particular positioning of the error messages depends on the output -method you're using:: - - >>> data = {'subject': '', - ... 'message': 'Hi there', - ... 'sender': 'invalid e-mail address', - ... 'cc_myself': True} - >>> f = ContactForm(data, auto_id=False) - >>> print f.as_table() - <tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr> - <tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr> - <tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul><input type="text" name="sender" value="invalid e-mail address" /></td></tr> - <tr><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr> - >>> print f.as_ul() - <li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li> - <li>Message: <input type="text" name="message" value="Hi there" /></li> - <li><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul>Sender: <input type="text" name="sender" value="invalid e-mail address" /></li> - <li>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li> - >>> print f.as_p() - <p><ul class="errorlist"><li>This field is required.</li></ul></p> - <p>Subject: <input type="text" name="subject" maxlength="100" /></p> - <p>Message: <input type="text" name="message" value="Hi there" /></p> - <p><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul></p> - <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p> - <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p> - -Customizing the error list format -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default, forms use ``django.forms.util.ErrorList`` to format validation -errors. If you'd like to use an alternate class for displaying errors, you can -pass that in at construction time:: - - >>> from django.forms.util import ErrorList - >>> class DivErrorList(ErrorList): - ... def __unicode__(self): - ... return self.as_divs() - ... def as_divs(self): - ... if not self: return u'' - ... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % e for e in self]) - >>> f = ContactForm(data, auto_id=False, error_class=DivErrorList) - >>> f.as_p() - <div class="errorlist"><div class="error">This field is required.</div></div> - <p>Subject: <input type="text" name="subject" maxlength="100" /></p> - <p>Message: <input type="text" name="message" value="Hi there" /></p> - <div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div> - <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p> - <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p> - -More granular output -~~~~~~~~~~~~~~~~~~~~ - -The ``as_p()``, ``as_ul()`` and ``as_table()`` methods are simply shortcuts for -lazy developers -- they're not the only way a form object can be displayed. - -To display the HTML for a single field in your form, use dictionary lookup -syntax using the field's name as the key, and print the resulting object:: - - >>> f = ContactForm() - >>> print f['subject'] - <input id="id_subject" type="text" name="subject" maxlength="100" /> - >>> print f['message'] - <input type="text" name="message" id="id_message" /> - >>> print f['sender'] - <input type="text" name="sender" id="id_sender" /> - >>> print f['cc_myself'] - <input type="checkbox" name="cc_myself" id="id_cc_myself" /> - -Call ``str()`` or ``unicode()`` on the field to get its rendered HTML as a -string or Unicode object, respectively:: - - >>> str(f['subject']) - '<input id="id_subject" type="text" name="subject" maxlength="100" />' - >>> unicode(f['subject']) - u'<input id="id_subject" type="text" name="subject" maxlength="100" />' - -Form objects define a custom ``__iter__()`` method, which allows you to loop -through their fields:: - - >>> f = ContactForm() - >>> for field in f: print field - <input id="id_subject" type="text" name="subject" maxlength="100" /> - <input type="text" name="message" id="id_message" /> - <input type="text" name="sender" id="id_sender" /> - <input type="checkbox" name="cc_myself" id="id_cc_myself" /> - -The field-specific output honors the form object's ``auto_id`` setting:: - - >>> f = ContactForm(auto_id=False) - >>> print f['message'] - <input type="text" name="message" /> - >>> f = ContactForm(auto_id='id_%s') - >>> print f['message'] - <input type="text" name="message" id="id_message" /> - -For a field's list of errors, access the field's ``errors`` attribute. This -is a list-like object that is displayed as an HTML ``<ul class="errorlist">`` -when printed:: - - >>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''} - >>> f = ContactForm(data, auto_id=False) - >>> print f['message'] - <input type="text" name="message" /> - >>> f['message'].errors - [u'This field is required.'] - >>> print f['message'].errors - <ul class="errorlist"><li>This field is required.</li></ul> - >>> f['subject'].errors - [] - >>> print f['subject'].errors - - >>> str(f['subject'].errors) - '' - -.. versionadded:: 1.2 - -When you use Django's rendering shortcuts, CSS classes are used to -indicate required form fields or fields that contain errors. If you're -manually rendering a form, you can access these CSS classes using the -``css_classes`` method:: - - >>> f = ContactForm(data) - >>> f['message'].css_classes() - 'required' - -If you want to provide some additional classes in addition to the -error and required classes that may be required, you can provide -those classes as an argument:: - - >>> f = ContactForm(data) - >>> f['message'].css_classes('foo bar') - 'foo bar required' - -.. _binding-uploaded-files: - -Binding uploaded files to a form --------------------------------- - -.. versionadded:: 1.0 - -Dealing with forms that have ``FileField`` and ``ImageField`` fields -is a little more complicated than a normal form. - -Firstly, in order to upload files, you'll need to make sure that your -``<form>`` element correctly defines the ``enctype`` as -``"multipart/form-data"``:: - - <form enctype="multipart/form-data" method="post" action="/foo/"> - -Secondly, when you use the form, you need to bind the file data. File -data is handled separately to normal form data, so when your form -contains a ``FileField`` and ``ImageField``, you will need to specify -a second argument when you bind your form. So if we extend our -ContactForm to include an ``ImageField`` called ``mugshot``, we -need to bind the file data containing the mugshot image:: - - # Bound form with an image field - >>> from django.core.files.uploadedfile import SimpleUploadedFile - >>> data = {'subject': 'hello', - ... 'message': 'Hi there', - ... 'sender': 'foo@example.com', - ... 'cc_myself': True} - >>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', <file data>)} - >>> f = ContactFormWithMugshot(data, file_data) - -In practice, you will usually specify ``request.FILES`` as the source -of file data (just like you use ``request.POST`` as the source of -form data):: - - # Bound form with an image field, data from the request - >>> f = ContactFormWithMugshot(request.POST, request.FILES) - -Constructing an unbound form is the same as always -- just omit both -form data *and* file data:: - - # Unbound form with a image field - >>> f = ContactFormWithMugshot() - -Testing for multipart forms -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you're writing reusable views or templates, you may not know ahead of time -whether your form is a multipart form or not. The ``is_multipart()`` method -tells you whether the form requires multipart encoding for submission:: - - >>> f = ContactFormWithMugshot() - >>> f.is_multipart() - True - -Here's an example of how you might use this in a template:: - - {% if form.is_multipart %} - <form enctype="multipart/form-data" method="post" action="/foo/"> - {% else %} - <form method="post" action="/foo/"> - {% endif %} - {{ form }} - </form> - -Subclassing forms ------------------ - -If you have multiple ``Form`` classes that share fields, you can use -subclassing to remove redundancy. - -When you subclass a custom ``Form`` class, the resulting subclass will -include all fields of the parent class(es), followed by the fields you define -in the subclass. - -In this example, ``ContactFormWithPriority`` contains all the fields from -``ContactForm``, plus an additional field, ``priority``. The ``ContactForm`` -fields are ordered first:: - - >>> class ContactFormWithPriority(ContactForm): - ... priority = forms.CharField() - >>> f = ContactFormWithPriority(auto_id=False) - >>> print f.as_ul() - <li>Subject: <input type="text" name="subject" maxlength="100" /></li> - <li>Message: <input type="text" name="message" /></li> - <li>Sender: <input type="text" name="sender" /></li> - <li>Cc myself: <input type="checkbox" name="cc_myself" /></li> - <li>Priority: <input type="text" name="priority" /></li> - -It's possible to subclass multiple forms, treating forms as "mix-ins." In this -example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm`` -(in that order), and its field list includes the fields from the parent -classes:: - - >>> class PersonForm(Form): - ... first_name = CharField() - ... last_name = CharField() - >>> class InstrumentForm(Form): - ... instrument = CharField() - >>> class BeatleForm(PersonForm, InstrumentForm): - ... haircut_type = CharField() - >>> b = BeatleForm(auto_id=False) - >>> print b.as_ul() - <li>First name: <input type="text" name="first_name" /></li> - <li>Last name: <input type="text" name="last_name" /></li> - <li>Instrument: <input type="text" name="instrument" /></li> - <li>Haircut type: <input type="text" name="haircut_type" /></li> - -.. _form-prefix: - -Prefixes for forms ------------------- - -.. attribute:: Form.prefix - -You can put several Django forms inside one ``<form>`` tag. To give each -``Form`` its own namespace, use the ``prefix`` keyword argument:: - - >>> mother = PersonForm(prefix="mother") - >>> father = PersonForm(prefix="father") - >>> print mother.as_ul() - <li><label for="id_mother-first_name">First name:</label> <input type="text" name="mother-first_name" id="id_mother-first_name" /></li> - <li><label for="id_mother-last_name">Last name:</label> <input type="text" name="mother-last_name" id="id_mother-last_name" /></li> - >>> print father.as_ul() - <li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" /></li> - <li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" /></li> diff --git a/parts/django/docs/ref/forms/fields.txt b/parts/django/docs/ref/forms/fields.txt deleted file mode 100644 index 91f245a..0000000 --- a/parts/django/docs/ref/forms/fields.txt +++ /dev/null @@ -1,939 +0,0 @@ -=========== -Form fields -=========== - -.. module:: django.forms.fields - :synopsis: Django's built-in form fields. - -.. currentmodule:: django.forms - -.. class:: Field(**kwargs) - -When you create a ``Form`` class, the most important part is defining the -fields of the form. Each field has custom validation logic, along with a few -other hooks. - -.. method:: Field.clean(value) - -Although the primary way you'll use ``Field`` classes is in ``Form`` classes, -you can also instantiate them and use them directly to get a better idea of -how they work. Each ``Field`` instance has a ``clean()`` method, which takes -a single argument and either raises a ``django.forms.ValidationError`` -exception or returns the clean value:: - - >>> from django import forms - >>> f = forms.EmailField() - >>> f.clean('foo@example.com') - u'foo@example.com' - >>> f.clean(u'foo@example.com') - u'foo@example.com' - >>> f.clean('invalid e-mail address') - Traceback (most recent call last): - ... - ValidationError: [u'Enter a valid e-mail address.'] - -Core field arguments --------------------- - -Each ``Field`` class constructor takes at least these arguments. Some -``Field`` classes take additional, field-specific arguments, but the following -should *always* be accepted: - -``required`` -~~~~~~~~~~~~ - -.. attribute:: Field.required - -By default, each ``Field`` class assumes the value is required, so if you pass -an empty value -- either ``None`` or the empty string (``""``) -- then -``clean()`` will raise a ``ValidationError`` exception:: - - >>> f = forms.CharField() - >>> f.clean('foo') - u'foo' - >>> f.clean('') - Traceback (most recent call last): - ... - ValidationError: [u'This field is required.'] - >>> f.clean(None) - Traceback (most recent call last): - ... - ValidationError: [u'This field is required.'] - >>> f.clean(' ') - u' ' - >>> f.clean(0) - u'0' - >>> f.clean(True) - u'True' - >>> f.clean(False) - u'False' - -To specify that a field is *not* required, pass ``required=False`` to the -``Field`` constructor:: - - >>> f = forms.CharField(required=False) - >>> f.clean('foo') - u'foo' - >>> f.clean('') - u'' - >>> f.clean(None) - u'' - >>> f.clean(0) - u'0' - >>> f.clean(True) - u'True' - >>> f.clean(False) - u'False' - -If a ``Field`` has ``required=False`` and you pass ``clean()`` an empty value, -then ``clean()`` will return a *normalized* empty value rather than raising -``ValidationError``. For ``CharField``, this will be a Unicode empty string. -For other ``Field`` classes, it might be ``None``. (This varies from field to -field.) - -``label`` -~~~~~~~~~ - -.. attribute:: Field.label - -The ``label`` argument lets you specify the "human-friendly" label for this -field. This is used when the ``Field`` is displayed in a ``Form``. - -As explained in "Outputting forms as HTML" above, the default label for a -``Field`` is generated from the field name by converting all underscores to -spaces and upper-casing the first letter. Specify ``label`` if that default -behavior doesn't result in an adequate label. - -Here's a full example ``Form`` that implements ``label`` for two of its fields. -We've specified ``auto_id=False`` to simplify the output:: - - >>> class CommentForm(forms.Form): - ... name = forms.CharField(label='Your name') - ... url = forms.URLField(label='Your Web site', required=False) - ... comment = forms.CharField() - >>> f = CommentForm(auto_id=False) - >>> print f - <tr><th>Your name:</th><td><input type="text" name="name" /></td></tr> - <tr><th>Your Web site:</th><td><input type="text" name="url" /></td></tr> - <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> - -``initial`` -~~~~~~~~~~~ - -.. attribute:: Field.initial - -The ``initial`` argument lets you specify the initial value to use when -rendering this ``Field`` in an unbound ``Form``. - -To specify dynamic initial data, see the :attr:`Form.initial` parameter. - -The use-case for this is when you want to display an "empty" form in which a -field is initialized to a particular value. For example:: - - >>> class CommentForm(forms.Form): - ... name = forms.CharField(initial='Your name') - ... url = forms.URLField(initial='http://') - ... comment = forms.CharField() - >>> f = CommentForm(auto_id=False) - >>> print f - <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr> - <tr><th>Url:</th><td><input type="text" name="url" value="http://" /></td></tr> - <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> - -You may be thinking, why not just pass a dictionary of the initial values as -data when displaying the form? Well, if you do that, you'll trigger validation, -and the HTML output will include any validation errors:: - - >>> class CommentForm(forms.Form): - ... name = forms.CharField() - ... url = forms.URLField() - ... comment = forms.CharField() - >>> default_data = {'name': 'Your name', 'url': 'http://'} - >>> f = CommentForm(default_data, auto_id=False) - >>> print f - <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr> - <tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="text" name="url" value="http://" /></td></tr> - <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr> - -This is why ``initial`` values are only displayed for unbound forms. For bound -forms, the HTML output will use the bound data. - -Also note that ``initial`` values are *not* used as "fallback" data in -validation if a particular field's value is not given. ``initial`` values are -*only* intended for initial form display:: - - >>> class CommentForm(forms.Form): - ... name = forms.CharField(initial='Your name') - ... url = forms.URLField(initial='http://') - ... comment = forms.CharField() - >>> data = {'name': '', 'url': '', 'comment': 'Foo'} - >>> f = CommentForm(data) - >>> f.is_valid() - False - # The form does *not* fall back to using the initial values. - >>> f.errors - {'url': [u'This field is required.'], 'name': [u'This field is required.']} - -Instead of a constant, you can also pass any callable:: - - >>> import datetime - >>> class DateForm(forms.Form): - ... day = forms.DateField(initial=datetime.date.today) - >>> print DateForm() - <tr><th>Day:</th><td><input type="text" name="day" value="12/23/2008" /><td></tr> - -The callable will be evaluated only when the unbound form is displayed, not when it is defined. - -``widget`` -~~~~~~~~~~ - -.. attribute:: Field.widget - -The ``widget`` argument lets you specify a ``Widget`` class to use when -rendering this ``Field``. See :doc:`/ref/forms/widgets` for more information. - -``help_text`` -~~~~~~~~~~~~~ - -.. attribute:: Field.help_text - -The ``help_text`` argument lets you specify descriptive text for this -``Field``. If you provide ``help_text``, it will be displayed next to the -``Field`` when the ``Field`` is rendered by one of the convenience ``Form`` -methods (e.g., ``as_ul()``). - -Here's a full example ``Form`` that implements ``help_text`` for two of its -fields. We've specified ``auto_id=False`` to simplify the output:: - - >>> class HelpTextContactForm(forms.Form): - ... subject = forms.CharField(max_length=100, help_text='100 characters max.') - ... message = forms.CharField() - ... sender = forms.EmailField(help_text='A valid e-mail address, please.') - ... cc_myself = forms.BooleanField(required=False) - >>> f = HelpTextContactForm(auto_id=False) - >>> print f.as_table() - <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br />100 characters max.</td></tr> - <tr><th>Message:</th><td><input type="text" name="message" /></td></tr> - <tr><th>Sender:</th><td><input type="text" name="sender" /><br />A valid e-mail address, please.</td></tr> - <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr> - >>> print f.as_ul() - <li>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</li> - <li>Message: <input type="text" name="message" /></li> - <li>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</li> - <li>Cc myself: <input type="checkbox" name="cc_myself" /></li> - >>> print f.as_p() - <p>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</p> - <p>Message: <input type="text" name="message" /></p> - <p>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</p> - <p>Cc myself: <input type="checkbox" name="cc_myself" /></p> - -``error_messages`` -~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. attribute:: Field.error_messages - -The ``error_messages`` argument lets you override the default messages that the -field will raise. Pass in a dictionary with keys matching the error messages you -want to override. For example, here is the default error message:: - - >>> generic = forms.CharField() - >>> generic.clean('') - Traceback (most recent call last): - ... - ValidationError: [u'This field is required.'] - -And here is a custom error message:: - - >>> name = forms.CharField(error_messages={'required': 'Please enter your name'}) - >>> name.clean('') - Traceback (most recent call last): - ... - ValidationError: [u'Please enter your name'] - -In the `built-in Field classes`_ section below, each ``Field`` defines the -error message keys it uses. - -``validators`` -~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - -.. attribute:: Field.validators - -The ``validators`` argument lets you provide a list of validation functions -for this field. - -See the :doc:`validators documentation </ref/validators>` for more information. - -``localize`` -~~~~~~~~~~~~ - -.. versionadded:: 1.2 - -.. attribute:: Field.localize - -The ``localize`` argument enables the localization of form data, input as well -as the rendered output. - -See the :ref:`format localization <format-localization>` documentation for -more information. - - -Built-in ``Field`` classes --------------------------- - -Naturally, the ``forms`` library comes with a set of ``Field`` classes that -represent common validation needs. This section documents each built-in field. - -For each field, we describe the default widget used if you don't specify -``widget``. We also specify the value returned when you provide an empty value -(see the section on ``required`` above to understand what that means). - -``BooleanField`` -~~~~~~~~~~~~~~~~ - -.. class:: BooleanField(**kwargs) - - * Default widget: ``CheckboxInput`` - * Empty value: ``False`` - * Normalizes to: A Python ``True`` or ``False`` value. - * Validates that the value is ``True`` (e.g. the check box is checked) if - the field has ``required=True``. - * Error message keys: ``required`` - -.. versionchanged:: 1.0 - The empty value for a ``CheckboxInput`` (and hence the standard - ``BooleanField``) has changed to return ``False`` instead of ``None`` in - the Django 1.0. - -.. note:: - - Since all ``Field`` subclasses have ``required=True`` by default, the - validation condition here is important. If you want to include a boolean - in your form that can be either ``True`` or ``False`` (e.g. a checked or - unchecked checkbox), you must remember to pass in ``required=False`` when - creating the ``BooleanField``. - -``CharField`` -~~~~~~~~~~~~~ - -.. class:: CharField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``''`` (an empty string) - * Normalizes to: A Unicode object. - * Validates ``max_length`` or ``min_length``, if they are provided. - Otherwise, all inputs are valid. - * Error message keys: ``required``, ``max_length``, ``min_length`` - -Has two optional arguments for validation: - -.. attribute:: CharField.max_length -.. attribute:: CharField.min_length - - If provided, these arguments ensure that the string is at most or at least - the given length. - -``ChoiceField`` -~~~~~~~~~~~~~~~ - -.. class:: ChoiceField(**kwargs) - - * Default widget: ``Select`` - * Empty value: ``''`` (an empty string) - * Normalizes to: A Unicode object. - * Validates that the given value exists in the list of choices. - * Error message keys: ``required``, ``invalid_choice`` - -Takes one extra required argument: - -.. attribute:: ChoiceField.choices - - An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this - field. This argument accepts the same formats as the ``choices`` argument - to a model field. See the :ref:`model field reference documentation on - choices <field-choices>` for more details. - -``TypedChoiceField`` -~~~~~~~~~~~~~~~~~~~~ - -.. class:: TypedChoiceField(**kwargs) - -Just like a :class:`ChoiceField`, except :class:`TypedChoiceField` takes an -extra ``coerce`` argument. - - * Default widget: ``Select`` - * Empty value: Whatever you've given as ``empty_value`` - * Normalizes to: the value returned by the ``coerce`` argument. - * Validates that the given value exists in the list of choices. - * Error message keys: ``required``, ``invalid_choice`` - -Takes extra arguments: - -.. attribute:: TypedChoiceField.coerce - - A function that takes one argument and returns a coerced value. Examples - include the built-in ``int``, ``float``, ``bool`` and other types. Defaults - to an identity function. - -.. attribute:: TypedChoiceField.empty_value - - The value to use to represent "empty." Defaults to the empty string; - ``None`` is another common choice here. - -``DateField`` -~~~~~~~~~~~~~ - -.. class:: DateField(**kwargs) - - * Default widget: ``DateInput`` - * Empty value: ``None`` - * Normalizes to: A Python ``datetime.date`` object. - * Validates that the given value is either a ``datetime.date``, - ``datetime.datetime`` or string formatted in a particular date format. - * Error message keys: ``required``, ``invalid`` - -Takes one optional argument: - -.. attribute:: DateField.input_formats - - A list of formats used to attempt to convert a string to a valid - ``datetime.date`` object. - -If no ``input_formats`` argument is provided, the default input formats are:: - - '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06' - '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006' - '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006' - '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006' - '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006' - -.. versionchanged:: 1.1 - The ``DateField`` previously used a ``TextInput`` widget by default. It now - uses a ``DateInput`` widget. - -``DateTimeField`` -~~~~~~~~~~~~~~~~~ - -.. class:: DateTimeField(**kwargs) - - * Default widget: ``DateTimeInput`` - * Empty value: ``None`` - * Normalizes to: A Python ``datetime.datetime`` object. - * Validates that the given value is either a ``datetime.datetime``, - ``datetime.date`` or string formatted in a particular datetime format. - * Error message keys: ``required``, ``invalid`` - -Takes one optional argument: - -.. attribute:: DateTimeField.input_formats - - A list of formats used to attempt to convert a string to a valid - ``datetime.datetime`` object. - -If no ``input_formats`` argument is provided, the default input formats are:: - - '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' - '%Y-%m-%d %H:%M', # '2006-10-25 14:30' - '%Y-%m-%d', # '2006-10-25' - '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' - '%m/%d/%Y %H:%M', # '10/25/2006 14:30' - '%m/%d/%Y', # '10/25/2006' - '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' - '%m/%d/%y %H:%M', # '10/25/06 14:30' - '%m/%d/%y', # '10/25/06' - -.. versionchanged:: 1.0 - The ``DateTimeField`` used to use a ``TextInput`` widget by default. This has now changed. - -``DecimalField`` -~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. class:: DecimalField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``None`` - * Normalizes to: A Python ``decimal``. - * Validates that the given value is a decimal. Leading and trailing - whitespace is ignored. - * Error message keys: ``required``, ``invalid``, ``max_value``, - ``min_value``, ``max_digits``, ``max_decimal_places``, - ``max_whole_digits`` - -Takes four optional arguments: - -.. attribute:: DecimalField.max_value -.. attribute:: DecimalField.min_value - - These attributes define the limits for the fields value. - -.. attribute:: DecimalField.max_digits - - The maximum number of digits (those before the decimal point plus those - after the decimal point, with leading zeros stripped) permitted in the - value. - -.. attribute:: DecimalField.decimal_places - - The maximum number of decimal places permitted. - -``EmailField`` -~~~~~~~~~~~~~~ - -.. class:: EmailField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``''`` (an empty string) - * Normalizes to: A Unicode object. - * Validates that the given value is a valid e-mail address, using a - moderately complex regular expression. - * Error message keys: ``required``, ``invalid`` - -Has two optional arguments for validation, ``max_length`` and ``min_length``. -If provided, these arguments ensure that the string is at most or at least the -given length. - -.. versionchanged:: 1.2 - The EmailField previously did not recognize e-mail addresses as valid that - contained an IDN (Internationalized Domain Name; a domain containing - unicode characters) domain part. This has now been corrected. - -``FileField`` -~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. class:: FileField(**kwargs) - - * Default widget: ``FileInput`` - * Empty value: ``None`` - * Normalizes to: An ``UploadedFile`` object that wraps the file content - and file name into a single object. - * Validates that non-empty file data has been bound to the form. - * Error message keys: ``required``, ``invalid``, ``missing``, ``empty`` - -To learn more about the ``UploadedFile`` object, see the :doc:`file uploads -documentation </topics/http/file-uploads>`. - -When you use a ``FileField`` in a form, you must also remember to -:ref:`bind the file data to the form <binding-uploaded-files>`. - -``FilePathField`` -~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. class:: FilePathField(**kwargs) - - * Default widget: ``Select`` - * Empty value: ``None`` - * Normalizes to: A unicode object - * Validates that the selected choice exists in the list of choices. - * Error message keys: ``required``, ``invalid_choice`` - -The field allows choosing from files inside a certain directory. It takes three -extra arguments; only ``path`` is required: - -.. attribute:: FilePathField.path - - The absolute path to the directory whose contents you want listed. This - directory must exist. - -.. attribute:: FilePathField.recursive - - If ``False`` (the default) only the direct contents of ``path`` will be - offered as choices. If ``True``, the directory will be descended into - recursively and all descendants will be listed as choices. - -.. attribute:: FilePathField.match - - A regular expression pattern; only files with names matching this expression - will be allowed as choices. - -``FloatField`` -~~~~~~~~~~~~~~ - - * Default widget: ``TextInput`` - * Empty value: ``None`` - * Normalizes to: A Python float. - * Validates that the given value is an float. Leading and trailing - whitespace is allowed, as in Python's ``float()`` function. - * Error message keys: ``required``, ``invalid``, ``max_value``, - ``min_value`` - -Takes two optional arguments for validation, ``max_value`` and ``min_value``. -These control the range of values permitted in the field. - -``ImageField`` -~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. class:: ImageField(**kwargs) - - * Default widget: ``FileInput`` - * Empty value: ``None`` - * Normalizes to: An ``UploadedFile`` object that wraps the file content - and file name into a single object. - * Validates that file data has been bound to the form, and that the - file is of an image format understood by PIL. - * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``, - ``invalid_image`` - -Using an ImageField requires that the `Python Imaging Library`_ is installed. - -When you use an ``ImageField`` on a form, you must also remember to -:ref:`bind the file data to the form <binding-uploaded-files>`. - -.. _Python Imaging Library: http://www.pythonware.com/products/pil/ - -``IntegerField`` -~~~~~~~~~~~~~~~~ - -.. class:: IntegerField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``None`` - * Normalizes to: A Python integer or long integer. - * Validates that the given value is an integer. Leading and trailing - whitespace is allowed, as in Python's ``int()`` function. - * Error message keys: ``required``, ``invalid``, ``max_value``, - ``min_value`` - -Takes two optional arguments for validation: - -.. attribute:: IntegerField.max_value -.. attribute:: IntegerField.min_value - - These control the range of values permitted in the field. - -``IPAddressField`` -~~~~~~~~~~~~~~~~~~ - -.. class:: IPAddressField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``''`` (an empty string) - * Normalizes to: A Unicode object. - * Validates that the given value is a valid IPv4 address, using a regular - expression. - * Error message keys: ``required``, ``invalid`` - -``MultipleChoiceField`` -~~~~~~~~~~~~~~~~~~~~~~~ - -.. class:: MultipleChoiceField(**kwargs) - - * Default widget: ``SelectMultiple`` - * Empty value: ``[]`` (an empty list) - * Normalizes to: A list of Unicode objects. - * Validates that every value in the given list of values exists in the list - of choices. - * Error message keys: ``required``, ``invalid_choice``, ``invalid_list`` - -Takes one extra argument, ``choices``, as for ``ChoiceField``. - -``NullBooleanField`` -~~~~~~~~~~~~~~~~~~~~ - -.. class:: NullBooleanField(**kwargs) - - * Default widget: ``NullBooleanSelect`` - * Empty value: ``None`` - * Normalizes to: A Python ``True``, ``False`` or ``None`` value. - * Validates nothing (i.e., it never raises a ``ValidationError``). - -``RegexField`` -~~~~~~~~~~~~~~ - -.. class:: RegexField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``''`` (an empty string) - * Normalizes to: A Unicode object. - * Validates that the given value matches against a certain regular - expression. - * Error message keys: ``required``, ``invalid`` - -Takes one required argument: - -.. attribute:: RegexField.regex - - A regular expression specified either as a string or a compiled regular - expression object. - -Also takes ``max_length`` and ``min_length``, which work just as they do for -``CharField``. - -The optional argument ``error_message`` is also accepted for backwards -compatibility. The preferred way to provide an error message is to use the -``error_messages`` argument, passing a dictionary with ``'invalid'`` as a key -and the error message as the value. - -``SlugField`` -~~~~~~~~~~~~~ - -.. class:: SlugField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``''`` (an empty string) - * Normalizes to: A Unicode object. - * Validates that the given value contains only letters, numbers, - underscores, and hyphens. - * Error messages: ``required``, ``invalid`` - -This field is intended for use in representing a model -:class:`~django.db.models.SlugField` in forms. - -``TimeField`` -~~~~~~~~~~~~~ - -.. class:: TimeField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``None`` - * Normalizes to: A Python ``datetime.time`` object. - * Validates that the given value is either a ``datetime.time`` or string - formatted in a particular time format. - * Error message keys: ``required``, ``invalid`` - -Takes one optional argument: - -.. attribute:: TimeField.input_formats - - A list of formats used to attempt to convert a string to a valid - ``datetime.time`` object. - -If no ``input_formats`` argument is provided, the default input formats are:: - - '%H:%M:%S', # '14:30:59' - '%H:%M', # '14:30' - -``URLField`` -~~~~~~~~~~~~ - -.. class:: URLField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``''`` (an empty string) - * Normalizes to: A Unicode object. - * Validates that the given value is a valid URL. - * Error message keys: ``required``, ``invalid``, ``invalid_link`` - -Takes the following optional arguments: - -.. attribute:: URLField.max_length -.. attribute:: URLField.min_length - - Same as ``CharField.max_length`` and ``CharField.min_length``. - -.. attribute:: URLField.verify_exists - - If ``True``, the validator will attempt to load the given URL, raising - ``ValidationError`` if the page gives a 404. Defaults to ``False``. - -.. attribute:: URLField.validator_user_agent - - String used as the user-agent used when checking for a URL's existence. - Defaults to the value of the ``URL_VALIDATOR_USER_AGENT`` setting. - -.. versionchanged:: 1.2 - The URLField previously did not recognize URLs as valid that contained an IDN - (Internationalized Domain Name; a domain name containing unicode characters) - domain name. This has now been corrected. - - -Slightly complex built-in ``Field`` classes -------------------------------------------- - -``ComboField`` -~~~~~~~~~~~~~~ - -.. class:: ComboField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``''`` (an empty string) - * Normalizes to: A Unicode object. - * Validates that the given value against each of the fields specified - as an argument to the ``ComboField``. - * Error message keys: ``required``, ``invalid`` - -Takes one extra required argument: - -.. attribute:: ComboField.fields - - The list of fields that should be used to validate the field's value (in - the order in which they are provided). - - >>> f = ComboField(fields=[CharField(max_length=20), EmailField()]) - >>> f.clean('test@example.com') - u'test@example.com' - >>> f.clean('longemailaddress@example.com') - Traceback (most recent call last): - ... - ValidationError: [u'Ensure this value has at most 20 characters (it has 28).'] - -``MultiValueField`` -~~~~~~~~~~~~~~~~~~~ - -.. class:: MultiValueField(**kwargs) - - * Default widget: ``TextInput`` - * Empty value: ``''`` (an empty string) - * Normalizes to: the type returned by the ``compress`` method of the subclass. - * Validates that the given value against each of the fields specified - as an argument to the ``MultiValueField``. - * Error message keys: ``required``, ``invalid`` - - This abstract field (must be subclassed) aggregates the logic of multiple - fields. Subclasses should not have to implement clean(). Instead, they must - implement compress(), which takes a list of valid values and returns a - "compressed" version of those values -- a single value. For example, - :class:`SplitDateTimeField` is a subclass which combines a time field and - a date field into a datetime object. - -Takes one extra required argument: - -.. attribute:: MultiValueField.fields - - A list of fields which are cleaned into a single field. Each value in - ``clean`` is cleaned by the corresponding field in ``fields`` -- the first - value is cleaned by the first field, the second value is cleaned by - the second field, etc. Once all fields are cleaned, the list of clean - values is "compressed" into a single value. - -``SplitDateTimeField`` -~~~~~~~~~~~~~~~~~~~~~~ - -.. class:: SplitDateTimeField(**kwargs) - - * Default widget: ``SplitDateTimeWidget`` - * Empty value: ``None`` - * Normalizes to: A Python ``datetime.datetime`` object. - * Validates that the given value is a ``datetime.datetime`` or string - formatted in a particular datetime format. - * Error message keys: ``required``, ``invalid`` - -Takes two optional arguments: - -.. attribute:: SplitDateTimeField.input_date_formats - - A list of formats used to attempt to convert a string to a valid - ``datetime.date`` object. - -If no ``input_date_formats`` argument is provided, the default input formats -for ``DateField`` are used. - -.. attribute:: SplitDateTimeField.input_time_formats - - A list of formats used to attempt to convert a string to a valid - ``datetime.time`` object. - -If no ``input_time_formats`` argument is provided, the default input formats -for ``TimeField`` are used. - -.. versionchanged:: 1.1 - The ``SplitDateTimeField`` previously used two ``TextInput`` widgets by - default. The ``input_date_formats`` and ``input_time_formats`` arguments - are also new. - -Fields which handle relationships ---------------------------------- - -Two fields are available for representing relationships between -models: :class:`ModelChoiceField` and -:class:`ModelMultipleChoiceField`. Both of these fields require a -single ``queryset`` parameter that is used to create the choices for -the field. Upon form validation, these fields will place either one -model object (in the case of ``ModelChoiceField``) or multiple model -objects (in the case of ``ModelMultipleChoiceField``) into the -``cleaned_data`` dictionary of the form. - -``ModelChoiceField`` -~~~~~~~~~~~~~~~~~~~~ - -.. class:: ModelChoiceField(**kwargs) - - * Default widget: ``Select`` - * Empty value: ``None`` - * Normalizes to: A model instance. - * Validates that the given id exists in the queryset. - * Error message keys: ``required``, ``invalid_choice`` - -Allows the selection of a single model object, suitable for -representing a foreign key. A single argument is required: - -.. attribute:: ModelChoiceField.queryset - - A ``QuerySet`` of model objects from which the choices for the - field will be derived, and which will be used to validate the - user's selection. - -``ModelChoiceField`` also takes one optional argument: - -.. attribute:: ModelChoiceField.empty_label - - By default the ``<select>`` widget used by ``ModelChoiceField`` will have a - an empty choice at the top of the list. You can change the text of this - label (which is ``"---------"`` by default) with the ``empty_label`` - attribute, or you can disable the empty label entirely by setting - ``empty_label`` to ``None``:: - - # A custom empty label - field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)") - - # No empty label - field2 = forms.ModelChoiceField(queryset=..., empty_label=None) - - Note that if a ``ModelChoiceField`` is required and has a default - initial value, no empty choice is created (regardless of the value - of ``empty_label``). - -The ``__unicode__`` method of the model will be called to generate -string representations of the objects for use in the field's choices; -to provide customized representations, subclass ``ModelChoiceField`` -and override ``label_from_instance``. This method will receive a model -object, and should return a string suitable for representing it. For -example:: - - class MyModelChoiceField(ModelChoiceField): - def label_from_instance(self, obj): - return "My Object #%i" % obj.id - -``ModelMultipleChoiceField`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. class:: ModelMultipleChoiceField(**kwargs) - - * Default widget: ``SelectMultiple`` - * Empty value: ``[]`` (an empty list) - * Normalizes to: A list of model instances. - * Validates that every id in the given list of values exists in the - queryset. - * Error message keys: ``required``, ``list``, ``invalid_choice``, - ``invalid_pk_value`` - -Allows the selection of one or more model objects, suitable for -representing a many-to-many relation. As with :class:`ModelChoiceField`, -you can use ``label_from_instance`` to customize the object -representations, and ``queryset`` is a required parameter: - -.. attribute:: ModelMultipleChoiceField.queryset - - A ``QuerySet`` of model objects from which the choices for the - field will be derived, and which will be used to validate the - user's selection. - -Creating custom fields ----------------------- - -If the built-in ``Field`` classes don't meet your needs, you can easily create -custom ``Field`` classes. To do this, just create a subclass of -``django.forms.Field``. Its only requirements are that it implement a -``clean()`` method and that its ``__init__()`` method accept the core arguments -mentioned above (``required``, ``label``, ``initial``, ``widget``, -``help_text``). diff --git a/parts/django/docs/ref/forms/index.txt b/parts/django/docs/ref/forms/index.txt deleted file mode 100644 index 866afed..0000000 --- a/parts/django/docs/ref/forms/index.txt +++ /dev/null @@ -1,13 +0,0 @@ -===== -Forms -===== - -Detailed form API reference. For introductory material, see :doc:`/topics/forms/index`. - -.. toctree:: - :maxdepth: 2 - - api - fields - widgets - validation diff --git a/parts/django/docs/ref/forms/validation.txt b/parts/django/docs/ref/forms/validation.txt deleted file mode 100644 index 1c047f2..0000000 --- a/parts/django/docs/ref/forms/validation.txt +++ /dev/null @@ -1,366 +0,0 @@ -Form and field validation -========================= - -.. versionchanged:: 1.2 - -Form validation happens when the data is cleaned. If you want to customize -this process, there are various places you can change, each one serving a -different purpose. Three types of cleaning methods are run during form -processing. These are normally executed when you call the ``is_valid()`` -method on a form. There are other things that can trigger cleaning and -validation (accessing the ``errors`` attribute or calling ``full_clean()`` -directly), but normally they won't be needed. - -In general, any cleaning method can raise ``ValidationError`` if there is a -problem with the data it is processing, passing the relevant error message to -the ``ValidationError`` constructor. If no ``ValidationError`` is raised, the -method should return the cleaned (normalized) data as a Python object. - -If you detect multiple errors during a cleaning method and wish to signal all -of them to the form submitter, it is possible to pass a list of errors to the -``ValidationError`` constructor. - -Most validation can be done using `validators`_ - simple helpers that can be -reused easily. Validators are simple functions (or callables) that take a single -argument and raise ``ValidationError`` on invalid input. Validators are run -after the field's ``to_python`` and ``validate`` methods have been called. - -Validation of a Form is split into several steps, which can be customized or -overridden: - - * The ``to_python()`` method on a Field is the first step in every - validation. It coerces the value to correct datatype and raises - ``ValidationError`` if that is not possible. This method accepts the raw - value from the widget and returns the converted value. For example, a - FloatField will turn the data into a Python ``float`` or raise a - ``ValidationError``. - - * The ``validate()`` method on a Field handles field-specific validation - that is not suitable for a validator, It takes a value that has been - coerced to correct datatype and raises ``ValidationError`` on any error. - This method does not return anything and shouldn't alter the value. You - should override it to handle validation logic that you can't or don't - want to put in a validator. - - * The ``run_validators()`` method on a Field runs all of the field's - validators and aggregates all the errors into a single - ``ValidationError``. You shouldn't need to override this method. - - * The ``clean()`` method on a Field subclass. This is responsible for - running ``to_python``, ``validate`` and ``run_validators`` in the correct - order and propagating their errors. If, at any time, any of the methods - raise ``ValidationError``, the validation stops and that error is raised. - This method returns the clean data, which is then inserted into the - ``cleaned_data`` dictionary of the form. - - * The ``clean_<fieldname>()`` method in a form subclass -- where - ``<fieldname>`` is replaced with the name of the form field attribute. - This method does any cleaning that is specific to that particular - attribute, unrelated to the type of field that it is. This method is not - passed any parameters. You will need to look up the value of the field - in ``self.cleaned_data`` and remember that it will be a Python object - at this point, not the original string submitted in the form (it will be - in ``cleaned_data`` because the general field ``clean()`` method, above, - has already cleaned the data once). - - For example, if you wanted to validate that the contents of a - ``CharField`` called ``serialnumber`` was unique, - ``clean_serialnumber()`` would be the right place to do this. You don't - need a specific field (it's just a ``CharField``), but you want a - formfield-specific piece of validation and, possibly, - cleaning/normalizing the data. - - Just like the general field ``clean()`` method, above, this method - should return the cleaned data, regardless of whether it changed - anything or not. - - * The Form subclass's ``clean()`` method. This method can perform - any validation that requires access to multiple fields from the form at - once. This is where you might put in things to check that if field ``A`` - is supplied, field ``B`` must contain a valid e-mail address and the - like. The data that this method returns is the final ``cleaned_data`` - attribute for the form, so don't forget to return the full list of - cleaned data if you override this method (by default, ``Form.clean()`` - just returns ``self.cleaned_data``). - - Note that any errors raised by your ``Form.clean()`` override will not - be associated with any field in particular. They go into a special - "field" (called ``__all__``), which you can access via the - ``non_field_errors()`` method if you need to. If you want to attach - errors to a specific field in the form, you will need to access the - ``_errors`` attribute on the form, which is `described later`_. - - Also note that there are special considerations when overriding - the ``clean()`` method of a ``ModelForm`` subclass. (see the - :ref:`ModelForm documentation - <overriding-modelform-clean-method>` for more information) - -These methods are run in the order given above, one field at a time. That is, -for each field in the form (in the order they are declared in the form -definition), the ``Field.clean()`` method (or its override) is run, then -``clean_<fieldname>()``. Finally, once those two methods are run for every -field, the ``Form.clean()`` method, or its override, is executed. - -Examples of each of these methods are provided below. - -As mentioned, any of these methods can raise a ``ValidationError``. For any -field, if the ``Field.clean()`` method raises a ``ValidationError``, any -field-specific cleaning method is not called. However, the cleaning methods -for all remaining fields are still executed. - -The ``clean()`` method for the ``Form`` class or subclass is always run. If -that method raises a ``ValidationError``, ``cleaned_data`` will be an empty -dictionary. - -The previous paragraph means that if you are overriding ``Form.clean()``, you -should iterate through ``self.cleaned_data.items()``, possibly considering the -``_errors`` dictionary attribute on the form as well. In this way, you will -already know which fields have passed their individual validation requirements. - -.. _described later: - -Form subclasses and modifying field errors ------------------------------------------- - -Sometimes, in a form's ``clean()`` method, you will want to add an error -message to a particular field in the form. This won't always be appropriate -and the more typical situation is to raise a ``ValidationError`` from -``Form.clean()``, which is turned into a form-wide error that is available -through the ``Form.non_field_errors()`` method. - -When you really do need to attach the error to a particular field, you should -store (or amend) a key in the ``Form._errors`` attribute. This attribute is an -instance of a ``django.forms.util.ErrorDict`` class. Essentially, though, it's -just a dictionary. There is a key in the dictionary for each field in the form -that has an error. Each value in the dictionary is a -``django.forms.util.ErrorList`` instance, which is a list that knows how to -display itself in different ways. So you can treat ``_errors`` as a dictionary -mapping field names to lists. - -If you want to add a new error to a particular field, you should check whether -the key already exists in ``self._errors`` or not. If not, create a new entry -for the given key, holding an empty ``ErrorList`` instance. In either case, -you can then append your error message to the list for the field name in -question and it will be displayed when the form is displayed. - -There is an example of modifying ``self._errors`` in the following section. - -.. admonition:: What's in a name? - - You may be wondering why is this attribute called ``_errors`` and not - ``errors``. Normal Python practice is to prefix a name with an underscore - if it's not for external usage. In this case, you are subclassing the - ``Form`` class, so you are essentially writing new internals. In effect, - you are given permission to access some of the internals of ``Form``. - - Of course, any code outside your form should never access ``_errors`` - directly. The data is available to external code through the ``errors`` - property, which populates ``_errors`` before returning it). - - Another reason is purely historical: the attribute has been called - ``_errors`` since the early days of the forms module and changing it now - (particularly since ``errors`` is used for the read-only property name) - would be inconvenient for a number of reasons. You can use whichever - explanation makes you feel more comfortable. The result is the same. - -Using validation in practice ----------------------------- - -The previous sections explained how validation works in general for forms. -Since it can sometimes be easier to put things into place by seeing each -feature in use, here are a series of small examples that use each of the -previous features. - -.. _validators: - -Using validators -~~~~~~~~~~~~~~~~ -.. versionadded:: 1.2 - -Django's form (and model) fields support use of simple utility functions and -classes known as validators. These can be passed to a field's constructor, via -the field's ``validators`` argument, or defined on the Field class itself with -the ``default_validators`` attribute. - -Simple validators can be used to validate values inside the field, let's have -a look at Django's ``EmailField``:: - - class EmailField(CharField): - default_error_messages = { - 'invalid': _(u'Enter a valid e-mail address.'), - } - default_validators = [validators.validate_email] - -As you can see, ``EmailField`` is just a ``CharField`` with customized error -message and a validator that validates e-mail addresses. This can also be done -on field definition so:: - - email = forms.EmailField() - -is equivalent to:: - - email = forms.CharField(validators=[validators.validate_email], - error_messages={'invalid': _(u'Enter a valid e-mail address.')}) - - -Form field default cleaning -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Let's firstly create a custom form field that validates its input is a string -containing comma-separated e-mail addresses. The full class looks like this:: - - from django import forms - from django.core.validators import validate_email - - class MultiEmailField(forms.Field): - def to_python(self, value): - "Normalize data to a list of strings." - - # Return an empty list if no input was given. - if not value: - return [] - return value.split(',') - - def validate(self, value): - "Check if value consists only of valid emails." - - # Use the parent's handling of required fields, etc. - super(MultiEmailField, self).validate(value) - - for email in value: - validate_email(email) - -Every form that uses this field will have these methods run before anything -else can be done with the field's data. This is cleaning that is specific to -this type of field, regardless of how it is subsequently used. - -Let's create a simple ``ContactForm`` to demonstrate how you'd use this -field:: - - class ContactForm(forms.Form): - subject = forms.CharField(max_length=100) - message = forms.CharField() - sender = forms.EmailField() - recipients = MultiEmailField() - cc_myself = forms.BooleanField(required=False) - -Simply use ``MultiEmailField`` like any other form field. When the -``is_valid()`` method is called on the form, the ``MultiEmailField.clean()`` -method will be run as part of the cleaning process and it will, in turn, call -the custom ``to_python()`` and ``validate()`` methods. - -Cleaning a specific field attribute -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Continuing on from the previous example, suppose that in our ``ContactForm``, -we want to make sure that the ``recipients`` field always contains the address -``"fred@example.com"``. This is validation that is specific to our form, so we -don't want to put it into the general ``MultiEmailField`` class. Instead, we -write a cleaning method that operates on the ``recipients`` field, like so:: - - class ContactForm(forms.Form): - # Everything as before. - ... - - def clean_recipients(self): - data = self.cleaned_data['recipients'] - if "fred@example.com" not in data: - raise forms.ValidationError("You have forgotten about Fred!") - - # Always return the cleaned data, whether you have changed it or - # not. - return data - -Cleaning and validating fields that depend on each other -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Suppose we add another requirement to our contact form: if the ``cc_myself`` -field is ``True``, the ``subject`` must contain the word ``"help"``. We are -performing validation on more than one field at a time, so the form's -``clean()`` method is a good spot to do this. Notice that we are talking about -the ``clean()`` method on the form here, whereas earlier we were writing a -``clean()`` method on a field. It's important to keep the field and form -difference clear when working out where to validate things. Fields are single -data points, forms are a collection of fields. - -By the time the form's ``clean()`` method is called, all the individual field -clean methods will have been run (the previous two sections), so -``self.cleaned_data`` will be populated with any data that has survived so -far. So you also need to remember to allow for the fact that the fields you -are wanting to validate might not have survived the initial individual field -checks. - -There are two way to report any errors from this step. Probably the most -common method is to display the error at the top of the form. To create such -an error, you can raise a ``ValidationError`` from the ``clean()`` method. For -example:: - - class ContactForm(forms.Form): - # Everything as before. - ... - - def clean(self): - cleaned_data = self.cleaned_data - cc_myself = cleaned_data.get("cc_myself") - subject = cleaned_data.get("subject") - - if cc_myself and subject: - # Only do something if both fields are valid so far. - if "help" not in subject: - raise forms.ValidationError("Did not send for 'help' in " - "the subject despite CC'ing yourself.") - - # Always return the full collection of cleaned data. - return cleaned_data - -In this code, if the validation error is raised, the form will display an -error message at the top of the form (normally) describing the problem. - -The second approach might involve assigning the error message to one of the -fields. In this case, let's assign an error message to both the "subject" and -"cc_myself" rows in the form display. Be careful when doing this in practice, -since it can lead to confusing form output. We're showing what is possible -here and leaving it up to you and your designers to work out what works -effectively in your particular situation. Our new code (replacing the previous -sample) looks like this:: - - class ContactForm(forms.Form): - # Everything as before. - ... - - def clean(self): - cleaned_data = self.cleaned_data - cc_myself = cleaned_data.get("cc_myself") - subject = cleaned_data.get("subject") - - if cc_myself and subject and "help" not in subject: - # We know these are not in self._errors now (see discussion - # below). - msg = u"Must put 'help' in subject when cc'ing yourself." - self._errors["cc_myself"] = self.error_class([msg]) - self._errors["subject"] = self.error_class([msg]) - - # These fields are no longer valid. Remove them from the - # cleaned data. - del cleaned_data["cc_myself"] - del cleaned_data["subject"] - - # Always return the full collection of cleaned data. - return cleaned_data - -As you can see, this approach requires a bit more effort, not withstanding the -extra design effort to create a sensible form display. The details are worth -noting, however. Firstly, earlier we mentioned that you might need to check if -the field name keys already exist in the ``_errors`` dictionary. In this case, -since we know the fields exist in ``self.cleaned_data``, they must have been -valid when cleaned as individual fields, so there will be no corresponding -entries in ``_errors``. - -Secondly, once we have decided that the combined data in the two fields we are -considering aren't valid, we must remember to remove them from the -``cleaned_data``. - -In fact, Django will currently completely wipe out the ``cleaned_data`` -dictionary if there are any errors in the form. However, this behaviour may -change in the future, so it's not a bad idea to clean up after yourself in the -first place. diff --git a/parts/django/docs/ref/forms/widgets.txt b/parts/django/docs/ref/forms/widgets.txt deleted file mode 100644 index 9d78b84..0000000 --- a/parts/django/docs/ref/forms/widgets.txt +++ /dev/null @@ -1,247 +0,0 @@ -======= -Widgets -======= - -.. module:: django.forms.widgets - :synopsis: Django's built-in form widgets. - -.. currentmodule:: django.forms - -A widget is Django's representation of a HTML input element. The widget -handles the rendering of the HTML, and the extraction of data from a GET/POST -dictionary that corresponds to the widget. - -Django provides a representation of all the basic HTML widgets, plus some -commonly used groups of widgets: - -.. class:: TextInput - - Text input: ``<input type='text' ...>`` - -.. class:: PasswordInput - - Password input: ``<input type='password' ...>`` - - Takes one optional argument: - - .. attribute:: PasswordInput.render_value - - Determines whether the widget will have a value filled in when the - form is re-displayed after a validation error (default is ``True``). - -.. class:: HiddenInput - - Hidden input: ``<input type='hidden' ...>`` - -.. class:: MultipleHiddenInput - - Multiple ``<input type='hidden' ...>`` widgets. - -.. class:: FileInput - - File upload input: ``<input type='file' ...>`` - -.. class:: DateInput - - .. versionadded:: 1.1 - - Date input as a simple text box: ``<input type='text' ...>`` - - Takes one optional argument: - - .. attribute:: DateInput.format - - The format in which this field's initial value will be displayed. - - If no ``format`` argument is provided, the default format is ``'%Y-%m-%d'``. - -.. class:: DateTimeInput - - .. versionadded:: 1.0 - - Date/time input as a simple text box: ``<input type='text' ...>`` - - Takes one optional argument: - - .. attribute:: DateTimeInput.format - - The format in which this field's initial value will be displayed. - - If no ``format`` argument is provided, the default format is ``'%Y-%m-%d - %H:%M:%S'``. - -.. class:: TimeInput - - Time input as a simple text box: ``<input type='text' ...>`` - - Takes one optional argument: - - .. attribute:: TimeInput.format - - The format in which this field's initial value will be displayed. - - If no ``format`` argument is provided, the default format is ``'%H:%M:%S'``. - - .. versionchanged:: 1.1 - The ``format`` argument was not supported in Django 1.0. - -.. class:: Textarea - - Text area: ``<textarea>...</textarea>`` - -.. class:: CheckboxInput - - Checkbox: ``<input type='checkbox' ...>`` - - Takes one optional argument: - - .. attribute:: CheckboxInput.check_test - - A callable that takes the value of the CheckBoxInput - and returns ``True`` if the checkbox should be checked for - that value. - -.. class:: Select - - Select widget: ``<select><option ...>...</select>`` - - Requires that your field provides :attr:`~Field.choices`. - -.. class:: NullBooleanSelect - - Select widget with options 'Unknown', 'Yes' and 'No' - -.. class:: SelectMultiple - - Select widget allowing multiple selection: ``<select - multiple='multiple'>...</select>`` - - Requires that your field provides :attr:`~Field.choices`. - -.. class:: RadioSelect - - A list of radio buttons: - - .. code-block:: html - - <ul> - <li><input type='radio' ...></li> - ... - </ul> - - Requires that your field provides :attr:`~Field.choices`. - -.. class:: CheckboxSelectMultiple - - A list of checkboxes: - - .. code-block:: html - - <ul> - <li><input type='checkbox' ...></li> - ... - </ul> - -.. class:: MultiWidget - - Wrapper around multiple other widgets - -.. class:: SplitDateTimeWidget - - Wrapper around two widgets: ``DateInput`` for the date, and ``TimeInput`` - for the time. - - Takes two optional arguments, ``date_format`` and ``time_format``, which - work just like the ``format`` argument for ``DateInput`` and ``TimeInput``. - - .. versionchanged:: 1.1 - The ``date_format`` and ``time_format`` arguments were not supported in Django 1.0. - -.. class:: SelectDateWidget - - Wrapper around three select widgets: one each for month, day, and year. - Note that this widget lives in a separate file from the standard widgets. - - .. code-block:: python - - from django.forms.extras.widgets import SelectDateWidget - - date = forms.DateField(widget=SelectDateWidget()) - -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:: - - from django import forms - - 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() - <tr><th>Name:</th><td><input type="text" name="name" /></td></tr> - <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> - <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> - - -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() - <tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr> - <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> - <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr> diff --git a/parts/django/docs/ref/generic-views.txt b/parts/django/docs/ref/generic-views.txt deleted file mode 100644 index ea7fe2a..0000000 --- a/parts/django/docs/ref/generic-views.txt +++ /dev/null @@ -1,1095 +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. - -A general introduction to generic views can be found in the :doc:`topic guide -</topics/http/generic-views>`. - -This reference contains details of Django's built-in generic views, along with -a list of all keyword arguments that a generic view expects. Remember that -arguments may either come from the URL pattern or from the ``extra_context`` -additional-information dictionary. - -Most generic views require the ``queryset`` key, which is a ``QuerySet`` -instance; see :doc:`/topics/db/queries` for more information about ``QuerySet`` -objects. - -"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<id>\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. Because keyword -interpolation is *always* done (even if no arguments are passed in), any ``"%"`` -characters in the URL must be written as ``"%%"`` so that Python will convert -them to a single percent sign on output. - -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. - -**Optional arguments:** - - * ``permanent``: Whether the redirect should be permanent. The only - difference here is the HTTP status code returned. If ``True``, then the - redirect will use status code 301. If ``False``, then the redirect will - use status code 302. By default, ``permanent`` is ``True``. - -.. versionadded:: 1.1 - The ``permanent`` keyword argument is new in Django 1.1. - -**Example:** - -This example issues a permanent redirect (HTTP status code 301) from -``/foo/<id>/`` to ``/bar/<id>/``:: - - urlpatterns = patterns('django.views.generic.simple', - ('^foo/(?P<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}), - ) - -This example issues a non-permanent redirect (HTTP status code 302) from -``/foo/<id>/`` to ``/bar/<id>/``:: - - urlpatterns = patterns('django.views.generic.simple', - ('^foo/(?P<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/', 'permanent': False}), - ) - -This example returns a 410 HTTP error for requests to ``/bar/``:: - - urlpatterns = patterns('django.views.generic.simple', - ('^bar/$', 'redirect_to', {'url': None}), - ) - -This example shows how ``"%"`` characters must be written in the URL in order -to avoid confusion with Python's string formatting markers. If the redirect -string is written as ``"%7Ejacob/"`` (with only a single ``%``), an exception would be raised:: - - urlpatterns = patterns('django.views.generic.simple', - ('^bar/$', 'redirect_to', {'url': '%%7Ejacob.'}), - ) - -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``. - - .. versionadded:: 1.0 - - * ``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 -``<app_label>/<model_name>_archive.html`` by default, where: - - * ``<model_name>`` is your model's name in all lowercase. For a model - ``StaffMember``, that'd be ``staffmember``. - - * ``<app_label>`` 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 ``DateQuerySet`` object containing all years that have - have objects available according to ``queryset``, represented as - ``datetime.datetime`` objects. These are ordered in reverse. This is - equivalent to ``queryset.dates(date_field, 'year')[::-1]``. - - .. versionchanged:: 1.0 - The behaviour depending on ``template_object_name`` is new in this version. - - * ``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``. - - 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 -``<app_label>/<model_name>_archive_year.html`` by default. - -**Template context:** - -In addition to ``extra_context``, the template's context will be: - - * ``date_list``: A ``DateQuerySet`` object containing all months that have - have objects available according to ``queryset``, represented as - ``datetime.datetime`` objects, 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 -``<app_label>/<model_name>_archive_month.html`` by default. - -**Template context:** - -.. versionadded:: 1.2 - The inclusion of ``date_list`` in the template's context is new. - -In addition to ``extra_context``, the template's context will be: - - * ``date_list``: A ``DateQuerySet`` object containing all days that have - have objects available in the given month, according to ``queryset``, - represented as ``datetime.datetime`` objects, in ascending order. - - * ``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://docs.python.org/library/time.html#time.strftime - -``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 -``<app_label>/<model_name>_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 -``<app_label>/<model_name>_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 previous 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 -``<app_label>/<model_name>_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 -``<app_label>/<model_name>_list.html`` by default. - -**Template context:** - -.. versionadded:: 1.0 - The ``paginator`` and ``page_obj`` context variables are new. - -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``: An instance of ``django.core.paginator.Paginator``. - - * ``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<page>[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 :doc:`pagination documentation -</topics/pagination>`. - -.. versionadded:: 1.0 - -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 -``<app_label>/<model_name>_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. - -.. versionchanged:: 1.0 - -``django.views.generic.create_update.create_object`` and -``django.views.generic.create_update.update_object`` now use the new :doc:`forms -library </topics/forms/index>` 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 :doc:`ModelForm docs </topics/forms/modelforms>` 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 :doc:`authentication system </topics/auth>`. 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 -``<app_label>/<model_name>_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 action="" method="post"> - <p>{{ form.name.label_tag }} {{ form.name }}</p> - <p>{{ form.address.label_tag }} {{ form.address }}</p> - </form> - - See the :doc:`forms documentation </topics/forms/index>` 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 :doc:`ModelForm docs </topics/forms/modelforms>` 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 :doc:`authentication system </topics/auth>`. 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 -``<app_label>/<model_name>_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 action="" method="post"> - <p>{{ form.name.label_tag }} {{ form.name }}</p> - <p>{{ form.address.label_tag }} {{ form.address }}</p> - </form> - - See the :doc:`forms documentation </topics/forms/index>` 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 :doc:`authentication system </topics/auth>`. 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 -``<app_label>/<model_name>_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/parts/django/docs/ref/index.txt b/parts/django/docs/ref/index.txt deleted file mode 100644 index 0919417..0000000 --- a/parts/django/docs/ref/index.txt +++ /dev/null @@ -1,24 +0,0 @@ -============= -API Reference -============= - -.. toctree:: - :maxdepth: 1 - - authbackends - contrib/index - databases - django-admin - exceptions - files/index - forms/index - generic-views - middleware - models/index - request-response - settings - signals - templates/index - unicode - utils - validators diff --git a/parts/django/docs/ref/middleware.txt b/parts/django/docs/ref/middleware.txt deleted file mode 100644 index b3ddb23..0000000 --- a/parts/django/docs/ref/middleware.txt +++ /dev/null @@ -1,212 +0,0 @@ -========== -Middleware -========== - -.. 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 :doc:`middleware usage guide </topics/http/middleware>`. - -Available middleware -==================== - -Cache middleware ----------------- - -.. module:: django.middleware.cache - :synopsis: Middleware for the site-wide cache. - -.. class:: UpdateCacheMiddleware - -.. class:: FetchFromCacheMiddleware - -Enable the site-wide cache. If these are enabled, each Django-powered page will -be cached for as long as the :setting:`CACHE_MIDDLEWARE_SECONDS` setting -defines. See the :doc:`cache documentation </topics/cache>`. - -"Common" middleware -------------------- - -.. module:: django.middleware.common - :synopsis: Middleware adding "common" conveniences for perfectionists. - -.. class:: 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/``. - - .. versionchanged:: 1.0 - The behavior of :setting:`APPEND_SLASH` has changed slightly in this - 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. - - * Sends broken link notification emails to :setting:`MANAGERS` if - :setting:`SEND_BROKEN_LINK_EMAILS` is set to ``True``. - - * 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:: 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 :doc:`automatic documentation system </ref/contrib/admin/admindocs>`. - -GZIP middleware ---------------- - -.. module:: django.middleware.gzip - :synopsis: Middleware to serve gziped content for performance. - -.. class:: 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:: 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:: SetRemoteAddrFromForwardedFor - -.. versionchanged:: 1.1 - -This middleware was removed in Django 1.1. See :ref:`the release notes -<removed-setremoteaddrfromforwardedfor-middleware>` for details. - -Locale middleware ------------------ - -.. module:: django.middleware.locale - :synopsis: Middleware to enable language selection based on the request. - -.. class:: LocaleMiddleware - -Enables language selection based on data from the request. It customizes -content for each user. See the :doc:`internationalization documentation -</topics/i18n/index>`. - -Message middleware ------------------- - -.. module:: django.contrib.messages.middleware - :synopsis: Message middleware. - -.. class:: MessageMiddleware - -.. versionadded:: 1.2 - ``MessageMiddleware`` was added. - -Enables cookie- and session-based message support. See the -:doc:`messages documentation </ref/contrib/messages>`. - -Session middleware ------------------- - -.. module:: django.contrib.sessions.middleware - :synopsis: Session middleware. - -.. class:: SessionMiddleware - -Enables session support. See the :doc:`session documentation -</topics/http/sessions>`. - -Authentication middleware -------------------------- - -.. module:: django.contrib.auth.middleware - :synopsis: Authentication middleware. - -.. class:: AuthenticationMiddleware - -Adds the ``user`` attribute, representing the currently-logged-in user, to -every incoming ``HttpRequest`` object. See :doc:`Authentication in Web requests -</topics/auth>`. - -CSRF protection middleware --------------------------- - -.. module:: django.middleware.csrf - :synopsis: Middleware adding protection against Cross Site Request - Forgeries. - -.. class:: CsrfMiddleware - -.. versionadded:: 1.0 - -Adds protection against Cross Site Request Forgeries by adding hidden form -fields to POST forms and checking requests for the correct value. See the -:doc:`Cross Site Request Forgery protection documentation </ref/contrib/csrf>`. - -Transaction middleware ----------------------- - -.. module:: django.middleware.transaction - :synopsis: Middleware binding a database transaction to each Web request. - -.. class:: 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 :doc:`transaction management documentation </topics/db/transactions>`. diff --git a/parts/django/docs/ref/models/fields.txt b/parts/django/docs/ref/models/fields.txt deleted file mode 100644 index 146ca43..0000000 --- a/parts/django/docs/ref/models/fields.txt +++ /dev/null @@ -1,1063 +0,0 @@ -===================== -Model field reference -===================== - -.. module:: django.db.models.fields - :synopsis: Built-in field types. - -.. currentmodule:: django.db.models - -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 :doc:`write your - own custom model fields </howto/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.<Foo>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 have the empty string as a possible - value, 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. - -.. _field-choices: - -``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. - -``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 <sqlindexes>` will output a -``CREATE INDEX`` statement for this field. - -``db_tablespace`` ------------------ - -.. attribute:: Field.db_tablespace - -.. versionadded:: 1.0 - -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``. - -``error_messages`` ------------------- - -.. versionadded:: 1.2 - -.. attribute:: Field.error_messages - -The ``error_messages`` argument lets you override the default messages that the -field will raise. Pass in a dictionary with keys matching the error messages you -want to override. - -``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: <em>YYYY-MM-DD</em>." - -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 <Field.null>` and :attr:`unique=True <Field.unique>`. -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 option is valid on all field types except :class:`ManyToManyField` and -:class:`FileField`. - -``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`. - -``verbose_name`` -------------------- - -.. attribute:: Field.verbose_name - -A human-readable name for the field. If the verbose name isn't given, Django -will automatically create it using the field's attribute name, converting -underscores to spaces. See :ref:`Verbose field names <verbose-field-names>`. - -``validators`` -------------------- - -.. versionadded:: 1.2 - -.. attribute:: Field.validators - -A list of validators to run for this field.See the :doc:`validators -documentation </ref/validators>` for more information. - -.. _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`. - -``BigIntegerField`` -------------------- - -.. versionadded:: 1.2 - -.. class:: BigIntegerField([**options]) - -A 64 bit integer, much like an :class:`IntegerField` except that it is -guaranteed to fit numbers from -9223372036854775808 to 9223372036854775807. The -admin represents this as an ``<input type="text">`` (a single-line input). - - -``BooleanField`` ----------------- - -.. class:: BooleanField(**options) - -A true/false field. - -The admin represents this as a checkbox. - -.. versionchanged:: 1.2 - - In previous versions of Django when running under MySQL ``BooleanFields`` - would return their data as ``ints``, instead of true ``bools``. See the - release notes for a complete description of the change. - -``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 ``<input type="text">`` (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. - -.. note:: - - If you are writing an application that must be portable to multiple - database backends, you should be aware that there are restrictions on - ``max_length`` for some backends. Refer to the :doc:`database backend - notes </ref/databases>` for details. - -.. admonition:: MySQL users - - If you are using this field with MySQLdb 1.2.2 and the ``utf8_bin`` - collation (which is *not* the default), there are some issues to be aware - of. Refer to the :ref:`MySQL database notes <mysql-collation>` for - details. - - -``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 and the note about database -portability mentioned there should be heeded. - -``DateField`` -------------- - -.. class:: DateField([auto_now=False, auto_now_add=False, **options]) - -A date, represented in Python by a ``datetime.date`` instance. 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 ``<input type="text">`` with a JavaScript -calendar, and a shortcut for "Today". The JavaScript calendar will always -start the week on a Sunday. - -.. note:: - As currently implemented, setting ``auto_now`` or ``auto_add_now`` to - ``True`` will cause the field to have ``editable=False`` and ``blank=True`` - set. - -``DateTimeField`` ------------------ - -.. class:: DateTimeField([auto_now=False, auto_now_add=False, **options]) - -A date and time, represented in Python by a ``datetime.datetime`` instance. -Takes the same extra arguments as :class:`DateField`. - -The admin represents this as two ``<input type="text">`` fields, with -JavaScript shortcuts. - -``DecimalField`` ----------------- - -.. versionadded:: 1.0 - -.. 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 ``<input type="text">`` (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. - -``FileField`` -------------- - -.. class:: FileField(upload_to=None, [max_length=100, **options]) - -A file-upload field. - -.. note:: - The ``primary_key`` and ``unique`` arguments are not supported, and will - raise a ``TypeError`` if used. - -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 value of the :attr:`~django.core.files.File.url` - attribute. - - 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). - - .. versionchanged:: 1.0 - - 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 - - .. versionadded:: 1.0 - - Optional. A storage object, which handles the storage and retrieval of your - files. See :doc:`/topics/files` for details on how to provide this object. - -The admin represents this field as an ``<input type="file">`` (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 :attr:`~django.core.files.File.url` function provided by - Django. For example, if your :class:`ImageField` is called ``mug_shot``, - you can get the absolute path to your image in a template with - ``{{ object.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 -:attr:`~django.core.files.File.name`, :attr:`~django.core.files.File.url` -and :attr:`~django.core.files.File.size` attributes; see :doc:`/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. - -.. versionadded:: 1.0 - The ``max_length`` argument was added in this 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/library/time.html#time.strftime - -FileField and FieldFile -~~~~~~~~~~~~~~~~~~~~~~~ - -When you access a :class:`FileField` on a model, you are given an instance -of :class:`FieldFile` as a proxy for accessing the underlying file. This -class has several methods that can be used to interact with file data: - -.. method:: FieldFile.open(mode='rb') - -Behaves like the standard Python ``open()`` method and opens the file -associated with this instance in the mode specified by ``mode``. - -.. method:: FieldFile.close() - -Behaves like the standard Python ``file.close()`` method and closes the file -associated with this instance. - -.. method:: FieldFile.save(name, content, save=True) - -This method takes a filename and file contents and passes them to the storage -class for the field, then associates the stored file with the model field. -If you want to manually associate file data with :class:`FileField` -instances on your model, the ``save()`` method is used to persist that file -data. - -Takes two required arguments: ``name`` which is the name of the file, and -``content`` which is a file-like object containing the file's contents. The -optional ``save`` argument controls whether or not the instance is saved after -the file has been altered. Defaults to ``True``. - -.. method:: FieldFile.delete(save=True) - -Deletes the file associated with this instance and clears all attributes on -the field. Note: This method will close the file if it happens to be open when -``delete()`` is called. - -The optional ``save`` argument controls whether or not the instance is saved -after the file has been deleted. Defaults to ``True``. - -``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``). - -.. versionadded:: 1.0 - The ``max_length`` argument was added in this 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]) - -.. versionchanged:: 1.0 - -A floating-point number represented in Python by a ``float`` instance. - -The admin represents this as an ``<input type="text">`` (a single-line input). - -``ImageField`` --------------- - -.. class:: ImageField(upload_to=None, [height_field=None, width_field=None, max_length=100, **options]) - -Inherits all attributes and methods from :class:`FileField`, but also -validates that the uploaded object is a valid image. - -In addition to the special attributes that are available for :class:`FileField`, -an :class:`ImageField` also has :attr:`~django.core.files.File.height` and -:attr:`~django.core.files.File.width` attributes. - -To facilitate querying on those attributes, :class:`ImageField` 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. - -Requires the `Python Imaging Library`_. - -.. _Python Imaging Library: http://www.pythonware.com/products/pil/ - -.. versionadded:: 1.0 - The ``max_length`` argument was added in this 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 ``<input type="text">`` (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 ``<input type="text">`` (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 ``<select>`` box with "Unknown", "Yes" and "No" choices. - -``PositiveIntegerField`` ------------------------- - -.. class:: PositiveIntegerField([**options]) - -Like an :class:`IntegerField`, but must be positive. - -``PositiveSmallIntegerField`` ------------------------------ - -.. class:: PositiveSmallIntegerField([**options]) - -Like a :class:`PositiveIntegerField`, but only allows values under a certain -(database-dependent) point. - -``SlugField`` -------------- - -.. class:: SlugField([max_length=50, **options]) - -:term:`Slug` is a newspaper term. A slug is a short label for something, -containing only letters, numbers, underscores or hyphens. They're generally used -in URLs. - -Like a CharField, you can specify :attr:`~CharField.max_length` (read the note -about database portability and :attr:`~CharField.max_length` in that section, -too). If :attr:`~CharField.max_length` is not specified, Django will use a -default length of 50. - -Implies setting :attr:`Field.db_index` to ``True``. - -It is often useful to automatically prepopulate a SlugField based on the value -of some other value. You can do this automatically in the admin using -:attr:`~django.contrib.admin.ModelAdmin.prepopulated_fields`. - -``SmallIntegerField`` ---------------------- - -.. class:: SmallIntegerField([**options]) - -Like an :class:`IntegerField`, but only allows values under a certain -(database-dependent) point. - -``TextField`` -------------- - -.. class:: TextField([**options]) - -A large text field. The admin represents this as a ``<textarea>`` (a multi-line -input). - -.. admonition:: MySQL users - - If you are using this field with MySQLdb 1.2.1p2 and the ``utf8_bin`` - collation (which is *not* the default), there are some issues to be aware - of. Refer to the :ref:`MySQL database notes <mysql-collation>` for - details. - -``TimeField`` -------------- - -.. class:: TimeField([auto_now=False, auto_now_add=False, **options]) - -A time, represented in Python by a ``datetime.time`` instance. Accepts the same -auto-population options as :class:`DateField`. - -The admin represents this as an ``<input type="text">`` with some JavaScript -shortcuts. - -``URLField`` ------------- - -.. class:: URLField([verify_exists=True, max_length=200, **options]) - -A :class:`CharField` for a URL. Has one extra optional argument: - -.. attribute:: URLField.verify_exists - - If ``True`` (the default), the URL given will be checked for existence - (i.e., the URL actually loads and doesn't give a 404 response). - - Note that when you're using the single-threaded development server, - validating a URL being served by the same server will hang. This should not - be a problem for multithreaded servers. - -The admin represents this as an ``<input type="text">`` (a single-line input). - -Like all :class:`CharField` subclasses, :class:`URLField` takes the optional -:attr:`~CharField.max_length`argument. If you don't specify -:attr:`~CharField.max_length`, a default of 200 is used. - -``XMLField`` ------------- - -.. class:: XMLField(schema_path=None, [**options]) - -A :class:`TextField` that checks that the value is valid XML that matches a -given schema. Takes one required argument: - -.. attribute:: schema_path - - The filesystem path to a RelaxNG_ schema against which to validate the - field. - -.. _RelaxNG: http://www.relaxng.org/ - -Relationship fields -=================== - -.. module:: django.db.models.fields.related - :synopsis: Related field types - -.. currentmodule:: django.db.models - -Django also defines a set of fields that represent relations. - -.. _ref-foreignkey: - -``ForeignKey`` --------------- - -.. class:: ForeignKey(othermodel, [**options]) - -A many-to-one relationship. Requires a positional argument: the class to which -the model is related. - -.. _recursive-relationships: - -To create a recursive relationship -- an object that has a many-to-one -relationship with itself -- use ``models.ForeignKey('self')``. - -.. _lazy-relationships: - -If you need to create a relationship on a model that has not yet been defined, -you can use the name of the model, rather than the model object itself:: - - class Car(models.Model): - manufacturer = models.ForeignKey('Manufacturer') - # ... - - class Manufacturer(models.Model): - # ... - -.. versionadded:: 1.0 - -To refer to models defined in another application, you can explicitly specify -a model with the full application label. For example, if the ``Manufacturer`` -model above is defined in another application called ``production``, you'd -need to use:: - - class Car(models.Model): - manufacturer = models.ForeignKey('production.Manufacturer') - -This sort of reference can be useful when resolving circular import -dependencies between two applications. - -Database Representation -~~~~~~~~~~~~~~~~~~~~~~~ - -Behind the scenes, Django appends ``"_id"`` to the field name to create its -database column name. In the above example, the database table for the ``Car`` -model will have a ``manufacturer_id`` column. (You can change this explicitly by -specifying :attr:`~Field.db_column`) However, your code should never have to -deal with the database column name, unless you write custom SQL. You'll always -deal with the field names of your model object. - -.. _foreign-key-arguments: - -Arguments -~~~~~~~~~ - -:class:`ForeignKey` accepts an extra set of arguments -- all optional -- that -define the details of how the relation works. - -.. attribute:: ForeignKey.limit_choices_to - - A dictionary of lookup arguments and values (see :doc:`/topics/db/queries`) - that limit the available admin choices for this object. Use this with - functions from the Python ``datetime`` module to limit choices of objects by - date. For example:: - - limit_choices_to = {'pub_date__lte': datetime.now} - - only allows the choice of related objects with a ``pub_date`` before the - current date/time to be chosen. - - Instead of a dictionary this can also be a :class:`~django.db.models.Q` - object for more :ref:`complex queries <complex-lookups-with-q>`. However, - if ``limit_choices_to`` is a :class:`~django.db.models.Q` object then it - will only have an effect on the choices available in the admin when the - field is not listed in ``raw_id_fields`` in the ``ModelAdmin`` for the model. - -.. attribute:: ForeignKey.related_name - - The name to use for the relation from the related object back to this one. - See the :ref:`related objects documentation <backwards-related-objects>` for - a full explanation and example. Note that you must set this value - when defining relations on :ref:`abstract models - <abstract-base-classes>`; and when you do so - :ref:`some special syntax <abstract-related-name>` is available. - - If you wish to suppress the provision of a backwards relation, you may - simply provide a ``related_name`` which ends with a ``'+'`` character. - For example:: - - user = models.ForeignKey(User, related_name='+') - - will ensure that no backwards relation to this model is provided on the - ``User`` model. - -.. attribute:: ForeignKey.to_field - - The field on the related object that the relation is to. By default, Django - uses the primary key of the related object. - -.. _ref-manytomany: - -``ManyToManyField`` -------------------- - -.. class:: ManyToManyField(othermodel, [**options]) - -A many-to-many relationship. Requires a positional argument: the class to which -the model is related. This works exactly the same as it does for -:class:`ForeignKey`, including all the options regarding :ref:`recursive -<recursive-relationships>` and :ref:`lazy <lazy-relationships>` relationships. - -Database Representation -~~~~~~~~~~~~~~~~~~~~~~~ - -Behind the scenes, Django creates an intermediary join table to -represent the many-to-many relationship. By default, this table name -is generated using the name of the many-to-many field and the model -that contains it. Since some databases don't support table names above -a certain length, these table names will be automatically truncated to -64 characters and a uniqueness hash will be used. This means you might -see table names like ``author_books_9cdf4``; this is perfectly normal. -You can manually provide the name of the join table using the -:attr:`~ManyToManyField.db_table` option. - -.. _manytomany-arguments: - -Arguments -~~~~~~~~~ - -:class:`ManyToManyField` accepts an extra set of arguments -- all optional -- -that control how the relationship functions. - -.. attribute:: ManyToManyField.related_name - - Same as :attr:`ForeignKey.related_name`. - -.. attribute:: ManyToManyField.limit_choices_to - - Same as :attr:`ForeignKey.limit_choices_to`. - - ``limit_choices_to`` has no effect when used on a ``ManyToManyField`` with a - custom intermediate table specified using the - :attr:`~ManyToManyField.through` parameter. - -.. attribute:: ManyToManyField.symmetrical - - Only used in the definition of ManyToManyFields on self. Consider the - following model:: - - class Person(models.Model): - friends = models.ManyToManyField("self") - - When Django processes this model, it identifies that it has a - :class:`ManyToManyField` on itself, and as a result, it doesn't add a - ``person_set`` attribute to the ``Person`` class. Instead, the - :class:`ManyToManyField` is assumed to be symmetrical -- that is, if I am - your friend, then you are my friend. - - If you do not want symmetry in many-to-many relationships with ``self``, set - :attr:`~ManyToManyField.symmetrical` to ``False``. This will force Django to - add the descriptor for the reverse relationship, allowing - :class:`ManyToManyField` relationships to be non-symmetrical. - -.. attribute:: ManyToManyField.through - - Django will automatically generate a table to manage many-to-many - relationships. However, if you want to manually specify the intermediary - table, you can use the :attr:`~ManyToManyField.through` option to specify - the Django model that represents the intermediate table that you want to - use. - - The most common use for this option is when you want to associate - :ref:`extra data with a many-to-many relationship - <intermediary-manytomany>`. - -.. attribute:: ManyToManyField.db_table - - The name of the table to create for storing the many-to-many data. If this - is not provided, Django will assume a default name based upon the names of - the two tables being joined. - -.. _ref-onetoone: - -``OneToOneField`` ------------------ - -.. class:: OneToOneField(othermodel, [parent_link=False, **options]) - -A one-to-one relationship. Conceptually, this is similar to a -:class:`ForeignKey` with :attr:`unique=True <Field.unique>`, but the -"reverse" side of the relation will directly return a single object. - -This is most useful as the primary key of a model which "extends" -another model in some way; :ref:`multi-table-inheritance` is -implemented by adding an implicit one-to-one relation from the child -model to the parent model, for example. - -One positional argument is required: the class to which the model will be -related. This works exactly the same as it does for :class:`ForeignKey`, -including all the options regarding :ref:`recursive <recursive-relationships>` -and :ref:`lazy <lazy-relationships>` relationships. - -.. _onetoone-arguments: - -Additionally, ``OneToOneField`` accepts all of the extra arguments -accepted by :class:`ForeignKey`, plus one extra argument: - -.. attribute:: OneToOneField.parent_link - - When ``True`` and used in a model which inherits from another - (concrete) model, indicates that this field should be used as the - link back to the parent class, rather than the extra - ``OneToOneField`` which would normally be implicitly created by - subclassing. diff --git a/parts/django/docs/ref/models/index.txt b/parts/django/docs/ref/models/index.txt deleted file mode 100644 index b5896c3..0000000 --- a/parts/django/docs/ref/models/index.txt +++ /dev/null @@ -1,14 +0,0 @@ -====== -Models -====== - -Model API reference. For introductory material, see :doc:`/topics/db/models`. - -.. toctree:: - :maxdepth: 1 - - fields - relations - options - instances - querysets diff --git a/parts/django/docs/ref/models/instances.txt b/parts/django/docs/ref/models/instances.txt deleted file mode 100644 index 1730ec6..0000000 --- a/parts/django/docs/ref/models/instances.txt +++ /dev/null @@ -1,570 +0,0 @@ -======================== -Model instance reference -======================== - -.. currentmodule:: django.db.models - -This document describes the details of the ``Model`` API. It builds on the -material presented in the :doc:`model </topics/db/models>` and :doc:`database -query </topics/db/queries>` guides, so you'll probably want to read and -understand those documents before reading this one. - -Throughout this reference we'll use the :ref:`example Weblog models -<queryset-model-example>` presented in the :doc:`database query guide -</topics/db/queries>`. - -Creating objects -================ - -To create a new instance of a model, just instantiate it like any other Python -class: - -.. class:: Model(**kwargs) - -The keyword arguments are simply the names of the fields you've defined on your -model. Note that instantiating a model in no way touches your database; for -that, you need to ``save()``. - -.. _validating-objects: - -Validating objects -================== - -.. versionadded:: 1.2 - -There are three steps involved in validating a model: - - 1. Validate the model fields - 2. Validate the model as a whole - 3. Validate the field uniqueness - -All three steps are performed when you call by a model's -``full_clean()`` method. - -When you use a ``ModelForm``, the call to ``is_valid()`` will perform -these validation steps for all the fields that are included on the -form. (See the :doc:`ModelForm documentation -</topics/forms/modelforms>` for more information.) You should only need -to call a model's ``full_clean()`` method if you plan to handle -validation errors yourself, or if you have excluded fields from the -ModelForm that require validation. - -.. method:: Model.full_clean(exclude=None) - -This method calls ``Model.clean_fields()``, ``Model.clean()``, and -``Model.validate_unique()``, in that order and raises a ``ValidationError`` -that has a ``message_dict`` attribute containing errors from all three stages. - -The optional ``exclude`` argument can be used to provide a list of field names -that can be excluded from validation and cleaning. ``ModelForm`` uses this -argument to exclude fields that aren't present on your form from being -validated since any errors raised could not be corrected by the user. - -Note that ``full_clean()`` will *not* be called automatically when you -call your model's ``save()`` method, nor as a result of ``ModelForm`` -validation. You'll need to call it manually when you want to run model -validation outside of a ``ModelForm``. - -Example:: - - try: - article.full_clean() - except ValidationError, e: - # Do something based on the errors contained in e.message_dict. - # Display them to a user, or handle them programatically. - -The first step ``full_clean()`` performs is to clean each individual field. - -.. method:: Model.clean_fields(exclude=None) - -This method will validate all fields on your model. The optional ``exclude`` -argument lets you provide a list of field names to exclude from validation. It -will raise a ``ValidationError`` if any fields fail validation. - -The second step ``full_clean()`` performs is to call ``Model.clean()``. -This method should be overridden to perform custom validation on your model. - -.. method:: Model.clean() - -This method should be used to provide custom model validation, and to modify -attributes on your model if desired. For instance, you could use it to -automatically provide a value for a field, or to do validation that requires -access to more than a single field:: - - def clean(self): - from django.core.exceptions import ValidationError - # Don't allow draft entries to have a pub_date. - if self.status == 'draft' and self.pub_date is not None: - raise ValidationError('Draft entries may not have a publication date.') - # Set the pub_date for published items if it hasn't been set already. - if self.status == 'published' and self.pub_date is None: - self.pub_date = datetime.datetime.now() - -Any ``ValidationError`` raised by ``Model.clean()`` will be stored under a -special key that is used for errors that are tied to the entire model instead -of to a specific field. You can access these errors with ``NON_FIELD_ERRORS``:: - - - from django.core.exceptions import ValidationError, NON_FIELD_ERRORS - try: - article.full_clean() - except ValidationError, e: - non_field_errors = e.message_dict[NON_FIELD_ERRORS] - -Finally, ``full_clean()`` will check any unique constraints on your model. - -.. method:: Model.validate_unique(exclude=None) - -This method is similar to ``clean_fields``, but validates all uniqueness -constraints on your model instead of individual field values. The optional -``exclude`` argument allows you to provide a list of field names to exclude -from validation. It will raise a ``ValidationError`` if any fields fail -validation. - -Note that if you provide an ``exclude`` argument to ``validate_unique``, any -``unique_together`` constraint that contains one of the fields you provided -will not be checked. - - -Saving objects -============== - -To save an object back to the database, call ``save()``: - -.. method:: Model.save([force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS]) - -.. versionadded:: 1.0 - The ``force_insert`` and ``force_update`` arguments were added. - -.. versionadded:: 1.2 - The ``using`` argument was added. - -If you want customized saving behavior, you can override this -``save()`` method. See :ref:`overriding-model-methods` for more -details. - -The model save process also has some subtleties; see the sections -below. - -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()``:: - - >>> 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 -documentation for ``AutoField`` for more details. - -The ``pk`` property -~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. attribute:: Model.pk - -Regardless of whether you define a primary key field yourself, or let Django -supply one for you, each model will have a property called ``pk``. It behaves -like a normal attribute on the model, but is actually an alias for whichever -attribute is the primary key field for the model. You can read and set this -value, just as you would for any other attribute, and it will update the -correct field in the model. - -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:: - - >>> 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.** The :doc:`signal </ref/signals>` - :attr:`django.db.models.signals.pre_save` is sent, allowing any - functions listening for that signal to take some customized - action. - - 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.** The signal - :attr:`django.db.models.signals.post_save` is sent, allowing - any functions listening for that signal to take some customized - action. - -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. - -.. _ref-models-force-insert: - -Forcing an INSERT or UPDATE -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -In some rare circumstances, it's necessary 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. - -Updating attributes based on existing fields --------------------------------------------- - -Sometimes you'll need to perform a simple arithmetic task on a field, such -as incrementing or decrementing the current value. The obvious way to -achieve this is to do something like:: - - >>> product = Product.objects.get(name='Venezuelan Beaver Cheese') - >>> product.number_sold += 1 - >>> product.save() - -If the old ``number_sold`` value retrieved from the database was 10, then -the value of 11 will be written back to the database. - -This can be optimized slightly by expressing the update relative to the -original field value, rather than as an explicit assignment of a new value. -Django provides :ref:`F() expressions <query-expressions>` as a way of -performing this kind of relative update. Using ``F()`` expressions, the -previous example would be expressed as:: - - >>> from django.db.models import F - >>> product = Product.objects.get(name='Venezuelan Beaver Cheese') - >>> product.number_sold = F('number_sold') + 1 - >>> product.save() - -This approach doesn't use the initial value from the database. Instead, it -makes the database do the update based on whatever value is current at the -time that the save() is executed. - -Once the object has been saved, you must reload the object in order to access -the actual value that was applied to the updated field:: - - >>> product = Products.objects.get(pk=product.pk) - >>> print product.number_sold - 42 - -For more details, see the documentation on :ref:`F() expressions -<query-expressions>` and their :ref:`use in update queries -<topics-db-queries-update>`. - -Deleting objects -================ - -.. method:: Model.delete([using=DEFAULT_DB_ALIAS]) - -.. versionadded:: 1.2 - The ``using`` argument was added. - -Issues a SQL ``DELETE`` for the object. This only deletes the object -in the database; the Python instance will still be around, and will -still have data in its fields. - -For more details, including how to delete objects in bulk, see -:ref:`topics-db-queries-delete`. - -If you want customized deletion behavior, you can override this -``delete()`` method. See :ref:`overriding-model-methods` for more -details. - -.. _model-instance-methods: - -Other model instance methods -============================ - -A few object methods have special purposes. - -``__str__`` ------------ - -.. method:: Model.__str__() - -``__str__()`` is a Python "magic method" that defines what should be returned -if you call ``str()`` on the object. Django uses ``str(obj)`` (or the related -function, ``unicode(obj)`` -- see below) in a number of places, most notably -as the value displayed to render an object in the Django admin site and as the -value inserted into a template when it displays an object. Thus, you should -always return a nice, human-readable string for the object's ``__str__``. -Although this isn't required, it's strongly encouraged (see the description of -``__unicode__``, below, before putting ``__str__`` methods everywhere). - -For example:: - - class Person(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - - def __str__(self): - # Note use of django.utils.encoding.smart_str() here because - # first_name and last_name will be unicode strings. - return smart_str('%s %s' % (self.first_name, self.last_name)) - -``__unicode__`` ---------------- - -.. method:: Model.__unicode__() - -The ``__unicode__()`` method is called whenever you call ``unicode()`` on an -object. Since Django's database backends will return Unicode strings in your -model's attributes, you would normally want to write a ``__unicode__()`` -method for your model. The example in the previous section could be written -more simply as:: - - class Person(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - - def __unicode__(self): - return u'%s %s' % (self.first_name, self.last_name) - -If you define a ``__unicode__()`` method on your model and not a ``__str__()`` -method, Django will automatically provide you with a ``__str__()`` that calls -``__unicode__()`` and then converts the result correctly to a UTF-8 encoded -string object. This is recommended development practice: define only -``__unicode__()`` and let Django take care of the conversion to string objects -when required. - -``get_absolute_url`` --------------------- - -.. method:: Model.get_absolute_url() - -Define a ``get_absolute_url()`` method to tell Django how to calculate the -URL for an object. For example:: - - def get_absolute_url(self): - return "/people/%i/" % self.id - -Django uses this in its admin interface. If an object defines -``get_absolute_url()``, the object-editing page will have a "View on site" -link that will jump you directly to the object's public view, according to -``get_absolute_url()``. - -Also, a couple of other bits of Django, such as the :doc:`syndication feed -framework </ref/contrib/syndication>`, use ``get_absolute_url()`` as a -convenience to reward people who've defined the method. - -It's good practice to use ``get_absolute_url()`` in templates, instead of -hard-coding your objects' URLs. For example, this template code is bad:: - - <a href="/people/{{ object.id }}/">{{ object.name }}</a> - -But this template code is good:: - - <a href="{{ object.get_absolute_url }}">{{ object.name }}</a> - -.. note:: - The string you return from ``get_absolute_url()`` must contain only ASCII - characters (required by the URI spec, `RFC 2396`_) that have been - URL-encoded, if necessary. Code and templates using ``get_absolute_url()`` - should be able to use the result directly without needing to do any - further processing. You may wish to use the - ``django.utils.encoding.iri_to_uri()`` function to help with this if you - are using unicode strings a lot. - -.. _RFC 2396: http://www.ietf.org/rfc/rfc2396.txt - -The ``permalink`` decorator -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The problem with the way we wrote ``get_absolute_url()`` above is that it -slightly violates the DRY principle: the URL for this object is defined both -in the URLconf file and in the model. - -You can further decouple your models from the URLconf using the ``permalink`` -decorator: - -.. function:: permalink() - -This decorator is passed the view function, a list of positional parameters and -(optionally) a dictionary of named parameters. Django then works out the correct -full URL path using the URLconf, substituting the parameters you have given into -the URL. For example, if your URLconf contained a line such as:: - - (r'^people/(\d+)/$', 'people.views.details'), - -...your model could have a ``get_absolute_url`` method that looked like this:: - - from django.db import models - - @models.permalink - def get_absolute_url(self): - return ('people.views.details', [str(self.id)]) - -Similarly, if you had a URLconf entry that looked like:: - - (r'/archive/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', archive_view) - -...you could reference this using ``permalink()`` as follows:: - - @models.permalink - def get_absolute_url(self): - return ('archive_view', (), { - 'year': self.created.year, - 'month': self.created.month, - 'day': self.created.day}) - -Notice that we specify an empty sequence for the second parameter in this case, -because we only want to pass keyword parameters, not positional ones. - -In this way, you're tying the model's absolute path to the view that is used -to display it, without repeating the URL information anywhere. You can still -use the ``get_absolute_url`` method in templates, as before. - -In some cases, such as the use of generic views or the re-use of -custom views for multiple models, specifying the view function may -confuse the reverse URL matcher (because multiple patterns point to -the same view). - -For that problem, Django has **named URL patterns**. Using a named -URL pattern, it's possible to give a name to a pattern, and then -reference the name rather than the view function. A named URL -pattern is defined by replacing the pattern tuple by a call to -the ``url`` function):: - - from django.conf.urls.defaults import * - - url(r'^people/(\d+)/$', - 'django.views.generic.list_detail.object_detail', - name='people_view'), - -...and then using that name to perform the reverse URL resolution instead -of the view name:: - - from django.db import models - - @models.permalink - def get_absolute_url(self): - return ('people_view', [str(self.id)]) - -More details on named URL patterns are in the :doc:`URL dispatch documentation -</topics/http/urls>`. - -Extra instance methods -====================== - -In addition to ``save()``, ``delete()``, a model object might get any or all -of the following methods: - -.. method:: Model.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' - -.. method:: Model.get_next_by_FOO(\**kwargs) -.. method:: Model.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 :ref:`Field lookups <field-lookups>`. - -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. diff --git a/parts/django/docs/ref/models/options.txt b/parts/django/docs/ref/models/options.txt deleted file mode 100644 index 1b04c46..0000000 --- a/parts/django/docs/ref/models/options.txt +++ /dev/null @@ -1,269 +0,0 @@ -====================== -Model ``Meta`` options -====================== - -This document explains all the possible :ref:`metadata options -<meta-options>` that you can give your model in its internal ``class -Meta``. - -Available ``Meta`` options -========================== - -.. currentmodule:: django.db.models - -``abstract`` ------------- - -.. attribute:: Options.abstract - -If ``True``, this model will be an :ref:`abstract base class <abstract-base-classes>`. - -``app_label`` -------------- - -.. attribute:: Options.app_label - -If a model exists outside of the standard :file:`models.py` (for instance, if -the app's models are in submodules of ``myapp.models``), the model must define -which app it is part of:: - - app_label = 'myapp' - -``db_table`` ------------- - -.. attribute:: Options.db_table - -The name of the database table to use for the model:: - - db_table = 'music_album' - -.. _table-names: - -Table names -~~~~~~~~~~~ - -To save you time, Django automatically derives the name of the database table -from the name of your model class and the app that contains it. A model's -database table name is constructed by joining the model's "app label" -- the -name you used in ``manage.py startapp`` -- to the model's class name, with an -underscore between them. - -For example, if you have an app ``bookstore`` (as created by -``manage.py startapp bookstore``), a model defined as ``class Book`` will have -a database table named ``bookstore_book``. - -To override the database table name, use the ``db_table`` parameter in -``class Meta``. - -If your database table 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_tablespace`` ------------------ - -.. attribute:: Options.db_tablespace - -.. versionadded:: 1.0 - -The name of the database tablespace to use for the model. If the backend doesn't -support tablespaces, this option is ignored. - -``get_latest_by`` ------------------ - -.. attribute:: Options.get_latest_by - -The name of a :class:`DateField` or :class:`DateTimeField` in the model. This -specifies the default field to use in your model :class:`Manager`'s -:class:`~QuerySet.latest` method. - -Example:: - - get_latest_by = "order_date" - -See the docs for :meth:`~django.db.models.QuerySet.latest` for more. - -``managed`` ------------------------ - -.. attribute:: Options.managed - -.. versionadded:: 1.1 - -Defaults to ``True``, meaning Django will create the appropriate database -tables in :djadmin:`syncdb` and remove them as part of a :djadmin:`reset` -management command. That is, Django *manages* the database tables' lifecycles. - -If ``False``, no database table creation or deletion operations will be -performed for this model. This is useful if the model represents an existing -table or a database view that has been created by some other means. This is -the *only* difference when ``managed`` is ``False``. All other aspects of -model handling are exactly the same as normal. This includes - - 1. Adding an automatic primary key field to the model if you don't declare - it. To avoid confusion for later code readers, it's recommended to - specify all the columns from the database table you are modeling when - using unmanaged models. - - 2. If a model with ``managed=False`` contains a - :class:`~django.db.models.ManyToManyField` that points to another - unmanaged model, then the intermediate table for the many-to-many join - will also not be created. However, a the intermediary table between one - managed and one unmanaged model *will* be created. - - If you need to change this default behavior, create the intermediary - table as an explicit model (with ``managed`` set as needed) and use the - :attr:`ManyToManyField.through` attribute to make the relation use your - custom model. - -For tests involving models with ``managed=False``, it's up to you to ensure -the correct tables are created as part of the test setup. - -If you're interested in changing the Python-level behavior of a model class, -you *could* use ``managed=False`` and create a copy of an existing model. -However, there's a better approach for that situation: :ref:`proxy-models`. - -``order_with_respect_to`` -------------------------- - -.. attribute:: Options.order_with_respect_to - -Marks this object as "orderable" with respect to the given field. This is almost -always used with related objects to allow them to be ordered with respect to a -parent object. For example, if an ``Answer`` relates to a ``Question`` object, -and a question has more than one answer, and the order of answers matters, you'd -do this:: - - class Answer(models.Model): - question = models.ForeignKey(Question) - # ... - - class Meta: - order_with_respect_to = 'question' - -When ``order_with_respect_to`` is set, two additional methods are provided to -retrieve and to set the order of the related objects: ``get_RELATED_order()`` -and ``set_RELATED_order()``, where ``RELATED`` is the lowercased model name. For -example, assuming that a ``Question`` object has multiple related ``Answer`` -objects, the list returned contains the primary keys of the related ``Answer`` -objects:: - - >>> question = Question.objects.get(id=1) - >>> question.get_answer_order() - [1, 2, 3] - -The order of a ``Question`` object's related ``Answer`` objects can be set by -passing in a list of ``Answer`` primary keys:: - - >>> question.set_answer_order([3, 1, 2]) - -The related objects also get two methods, ``get_next_in_order()`` and -``get_previous_in_order()``, which can be used to access those objects in their -proper order. Assuming the ``Answer`` objects are ordered by ``id``:: - - >>> answer = Answer.objects.get(id=2) - >>> answer.get_next_in_order() - <Answer: 3> - >>> answer.get_previous_in_order() - <Answer: 1> - -``ordering`` ------------- - -.. attribute:: Options.ordering - -The default ordering for the object, for use when obtaining lists of objects:: - - ordering = ['-order_date'] - -This is a tuple or list of strings. Each string is a field name with an optional -"-" prefix, which indicates descending order. Fields without a leading "-" will -be ordered ascending. Use the string "?" to order randomly. - -.. note:: - - Regardless of how many fields are in :attr:`~Options.ordering`, the admin - site uses only the first field. - -For example, to order by a ``pub_date`` field ascending, use this:: - - ordering = ['pub_date'] - -To order by ``pub_date`` descending, use this:: - - ordering = ['-pub_date'] - -To order by ``pub_date`` descending, then by ``author`` ascending, use this:: - - ordering = ['-pub_date', 'author'] - -``permissions`` ---------------- - -.. attribute:: Options.permissions - -Extra permissions to enter into the permissions table when creating this object. -Add, delete and change permissions are automatically created for each object -that has ``admin`` set. This example specifies an extra permission, -``can_deliver_pizzas``:: - - permissions = (("can_deliver_pizzas", "Can deliver pizzas"),) - -This is a list or tuple of 2-tuples in the format ``(permission_code, -human_readable_permission_name)``. - -``proxy`` ---------- - -.. attribute:: Options.proxy - -.. versionadded:: 1.1 - -If set to ``True``, a model which subclasses another model will be treated as -a :ref:`proxy model <proxy-models>`. - -``unique_together`` -------------------- - -.. attribute:: Options.unique_together - -Sets of field names that, taken together, must be unique:: - - unique_together = (("driver", "restaurant"),) - -This is a list of lists of fields that must be unique when considered together. -It's used in the Django admin and is enforced at the database level (i.e., the -appropriate ``UNIQUE`` statements are included in the ``CREATE TABLE`` -statement). - -.. versionadded:: 1.0 - -For convenience, unique_together can be a single list when dealing with a single -set of fields:: - - unique_together = ("driver", "restaurant") - -``verbose_name`` ----------------- - -.. attribute:: Options.verbose_name - -A human-readable name for the object, singular:: - - verbose_name = "pizza" - -If this isn't given, Django will use a munged version of the class name: -``CamelCase`` becomes ``camel case``. - -``verbose_name_plural`` ------------------------ - -.. attribute:: Options.verbose_name_plural - -The plural name for the object:: - - verbose_name_plural = "stories" - -If this isn't given, Django will use :attr:`~Options.verbose_name` + ``"s"``. diff --git a/parts/django/docs/ref/models/querysets.txt b/parts/django/docs/ref/models/querysets.txt deleted file mode 100644 index 9f0de1f..0000000 --- a/parts/django/docs/ref/models/querysets.txt +++ /dev/null @@ -1,1888 +0,0 @@ -====================== -QuerySet API reference -====================== - -.. currentmodule:: django.db.models.QuerySet - -This document describes the details of the ``QuerySet`` API. It builds on the -material presented in the :doc:`model </topics/db/models>` and :doc:`database -query </topics/db/queries>` guides, so you'll probably want to read and -understand those documents before reading this one. - -Throughout this reference we'll use the :ref:`example Weblog models -<queryset-model-example>` presented in the :doc:`database query guide -</topics/db/queries>`. - -.. _when-querysets-are-evaluated: - -When QuerySets are evaluated -============================ - -Internally, a ``QuerySet`` can be constructed, filtered, sliced, and generally -passed around without actually hitting the database. No database activity -actually occurs until you do something to evaluate the queryset. - -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 :ref:`limiting-querysets`, 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. - - * **Pickling/Caching.** See the following section for details of what - is involved when `pickling QuerySets`_. The important thing for the - purposes of this section is that the results are read from the database. - - * **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. - - * **bool().** Testing a ``QuerySet`` in a boolean context, such as using - ``bool()``, ``or``, ``and`` or an ``if`` statement, will cause the query - to be executed. If there is at least one result, the ``QuerySet`` is - ``True``, otherwise ``False``. For example:: - - if Entry.objects.filter(headline="Test"): - print "There is at least one Entry with the headline Test" - - Note: *Don't* use this if all you want to do is determine if at least one - result exists, and don't need the actual objects. It's more efficient to - use ``exists()`` (see below). - -.. _pickling QuerySets: - -Pickling QuerySets ------------------- - -If you pickle_ a ``QuerySet``, this will force all the results to be loaded -into memory prior to pickling. Pickling is usually used as a precursor to -caching and when the cached queryset is reloaded, you want the results to -already be present and ready for use (reading from the database can take some -time, defeating the purpose of caching). 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'. - -The ``query`` attribute is an opaque object. It represents the internals of -the query construction and is not part of the public API. However, it is safe -(and fully supported) to pickle and unpickle the attribute's contents as -described here. - -.. admonition:: You can't share pickles between versions - - Pickles of QuerySets are only valid for the version of Django that - was used to generate them. If you generate a pickle using Django - version N, there is no guarantee that pickle will be readable with - Django version N+1. Pickles should not be used as part of a long-term - archival strategy. - -.. _pickle: http://docs.python.org/library/pickle.html - -.. _queryset-api: - -QuerySet API -============ - -Though you usually won't create one manually -- you'll go through a -:class:`Manager` -- here's the formal declaration of a ``QuerySet``: - -.. class:: QuerySet([model=None]) - -Usually when you'll interact with a ``QuerySet`` you'll use it by :ref:`chaining -filters <chaining-filters>`. To make this work, most ``QuerySet`` methods return new querysets. - -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 -~~~~~~ - -.. method:: 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 -~~~~~~~ - -.. method:: 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. - -annotate -~~~~~~~~ - -.. method:: annotate(*args, **kwargs) - -.. versionadded:: 1.1 - -Annotates each object in the ``QuerySet`` with the provided list of -aggregate values (averages, sums, etc) that have been computed over -the objects that are related to the objects in the ``QuerySet``. -Each argument to ``annotate()`` is an annotation that will be added -to each object in the ``QuerySet`` that is returned. - -The aggregation functions that are provided by Django are described -in `Aggregation Functions`_ below. - -Annotations specified using keyword arguments will use the keyword as -the alias for the annotation. Anonymous arguments will have an alias -generated for them based upon the name of the aggregate function and -the model field that is being aggregated. - -For example, if you were manipulating a list of blogs, you may want -to determine how many entries have been made in each blog:: - - >>> q = Blog.objects.annotate(Count('entry')) - # The name of the first blog - >>> q[0].name - 'Blogasaurus' - # The number of entries on the first blog - >>> q[0].entry__count - 42 - -The ``Blog`` model doesn't define an ``entry__count`` attribute by itself, -but by using a keyword argument to specify the aggregate function, you can -control the name of the annotation:: - - >>> q = Blog.objects.annotate(number_of_entries=Count('entry')) - # The number of entries on the first blog, using the name provided - >>> q[0].number_of_entries - 42 - -For an in-depth discussion of aggregation, see :doc:`the topic guide on -Aggregation </topics/db/aggregation>`. - -order_by -~~~~~~~~ - -.. method:: 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 :meth:`distinct` 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. - -.. versionadded:: 1.0 - -The syntax for ordering across related models has changed. See the `Django 0.96 -documentation`_ for the old behaviour. - -.. _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. - -If you don't want any ordering to be applied to a query, not even the default -ordering, call ``order_by()`` with no parameters. - -.. versionadded:: 1.1 - -You can tell if a query is ordered or not by checking the -:attr:`QuerySet.ordered` attribute, which will be ``True`` if the -``QuerySet`` has been ordered in any way. - -reverse -~~~~~~~ - -.. method:: reverse() - -.. versionadded:: 1.0 - -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 -~~~~~~~~ - -.. method:: 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 :meth:`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 -~~~~~~ - -.. method:: values(*fields) - -Returns a ``ValuesQuerySet`` -- a ``QuerySet`` that returns dictionaries when -used as an iterable, rather than 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') - [<Blog: 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'}] - -A couple of subtleties that are worth mentioning: - - * The ``values()`` method does not return anything for - :class:`~django.db.models.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 - :class:`~django.db.models.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 :meth:`distinct` for - details. - - * If you use a ``values()`` clause after an ``extra()`` clause, - any fields defined by a ``select`` argument in the ``extra()`` - must be explicitly included in the ``values()`` clause. However, - if the ``extra()`` clause is used after the ``values()``, the - fields added by the select will be included automatically. - -.. versionadded:: 1.0 - -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 -~~~~~~~~~~~ - -.. method:: values_list(*fields) - -.. versionadded:: 1.0 - -This is similar to ``values()`` except that instead of returning dictionaries, -it returns tuples when iterated over. 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 -~~~~~ - -.. method:: 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 -~~~~ - -.. method:: none() - -.. versionadded:: 1.0 - -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 -~~~ - -.. method:: all() - -.. versionadded:: 1.0 - -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: - -select_related -~~~~~~~~~~~~~~ - -.. method:: 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. - -Sometimes you only want 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 you 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 you only needed to work with the ``room`` and ``subject`` attributes, -you 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 refer to any ``ForeignKey`` or ``OneToOneField`` relation in -the list of fields passed to ``select_related``. Ths includes 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. - -.. versionadded:: 1.0 - -Both the ``depth`` argument and the ability to specify field names in the call -to ``select_related()`` are new in Django version 1.0. - -.. versionchanged:: 1.2 - -You can also refer to the reverse direction of a ``OneToOneFields`` in -the list of fields passed to ``select_related`` -- that is, you can traverse -a ``OneToOneField`` back to the object on which the field is defined. Instead -of specifying the field name, use the ``related_name`` for the field on the -related object. - -``OneToOneFields`` will not be traversed in the reverse direction if you -are performing a depth-based ``select_related``. - -extra -~~~~~ - -.. method:: 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 something - like:: - - SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent - 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) AS entry_count - 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. - - .. versionadded:: 1.0 - - 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']) - -defer -~~~~~ - -.. method:: defer(*fields) - -.. versionadded:: 1.1 - -In some complex data-modeling situations, your models might contain a lot of -fields, some of which could contain a lot of data (for example, text fields), -or require expensive processing to convert them to Python objects. If you are -using the results of a queryset in some situation where you know you don't -need those particular fields, you can tell Django not to retrieve them from -the database. - -This is done by passing the names of the fields to not load to ``defer()``:: - - Entry.objects.defer("headline", "body") - -A queryset that has deferred fields will still return model instances. Each -deferred field will be retrieved from the database if you access that field -(one at a time, not all the deferred fields at once). - -You can make multiple calls to ``defer()``. Each call adds new fields to the -deferred set:: - - # Defers both the body and headline fields. - Entry.objects.defer("body").filter(rating=5).defer("headline") - -The order in which fields are added to the deferred set does not matter. -Calling ``defer()`` with a field name that has already been deferred is -harmless (the field will still be deferred). - -You can defer loading of fields in related models (if the related models are -loading via ``select_related()``) by using the standard double-underscore -notation to separate related fields:: - - Blog.objects.select_related().defer("entry__headline", "entry__body") - -If you want to clear the set of deferred fields, pass ``None`` as a parameter -to ``defer()``:: - - # Load all fields immediately. - my_queryset.defer(None) - -Some fields in a model won't be deferred, even if you ask for them. You can -never defer the loading of the primary key. If you are using -``select_related()`` to retrieve other models at the same time you shouldn't -defer the loading of the field that connects from the primary model to the -related one (at the moment, that doesn't raise an error, but it will -eventually). - -.. note:: - - The ``defer()`` method (and its cousin, ``only()``, below) are only for - advanced use-cases. They provide an optimization for when you have - analyzed your queries closely and understand *exactly* what information - you need and have measured that the difference between returning the - fields you need and the full set of fields for the model will be - significant. When you are initially developing your applications, don't - bother using ``defer()``; leave it until your query construction has - settled down and you understand where the hot-points are. - -only -~~~~ - -.. method:: only(*fields) - -.. versionadded:: 1.1 - -The ``only()`` method is more or less the opposite of ``defer()``. You -call it with the fields that should *not* be deferred when retrieving a model. -If you have a model where almost all the fields need to be deferred, using -``only()`` to specify the complementary set of fields could result in simpler -code. - -If you have a model with fields ``name``, ``age`` and ``biography``, the -following two querysets are the same, in terms of deferred fields:: - - Person.objects.defer("age", "biography") - Person.objects.only("name") - -Whenever you call ``only()`` it *replaces* the set of fields to load -immediately. The method's name is mnemonic: **only** those fields are loaded -immediately; the remainder are deferred. Thus, successive calls to ``only()`` -result in only the final fields being considered:: - - # This will defer all fields except the headline. - Entry.objects.only("body", "rating").only("headline") - -Since ``defer()`` acts incrementally (adding fields to the deferred list), you -can combine calls to ``only()`` and ``defer()`` and things will behave -logically:: - - # Final result is that everything except "headline" is deferred. - Entry.objects.only("headline", "body").defer("body") - - # Final result loads headline and body immediately (only() replaces any - # existing set of fields). - Entry.objects.defer("body").only("headline", "body") - -using -~~~~~ - -.. method:: using(alias) - -.. versionadded:: 1.2 - -This method is for controlling which database the ``QuerySet`` will be -evaluated against if you are using more than one database. The only argument -this method takes is the alias of a database, as defined in -:setting:`DATABASES`. - -For example:: - - # queries the database with the 'default' alias. - >>> Entry.objects.all() - - # queries the database with the 'backup' alias - >>> Entry.objects.using('backup') - - -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 :ref:`caching-and-querysets`). Rather, -they query the database each time they're called. - -get -~~~ - -.. method:: 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. - -``get()`` raises a ``DoesNotExist`` exception if an object wasn't found for -the given parameters. This exception is also 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 -~~~~~~ - -.. method:: 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(force_insert=True) - -are equivalent. - -The :ref:`force_insert <ref-models-force-insert>` parameter is documented -elsewhere, but all it means is that a new object will always be created. -Normally you won't need to worry about this. However, if your model contains a -manual primary key value that you set and if that value already exists in the -database, a call to ``create()`` will fail with an :exc:`IntegrityError` since -primary keys must be unique. So remember to be prepared to handle the exception -if you are using manual primary keys. - -get_or_create -~~~~~~~~~~~~~ - -.. method:: 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 roughly 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. As hinted at -above, this is a simplification of the algorithm that is used, but it contains -all the pertinent details. The internal implementation has some more -error-checking than this and handles some extra edge-conditions; if you're -interested, read the code. - -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'}) - - -The ``get_or_create()`` method has similar error behaviour to ``create()`` -when you are using manually specified primary keys. If an object needs to be -created and the key already exists in the database, an ``IntegrityError`` will -be raised. - -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 -~~~~~ - -.. method:: 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 (unless you need to load the -objects into memory anyway, in which case ``len()`` will be faster). - -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 -~~~~~~~ - -.. method:: 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: <Blog: Beatles Blog>} - >>> Blog.objects.in_bulk([1, 2]) - {1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>} - >>> Blog.objects.in_bulk([]) - {} - -If you pass ``in_bulk()`` an empty list, you'll get an empty dictionary. - -iterator -~~~~~~~~ - -.. method:: iterator() - -Evaluates the ``QuerySet`` (by performing the query) and returns an -`iterator`_ over the results. A ``QuerySet`` typically caches its -results internally so that repeated evaluations do not result in -additional queries; ``iterator()`` will instead read results directly, -without doing any caching at the ``QuerySet`` level. For a -``QuerySet`` which returns a large number of objects, this often -results in better performance and a significant reduction in memory - -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 -~~~~~~ - -.. method:: 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. - -aggregate -~~~~~~~~~ - -.. method:: aggregate(*args, **kwargs) - -.. versionadded:: 1.1 - -Returns a dictionary of aggregate values (averages, sums, etc) calculated -over the ``QuerySet``. Each argument to ``aggregate()`` specifies -a value that will be included in the dictionary that is returned. - -The aggregation functions that are provided by Django are described -in `Aggregation Functions`_ below. - -Aggregates specified using keyword arguments will use the keyword as -the name for the annotation. Anonymous arguments will have an name -generated for them based upon the name of the aggregate function and -the model field that is being aggregated. - -For example, if you were manipulating blog entries, you may want to know -the number of authors that have contributed blog entries:: - - >>> q = Blog.objects.aggregate(Count('entry')) - {'entry__count': 16} - -By using a keyword argument to specify the aggregate function, you can -control the name of the aggregation value that is returned:: - - >>> q = Blog.objects.aggregate(number_of_entries=Count('entry')) - {'number_of_entries': 16} - -For an in-depth discussion of aggregation, see :doc:`the topic guide on -Aggregation </topics/db/aggregation>`. - -exists -~~~~~~ - -.. method:: exists() - -.. versionadded:: 1.2 - -Returns ``True`` if the :class:`QuerySet` contains any results, and ``False`` -if not. This tries to perform the query in the simplest and fastest way -possible, but it *does* execute nearly the same query. This means that calling -:meth:`QuerySet.exists()` is faster than ``bool(some_query_set)``, but not by -a large degree. If ``some_query_set`` has not yet been evaluated, but you know -that it will be at some point, then using ``some_query_set.exists()`` will do -more overall work (an additional query) than simply using -``bool(some_query_set)``. - -update -~~~~~~ - -.. method:: update(**kwargs) - -Performs an SQL update query for the specified fields, and returns -the number of rows affected. The ``update()`` method is applied instantly and -the only restriction on the :class:`QuerySet` that is updated is that it can -only update columns in the model's main table. Filtering based on related -fields is still possible. You cannot call ``update()`` on a -:class:`QuerySet` that has had a slice taken or can otherwise no longer be -filtered. - -For example, if you wanted to update all the entries in a particular blog -to use the same headline:: - - >>> b = Blog.objects.get(pk=1) - - # Update all the headlines belonging to this Blog. - >>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same') - -The ``update()`` method does a bulk update and does not call any ``save()`` -methods on your models, nor does it emit the ``pre_save`` or ``post_save`` -signals (which are a consequence of calling ``save()``). - -delete -~~~~~~ - -.. method:: delete() - -Performs an SQL delete query on all rows in the :class:`QuerySet`. The -``delete()`` is applied instantly. You cannot call ``delete()`` on a -:class:`QuerySet` that has had a slice taken or can otherwise no longer be -filtered. - -For example, to delete all the entries in a particular blog:: - - >>> b = Blog.objects.get(pk=1) - - # Delete all the entries belonging to this Blog. - >>> Entry.objects.filter(blog=b).delete() - -Django emulates the SQL constraint ``ON DELETE CASCADE`` -- in other words, any -objects with foreign keys pointing at the objects to be deleted will be deleted -along with them. For example:: - - blogs = Blog.objects.all() - # This will delete all Blogs and all of their Entry objects. - blogs.delete() - -The ``delete()`` method does a bulk delete and does not call any ``delete()`` -methods on your models. It does, however, emit the -:data:`~django.db.models.signals.pre_delete` and -:data:`~django.db.models.signals.post_delete` signals for all deleted objects -(including cascaded deletions). - -.. _field-lookups: - -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()``. - -For an introduction, see :ref:`field-lookups-intro`. - -.. fieldlookup:: exact - -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; - -.. versionchanged:: 1.0 - The semantics of ``id__exact=None`` have changed in Django 1.0. 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, a database table's "collation" setting determines whether - ``exact`` comparisons are case-sensitive. This is a database setting, *not* - a Django setting. It's possible to configure your MySQL tables to use - case-sensitive comparisons, but some trade-offs are involved. For more - information about this, see the :ref:`collation section <mysql-collation>` - in the :doc:`databases </ref/databases>` documentation. - -.. fieldlookup:: iexact - -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. - -.. admonition:: SQLite users - - When using the SQLite backend and Unicode (non-ASCII) strings, bear in - mind the :ref:`database note <sqlite-string-matching>` about string - comparisons. SQLite does not do case-insensitive matching for Unicode - strings. - -.. fieldlookup:: contains - -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. - -.. fieldlookup:: icontains - -icontains -~~~~~~~~~ - -Case-insensitive containment test. - -Example:: - - Entry.objects.get(headline__icontains='Lennon') - -SQL equivalent:: - - SELECT ... WHERE headline ILIKE '%Lennon%'; - -.. admonition:: SQLite users - - When using the SQLite backend and Unicode (non-ASCII) strings, bear in - mind the :ref:`database note <sqlite-string-matching>` about string - comparisons. - -.. fieldlookup:: in - -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:: - - inner_qs = Blog.objects.filter(name__contains='Cheddar') - entries = Entry.objects.filter(blog__in=inner_qs) - -This queryset will be evaluated as subselect statement:: - - SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%') - -The above code fragment could also be written as follows:: - - inner_q = Blog.objects.filter(name__contains='Cheddar').values('pk').query - entries = Entry.objects.filter(blog__in=inner_q) - - -.. versionchanged:: 1.1 - In Django 1.0, only the latter piece of code is valid. - -This second form is a bit less readable and unnatural to write, since it -accesses the internal ``query`` attribute and requires a ``ValuesQuerySet``. -If your code doesn't require compatibility with Django 1.0, use the first -form, passing in a queryset directly. - -If you pass in a ``ValuesQuerySet`` or ``ValuesListQuerySet`` (the result of -calling ``values()`` or ``values_list()`` on a queryset) as the value to an -``__in`` lookup, you need to ensure you are only extracting one field in the -result. For example, this will work (filtering on the blog names):: - - inner_qs = Blog.objects.filter(name__contains='Ch').values('name') - entries = Entry.objects.filter(blog__name__in=inner_qs) - -This example will raise an exception, since the inner query is trying to -extract two field values, where only one is expected:: - - # Bad code! Will raise a TypeError. - inner_qs = Blog.objects.filter(name__contains='Ch').values('name', 'id') - entries = Entry.objects.filter(blog__name__in=inner_qs) - -.. warning:: - - This ``query`` attribute should be considered an opaque internal attribute. - It's fine to use it like above, but its API may change between Django - versions. - -.. admonition:: Performance considerations - - Be cautious about using nested queries and understand your database - server's performance characteristics (if in doubt, benchmark!). Some - database backends, most notably MySQL, don't optimize nested queries very - well. It is more efficient, in those cases, to extract a list of values - and then pass that into the second query. That is, execute two queries - instead of one:: - - values = Blog.objects.filter( - name__contains='Cheddar').values_list('pk', flat=True) - entries = Entry.objects.filter(blog__in=list(values)) - - Note the ``list()`` call around the Blog ``QuerySet`` to force execution of - the first query. Without it, a nested query would be executed, because - :ref:`querysets-are-lazy`. - -.. fieldlookup:: gt - -gt -~~ - -Greater than. - -Example:: - - Entry.objects.filter(id__gt=4) - -SQL equivalent:: - - SELECT ... WHERE id > 4; - -.. fieldlookup:: gte - -gte -~~~ - -Greater than or equal to. - -.. fieldlookup:: lt - -lt -~~ - -Less than. - -.. fieldlookup:: lte - -lte -~~~ - -Less than or equal to. - -.. fieldlookup:: startswith - -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. - -.. fieldlookup:: istartswith - -istartswith -~~~~~~~~~~~ - -Case-insensitive starts-with. - -Example:: - - Entry.objects.filter(headline__istartswith='will') - -SQL equivalent:: - - SELECT ... WHERE headline ILIKE 'Will%'; - -.. admonition:: SQLite users - - When using the SQLite backend and Unicode (non-ASCII) strings, bear in - mind the :ref:`database note <sqlite-string-matching>` about string - comparisons. - -.. fieldlookup:: endswith - -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. - -.. fieldlookup:: iendswith - -iendswith -~~~~~~~~~ - -Case-insensitive ends-with. - -Example:: - - Entry.objects.filter(headline__iendswith='will') - -SQL equivalent:: - - SELECT ... WHERE headline ILIKE '%will' - -.. admonition:: SQLite users - - When using the SQLite backend and Unicode (non-ASCII) strings, bear in - mind the :ref:`database note <sqlite-string-matching>` about string - comparisons. - -.. fieldlookup:: range - -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. - -.. fieldlookup:: year - -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.) - -.. fieldlookup:: month - -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.) - -.. fieldlookup:: day - -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. - -.. fieldlookup:: week_day - -week_day -~~~~~~~~ - -.. versionadded:: 1.1 - -For date/datetime fields, a 'day of the week' match. - -Takes an integer value representing the day of week from 1 (Sunday) to 7 -(Saturday). - -Example:: - - Entry.objects.filter(pub_date__week_day=2) - -(No equivalent SQL code fragment is included for this lookup because -implementation of the relevant query varies among different database engines.) - -Note this will match any record with a pub_date that falls on a Monday (day 2 -of the week), regardless of the month or year in which it occurs. Week days -are indexed with day 1 being Sunday and day 7 being Saturday. - -.. fieldlookup:: isnull - -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; - -.. fieldlookup:: search - -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. - -Example:: - - Entry.objects.filter(headline__search="+Django -jazz Python") - -SQL equivalent:: - - SELECT ... WHERE MATCH(tablename, headline) AGAINST (+Django -jazz Python IN BOOLEAN MODE); - -Note this is only available in MySQL and requires direct manipulation of the -database to add the full-text index. By default Django uses BOOLEAN MODE for -full text searches. `See the MySQL documentation for additional details. -<http://dev.mysql.com/doc/refman/5.1/en/fulltext-boolean.html>`_ - - -.. fieldlookup:: regex - -regex -~~~~~ - -.. versionadded:: 1.0 - -Case-sensitive regular expression match. - -The regular expression syntax is that of the database backend in use. -In the case of SQLite, which has no built in regular expression support, -this feature is provided by a (Python) user-defined REGEXP function, and -the regular expression syntax is therefore 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. - -.. fieldlookup:: iregex - -iregex -~~~~~~ - -.. versionadded:: 1.0 - -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 - -.. _aggregation-functions: - -Aggregation Functions ---------------------- - -.. versionadded:: 1.1 - -Django provides the following aggregation functions in the -``django.db.models`` module. For details on how to use these -aggregate functions, see -:doc:`the topic guide on aggregation </topics/db/aggregation>`. - -Avg -~~~ - -.. class:: Avg(field) - -Returns the mean value of the given field. - - * Default alias: ``<field>__avg`` - * Return type: float - -Count -~~~~~ - -.. class:: Count(field, distinct=False) - -Returns the number of objects that are related through the provided field. - - * Default alias: ``<field>__count`` - * Return type: integer - -Has one optional argument: - -.. attribute:: distinct - - If distinct=True, the count will only include unique instances. This has - the SQL equivalent of ``COUNT(DISTINCT field)``. Default value is ``False``. - -Max -~~~ - -.. class:: Max(field) - -Returns the maximum value of the given field. - - * Default alias: ``<field>__max`` - * Return type: same as input field - -Min -~~~ - -.. class:: Min(field) - -Returns the minimum value of the given field. - - * Default alias: ``<field>__min`` - * Return type: same as input field - -StdDev -~~~~~~ - -.. class:: StdDev(field, sample=False) - -Returns the standard deviation of the data in the provided field. - - * Default alias: ``<field>__stddev`` - * Return type: float - -Has one optional argument: - -.. attribute:: sample - - By default, ``StdDev`` returns the population standard deviation. However, - if ``sample=True``, the return value will be the sample standard deviation. - -.. admonition:: SQLite - - SQLite doesn't provide ``StdDev`` out of the box. An implementation is - available as an extension module for SQLite. Consult the SQlite - documentation for instructions on obtaining and installing this extension. - -Sum -~~~ - -.. class:: Sum(field) - -Computes the sum of all values of the given field. - - * Default alias: ``<field>__sum`` - * Return type: same as input field - -Variance -~~~~~~~~ - -.. class:: Variance(field, sample=False) - -Returns the variance of the data in the provided field. - - * Default alias: ``<field>__variance`` - * Return type: float - -Has one optional argument: - -.. attribute:: sample - - By default, ``Variance`` returns the population variance. However, - if ``sample=True``, the return value will be the sample variance. - -.. admonition:: SQLite - - SQLite doesn't provide ``Variance`` out of the box. An implementation is - available as an extension module for SQLite. Consult the SQlite - documentation for instructions on obtaining and installing this extension. diff --git a/parts/django/docs/ref/models/relations.txt b/parts/django/docs/ref/models/relations.txt deleted file mode 100644 index ee6bcdd..0000000 --- a/parts/django/docs/ref/models/relations.txt +++ /dev/null @@ -1,105 +0,0 @@ -========================= -Related objects reference -========================= - -.. currentmodule:: django.db.models.fields.related - -.. class:: RelatedManager - - A "related manager" is a manager used in a one-to-many or many-to-many - related context. This happens in two cases: - - * The "other side" of a :class:`~django.db.models.ForeignKey` relation. - That is:: - - class Reporter(models.Model): - ... - - class Article(models.Model): - reporter = models.ForeignKey(Reporter) - - In the above example, the methods below will be available on - the manager ``reporter.article_set``. - - * Both sides of a :class:`~django.db.models.ManyToManyField` relation:: - - class Topping(models.Model): - ... - - class Pizza(models.Model): - toppings = models.ManyToManyField(Topping) - - In this example, the methods below will be available both on - ``topping.pizza_set`` and on ``pizza.toppings``. - - These related managers have some extra methods: - - .. method:: 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. - - .. method:: create(**kwargs) - - Creates a new object, saves it and puts it in the related object set. - Returns the newly created object:: - - >>> 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(force_insert=True) - - 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``. - - .. method:: remove(obj1, [obj2, ...]) - - Removes the specified model objects from the related object set:: - - >>> 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 - :class:`~django.db.models.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`` - :class:`~django.db.models.ForeignKey` doesn't have ``null=True``, this - is invalid. - - .. method:: clear() - - Removes all objects from the related object set:: - - >>> 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 - :class:`~django.db.models.ForeignKey`\s where ``null=True``. diff --git a/parts/django/docs/ref/request-response.txt b/parts/django/docs/ref/request-response.txt deleted file mode 100644 index c663c1e..0000000 --- a/parts/django/docs/ref/request-response.txt +++ /dev/null @@ -1,646 +0,0 @@ -============================ -Request and response objects -============================ - -.. module:: django.http - :synopsis: Classes dealing with HTTP requests and responses. - -Quick overview -============== - -Django uses request and response objects to pass state through the system. - -When a page is requested, Django creates an :class:`HttpRequest` object that -contains metadata about the request. Then Django loads the appropriate view, -passing the :class:`HttpRequest` as the first argument to the view function. -Each view is responsible for returning an :class:`HttpResponse` object. - -This document explains the APIs for :class:`HttpRequest` and -:class:`HttpResponse` objects. - -HttpRequest objects -=================== - -.. class:: HttpRequest - -Attributes ----------- - -All attributes except ``session`` should be considered read-only. - -.. attribute:: HttpRequest.path - - A string representing the full path to the requested page, not including - the domain. - - Example: ``"/music/bands/the_beatles/"`` - -.. attribute:: HttpRequest.path_info - - Under some web server configurations, the portion of the URL after the host - name is split up into a script prefix portion and a path info portion - (this happens, for example, when using the ``django.root`` option - with the :ref:`modpython handler from Apache <howto-deployment-modpython>`). - The ``path_info`` attribute always contains the path info portion of the - path, no matter what web server is being used. Using this instead of - attr:`~HttpRequest.path` can make your code much easier to move between test - and deployment servers. - - For example, if the ``django.root`` for your application is set to - ``"/minfo"``, then ``path`` might be ``"/minfo/music/bands/the_beatles/"`` - and ``path_info`` would be ``"/music/bands/the_beatles/"``. - -.. attribute:: HttpRequest.method - - A string representing the HTTP method used in the request. This is - guaranteed to be uppercase. Example:: - - if request.method == 'GET': - do_something() - elif request.method == 'POST': - do_something_else() - -.. attribute:: HttpRequest.encoding - - A string representing the current encoding used to decode form submission - data (or ``None``, which means the :setting:`DEFAULT_CHARSET` setting is - used). You can write to this attribute to change the encoding used when - accessing the form data. Any subsequent attribute accesses (such as reading - from ``GET`` or ``POST``) will use the new ``encoding`` value. Useful if - you know the form data is not in the :setting:`DEFAULT_CHARSET` encoding. - -.. attribute:: HttpRequest.GET - - A dictionary-like object containing all given HTTP GET parameters. See the - :class:`QueryDict` documentation below. - -.. attribute:: HttpRequest.POST - - A dictionary-like object containing all given HTTP POST parameters. See the - :class:`QueryDict` documentation below. - - It's possible that a request can come in via POST with an empty ``POST`` - dictionary -- if, say, a form is requested via the POST HTTP method but - does not include form data. Therefore, you shouldn't use ``if request.POST`` - to check for use of the POST method; instead, use ``if request.method == - "POST"`` (see above). - - Note: ``POST`` does *not* include file-upload information. See ``FILES``. - -.. attribute:: HttpRequest.REQUEST - - For convenience, a dictionary-like object that searches ``POST`` first, - then ``GET``. Inspired by PHP's ``$_REQUEST``. - - For example, if ``GET = {"name": "john"}`` and ``POST = {"age": '34'}``, - ``REQUEST["name"]`` would be ``"john"``, and ``REQUEST["age"]`` would be - ``"34"``. - - It's strongly suggested that you use ``GET`` and ``POST`` instead of - ``REQUEST``, because the former are more explicit. - -.. attribute:: HttpRequest.COOKIES - - A standard Python dictionary containing all cookies. Keys and values are - strings. - -.. attribute:: HttpRequest.FILES - - A dictionary-like object containing all uploaded files. Each key in - ``FILES`` is the ``name`` from the ``<input type="file" name="" />``. Each - value in ``FILES`` is an :class:`UploadedFile` as described below. - - See :doc:`/topics/files` for more information. - - Note that ``FILES`` will only contain data if the request method was POST - and the ``<form>`` that posted to the request had - ``enctype="multipart/form-data"``. Otherwise, ``FILES`` will be a blank - dictionary-like object. - - .. versionchanged:: 1.0 - - In previous versions of Django, ``request.FILES`` contained simple ``dict`` - objects representing uploaded files. This is no longer true -- files are - represented by :class:`UploadedFile` objects. - - These :class:`UploadedFile` objects will emulate the old-style ``dict`` - interface, but this is deprecated and will be removed in the next release - of Django. - -.. attribute:: HttpRequest.META - - A standard Python dictionary containing all available HTTP headers. - Available headers depend on the client and server, but here are some - examples: - - * ``CONTENT_LENGTH`` - * ``CONTENT_TYPE`` - * ``HTTP_ACCEPT_ENCODING`` - * ``HTTP_ACCEPT_LANGUAGE`` - * ``HTTP_HOST`` -- The HTTP Host header sent by the client. - * ``HTTP_REFERER`` -- The referring page, if any. - * ``HTTP_USER_AGENT`` -- The client's user-agent string. - * ``QUERY_STRING`` -- The query string, as a single (unparsed) string. - * ``REMOTE_ADDR`` -- The IP address of the client. - * ``REMOTE_HOST`` -- The hostname of the client. - * ``REMOTE_USER`` -- The user authenticated by the Web server, if any. - * ``REQUEST_METHOD`` -- A string such as ``"GET"`` or ``"POST"``. - * ``SERVER_NAME`` -- The hostname of the server. - * ``SERVER_PORT`` -- The port of the server. - - With the exception of ``CONTENT_LENGTH`` and ``CONTENT_TYPE``, as given - above, any HTTP headers in the request are converted to ``META`` keys by - converting all characters to uppercase, replacing any hyphens with - underscores and adding an ``HTTP_`` prefix to the name. So, for example, a - header called ``X-Bender`` would be mapped to the ``META`` key - ``HTTP_X_BENDER``. - -.. attribute:: HttpRequest.user - - A ``django.contrib.auth.models.User`` object representing the currently - logged-in user. If the user isn't currently logged in, ``user`` will be set - to an instance of ``django.contrib.auth.models.AnonymousUser``. You - can tell them apart with ``is_authenticated()``, like so:: - - if request.user.is_authenticated(): - # Do something for logged-in users. - else: - # Do something for anonymous users. - - ``user`` is only available if your Django installation has the - ``AuthenticationMiddleware`` activated. For more, see - :doc:`/topics/auth`. - -.. attribute:: HttpRequest.session - - A readable-and-writable, dictionary-like object that represents the current - session. This is only available if your Django installation has session - support activated. See the :doc:`session documentation - </topics/http/sessions>` for full details. - -.. attribute:: HttpRequest.raw_post_data - - The raw HTTP POST data. This is only useful for advanced processing. Use - ``POST`` instead. - -.. attribute:: HttpRequest.urlconf - - Not defined by Django itself, but will be read if other code (e.g., a custom - middleware class) sets it. When present, this will be used as the root - URLconf for the current request, overriding the :setting:`ROOT_URLCONF` - setting. See :ref:`how-django-processes-a-request` for details. - -Methods -------- - -.. method:: HttpRequest.get_host() - - Returns the originating host of the request using information from the - ``HTTP_X_FORWARDED_HOST`` and ``HTTP_HOST`` headers (in that order). If - they don't provide a value, the method uses a combination of - ``SERVER_NAME`` and ``SERVER_PORT`` as detailed in `PEP 333`_. - - .. _PEP 333: http://www.python.org/dev/peps/pep-0333/ - - Example: ``"127.0.0.1:8000"`` - - .. note:: The :meth:`~HttpRequest.get_host()` method fails when the host is - behind multiple proxies. One solution is to use middleware to rewrite - the proxy headers, as in the following example:: - - class MultipleProxyMiddleware(object): - FORWARDED_FOR_FIELDS = [ - 'HTTP_X_FORWARDED_FOR', - 'HTTP_X_FORWARDED_HOST', - 'HTTP_X_FORWARDED_SERVER', - ] - - def process_request(self, request): - """ - Rewrites the proxy headers so that only the most - recent proxy is used. - """ - for field in self.FORWARDED_FOR_FIELDS: - if field in request.META: - if ',' in request.META[field]: - parts = request.META[field].split(',') - request.META[field] = parts[-1].strip() - - -.. method:: HttpRequest.get_full_path() - - Returns the ``path``, plus an appended query string, if applicable. - - Example: ``"/music/bands/the_beatles/?print=true"`` - -.. method:: HttpRequest.build_absolute_uri(location) - - Returns the absolute URI form of ``location``. If no location is provided, - the location will be set to ``request.get_full_path()``. - - If the location is already an absolute URI, it will not be altered. - Otherwise the absolute URI is built using the server variables available in - this request. - - Example: ``"http://example.com/music/bands/the_beatles/?print=true"`` - -.. method:: HttpRequest.is_secure() - - Returns ``True`` if the request is secure; that is, if it was made with - HTTPS. - -.. method:: HttpRequest.is_ajax() - - Returns ``True`` if the request was made via an ``XMLHttpRequest``, by - checking the ``HTTP_X_REQUESTED_WITH`` header for the string - ``'XMLHttpRequest'``. Most modern JavaScript libraries send this header. - If you write your own XMLHttpRequest call (on the browser side), you'll - have to set this header manually if you want ``is_ajax()`` to work. - - -UploadedFile objects -==================== - -.. class:: UploadedFile - - -Attributes ----------- - -.. attribute:: UploadedFile.name - - The name of the uploaded file. - -.. attribute:: UploadedFile.size - - The size, in bytes, of the uploaded file. - -Methods ----------- - -.. method:: UploadedFile.chunks(chunk_size=None) - - Returns a generator that yields sequential chunks of data. - -.. method:: UploadedFile.read(num_bytes=None) - - Read a number of bytes from the file. - - - -QueryDict objects -================= - -.. class:: QueryDict - -In an :class:`HttpRequest` object, the ``GET`` and ``POST`` attributes are instances -of ``django.http.QueryDict``. :class:`QueryDict` is a dictionary-like -class customized to deal with multiple values for the same key. This is -necessary because some HTML form elements, notably -``<select multiple="multiple">``, pass multiple values for the same key. - -``QueryDict`` instances are immutable, unless you create a ``copy()`` of them. -That means you can't change attributes of ``request.POST`` and ``request.GET`` -directly. - -Methods -------- - -:class:`QueryDict` implements all the standard dictionary methods, because it's -a subclass of dictionary. Exceptions are outlined here: - -.. method:: QueryDict.__getitem__(key) - - Returns the value for the given key. If the key has more than one value, - ``__getitem__()`` returns the last value. Raises - ``django.utils.datastructures.MultiValueDictKeyError`` if the key does not - exist. (This is a subclass of Python's standard ``KeyError``, so you can - stick to catching ``KeyError``.) - -.. method:: QueryDict.__setitem__(key, value) - - Sets the given key to ``[value]`` (a Python list whose single element is - ``value``). Note that this, as other dictionary functions that have side - effects, can only be called on a mutable ``QueryDict`` (one that was created - via ``copy()``). - -.. method:: QueryDict.__contains__(key) - - Returns ``True`` if the given key is set. This lets you do, e.g., ``if "foo" - in request.GET``. - -.. method:: QueryDict.get(key, default) - - Uses the same logic as ``__getitem__()`` above, with a hook for returning a - default value if the key doesn't exist. - -.. method:: QueryDict.setdefault(key, default) - - Just like the standard dictionary ``setdefault()`` method, except it uses - ``__setitem__()`` internally. - -.. method:: QueryDict.update(other_dict) - - Takes either a ``QueryDict`` or standard dictionary. Just like the standard - dictionary ``update()`` method, except it *appends* to the current - dictionary items rather than replacing them. For example:: - - >>> q = QueryDict('a=1') - >>> q = q.copy() # to make it mutable - >>> q.update({'a': '2'}) - >>> q.getlist('a') - [u'1', u'2'] - >>> q['a'] # returns the last - [u'2'] - -.. method:: QueryDict.items() - - Just like the standard dictionary ``items()`` method, except this uses the - same last-value logic as ``__getitem__()``. For example:: - - >>> q = QueryDict('a=1&a=2&a=3') - >>> q.items() - [(u'a', u'3')] - -.. method:: QueryDict.iteritems() - - Just like the standard dictionary ``iteritems()`` method. Like - :meth:`QueryDict.items()` this uses the same last-value logic as - :meth:`QueryDict.__getitem__()`. - -.. method:: QueryDict.iterlists() - - Like :meth:`QueryDict.iteritems()` except it includes all values, as a list, - for each member of the dictionary. - -.. method:: QueryDict.values() - - Just like the standard dictionary ``values()`` method, except this uses the - same last-value logic as ``__getitem__()``. For example:: - - >>> q = QueryDict('a=1&a=2&a=3') - >>> q.values() - [u'3'] - -.. method:: QueryDict.itervalues() - - Just like :meth:`QueryDict.values()`, except an iterator. - -In addition, ``QueryDict`` has the following methods: - -.. method:: QueryDict.copy() - - Returns a copy of the object, using ``copy.deepcopy()`` from the Python - standard library. The copy will be mutable -- that is, you can change its - values. - -.. method:: QueryDict.getlist(key) - - Returns the data with the requested key, as a Python list. Returns an - empty list if the key doesn't exist. It's guaranteed to return a list of - some sort. - -.. method:: QueryDict.setlist(key, list_) - - Sets the given key to ``list_`` (unlike ``__setitem__()``). - -.. method:: QueryDict.appendlist(key, item) - - Appends an item to the internal list associated with key. - -.. method:: QueryDict.setlistdefault(key, default_list) - - Just like ``setdefault``, except it takes a list of values instead of a - single value. - -.. method:: QueryDict.lists() - - Like :meth:`items()`, except it includes all values, as a list, for each - member of the dictionary. For example:: - - >>> q = QueryDict('a=1&a=2&a=3') - >>> q.lists() - [(u'a', [u'1', u'2', u'3'])] - -.. method:: QueryDict.urlencode() - - Returns a string of the data in query-string format. - Example: ``"a=2&b=3&b=5"``. - -HttpResponse objects -==================== - -.. class:: HttpResponse - -In contrast to :class:`HttpRequest` objects, which are created automatically by -Django, :class:`HttpResponse` objects are your responsibility. Each view you -write is responsible for instantiating, populating and returning an -:class:`HttpResponse`. - -The :class:`HttpResponse` class lives in the :mod:`django.http` module. - -Usage ------ - -Passing strings -~~~~~~~~~~~~~~~ - -Typical usage is to pass the contents of the page, as a string, to the -:class:`HttpResponse` constructor:: - - >>> response = HttpResponse("Here's the text of the Web page.") - >>> response = HttpResponse("Text only, please.", mimetype="text/plain") - -But if you want to add content incrementally, you can use ``response`` as a -file-like object:: - - >>> response = HttpResponse() - >>> response.write("<p>Here's the text of the Web page.</p>") - >>> response.write("<p>Here's another paragraph.</p>") - -Passing iterators -~~~~~~~~~~~~~~~~~ - -Finally, you can pass ``HttpResponse`` an iterator rather than passing it -hard-coded strings. If you use this technique, follow these guidelines: - - * The iterator should return strings. - * If an :class:`HttpResponse` has been initialized with an iterator as its - content, you can't use the class:`HttpResponse` instance as a file-like - object. Doing so will raise ``Exception``. - -Setting headers -~~~~~~~~~~~~~~~ - -To set or remove a header in your response, treat it like a dictionary:: - - >>> response = HttpResponse() - >>> response['Cache-Control'] = 'no-cache' - >>> del response['Cache-Control'] - -Note that unlike a dictionary, ``del`` doesn't raise ``KeyError`` if the header -doesn't exist. - -.. versionadded:: 1.1 - -HTTP headers cannot contain newlines. An attempt to set a header containing a -newline character (CR or LF) will raise ``BadHeaderError`` - -Telling the browser to treat the response as a file attachment -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To tell the browser to treat the response as a file attachment, use the -``mimetype`` argument and set the ``Content-Disposition`` header. For example, -this is how you might return a Microsoft Excel spreadsheet:: - - >>> response = HttpResponse(my_data, mimetype='application/vnd.ms-excel') - >>> response['Content-Disposition'] = 'attachment; filename=foo.xls' - -There's nothing Django-specific about the ``Content-Disposition`` header, but -it's easy to forget the syntax, so we've included it here. - -Attributes ----------- - -.. attribute:: HttpResponse.content - - A normal Python string representing the content, encoded from a Unicode - object if necessary. - -.. attribute:: HttpResponse.status_code - - The `HTTP Status code`_ for the response. - -Methods -------- - -.. method:: HttpResponse.__init__(content='', mimetype=None, status=200, content_type=DEFAULT_CONTENT_TYPE) - - Instantiates an ``HttpResponse`` object with the given page content (a - string) and MIME type. The :setting:`DEFAULT_CONTENT_TYPE` is - ``'text/html'``. - - ``content`` can be an iterator or a string. If it's an iterator, it should - return strings, and those strings will be joined together to form the - content of the response. - - ``status`` is the `HTTP Status code`_ for the response. - - ``content_type`` is an alias for ``mimetype``. Historically, this parameter - was only called ``mimetype``, but since this is actually the value included - in the HTTP ``Content-Type`` header, it can also include the character set - encoding, which makes it more than just a MIME type specification. - If ``mimetype`` is specified (not ``None``), that value is used. - Otherwise, ``content_type`` is used. If neither is given, the - :setting:`DEFAULT_CONTENT_TYPE` setting is used. - -.. method:: HttpResponse.__setitem__(header, value) - - Sets the given header name to the given value. Both ``header`` and - ``value`` should be strings. - -.. method:: HttpResponse.__delitem__(header) - - Deletes the header with the given name. Fails silently if the header - doesn't exist. Case-insensitive. - -.. method:: HttpResponse.__getitem__(header) - - Returns the value for the given header name. Case-insensitive. - -.. method:: HttpResponse.has_header(header) - - Returns ``True`` or ``False`` based on a case-insensitive check for a - header with the given name. - -.. method:: HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None) - - Sets a cookie. The parameters are the same as in the `cookie Morsel`_ - object in the Python standard library. - - * ``max_age`` should be a number of seconds, or ``None`` (default) if - the cookie should last only as long as the client's browser session. - * ``expires`` should be a string in the format - ``"Wdy, DD-Mon-YY HH:MM:SS GMT"``. - * Use ``domain`` if you want to set a cross-domain cookie. For example, - ``domain=".lawrence.com"`` will set a cookie that is readable by - the domains www.lawrence.com, blogs.lawrence.com and - calendars.lawrence.com. Otherwise, a cookie will only be readable by - the domain that set it. - - .. _`cookie Morsel`: http://docs.python.org/library/cookie.html#Cookie.Morsel - -.. method:: HttpResponse.delete_cookie(key, path='/', domain=None) - - Deletes the cookie with the given key. Fails silently if the key doesn't - exist. - - Due to the way cookies work, ``path`` and ``domain`` should be the same - values you used in ``set_cookie()`` -- otherwise the cookie may not be - deleted. - -.. method:: HttpResponse.write(content) - - This method makes an :class:`HttpResponse` instance a file-like object. - -.. method:: HttpResponse.flush() - - This method makes an :class:`HttpResponse` instance a file-like object. - -.. method:: HttpResponse.tell() - - This method makes an :class:`HttpResponse` instance a file-like object. - -.. _HTTP Status code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 - - -.. _ref-httpresponse-subclasses: - -HttpResponse subclasses ------------------------ - -Django includes a number of ``HttpResponse`` subclasses that handle different -types of HTTP responses. Like ``HttpResponse``, these subclasses live in -:mod:`django.http`. - -.. class:: HttpResponseRedirect - - The constructor takes a single argument -- the path to redirect to. This - can be a fully qualified URL (e.g. ``'http://www.yahoo.com/search/'``) or - an absolute path with no domain (e.g. ``'/search/'``). Note that this - returns an HTTP status code 302. - -.. class:: HttpResponsePermanentRedirect - - Like :class:`HttpResponseRedirect`, but it returns a permanent redirect - (HTTP status code 301) instead of a "found" redirect (status code 302). - -.. class:: HttpResponseNotModified - - The constructor doesn't take any arguments. Use this to designate that a - page hasn't been modified since the user's last request (status code 304). - -.. class:: HttpResponseBadRequest - - Acts just like :class:`HttpResponse` but uses a 400 status code. - -.. class:: HttpResponseNotFound - - Acts just like :class:`HttpResponse` but uses a 404 status code. - -.. class:: HttpResponseForbidden - - Acts just like :class:`HttpResponse` but uses a 403 status code. - -.. class:: HttpResponseNotAllowed - - Like :class:`HttpResponse`, but uses a 405 status code. Takes a single, - required argument: a list of permitted methods (e.g. ``['GET', 'POST']``). - -.. class:: HttpResponseGone - - Acts just like :class:`HttpResponse` but uses a 410 status code. - -.. class:: HttpResponseServerError - - Acts just like :class:`HttpResponse` but uses a 500 status code. diff --git a/parts/django/docs/ref/settings.txt b/parts/django/docs/ref/settings.txt deleted file mode 100644 index ab1f28c..0000000 --- a/parts/django/docs/ref/settings.txt +++ /dev/null @@ -1,1836 +0,0 @@ -======== -Settings -======== - -.. contents:: - :local: - :depth: 1 - -Available settings -================== - -Here's a full list of all available settings, in alphabetical order, and their -default values. - -.. setting:: ABSOLUTE_URL_OVERRIDES - -ABSOLUTE_URL_OVERRIDES ----------------------- - -Default: ``{}`` (Empty dictionary) - -A dictionary mapping ``"app_label.model_name"`` strings to functions that take -a model object and return its URL. This is a way of overriding -``get_absolute_url()`` methods on a per-installation basis. Example:: - - ABSOLUTE_URL_OVERRIDES = { - 'blogs.weblog': lambda o: "/blogs/%s/" % o.slug, - 'news.story': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug), - } - -Note that the model name used in this setting should be all lower-case, regardless -of the case of the actual model class name. - -.. 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. - -.. setting:: ADMIN_MEDIA_PREFIX - -ADMIN_MEDIA_PREFIX ------------------- - -Default: ``'/media/'`` - -The URL prefix for admin media -- CSS, JavaScript and images used by -the Django administrative interface. Make sure to use a trailing -slash, and to have this be different from the ``MEDIA_URL`` setting -(since the same URL cannot be mapped onto two different sets of -files). - -.. setting:: ADMINS - -ADMINS ------- - -Default: ``()`` (Empty tuple) - -A tuple that lists people who get code error notifications. When -``DEBUG=False`` and a view raises an exception, Django will e-mail these people -with the full exception information. Each member of the tuple should be a tuple -of (Full name, e-mail address). Example:: - - (('John', 'john@example.com'), ('Mary', 'mary@example.com')) - -Note that Django will e-mail *all* of these people whenever an error happens. -See :doc:`/howto/error-reporting` for more information. - -.. setting:: ALLOWED_INCLUDE_ROOTS - -ALLOWED_INCLUDE_ROOTS ---------------------- - -Default: ``()`` (Empty tuple) - -A tuple of strings representing allowed prefixes for the ``{% ssi %}`` template -tag. This is a security measure, so that template authors can't access files -that they shouldn't be accessing. - -For example, if ``ALLOWED_INCLUDE_ROOTS`` is ``('/home/html', '/var/www')``, -then ``{% ssi /home/html/foo.txt %}`` would work, but ``{% ssi /etc/passwd %}`` -wouldn't. - -.. setting:: APPEND_SLASH - -APPEND_SLASH ------------- - -Default: ``True`` - -When set to ``True``, if the request URL does not match any of the patterns -in the URLconf and it doesn't end in a slash, an HTTP redirect is issued to the -same URL with a slash appended. Note that the redirect may cause any data -submitted in a POST request to be lost. - -The ``APPEND_SLASH`` setting is only used if -:class:`~django.middleware.common.CommonMiddleware` is installed -(see :doc:`/topics/http/middleware`). See also :setting:`PREPEND_WWW`. - -.. setting:: AUTHENTICATION_BACKENDS - -AUTHENTICATION_BACKENDS ------------------------ - -Default: ``('django.contrib.auth.backends.ModelBackend',)`` - -A tuple of authentication backend classes (as strings) to use when attempting to -authenticate a user. See the :doc:`authentication backends documentation -</ref/authbackends>` for details. - -.. setting:: AUTH_PROFILE_MODULE - -AUTH_PROFILE_MODULE -------------------- - -Default: Not defined - -The site-specific user profile model used by this site. See -:ref:`auth-profiles`. - -.. setting:: CACHE_BACKEND - -CACHE_BACKEND -------------- - -Default: ``'locmem://'`` - -The cache backend to use. See :doc:`/topics/cache`. - -.. setting:: CACHE_MIDDLEWARE_ANONYMOUS_ONLY - -CACHE_MIDDLEWARE_ANONYMOUS_ONLY -------------------------------- - -Default: ``False`` - -If the value of this setting is ``True``, only anonymous requests (i.e., not -those made by a logged-in user) will be cached. Otherwise, the middleware -caches every page that doesn't have GET or POST parameters. - -If you set the value of this setting to ``True``, you should make sure you've -activated ``AuthenticationMiddleware``. - -See the :doc:`cache documentation </topics/cache>` for more information. - -.. setting:: CACHE_MIDDLEWARE_KEY_PREFIX - -CACHE_MIDDLEWARE_KEY_PREFIX ---------------------------- - -Default: ``''`` (Empty string) - -The cache key prefix that the cache middleware should use. See -:doc:`/topics/cache`. - -.. setting:: CACHE_MIDDLEWARE_SECONDS - -CACHE_MIDDLEWARE_SECONDS ------------------------- - -Default: ``600`` - -The default number of seconds to cache a page when the caching middleware or -``cache_page()`` decorator is used. - -.. setting:: CSRF_COOKIE_DOMAIN - -CSRF_COOKIE_DOMAIN ------------------- - -.. versionadded:: 1.2 - -Default: ``None`` - -The domain to be used when setting the CSRF cookie. This can be useful for -allowing cross-subdomain requests to be exluded from the normal cross site -request forgery protection. It should be set to a string such as -``".lawrence.com"`` to allow a POST request from a form on one subdomain to be -accepted by accepted by a view served from another subdomain. - -.. setting:: CSRF_COOKIE_NAME - -CSRF_COOKIE_NAME ----------------- - -.. versionadded:: 1.2 - -Default: ``'csrftoken'`` - -The name of the cookie to use for the CSRF authentication token. This can be whatever you -want. See :doc:`/ref/contrib/csrf`. - -.. setting:: CSRF_FAILURE_VIEW - -CSRF_FAILURE_VIEW ------------------ - -.. versionadded:: 1.2 - -Default: ``'django.views.csrf.csrf_failure'`` - -A dotted path to the view function to be used when an incoming request -is rejected by the CSRF protection. The function should have this signature:: - - def csrf_failure(request, reason="") - -where ``reason`` is a short message (intended for developers or logging, not for -end users) indicating the reason the request was rejected. See -:doc:`/ref/contrib/csrf`. - - -.. setting:: DATABASES - -DATABASES ---------- - -.. versionadded:: 1.2 - -Default: ``{}`` (Empty dictionary) - -A dictionary containing the settings for all databases to be used with -Django. It is a nested dictionary whose contents maps database aliases -to a dictionary containing the options for an individual database. - -The :setting:`DATABASES` setting must configure a ``default`` database; -any number of additional databases may also be specified. - -The simplest possible settings file is for a single-database setup using -SQLite. This can be configured using the following:: - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'mydatabase' - } - } - -For other database backends, or more complex SQLite configurations, other options -will be required. The following inner options are available. - -.. setting:: ENGINE - -ENGINE -~~~~~~ - -Default: ``''`` (Empty string) - -The database backend to use. The built-in database backends are: - - * ``'django.db.backends.postgresql_psycopg2'`` - * ``'django.db.backends.postgresql'`` - * ``'django.db.backends.mysql'`` - * ``'django.db.backends.sqlite3'`` - * ``'django.db.backends.oracle'`` - -You can use a database backend that doesn't ship with Django by setting -``ENGINE`` to a fully-qualified path (i.e. -``mypackage.backends.whatever``). Writing a whole new database backend from -scratch is left as an exercise to the reader; see the other backends for -examples. - -.. note:: - Prior to Django 1.2, you could use a short version of the backend name - to reference the built-in database backends (e.g., you could use - ``'sqlite3'`` to refer to the SQLite backend). This format has been - deprecated, and will be removed in Django 1.4. - -.. setting:: HOST - -HOST -~~~~ - -Default: ``''`` (Empty string) - -Which host to use when connecting to the database. An empty string means -localhost. Not used with SQLite. - -If this value starts with a forward slash (``'/'``) and you're using MySQL, -MySQL will connect via a Unix socket to the specified socket. For example:: - - "HOST": '/var/run/mysql' - -If you're using MySQL and this value *doesn't* start with a forward slash, then -this value is assumed to be the host. - -If you're using PostgreSQL, an empty string means to use a Unix domain socket -for the connection, rather than a network connection to localhost. If you -explicitly need to use a TCP/IP connection on the local machine with -PostgreSQL, specify ``localhost`` here. - -.. setting:: NAME - -NAME -~~~~ - -Default: ``''`` (Empty string) - -The name of the database to use. For SQLite, it's the full path to the database -file. When specifying the path, always use forward slashes, even on Windows -(e.g. ``C:/homes/user/mysite/sqlite3.db``). - -.. setting:: OPTIONS - -OPTIONS -~~~~~~~ - -Default: ``{}`` (Empty dictionary) - -Extra parameters to use when connecting to the database. Available parameters -vary depending on your database backend. - -Some information on available parameters can be found in the -:doc:`Database Backends </ref/databases>` documentation. For more information, -consult your backend module's own documentation. - -.. setting:: PASSWORD - -PASSWORD -~~~~~~~~ - -Default: ``''`` (Empty string) - -The password to use when connecting to the database. Not used with SQLite. - -.. setting:: PORT - -PORT -~~~~ - -Default: ``''`` (Empty string) - -The port to use when connecting to the database. An empty string means the -default port. Not used with SQLite. - -.. setting:: USER - -USER -~~~~ - -Default: ``''`` (Empty string) - -The username to use when connecting to the database. Not used with SQLite. - -.. setting:: TEST_CHARSET - -TEST_CHARSET -~~~~~~~~~~~~ - -Default: ``None`` - -The character set encoding used to create the test database. The value of this -string is passed directly through to the database, so its format is -backend-specific. - -Supported for the PostgreSQL_ (``postgresql``, ``postgresql_psycopg2``) and -MySQL_ (``mysql``) backends. - -.. _PostgreSQL: http://www.postgresql.org/docs/8.2/static/multibyte.html -.. _MySQL: http://dev.mysql.com/doc/refman/5.0/en/charset-database.html - -.. setting:: TEST_COLLATION - -TEST_COLLATION -~~~~~~~~~~~~~~ - -Default: ``None`` - -The collation order to use when creating the test database. This value is -passed directly to the backend, so its format is backend-specific. - -Only supported for the ``mysql`` backend (see the `MySQL manual`_ for details). - -.. _MySQL manual: MySQL_ - -.. setting:: TEST_DEPENDENCIES - -TEST_DEPENDENCIES -~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2.4 - -Default: ``['default']``, for all databases other than ``default``, -which has no dependencies. - -The creation-order dependencies of the database. See the documentation -on :ref:`controlling the creation order of test databases -<topics-testing-creation-dependencies>` for details. - -.. setting:: TEST_MIRROR - -TEST_MIRROR -~~~~~~~~~~~ - -Default: ``None`` - -The alias of the database that this database should mirror during -testing. - -This setting exists to allow for testing of master/slave -configurations of multiple databases. See the documentation on -:ref:`testing master/slave configurations -<topics-testing-masterslave>` for details. - -.. setting:: TEST_NAME - -TEST_NAME -~~~~~~~~~ - -Default: ``None`` - -The name of database to use when running the test suite. - -If the default value (``None``) is used with the SQLite database engine, the -tests will use a memory resident database. For all other database engines the -test database will use the name ``'test_' + DATABASE_NAME``. - -See :doc:`/topics/testing`. - -.. setting:: TEST_USER - -TEST_USER -~~~~~~~~~ - -Default: ``None`` - -This is an Oracle-specific setting. - -The username to use when connecting to the Oracle database that will be used -when running tests. - -.. setting:: DATABASE_ROUTERS - -DATABASE_ROUTERS ----------------- - -.. versionadded:: 1.2 - -Default: ``[]`` (Empty list) - -The list of routers that will be used to determine which database -to use when performing a database queries. - -See the documentation on :ref:`automatic database routing in multi -database configurations <topics-db-multi-db-routing>`. - -.. setting:: DATE_FORMAT - -DATE_FORMAT ------------ - -Default: ``'N j, Y'`` (e.g. ``Feb. 4, 2003``) - -The default formatting to use for displaying date fields in any part of the -system. Note that if :setting:`USE_L10N` is set to ``True``, then the -locale-dictated format has higher precedence and will be applied instead. See -:tfilter:`allowed date format strings <date>`. - -.. versionchanged:: 1.2 - This setting can now be overriden by setting ``USE_L10N`` to ``True``. - -See also ``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``SHORT_DATE_FORMAT``. - -.. setting:: DATE_INPUT_FORMATS - -DATE_INPUT_FORMATS ------------------- - -.. versionadded:: 1.2 - -Default:: - - ('%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', '%b %d %Y', - '%b %d, %Y', '%d %b %Y', '%d %b, %Y', '%B %d %Y', - '%B %d, %Y', '%d %B %Y', '%d %B, %Y') - -A tuple of formats that will be accepted when inputting data on a date -field. Formats will be tried in order, using the first valid. -Note that these format strings are specified in Python's datetime_ module -syntax, that is different from the one used by Django for formatting dates -to be displayed. - -See also ``DATETIME_INPUT_FORMATS`` and ``TIME_INPUT_FORMATS``. - -.. _datetime: http://docs.python.org/library/datetime.html#strftime-strptime-behavior - -.. setting:: DATETIME_FORMAT - -DATETIME_FORMAT ---------------- - -Default: ``'N j, Y, P'`` (e.g. ``Feb. 4, 2003, 4 p.m.``) - -The default formatting to use for displaying datetime fields in any part of the -system. Note that if :setting:`USE_L10N` is set to ``True``, then the -locale-dictated format has higher precedence and will be applied instead. See -:tfilter:`allowed date format strings <date>`. - -.. versionchanged:: 1.2 - This setting can now be overriden by setting ``USE_L10N`` to ``True``. - -See also ``DATE_FORMAT``, ``TIME_FORMAT`` and ``SHORT_DATETIME_FORMAT``. - -.. setting:: DATETIME_INPUT_FORMATS - -DATETIME_INPUT_FORMATS ----------------------- - -.. versionadded:: 1.2 - -Default:: - - ('%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M', '%Y-%m-%d', - '%m/%d/%Y %H:%M:%S', '%m/%d/%Y %H:%M', '%m/%d/%Y', - '%m/%d/%y %H:%M:%S', '%m/%d/%y %H:%M', '%m/%d/%y') - -A tuple of formats that will be accepted when inputting data on a datetime -field. Formats will be tried in order, using the first valid. -Note that these format strings are specified in Python's datetime_ module -syntax, that is different from the one used by Django for formatting dates -to be displayed. - -See also ``DATE_INPUT_FORMATS`` and ``TIME_INPUT_FORMATS``. - -.. _datetime: http://docs.python.org/library/datetime.html#strftime-strptime-behavior - -.. setting:: DEBUG - -DEBUG ------ - -Default: ``False`` - -A boolean that turns on/off debug mode. - -If you define custom settings, `django/views/debug.py`_ has a ``HIDDEN_SETTINGS`` -regular expression which will hide from the DEBUG view anything that contains -``'SECRET'``, ``'PASSWORD'``, ``'PROFANITIES'``, or ``'SIGNATURE'``. This allows -untrusted users to be able to give backtraces without seeing sensitive (or -offensive) settings. - -Still, note that there are always going to be sections of your debug output that -are inappropriate for public consumption. File paths, configuration options, and -the like all give attackers extra information about your server. - -It is also important to remember that when running with ``DEBUG`` turned on, Django -will remember every SQL query it executes. This is useful when you are debugging, -but on a production server, it will rapidly consume memory. - -Never deploy a site into production with ``DEBUG`` turned on. - -.. _django/views/debug.py: http://code.djangoproject.com/browser/django/trunk/django/views/debug.py - -DEBUG_PROPAGATE_EXCEPTIONS --------------------------- - -.. versionadded:: 1.0 - -Default: ``False`` - -If set to True, Django's normal exception handling of view functions -will be suppressed, and exceptions will propagate upwards. This can -be useful for some test setups, and should never be used on a live -site. - -.. setting:: DECIMAL_SEPARATOR - -DECIMAL_SEPARATOR ------------------ - -.. versionadded:: 1.2 - -Default: ``'.'`` (Dot) - -Default decimal separator used when formatting decimal numbers. - -.. setting:: DEFAULT_CHARSET - -DEFAULT_CHARSET ---------------- - -Default: ``'utf-8'`` - -Default charset to use for all ``HttpResponse`` objects, if a MIME type isn't -manually specified. Used with ``DEFAULT_CONTENT_TYPE`` to construct the -``Content-Type`` header. - -.. setting:: DEFAULT_CONTENT_TYPE - -DEFAULT_CONTENT_TYPE --------------------- - -Default: ``'text/html'`` - -Default content type to use for all ``HttpResponse`` objects, if a MIME type -isn't manually specified. Used with ``DEFAULT_CHARSET`` to construct the -``Content-Type`` header. - -.. setting:: DEFAULT_FILE_STORAGE - -DEFAULT_FILE_STORAGE --------------------- - -Default: :class:`django.core.files.storage.FileSystemStorage` - -Default file storage class to be used for any file-related operations that don't -specify a particular storage system. See :doc:`/topics/files`. - -.. setting:: DEFAULT_FROM_EMAIL - -DEFAULT_FROM_EMAIL ------------------- - -Default: ``'webmaster@localhost'`` - -Default e-mail address to use for various automated correspondence from the -site manager(s). - -.. setting:: DEFAULT_INDEX_TABLESPACE - -DEFAULT_INDEX_TABLESPACE ------------------------- - -.. versionadded:: 1.0 - -Default: ``''`` (Empty string) - -Default tablespace to use for indexes on fields that don't specify -one, if the backend supports it. - -.. setting:: DEFAULT_TABLESPACE - -DEFAULT_TABLESPACE ------------------- - -.. versionadded:: 1.0 - -Default: ``''`` (Empty string) - -Default tablespace to use for models that don't specify one, if the -backend supports it. - -.. setting:: DISALLOWED_USER_AGENTS - -DISALLOWED_USER_AGENTS ----------------------- - -Default: ``()`` (Empty tuple) - -List of compiled regular expression objects representing User-Agent strings that -are not allowed to visit any page, systemwide. Use this for bad robots/crawlers. -This is only used if ``CommonMiddleware`` is installed (see -:doc:`/topics/http/middleware`). - -.. setting:: EMAIL_BACKEND - -EMAIL_BACKEND -------------- - -.. versionadded:: 1.2 - -Default: ``'django.core.mail.backends.smtp.EmailBackend'`` - -The backend to use for sending emails. For the list of available backends see -:doc:`/topics/email`. - -.. setting:: EMAIL_FILE_PATH - -EMAIL_FILE_PATH ---------------- - -.. versionadded:: 1.2 - -Default: Not defined - -The directory used by the ``file`` email backend to store output files. - -.. setting:: EMAIL_HOST - -EMAIL_HOST ----------- - -Default: ``'localhost'`` - -The host to use for sending e-mail. - -See also ``EMAIL_PORT``. - -.. setting:: EMAIL_HOST_PASSWORD - -EMAIL_HOST_PASSWORD -------------------- - -Default: ``''`` (Empty string) - -Password to use for the SMTP server defined in ``EMAIL_HOST``. This setting is -used in conjunction with ``EMAIL_HOST_USER`` when authenticating to the SMTP -server. If either of these settings is empty, Django won't attempt -authentication. - -See also ``EMAIL_HOST_USER``. - -.. setting:: EMAIL_HOST_USER - -EMAIL_HOST_USER ---------------- - -Default: ``''`` (Empty string) - -Username to use for the SMTP server defined in ``EMAIL_HOST``. If empty, -Django won't attempt authentication. - -See also ``EMAIL_HOST_PASSWORD``. - -.. setting:: EMAIL_PORT - -EMAIL_PORT ----------- - -Default: ``25`` - -Port to use for the SMTP server defined in ``EMAIL_HOST``. - -.. setting:: EMAIL_SUBJECT_PREFIX - -EMAIL_SUBJECT_PREFIX --------------------- - -Default: ``'[Django] '`` - -Subject-line prefix for e-mail messages sent with ``django.core.mail.mail_admins`` -or ``django.core.mail.mail_managers``. You'll probably want to include the -trailing space. - -.. setting:: EMAIL_USE_TLS - -EMAIL_USE_TLS -------------- - -.. versionadded:: 1.0 - -Default: ``False`` - -Whether to use a TLS (secure) connection when talking to the SMTP server. - -.. setting:: FILE_CHARSET - -FILE_CHARSET ------------- - -.. versionadded:: 1.0 - -Default: ``'utf-8'`` - -The character encoding used to decode any files read from disk. This includes -template files and initial SQL data files. - -.. setting:: FILE_UPLOAD_HANDLERS - -FILE_UPLOAD_HANDLERS --------------------- - -.. versionadded:: 1.0 - -Default:: - - ("django.core.files.uploadhandler.MemoryFileUploadHandler", - "django.core.files.uploadhandler.TemporaryFileUploadHandler",) - -A tuple of handlers to use for uploading. See :doc:`/topics/files` for details. - -.. setting:: FILE_UPLOAD_MAX_MEMORY_SIZE - -FILE_UPLOAD_MAX_MEMORY_SIZE ---------------------------- - -.. versionadded:: 1.0 - -Default: ``2621440`` (i.e. 2.5 MB). - -The maximum size (in bytes) that an upload will be before it gets streamed to -the file system. See :doc:`/topics/files` for details. - -.. setting:: FILE_UPLOAD_PERMISSIONS - -FILE_UPLOAD_PERMISSIONS ------------------------ - -Default: ``None`` - -The numeric mode (i.e. ``0644``) to set newly uploaded files to. For -more information about what these modes mean, see the `documentation for -os.chmod`_ - -If this isn't given or is ``None``, you'll get operating-system -dependent behavior. On most platforms, temporary files will have a mode -of ``0600``, and files saved from memory will be saved using the -system's standard umask. - -.. warning:: - - **Always prefix the mode with a 0.** - - If you're not familiar with file modes, please note that the leading - ``0`` is very important: it indicates an octal number, which is the - way that modes must be specified. If you try to use ``644``, you'll - get totally incorrect behavior. - - -.. _documentation for os.chmod: http://docs.python.org/library/os.html#os.chmod - -.. setting:: FILE_UPLOAD_TEMP_DIR - -FILE_UPLOAD_TEMP_DIR --------------------- - -.. versionadded:: 1.0 - -Default: ``None`` - -The directory to store data temporarily while uploading files. If ``None``, -Django will use the standard temporary directory for the operating system. For -example, this will default to '/tmp' on \*nix-style operating systems. - -See :doc:`/topics/files` for details. - -.. setting:: FIRST_DAY_OF_WEEK - -FIRST_DAY_OF_WEEK ------------------ - -.. versionadded:: 1.2 - -Default: ``0`` (Sunday) - -Number representing the first day of the week. This is especially useful -when displaying a calendar. This value is only used when not using -format internationalization, or when a format cannot be found for the -current locale. - -The value must be an integer from 0 to 6, where 0 means Sunday, 1 means -Monday and so on. - -.. setting:: FIXTURE_DIRS - -FIXTURE_DIRS -------------- - -Default: ``()`` (Empty tuple) - -List of locations of the fixture data files, in search order. Note that -these paths should use Unix-style forward slashes, even on Windows. See -:doc:`/topics/testing`. - -FORCE_SCRIPT_NAME ------------------- - -Default: ``None`` - -If not ``None``, this will be used as the value of the ``SCRIPT_NAME`` -environment variable in any HTTP request. This setting can be used to override -the server-provided value of ``SCRIPT_NAME``, which may be a rewritten version -of the preferred value or not supplied at all. - -.. setting:: FORMAT_MODULE_PATH - -FORMAT_MODULE_PATH ------------------- - -.. versionadded:: 1.2 - -Default: ``None`` - -A full Python path to a Python package that contains format definitions for -project locales. If not ``None``, Django will check for a ``formats.py`` -file, under the directory named as the current locale, and will use the -formats defined on this file. - -For example, if ``FORMAT_MODULE_PATH`` is set to ``mysite.formats``, and -current language is ``en`` (English), Django will expect a directory tree -like:: - - mysite/ - formats/ - __init__.py - en/ - __init__.py - formats.py - -Available formats are ``DATE_FORMAT``, ``TIME_FORMAT``, ``DATETIME_FORMAT``, -``YEAR_MONTH_FORMAT``, ``MONTH_DAY_FORMAT``, ``SHORT_DATE_FORMAT``, -``SHORT_DATETIME_FORMAT``, ``FIRST_DAY_OF_WEEK``, ``DECIMAL_SEPARATOR``, -``THOUSAND_SEPARATOR`` and ``NUMBER_GROUPING``. - -.. setting:: IGNORABLE_404_ENDS - -IGNORABLE_404_ENDS ------------------- - -Default: ``('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')`` - -See also ``IGNORABLE_404_STARTS`` and ``Error reporting via e-mail``. - -.. setting:: IGNORABLE_404_STARTS - -IGNORABLE_404_STARTS --------------------- - -Default: ``('/cgi-bin/', '/_vti_bin', '/_vti_inf')`` - -A tuple of strings that specify beginnings of URLs that should be ignored by -the 404 e-mailer. See ``SEND_BROKEN_LINK_EMAILS``, ``IGNORABLE_404_ENDS`` and -the :doc:`/howto/error-reporting`. - -.. setting:: INSTALLED_APPS - -INSTALLED_APPS --------------- - -Default: ``()`` (Empty tuple) - -A tuple of strings designating all applications that are enabled in this Django -installation. Each string should be a full Python path to a Python package that -contains a Django application, as created by :djadmin:`django-admin.py startapp -<startapp>`. - -.. admonition:: App names must be unique - - The application names (that is, the final dotted part of the - path to the module containing ``models.py``) defined in - :setting:`INSTALLED_APPS` *must* be unique. For example, you can't - include both ``django.contrib.auth`` and ``myproject.auth`` in - INSTALLED_APPS. - -.. setting:: INTERNAL_IPS - -INTERNAL_IPS ------------- - -Default: ``()`` (Empty tuple) - -A tuple of IP addresses, as strings, that: - - * See debug comments, when ``DEBUG`` is ``True`` - * Receive X headers if the ``XViewMiddleware`` is installed (see - :doc:`/topics/http/middleware`) - -.. setting:: LANGUAGE_CODE - -LANGUAGE_CODE -------------- - -Default: ``'en-us'`` - -A string representing the language code for this installation. This should be in -standard :term:`language format<language code>`. For example, U.S. English is -``"en-us"``. See :doc:`/topics/i18n/index`. - -.. setting:: LANGUAGE_COOKIE_NAME - -LANGUAGE_COOKIE_NAME --------------------- - -.. versionadded:: 1.0 - -Default: ``'django_language'`` - -The name of the cookie to use for the language cookie. This can be whatever you -want (but should be different from ``SESSION_COOKIE_NAME``). See -:doc:`/topics/i18n/index`. - -.. setting:: LANGUAGES - -LANGUAGES ---------- - -Default: A tuple of all available languages. This list is continually growing -and including a copy here would inevitably become rapidly out of date. You can -see the current list of translated languages by looking in -``django/conf/global_settings.py`` (or view the `online source`_). - -.. _online source: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py - -The list is a tuple of two-tuples in the format ``(language code, language -name)``, the ``language code`` part should be a -:term:`language name<language code>` -- for example, ``('ja', 'Japanese')``. -This specifies which languages are available for language selection. See -:doc:`/topics/i18n/index`. - -Generally, the default value should suffice. Only set this setting if you want -to restrict language selection to a subset of the Django-provided languages. - -If you define a custom ``LANGUAGES`` setting, it's OK to mark the languages as -translation strings (as in the default value referred to above) -- but use a -"dummy" ``gettext()`` function, not the one in ``django.utils.translation``. -You should *never* import ``django.utils.translation`` from within your -settings file, because that module in itself depends on the settings, and that -would cause a circular import. - -The solution is to use a "dummy" ``gettext()`` function. Here's a sample -settings file:: - - gettext = lambda s: s - - LANGUAGES = ( - ('de', gettext('German')), - ('en', gettext('English')), - ) - -With this arrangement, ``django-admin.py makemessages`` will still find and -mark these strings for translation, but the translation won't happen at -runtime -- so you'll have to remember to wrap the languages in the *real* -``gettext()`` in any code that uses ``LANGUAGES`` at runtime. - -.. setting:: LOCALE_PATHS - -LOCALE_PATHS ------------- - -Default: ``()`` (Empty tuple) - -A tuple of directories where Django looks for translation files. -See :ref:`using-translations-in-your-own-projects`. - -.. setting:: LOGIN_REDIRECT_URL - -LOGIN_REDIRECT_URL ------------------- - -.. versionadded:: 1.0 - -Default: ``'/accounts/profile/'`` - -The URL where requests are redirected after login when the -``contrib.auth.login`` view gets no ``next`` parameter. - -This is used by the :func:`~django.contrib.auth.decorators.login_required` -decorator, for example. - -.. setting:: LOGIN_URL - -LOGIN_URL ---------- - -.. versionadded:: 1.0 - -Default: ``'/accounts/login/'`` - -The URL where requests are redirected for login, especially when using the -:func:`~django.contrib.auth.decorators.login_required` decorator. - -.. setting:: LOGOUT_URL - -LOGOUT_URL ----------- - -.. versionadded:: 1.0 - -Default: ``'/accounts/logout/'`` - -LOGIN_URL counterpart. - -.. setting:: MANAGERS - -MANAGERS --------- - -Default: ``()`` (Empty tuple) - -A tuple in the same format as ``ADMINS`` that specifies who should get -broken-link notifications when ``SEND_BROKEN_LINK_EMAILS=True``. - -.. setting:: MEDIA_ROOT - -MEDIA_ROOT ----------- - -Default: ``''`` (Empty string) - -Absolute path to the directory that holds media for this installation. -Example: ``"/home/media/media.lawrence.com/"`` See also ``MEDIA_URL``. - -.. setting:: MEDIA_URL - -MEDIA_URL ---------- - -Default: ``''`` (Empty string) - -URL that handles the media served from ``MEDIA_ROOT``. -Example: ``"http://media.lawrence.com"`` - -Note that this should have a trailing slash if it has a path component. - -Good: ``"http://www.example.com/static/"`` -Bad: ``"http://www.example.com/static"`` - -.. setting:: MIDDLEWARE_CLASSES - -MESSAGE_LEVEL -------------- - -.. versionadded:: 1.2 - -Default: `messages.INFO` - -Sets the minimum message level that will be recorded by the messages -framework. See the :doc:`messages documentation </ref/contrib/messages>` for -more details. - -MESSAGE_STORAGE ---------------- - -.. versionadded:: 1.2 - -Default: ``'django.contrib.messages.storage.user_messages.LegacyFallbackStorage'`` - -Controls where Django stores message data. See the -:doc:`messages documentation </ref/contrib/messages>` for more details. - -MESSAGE_TAGS ------------- - -.. versionadded:: 1.2 - -Default:: - - {messages.DEBUG: 'debug', - messages.INFO: 'info', - messages.SUCCESS: 'success', - messages.WARNING: 'warning', - messages.ERROR: 'error',} - -Sets the mapping of message levels to message tags. See the -:doc:`messages documentation </ref/contrib/messages>` for more details. - -MIDDLEWARE_CLASSES ------------------- - -Default:: - - ('django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware',) - -A tuple of middleware classes to use. See :doc:`/topics/http/middleware`. - -.. versionchanged:: 1.2 - ``'django.contrib.messages.middleware.MessageMiddleware'`` was added to the - default. For more information, see the :doc:`messages documentation - </ref/contrib/messages>`. - -.. setting:: MONTH_DAY_FORMAT - -MONTH_DAY_FORMAT ----------------- - -Default: ``'F j'`` - -The default formatting to use for date fields on Django admin change-list -pages -- and, possibly, by other parts of the system -- in cases when only the -month and day are displayed. - -For example, when a Django admin change-list page is being filtered by a date -drilldown, the header for a given day displays the day and month. Different -locales have different formats. For example, U.S. English would say -"January 1," whereas Spanish might say "1 Enero." - -See :tfilter:`allowed date format strings <date>`. See also ``DATE_FORMAT``, -``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``YEAR_MONTH_FORMAT``. - -.. setting:: NUMBER_GROUPING - -NUMBER_GROUPING ----------------- - -.. versionadded:: 1.2 - -Default: ``0`` - -Number of digits grouped together on the integer part of a number. Common use -is to display a thousand separator. If this setting is ``0``, then, no grouping -will be applied to the number. If this setting is greater than ``0`` then the -setting :setting:`THOUSAND_SEPARATOR` will be used as the separator between those -groups. - -See also :setting:`THOUSAND_SEPARATOR` and :setting:`USE_THOUSAND_SEPARATOR`. - -.. setting:: PASSWORD_RESET_TIMEOUT_DAYS - -PASSWORD_RESET_TIMEOUT_DAYS ---------------------------- - -Default: ``3`` - -The number of days a password reset link is valid for. Used by the -:mod:`django.contrib.auth` password reset mechanism. - -.. setting:: PREPEND_WWW - -PREPEND_WWW ------------ - -Default: ``False`` - -Whether to prepend the "www." subdomain to URLs that don't have it. This is only -used if :class:`~django.middleware.common.CommonMiddleware` is installed -(see :doc:`/topics/http/middleware`). See also :setting:`APPEND_SLASH`. - -.. setting:: PROFANITIES_LIST - -PROFANITIES_LIST ----------------- - -A tuple of profanities, as strings, that will trigger a validation error when -the ``hasNoProfanities`` validator is called. - -We don't list the default values here, because that would be profane. To see -the default values, see the file `django/conf/global_settings.py`_. - -.. _django/conf/global_settings.py: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py - -.. setting:: RESTRUCTUREDTEXT_FILTER_SETTINGS - -RESTRUCTUREDTEXT_FILTER_SETTINGS --------------------------------- - -Default: ``{}`` - -A dictionary containing settings for the ``restructuredtext`` markup filter from -the :doc:`django.contrib.markup application </ref/contrib/markup>`. They override -the default writer settings. See the Docutils restructuredtext `writer settings -docs`_ for details. - -.. _writer settings docs: http://docutils.sourceforge.net/docs/user/config.html#html4css1-writer - -.. setting:: ROOT_URLCONF - -ROOT_URLCONF ------------- - -Default: Not defined - -A string representing the full Python import path to your root URLconf. For example: -``"mydjangoapps.urls"``. Can be overridden on a per-request basis by -setting the attribute ``urlconf`` on the incoming ``HttpRequest`` -object. See :ref:`how-django-processes-a-request` for details. - -.. setting:: SECRET_KEY - -SECRET_KEY ----------- - -Default: ``''`` (Empty string) - -A secret key for this particular Django installation. Used to provide a seed in -secret-key hashing algorithms. Set this to a random string -- the longer, the -better. ``django-admin.py startproject`` creates one automatically. - -.. setting:: SEND_BROKEN_LINK_EMAILS - -SEND_BROKEN_LINK_EMAILS ------------------------ - -Default: ``False`` - -Whether to send an e-mail to the ``MANAGERS`` each time somebody visits a -Django-powered page that is 404ed with a non-empty referer (i.e., a broken -link). This is only used if ``CommonMiddleware`` is installed (see -:doc:`/topics/http/middleware`. See also ``IGNORABLE_404_STARTS``, -``IGNORABLE_404_ENDS`` and :doc:`/howto/error-reporting`. - -.. setting:: SERIALIZATION_MODULES - -SERIALIZATION_MODULES ---------------------- - -Default: Not defined. - -A dictionary of modules containing serializer definitions (provided as -strings), keyed by a string identifier for that serialization type. For -example, to define a YAML serializer, use:: - - SERIALIZATION_MODULES = { 'yaml' : 'path.to.yaml_serializer' } - -.. setting:: SERVER_EMAIL - -SERVER_EMAIL ------------- - -Default: ``'root@localhost'`` - -The e-mail address that error messages come from, such as those sent to -``ADMINS`` and ``MANAGERS``. - -.. setting:: SESSION_COOKIE_AGE - -SESSION_COOKIE_AGE ------------------- - -Default: ``1209600`` (2 weeks, in seconds) - -The age of session cookies, in seconds. See :doc:`/topics/http/sessions`. - -.. setting:: SESSION_COOKIE_DOMAIN - -SESSION_COOKIE_DOMAIN ---------------------- - -Default: ``None`` - -The domain to use for session cookies. Set this to a string such as -``".lawrence.com"`` for cross-domain cookies, or use ``None`` for a standard -domain cookie. See the :doc:`/topics/http/sessions`. - -.. setting:: SESSION_COOKIE_NAME - -SESSION_COOKIE_NAME -------------------- - -Default: ``'sessionid'`` - -The name of the cookie to use for sessions. This can be whatever you want (but -should be different from ``LANGUAGE_COOKIE_NAME``). See the :doc:`/topics/http/sessions`. - -.. setting:: SESSION_COOKIE_PATH - -SESSION_COOKIE_PATH -------------------- - -.. versionadded:: 1.0 - -Default: ``'/'`` - -The path set on the session cookie. This should either match the URL path of your -Django installation or be parent of that path. - -This is useful if you have multiple Django instances running under the same -hostname. They can use different cookie paths, and each instance will only see -its own session cookie. - -.. setting:: SESSION_COOKIE_SECURE - -SESSION_COOKIE_SECURE ---------------------- - -Default: ``False`` - -Whether to use a secure cookie for the session cookie. If this is set to -``True``, the cookie will be marked as "secure," which means browsers may -ensure that the cookie is only sent under an HTTPS connection. -See the :doc:`/topics/http/sessions`. - -.. setting:: SESSION_ENGINE - -SESSION_ENGINE --------------- - -.. versionadded:: 1.0 - -.. versionchanged:: 1.1 - The ``cached_db`` backend was added - -Default: ``django.contrib.sessions.backends.db`` - -Controls where Django stores session data. Valid values are: - - * ``'django.contrib.sessions.backends.db'`` - * ``'django.contrib.sessions.backends.file'`` - * ``'django.contrib.sessions.backends.cache'`` - * ``'django.contrib.sessions.backends.cached_db'`` - -See :doc:`/topics/http/sessions`. - -.. setting:: SESSION_EXPIRE_AT_BROWSER_CLOSE - -SESSION_EXPIRE_AT_BROWSER_CLOSE -------------------------------- - -Default: ``False`` - -Whether to expire the session when the user closes his or her browser. -See the :doc:`/topics/http/sessions`. - -.. setting:: SESSION_FILE_PATH - -SESSION_FILE_PATH ------------------ - -.. versionadded:: 1.0 - -Default: ``None`` - -If you're using file-based session storage, this sets the directory in -which Django will store session data. See :doc:`/topics/http/sessions`. When -the default value (``None``) is used, Django will use the standard temporary -directory for the system. - -.. setting:: SESSION_SAVE_EVERY_REQUEST - -SESSION_SAVE_EVERY_REQUEST --------------------------- - -Default: ``False`` - -Whether to save the session data on every request. See -:doc:`/topics/http/sessions`. - -.. setting:: SHORT_DATE_FORMAT - -SHORT_DATE_FORMAT ------------------ - -.. versionadded:: 1.2 - -Default: ``m/d/Y`` (e.g. ``12/31/2003``) - -An available formatting that can be used for displaying date fields on -templates. Note that if :setting:`USE_L10N` is set to ``True``, then the -corresponding locale-dictated format has higher precedence and will be applied. -See :tfilter:`allowed date format strings <date>`. - -See also ``DATE_FORMAT`` and ``SHORT_DATETIME_FORMAT``. - -.. setting:: SHORT_DATETIME_FORMAT - -SHORT_DATETIME_FORMAT ---------------------- - -.. versionadded:: 1.2 - -Default: ``m/d/Y P`` (e.g. ``12/31/2003 4 p.m.``) - -An available formatting that can be used for displaying datetime fields on -templates. Note that if :setting:`USE_L10N` is set to ``True``, then the -corresponding locale-dictated format has higher precedence and will be applied. -See :tfilter:`allowed date format strings <date>`. - -See also ``DATE_FORMAT`` and ``SHORT_DATETIME_FORMAT``. - -.. setting:: SITE_ID - -SITE_ID -------- - -Default: Not defined - -The ID, as an integer, of the current site in the ``django_site`` database -table. This is used so that application data can hook into specific site(s) -and a single database can manage content for multiple sites. - -See :doc:`/ref/contrib/sites`. - -.. _site framework docs: ../sites/ - -.. setting:: TEMPLATE_CONTEXT_PROCESSORS - -TEMPLATE_CONTEXT_PROCESSORS ---------------------------- - -Default:: - - ("django.contrib.auth.context_processors.auth", - "django.core.context_processors.debug", - "django.core.context_processors.i18n", - "django.core.context_processors.media", - "django.contrib.messages.context_processors.messages") - -A tuple of callables that are used to populate the context in ``RequestContext``. -These callables take a request object as their argument and return a dictionary -of items to be merged into the context. - -.. versionchanged:: 1.2 - ``"django.contrib.messages.context_processors.messages"`` was added to the - default. For more information, see the :doc:`messages documentation - </ref/contrib/messages>`. - -.. versionchanged:: 1.2 - The auth context processor was moved in this release from its old location - ``django.core.context_processors.auth`` to - ``django.contrib.auth.context_processors.auth``. - -.. setting:: TEMPLATE_DEBUG - -TEMPLATE_DEBUG --------------- - -Default: ``False`` - -A boolean that turns on/off template debug mode. If this is ``True``, the fancy -error page will display a detailed report for any ``TemplateSyntaxError``. This -report contains the relevant snippet of the template, with the appropriate line -highlighted. - -Note that Django only displays fancy error pages if ``DEBUG`` is ``True``, so -you'll want to set that to take advantage of this setting. - -See also ``DEBUG``. - -.. setting:: TEMPLATE_DIRS - -TEMPLATE_DIRS -------------- - -Default: ``()`` (Empty tuple) - -List of locations of the template source files, in search order. Note that -these paths should use Unix-style forward slashes, even on Windows. - -See :doc:`/topics/templates`. - -.. setting:: TEMPLATE_LOADERS - -TEMPLATE_LOADERS ----------------- - -Default:: - - ('django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader') - -A tuple of template loader classes, specified as strings. Each ``Loader`` class -knows how to import templates from a particular source. Optionally, a tuple can be -used instead of a string. The first item in the tuple should be the ``Loader``'s -module, subsequent items are passed to the ``Loader`` during initialization. See -:doc:`/ref/templates/api`. - -.. setting:: TEMPLATE_STRING_IF_INVALID - -TEMPLATE_STRING_IF_INVALID --------------------------- - -Default: ``''`` (Empty string) - -Output, as a string, that the template system should use for invalid (e.g. -misspelled) variables. See :ref:`invalid-template-variables`.. - -.. setting:: TEST_RUNNER - -TEST_RUNNER ------------ - -Default: ``'django.test.simple.DjangoTestSuiteRunner'`` - -.. versionchanged:: 1.2 - Prior to 1.2, test runners were a function, not a class. - -The name of the class to use for starting the test suite. See -:doc:`/topics/testing`. - -.. _Testing Django Applications: ../testing/ - -.. setting:: THOUSAND_SEPARATOR - -THOUSAND_SEPARATOR ------------------- - -.. versionadded:: 1.2 - -Default ``,`` (Comma) - -Default thousand separator used when formatting numbers. This setting is -used only when ``NUMBER_GROUPING`` and ``USE_THOUSAND_SEPARATOR`` are set. - -See also :setting:`NUMBER_GROUPING`, :setting:`DECIMAL_SEPARATOR` and -:setting:`USE_THOUSAND_SEPARATOR`. - -.. setting:: TIME_FORMAT - -TIME_FORMAT ------------ - -Default: ``'P'`` (e.g. ``4 p.m.``) - -The default formatting to use for displaying time fields in any part of the -system. Note that if :setting:`USE_L10N` is set to ``True``, then the -locale-dictated format has higher precedence and will be applied instead. See -:tfilter:`allowed date format strings <date>`. - -.. versionchanged:: 1.2 - This setting can now be overriden by setting ``USE_L10N`` to ``True``. - -See also ``DATE_FORMAT`` and ``DATETIME_FORMAT``. - -.. setting:: TIME_INPUT_FORMATS - -TIME_INPUT_FORMATS ------------------- - -.. versionadded:: 1.2 - -Default: ``('%H:%M:%S', '%H:%M')`` - -A tuple of formats that will be accepted when inputting data on a time -field. Formats will be tried in order, using the first valid. -Note that these format strings are specified in Python's datetime_ module -syntax, that is different from the one used by Django for formatting dates -to be displayed. - -See also ``DATE_INPUT_FORMATS`` and ``DATETIME_INPUT_FORMATS``. - -.. _datetime: http://docs.python.org/library/datetime.html#strftime-strptime-behavior - -.. setting:: TIME_ZONE - -TIME_ZONE ---------- - -Default: ``'America/Chicago'`` - -.. versionchanged:: 1.2 - ``None`` was added as an allowed value. - -A string representing the time zone for this installation, or -``None``. `See available choices`_. (Note that list of available -choices lists more than one on the same line; you'll want to use just -one of the choices for a given time zone. For instance, one line says -``'Europe/London GB GB-Eire'``, but you should use the first bit of -that -- ``'Europe/London'`` -- as your ``TIME_ZONE`` setting.) - -Note that this is the time zone to which Django will convert all -dates/times -- not necessarily the timezone of the server. For -example, one server may serve multiple Django-powered sites, each with -a separate time-zone setting. - -Normally, Django sets the ``os.environ['TZ']`` variable to the time -zone you specify in the ``TIME_ZONE`` setting. Thus, all your views -and models will automatically operate in the correct time zone. -However, Django won't set the ``TZ`` environment variable under the -following conditions: - - * If you're using the manual configuration option as described in - :ref:`manually configuring settings - <settings-without-django-settings-module>`, or - - * If you specify ``TIME_ZONE = None``. This will cause Django to fall - back to using the system timezone. - -If Django doesn't set the ``TZ`` environment variable, it's up to you -to ensure your processes are running in the correct environment. - -.. note:: - Django cannot reliably use alternate time zones in a Windows - environment. If you're running Django on Windows, this variable - must be set to match the system timezone. - - -.. _See available choices: http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE - -.. setting:: URL_VALIDATOR_USER_AGENT - -URL_VALIDATOR_USER_AGENT ------------------------- - -Default: ``Django/<version> (http://www.djangoproject.com/)`` - -The string to use as the ``User-Agent`` header when checking to see if URLs -exist (see the ``verify_exists`` option on :class:`~django.db.models.URLField`). - -.. setting:: USE_ETAGS - -USE_ETAGS ---------- - -Default: ``False`` - -A boolean that specifies whether to output the "Etag" header. This saves -bandwidth but slows down performance. This is only used if ``CommonMiddleware`` -is installed (see :doc:`/topics/http/middleware`). - -.. setting:: USE_I18N - -USE_I18N --------- - -Default: ``True`` - -A boolean that specifies whether Django's internationalization system should be -enabled. This provides an easy way to turn it off, for performance. If this is -set to ``False``, Django will make some optimizations so as not to load the -internationalization machinery. - -See also ``USE_L10N`` - -.. setting:: USE_L10N - -USE_L10N --------- - -.. versionadded:: 1.2 - -Default ``False`` - -A boolean that specifies if data will be localized by default or not. If this -is set to ``True``, e.g. Django will display numbers and dates using the -format of the current locale. - -See also ``USE_I18N`` and ``LANGUAGE_CODE`` - -.. setting:: USE_THOUSAND_SEPARATOR - -USE_THOUSAND_SEPARATOR ----------------------- - -.. versionadded:: 1.2 - -Default ``False`` - -A boolean that specifies wheter to display numbers using a thousand separator. -If this is set to ``True``, Django will use values from ``THOUSAND_SEPARATOR`` -and ``NUMBER_GROUPING`` from current locale, to format the number. -``USE_L10N`` must be set to ``True``, in order to format numbers. - -See also ``THOUSAND_SEPARATOR`` and ``NUMBER_GROUPING``. - -.. setting:: YEAR_MONTH_FORMAT - -YEAR_MONTH_FORMAT ------------------ - -Default: ``'F Y'`` - -The default formatting to use for date fields on Django admin change-list -pages -- and, possibly, by other parts of the system -- in cases when only the -year and month are displayed. - -For example, when a Django admin change-list page is being filtered by a date -drilldown, the header for a given month displays the month and the year. -Different locales have different formats. For example, U.S. English would say -"January 2006," whereas another locale might say "2006/January." - -See :tfilter:`allowed date format strings <date>`. See also ``DATE_FORMAT``, -``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``MONTH_DAY_FORMAT``. - -Deprecated settings -=================== - -.. setting:: DATABASE_ENGINE - -DATABASE_ENGINE ---------------- - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`ENGINE` in - :setting:`DATABASES`. - -.. setting:: DATABASE_HOST - -DATABASE_HOST -------------- - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`HOST` in - :setting:`DATABASES`. - -.. setting:: DATABASE_NAME - -DATABASE_NAME -------------- - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`NAME` in - :setting:`DATABASES`. - -.. setting:: DATABASE_OPTIONS - -DATABASE_OPTIONS ----------------- - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`OPTIONS` in - :setting:`DATABASES`. - -.. setting:: DATABASE_PASSWORD - -DATABASE_PASSWORD ------------------ - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`PASSWORD` in - :setting:`DATABASES`. - -.. setting:: DATABASE_PORT - -DATABASE_PORT -------------- - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`PORT` in - :setting:`DATABASES`. - -.. setting:: DATABASE_USER - -DATABASE_USER -------------- - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`USER` in - :setting:`DATABASES`. - -.. setting:: TEST_DATABASE_CHARSET - -TEST_DATABASE_CHARSET ---------------------- - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`TEST_CHARSET` in - :setting:`DATABASES`. - -.. setting:: TEST_DATABASE_COLLATION - -TEST_DATABASE_COLLATION ------------------------ - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`TEST_COLLATION` in - :setting:`DATABASES`. - -.. setting:: TEST_DATABASE_NAME - -TEST_DATABASE_NAME ------------------- - -.. deprecated:: 1.2 - This setting has been replaced by :setting:`TEST_NAME` in - :setting:`DATABASES`. - diff --git a/parts/django/docs/ref/signals.txt b/parts/django/docs/ref/signals.txt deleted file mode 100644 index 4bc1f3f..0000000 --- a/parts/django/docs/ref/signals.txt +++ /dev/null @@ -1,475 +0,0 @@ -======= -Signals -======= - -A list of all the signals that Django sends. - -.. seealso:: - - See the documentation on the :doc:`signal dispatcher </topics/signals>` for - information regarding how to register for and receive signals. - - The :doc:`comment framework </ref/contrib/comments/index>` sends a :doc:`set - of comment-related signals </ref/contrib/comments/signals>`. - -Model signals -============= - -.. module:: django.db.models.signals - :synopsis: Signals sent by the model system. - -The :mod:`django.db.models.signals` module defines a set of signals sent by the -module system. - -.. warning:: - - Many of these signals are sent by various model methods like - :meth:`~django.db.models.Model.__init__` or - :meth:`~django.db.models.Model.save` that you can overwrite in your own - code. - - If you override these methods on your model, you must call the parent class' - methods for this signals to be sent. - - Note also that Django stores signal handlers as weak references by default, - so if your handler is a local function, it may be garbage collected. To - prevent this, pass ``weak=False`` when you call the signal's :meth:`~django.dispatch.Signal.connect`. - -pre_init --------- - -.. attribute:: django.db.models.signals.pre_init - :module: - -.. ^^^^^^^ this :module: hack keeps Sphinx from prepending the module. - -Whenever you instantiate a Django model,, this signal is sent at the beginning -of the model's :meth:`~django.db.models.Model.__init__` method. - -Arguments sent with this signal: - - ``sender`` - The model class that just had an instance created. - - ``args`` - A list of positional arguments passed to - :meth:`~django.db.models.Model.__init__`: - - ``kwargs`` - A dictionary of keyword arguments passed to - :meth:`~django.db.models.Model.__init__`:. - -For example, the :doc:`tutorial </intro/tutorial01>` has this line: - -.. code-block:: python - - p = Poll(question="What's up?", pub_date=datetime.now()) - -The arguments sent to a :data:`pre_init` handler would be: - - ========== =============================================================== - Argument Value - ========== =============================================================== - ``sender`` ``Poll`` (the class itself) - - ``args`` ``[]`` (an empty list because there were no positional - arguments passed to ``__init__``.) - - ``kwargs`` ``{'question': "What's up?", 'pub_date': datetime.now()}`` - ========== =============================================================== - -post_init ---------- - -.. data:: django.db.models.signals.post_init - :module: - -Like pre_init, but this one is sent when the :meth:`~django.db.models.Model.__init__`: method finishes. - -Arguments sent with this signal: - - ``sender`` - As above: the model class that just had an instance created. - - ``instance`` - The actual instance of the model that's just been created. - -pre_save --------- - -.. data:: django.db.models.signals.pre_save - :module: - -This is sent at the beginning of a model's :meth:`~django.db.models.Model.save` -method. - -Arguments sent with this signal: - - ``sender`` - The model class. - - ``instance`` - The actual instance being saved. - -post_save ---------- - -.. data:: django.db.models.signals.post_save - :module: - -Like :data:`pre_save`, but sent at the end of the -:meth:`~django.db.models.Model.save` method. - -Arguments sent with this signal: - - ``sender`` - The model class. - - ``instance`` - The actual instance being saved. - - ``created`` - A boolean; ``True`` if a new record was created. - -pre_delete ----------- - -.. data:: django.db.models.signals.pre_delete - :module: - -Sent at the beginning of a model's :meth:`~django.db.models.Model.delete` -method. - -Arguments sent with this signal: - - ``sender`` - The model class. - - ``instance`` - The actual instance being deleted. - -post_delete ------------ - -.. data:: django.db.models.signals.post_delete - :module: - -Like :data:`pre_delete`, but sent at the end of the -:meth:`~django.db.models.Model.delete` method. - -Arguments sent with this signal: - - ``sender`` - The model class. - - ``instance`` - The actual instance being deleted. - - Note that the object will no longer be in the database, so be very - careful what you do with this instance. - -m2m_changed ------------ - -.. data:: django.db.models.signals.m2m_changed - :module: - -.. versionadded:: 1.2 - -Sent when a :class:`ManyToManyField` is changed on a model instance. -Strictly speaking, this is not a model signal since it is sent by the -:class:`ManyToManyField`, but since it complements the -:data:`pre_save`/:data:`post_save` and :data:`pre_delete`/:data:`post_delete` -when it comes to tracking changes to models, it is included here. - -Arguments sent with this signal: - - ``sender`` - The intermediate model class describing the :class:`ManyToManyField`. - This class is automatically created when a many-to-many field is - defined; you can access it using the ``through`` attribute on the - many-to-many field. - - ``instance`` - The instance whose many-to-many relation is updated. This can be an - instance of the ``sender``, or of the class the :class:`ManyToManyField` - is related to. - - ``action`` - A string indicating the type of update that is done on the relation. - This can be one of the following: - - ``"pre_add"`` - Sent *before* one or more objects are added to the relation - ``"post_add"`` - Sent *after* one or more objects are added to the relation - ``"pre_remove"`` - Sent *after* one or more objects are removed from the relation - ``"post_remove"`` - Sent *after* one or more objects are removed from the relation - ``"pre_clear"`` - Sent *before* the relation is cleared - ``"post_clear"`` - Sent *after* the relation is cleared - - ``reverse`` - Indicates which side of the relation is updated (i.e., if it is the - forward or reverse relation that is being modified). - - ``model`` - The class of the objects that are added to, removed from or cleared - from the relation. - - ``pk_set`` - For the ``pre_add``, ``post_add``, ``pre_remove`` and ``post_remove`` - actions, this is a list of primary key values that have been added to - or removed from the relation. - - For the ``pre_clear`` and ``post_clear`` actions, this is ``None``. - -For example, if a ``Pizza`` can have multiple ``Topping`` objects, modeled -like this: - -.. code-block:: python - - class Topping(models.Model): - # ... - - class Pizza(models.Model): - # ... - toppings = models.ManyToManyField(Topping) - -If we would do something like this: - -.. code-block:: python - - >>> p = Pizza.object.create(...) - >>> t = Topping.objects.create(...) - >>> p.toppings.add(t) - -the arguments sent to a :data:`m2m_changed` handler would be: - - ============== ============================================================ - Argument Value - ============== ============================================================ - ``sender`` ``Pizza.toppings.through`` (the intermediate m2m class) - - ``instance`` ``p`` (the ``Pizza`` instance being modified) - - ``action`` ``"pre_add"`` (followed by a separate signal with ``"post_add"``) - - ``reverse`` ``False`` (``Pizza`` contains the :class:`ManyToManyField`, - so this call modifies the forward relation) - - ``model`` ``Topping`` (the class of the objects added to the - ``Pizza``) - - ``pk_set`` ``[t.id]`` (since only ``Topping t`` was added to the relation) - ============== ============================================================ - -And if we would then do something like this: - -.. code-block:: python - - >>> t.pizza_set.remove(p) - -the arguments sent to a :data:`m2m_changed` handler would be: - - ============== ============================================================ - Argument Value - ============== ============================================================ - ``sender`` ``Pizza.toppings.through`` (the intermediate m2m class) - - ``instance`` ``t`` (the ``Topping`` instance being modified) - - ``action`` ``"pre_remove"`` (followed by a separate signal with ``"post_remove"``) - - ``reverse`` ``True`` (``Pizza`` contains the :class:`ManyToManyField`, - so this call modifies the reverse relation) - - ``model`` ``Pizza`` (the class of the objects removed from the - ``Topping``) - - ``pk_set`` ``[p.id]`` (since only ``Pizza p`` was removed from the - relation) - ============== ============================================================ - -class_prepared --------------- - -.. data:: django.db.models.signals.class_prepared - :module: - -Sent whenever a model class has been "prepared" -- that is, once model has -been defined and registered with Django's model system. Django uses this -signal internally; it's not generally used in third-party applications. - -Arguments that are sent with this signal: - -``sender`` - The model class which was just prepared. - -Management signals -================== - -Signals sent by :doc:`django-admin </ref/django-admin>`. - -post_syncdb ------------ - -.. data:: django.db.models.signals.post_syncdb - :module: - -Sent by :djadmin:`syncdb` after it installs an application. - -Any handlers that listen to this signal need to be written in a particular -place: a ``management`` module in one of your :setting:`INSTALLED_APPS`. If -handlers are registered anywhere else they may not be loaded by -:djadmin:`syncdb`. - -Arguments sent with this signal: - - ``sender`` - The ``models`` module that was just installed. That is, if - :djadmin:`syncdb` just installed an app called ``"foo.bar.myapp"``, - ``sender`` will be the ``foo.bar.myapp.models`` module. - - ``app`` - Same as ``sender``. - - ``created_models`` - A list of the model classes from any app which :djadmin:`syncdb` has - created so far. - - ``verbosity`` - Indicates how much information manage.py is printing on screen. See - the :djadminopt:`--verbosity` flag for details. - - Functions which listen for :data:`post_syncdb` should adjust what they - output to the screen based on the value of this argument. - - ``interactive`` - If ``interactive`` is ``True``, it's safe to prompt the user to input - things on the command line. If ``interactive`` is ``False``, functions - which listen for this signal should not try to prompt for anything. - - For example, the :mod:`django.contrib.auth` app only prompts to create a - superuser when ``interactive`` is ``True``. - -Request/response signals -======================== - -.. module:: django.core.signals - :synopsis: Core signals sent by the request/response system. - -Signals sent by the core framework when processing a request. - -request_started ---------------- - -.. data:: django.core.signals.request_started - :module: - -Sent when Django begins processing an HTTP request. - -Arguments sent with this signal: - - ``sender`` - The handler class -- i.e. - :class:`django.core.handlers.modpython.ModPythonHandler` or - :class:`django.core.handlers.wsgi.WsgiHandler` -- that handled - the request. - -request_finished ----------------- - -.. data:: django.core.signals.request_finished - :module: - -Sent when Django finishes processing an HTTP request. - -Arguments sent with this signal: - - ``sender`` - The handler class, as above. - -got_request_exception ---------------------- - -.. data:: django.core.signals.got_request_exception - :module: - -This signal is sent whenever Django encounters an exception while processing an incoming HTTP request. - -Arguments sent with this signal: - - ``sender`` - The handler class, as above. - - ``request`` - The :class:`~django.http.HttpRequest` object. - -Test signals -============ - -.. module:: django.test.signals - :synopsis: Signals sent during testing. - -Signals only sent when :doc:`running tests </topics/testing>`. - -template_rendered ------------------ - -.. data:: django.test.signals.template_rendered - :module: - -Sent when the test system renders a template. This signal is not emitted during -normal operation of a Django server -- it is only available during testing. - -Arguments sent with this signal: - - sender - The :class:`~django.template.Template` object which was rendered. - - template - Same as sender - - context - The :class:`~django.template.Context` with which the template was - rendered. - -Database Wrappers -================= - -.. module:: django.db.backends - :synopsis: Core signals sent by the database wrapper. - -Signals sent by the database wrapper when a database connection is -initiated. - -connection_created ------------------- - -.. data:: django.db.backends.signals.connection_created - :module: - -.. versionadded:: 1.1 - -.. versionchanged:: 1.2 - The connection argument was added - -Sent when the database wrapper makes the initial connection to the -database. This is particularly useful if you'd like to send any post -connection commands to the SQL backend. - -Arguments sent with this signal: - - sender - The database wrapper class -- i.e. - :class: `django.db.backends.postgresql_psycopg2.DatabaseWrapper` or - :class: `django.db.backends.mysql.DatabaseWrapper`, etc. - - connection - The database connection that was opened. This can be used in a - multiple-database configuration to differentiate connection signals - from different databases. diff --git a/parts/django/docs/ref/templates/api.txt b/parts/django/docs/ref/templates/api.txt deleted file mode 100644 index 1111869..0000000 --- a/parts/django/docs/ref/templates/api.txt +++ /dev/null @@ -1,815 +0,0 @@ -==================================================== -The Django template language: For Python programmers -==================================================== - -This document explains the Django template system from a technical -perspective -- how it works and how to extend it. If you're just looking for -reference on the language syntax, see :doc:`/topics/templates`. - -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. - -.. _configuration: `configuring the template system in standalone mode`_ - -Basics -====== - -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**. - -A **block tag** is a symbol within a template that does something. - -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. - -Block tags are surrounded by ``"{%"`` and ``"%}"``. - -Example template with block tags: - -.. code-block:: html+django - - {% 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: - -.. code-block:: html+django - - 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 -========================= - -.. class:: django.template.Template - -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 :class:`django.template.Template`. The constructor -takes one argument -- the raw template code:: - - >>> from django.template import Template - >>> t = Template("My name is {{ my_name }}.") - >>> print t - <django.template.Template instance> - -.. admonition:: Behind the scenes - - The system only parses your raw template code once -- when you create the - ``Template`` object. From then on, it's stored internally as a "node" - structure for performance. - - Even the parsing itself is quite fast. Most of the parsing happens via a - single call to a single, short, regular expression. - -Rendering a context -------------------- - -.. method:: render(context) - -Once you have a compiled ``Template`` object, you can render a context -- or -multiple contexts -- with it. The ``Context`` class lives at -:class:`django.template.Context`, and the constructor takes two (optional) -arguments: - - * A dictionary mapping variable names to variable values. - - * The name of the current application. This application name is used - to help :ref:`resolve namespaced URLs<topics-http-reversing-url-namespaces>`. - If you're not using namespaced URLs, you can ignore this argument. - -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 :exc:`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 :meth:`~django.db.models.Model.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 - :meth:`~django.db.models.Model.delete` and - :meth:`~django.db.models.Model.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 - -.. _invalid-template-variables: - -How invalid variables are handled -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Generally, if a variable doesn't exist, the template system inserts the -value of the :setting:`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 -:setting:`TEMPLATE_STRING_IF_INVALID` is set to ``''`` (the empty string). If -:setting:`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 :setting:`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 :setting:`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 - :setting:`TEMPLATE_STRING_IF_INVALID`, you will experience rendering - problems with these templates and sites. - - Generally, :setting:`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 ----------------------------- - -.. class:: django.template.Context - -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' - -.. method:: pop() -.. method:: push() -.. exception:: django.template.ContextPopException - -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 - -.. method:: update(other_dict) - -In addition to ``push()`` and ``pop()``, the ``Context`` -object also defines an ``update()`` method. This works like ``push()`` -but takes a dictionary as an argument and pushes that dictionary onto -the stack instead of an empty one. - - >>> c = Context() - >>> c['foo'] = 'first level' - >>> c.update({'foo': 'updated'}) - {'foo': 'updated'} - >>> c['foo'] - 'updated' - >>> c.pop() - {'foo': 'updated'} - >>> c['foo'] - 'first level' - -Using a ``Context`` as a stack comes in handy in some custom template tags, as -you'll see below. - -.. _subclassing-context-requestcontext: - -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 -:class:`~django.http.HttpRequest` 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 :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting. - -The :setting:`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, -:setting:`TEMPLATE_CONTEXT_PROCESSORS` is set to:: - - ("django.contrib.auth.context_processors.auth", - "django.core.context_processors.debug", - "django.core.context_processors.i18n", - "django.core.context_processors.media", - "django.contrib.messages.context_processors.messages") - -.. versionadded:: 1.2 - In addition to these, ``RequestContext`` always uses - ``django.core.context_processors.csrf``. This is a security - related context processor required by the admin and other contrib apps, and, - in case of accidental misconfiguration, it is deliberately hardcoded in and - cannot be turned off by the :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting. - -.. versionadded:: 1.2 - The ``'messages'`` context processor was added. For more information, see - the :doc:`messages documentation </ref/contrib/messages>`. - -.. versionchanged:: 1.2 - The auth context processor was moved in this release from its old location - ``django.core.context_processors.auth`` to - ``django.contrib.auth.context_processors.auth``. - -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. - -.. admonition:: When context processors are applied - - When you use ``RequestContext``, the variables you supply directly - are added first, followed any variables supplied by context - processors. This means that a context processor may overwrite a - variable you've supplied, so take care to avoid variable names - which overlap with those supplied by your context processors. - -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 HttpResponse(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: - -django.contrib.auth.context_processors.auth -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If :setting:`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). - - * ``messages`` -- A list of messages (as strings) that have been set - via the :doc:`messages framework </ref/contrib/messages>`. - - * ``perms`` -- An instance of - ``django.core.context_processors.PermWrapper``, representing the - permissions that the currently logged-in user has. - -.. versionchanged:: 1.2 - This context processor was moved in this release from - ``django.core.context_processors.auth`` to its current location. - -.. versionchanged:: 1.2 - Prior to version 1.2, the ``messages`` variable was a lazy accessor for - ``user.get_and_delete_messages()``. It has been changed to include any - messages added via the :doc:`messages framework </ref/contrib/messages>`. - -django.core.context_processors.debug -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every -``RequestContext`` will contain these two variables -- but only if your -:setting:`DEBUG` setting is set to ``True`` and the request's IP address -(``request.META['REMOTE_ADDR']``) is in the :setting:`INTERNAL_IPS` setting: - - * ``debug`` -- ``True``. You can use this in templates to test whether - you're in :setting:`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 :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every -``RequestContext`` will contain these two variables: - - * ``LANGUAGES`` -- The value of the :setting:`LANGUAGES` setting. - * ``LANGUAGE_CODE`` -- ``request.LANGUAGE_CODE``, if it exists. Otherwise, - the value of the :setting:`LANGUAGE_CODE` setting. - -See :doc:`/topics/i18n/index` for more. - -django.core.context_processors.media -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every -``RequestContext`` will contain a variable ``MEDIA_URL``, providing the -value of the :setting:`MEDIA_URL` setting. - -django.core.context_processors.csrf -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - -This processor adds a token that is needed by the ``csrf_token`` template tag -for protection against :doc:`Cross Site Request Forgeries </ref/contrib/csrf>`. - -django.core.context_processors.request -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every -``RequestContext`` will contain a variable ``request``, which is the current -:class:`~django.http.HttpRequest`. Note that this processor is not enabled by default; -you'll have to activate it. - -django.contrib.messages.context_processors.messages -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every -``RequestContext`` will contain a single additional variable: - - * ``messages`` -- A list of messages (as strings) that have been set - via the user model (using ``user.message_set.create``) or through - the :doc:`messages framework </ref/contrib/messages>`. - -.. versionadded:: 1.2 - This template context variable was previously supplied by the ``'auth'`` - context processor. For backwards compatibility the ``'auth'`` context - processor will continue to supply the ``messages`` variable until Django - 1.4. If you use the ``messages`` variable, your project will work with - either (or both) context processors, but it is recommended to add - ``django.contrib.messages.context_processors.messages`` so your project - will be prepared for the future upgrade. - -Writing your own context processors -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A context processor has a very simple interface: It's just a Python function -that takes one argument, an :class:`~django.http.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 -:setting:`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 :setting:`TEMPLATE_DIRS` -setting. - -The TEMPLATE_DIRS setting -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Tell Django what your template directories are by using the -:setting:`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. - -.. _ref-templates-api-the-python-api: - -The Python API -~~~~~~~~~~~~~~ - -Django has two ways to load templates from files: - -.. function:: 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``. - -.. function:: 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 :setting:`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 :setting:`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`` - -.. _template-loaders: - -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. - -Some of these other loaders are disabled by default, but you can activate them -by editing your :setting:`TEMPLATE_LOADERS` setting. :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.Loader`` - Loads templates from the filesystem, according to :setting:`TEMPLATE_DIRS`. - This loader is enabled by default. - -``django.template.loaders.app_directories.Loader`` - Loads templates from Django apps on the filesystem. For each app in - :setting:`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 :setting:`INSTALLED_APPS` packages have a - ``templates`` subdirectory. - - This loader is enabled by default. - -``django.template.loaders.eggs.Loader`` - Just like ``app_directories`` above, but it loads templates from Python - eggs rather than from the filesystem. - - This loader is disabled by default. - -``django.template.loaders.cached.Loader`` - By default, the templating system will read and compile your templates every - time they need to be rendered. While the Django templating system is quite - fast, the overhead from reading and compiling templates can add up. - - The cached template loader is a class-based loader that you configure with - a list of other loaders that it should wrap. The wrapped loaders are used to - locate unknown templates when they are first encountered. The cached loader - then stores the compiled ``Template`` in memory. The cached ``Template`` - instance is returned for subsequent requests to load the same template. - - For example, to enable template caching with the ``filesystem`` and - ``app_directories`` template loaders you might use the following settings:: - - TEMPLATE_LOADERS = ( - ('django.template.loaders.cached.Loader', ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - )), - ) - - .. note:: - All of the built-in Django template tags are safe to use with the cached - loader, but if you're using custom template tags that come from third - party packages, or that you wrote yourself, you should ensure that the - ``Node`` implementation for each tag is thread-safe. For more - information, see - :ref:`template tag thread safety considerations<template_tag_thread_safety>`. - - This loader is disabled by default. - -Django uses the template loaders in order according to the -:setting:`TEMPLATE_LOADERS` setting. It uses each loader until a loader finds a -match. - -The ``render_to_string`` shortcut -=================================== - -.. function:: django.template.loader.render_to_string(template_name, dictionary=None, context_instance=None) - -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 -:mod:`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 (or a list of template names, in which case Django will use -the first template in the list that exists) -- 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 :func:`~django.shortcuts.render_to_response()` shortcut, which -calls ``render_to_string`` and feeds the result into an :class:`~django.http.HttpResponse` -suitable for returning directly from a view. - -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 :envvar:`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 :ref:`settings-without-django-settings-module`. Simply import the appropriate -pieces of the templating system and then, *before* you call any of the -templating functions, call :func:`django.conf.settings.configure()` with any -settings you wish to specify. You might want to consider setting at least -:setting:`TEMPLATE_DIRS` (if you're going to use template loaders), -:setting:`DEFAULT_CHARSET` (although the default of ``utf-8`` is probably fine) -and :setting:`TEMPLATE_DEBUG`. All available settings are described in the -:doc:`settings documentation </ref/settings>`, and any setting starting with -``TEMPLATE_`` is of obvious interest. - -.. _topic-template-alternate-language: - -Using an alternative template language -====================================== - -.. versionadded:: 1.2 - -The Django ``Template`` and ``Loader`` classes implement a simple API for -loading and rendering templates. By providing some simple wrapper classes that -implement this API we can use third party template systems like `Jinja2 -<http://jinja.pocoo.org/2/>`_ or `Cheetah <http://www.cheetahtemplate.org/>`_. This -allows us to use third-party template libraries without giving up useful Django -features like the Django ``Context`` object and handy shortcuts like -``render_to_response()``. - -The core component of the Django templating system is the ``Template`` class. -This class has a very simple interface: it has a constructor that takes a single -positional argument specifying the template string, and a ``render()`` method -that takes a :class:`~django.template.Context` object and returns a string -containing the rendered response. - -Suppose we're using a template language that defines a ``Template`` object with -a ``render()`` method that takes a dictionary rather than a ``Context`` object. -We can write a simple wrapper that implements the Django ``Template`` interface:: - - import some_template_language - class Template(some_template_language.Template): - def render(self, context): - # flatten the Django Context into a single dictionary. - context_dict = {} - for d in context.dicts: - context_dict.update(d) - return super(Template, self).render(context_dict) - -That's all that's required to make our fictional ``Template`` class compatible -with the Django loading and rendering system! - -The next step is to write a ``Loader`` class that returns instances of our custom -template class instead of the default :class:`~django.template.Template`. Custom ``Loader`` -classes should inherit from ``django.template.loader.BaseLoader`` and override -the ``load_template_source()`` method, which takes a ``template_name`` argument, -loads the template from disk (or elsewhere), and returns a tuple: -``(template_string, template_origin)``. - -The ``load_template()`` method of the ``Loader`` class retrieves the template -string by calling ``load_template_source()``, instantiates a ``Template`` from -the template source, and returns a tuple: ``(template, template_origin)``. Since -this is the method that actually instantiates the ``Template``, we'll need to -override it to use our custom template class instead. We can inherit from the -builtin :class:`django.template.loaders.app_directories.Loader` to take advantage -of the ``load_template_source()`` method implemented there:: - - from django.template.loaders import app_directories - class Loader(app_directories.Loader): - is_usable = True - - def load_template(self, template_name, template_dirs=None): - source, origin = self.load_template_source(template_name, template_dirs) - template = Template(source) - return template, origin - -Finally, we need to modify our project settings, telling Django to use our custom -loader. Now we can write all of our templates in our alternative template -language while continuing to use the rest of the Django templating system. diff --git a/parts/django/docs/ref/templates/builtins.txt b/parts/django/docs/ref/templates/builtins.txt deleted file mode 100644 index 44bbc37..0000000 --- a/parts/django/docs/ref/templates/builtins.txt +++ /dev/null @@ -1,2107 +0,0 @@ -================================== -Built-in template tags and filters -================================== - -This document describes Django's built-in template tags and filters. It is -recommended that you use the :doc:`automatic documentation -</ref/contrib/admin/admindocs>`, if available, as this will also include -documentation for any custom tags or filters installed. - -.. _ref-templates-builtins-tags: - -Built-in tag reference ----------------------- - -.. highlightlang:: html+django - -.. templatetag:: autoescape - -autoescape -~~~~~~~~~~ - -.. versionadded:: 1.0 - -Control the current auto-escaping behavior. This tag takes either ``on`` or -``off`` as an argument and that determines whether auto-escaping is in effect -inside the block. The block is closed with an ``endautoescape`` ending tag. - -When auto-escaping is in effect, all variable content has HTML escaping applied -to it before placing the result into the output (but after any filters have -been applied). This is equivalent to manually applying the ``escape`` filter -to each variable. - -The only exceptions are variables that are already marked as "safe" from -escaping, either by the code that populated the variable, or because it has had -the ``safe`` or ``escape`` filters applied. - -Sample usage:: - - {% autoescape on %} - {{ body }} - {% endautoescape %} - -.. templatetag:: block - -block -~~~~~ - -Define a block that can be overridden by child templates. See -:ref:`Template inheritance <template-inheritance>` for more information. - -.. templatetag:: comment - -comment -~~~~~~~ - -Ignore everything between ``{% comment %}`` and ``{% endcomment %}`` - -.. templatetag:: csrf_token - -csrf_token -~~~~~~~~~~ - -.. versionadded:: 1.1.2 - -In the Django 1.1.X series, this is a no-op tag that returns an empty string for -future compatibility purposes. In Django 1.2 and later, it is used for CSRF -protection, as described in the documentation for :doc:`Cross Site Request -Forgeries </ref/contrib/csrf>`. - -.. templatetag:: cycle - -cycle -~~~~~ - -.. versionchanged:: 1.0 - Cycle among the given strings or variables each time this tag is encountered. - -Within a loop, cycles among the given strings each time through the -loop:: - - {% for o in some_list %} - <tr class="{% cycle 'row1' 'row2' %}"> - ... - </tr> - {% endfor %} - -You can use variables, too. For example, if you have two template variables, -``rowvalue1`` and ``rowvalue2``, you can cycle between their values like this:: - - {% for o in some_list %} - <tr class="{% cycle rowvalue1 rowvalue2 %}"> - ... - </tr> - {% endfor %} - -Yes, you can mix variables and strings:: - - {% for o in some_list %} - <tr class="{% cycle 'row1' rowvalue2 'row3' %}"> - ... - </tr> - {% endfor %} - -In some cases you might want to refer to the next value of a cycle from -outside of a loop. To do this, just give the ``{% cycle %}`` tag a name, using -"as", like this:: - - {% cycle 'row1' 'row2' as rowcolors %} - -From then on, you can insert the current value of the cycle wherever you'd like -in your template:: - - <tr class="{% cycle rowcolors %}">...</tr> - <tr class="{% cycle rowcolors %}">...</tr> - -You can use any number of values in a ``{% cycle %}`` tag, separated by spaces. -Values enclosed in single (``'``) or double quotes (``"``) are treated as -string literals, while values without quotes are treated as template variables. - -Note that the variables included in the cycle will not be escaped. -This is because template tags do not escape their content. Any HTML or -Javascript code contained in the printed variable will be rendered -as-is, which could potentially lead to security issues. - -If you need to escape the variables in the cycle, you must do so -explicitly:: - - {% filter force_escape %} - {% cycle var1 var2 var3 %} - {% endfilter %} - -For backwards compatibility, the ``{% cycle %}`` tag supports the much inferior -old syntax from previous Django versions. You shouldn't use this in any new -projects, but for the sake of the people who are still using it, here's what it -looks like:: - - {% cycle row1,row2,row3 %} - -In this syntax, each value gets interpreted as a literal string, and there's no -way to specify variable values. Or literal commas. Or spaces. Did we mention -you shouldn't use this syntax in any new projects? - -.. templatetag:: debug - -debug -~~~~~ - -Output a whole load of debugging information, including the current context and -imported modules. - -.. templatetag:: extends - -extends -~~~~~~~ - -Signal that this template extends a parent template. - -This tag can be used in two ways: - - * ``{% extends "base.html" %}`` (with quotes) uses the literal value - ``"base.html"`` as the name of the parent template to extend. - - * ``{% extends variable %}`` uses the value of ``variable``. If the variable - evaluates to a string, Django will use that string as the name of the - parent template. If the variable evaluates to a ``Template`` object, - Django will use that object as the parent template. - -See :ref:`template-inheritance` for more information. - -.. templatetag:: filter - -filter -~~~~~~ - -Filter the contents of the variable through variable filters. - -Filters can also be piped through each other, and they can have arguments -- -just like in variable syntax. - -Sample usage:: - - {% filter force_escape|lower %} - This text will be HTML-escaped, and will appear in all lowercase. - {% endfilter %} - -.. templatetag:: firstof - -firstof -~~~~~~~ - -Outputs the first variable passed that is not False, without escaping. - -Outputs nothing if all the passed variables are False. - -Sample usage:: - - {% firstof var1 var2 var3 %} - -This is equivalent to:: - - {% if var1 %} - {{ var1|safe }} - {% else %}{% if var2 %} - {{ var2|safe }} - {% else %}{% if var3 %} - {{ var3|safe }} - {% endif %}{% endif %}{% endif %} - -You can also use a literal string as a fallback value in case all -passed variables are False:: - - {% firstof var1 var2 var3 "fallback value" %} - -Note that the variables included in the firstof tag will not be -escaped. This is because template tags do not escape their content. -Any HTML or Javascript code contained in the printed variable will be -rendered as-is, which could potentially lead to security issues. - -If you need to escape the variables in the firstof tag, you must do so -explicitly:: - - {% filter force_escape %} - {% firstof var1 var2 var3 "fallback value" %} - {% endfilter %} - -.. templatetag:: for - -for -~~~ - -Loop over each item in an array. For example, to display a list of athletes -provided in ``athlete_list``:: - - <ul> - {% for athlete in athlete_list %} - <li>{{ athlete.name }}</li> - {% endfor %} - </ul> - -You can loop over a list in reverse by using ``{% for obj in list reversed %}``. - -.. versionadded:: 1.0 - -If you need to loop over a list of lists, you can unpack the values -in each sub-list into individual variables. For example, if your context -contains a list of (x,y) coordinates called ``points``, you could use the -following to output the list of points:: - - {% for x, y in points %} - There is a point at {{ x }},{{ y }} - {% endfor %} - -This can also be useful if you need to access the items in a dictionary. -For example, if your context contained a dictionary ``data``, the following -would display the keys and values of the dictionary:: - - {% for key, value in data.items %} - {{ key }}: {{ value }} - {% endfor %} - -The for loop sets a number of variables available within the loop: - - ========================== ================================================ - Variable Description - ========================== ================================================ - ``forloop.counter`` The current iteration of the loop (1-indexed) - ``forloop.counter0`` The current iteration of the loop (0-indexed) - ``forloop.revcounter`` The number of iterations from the end of the - loop (1-indexed) - ``forloop.revcounter0`` The number of iterations from the end of the - loop (0-indexed) - ``forloop.first`` True if this is the first time through the loop - ``forloop.last`` True if this is the last time through the loop - ``forloop.parentloop`` For nested loops, this is the loop "above" the - current one - ========================== ================================================ - -for ... empty -^^^^^^^^^^^^^ - -.. versionadded:: 1.1 - -The ``for`` tag can take an optional ``{% empty %}`` clause that will be -displayed if the given array is empty or could not be found:: - - <ul> - {% for athlete in athlete_list %} - <li>{{ athlete.name }}</li> - {% empty %} - <li>Sorry, no athlete in this list!</li> - {% endfor %} - <ul> - -The above is equivalent to -- but shorter, cleaner, and possibly faster -than -- the following:: - - <ul> - {% if athlete_list %} - {% for athlete in athlete_list %} - <li>{{ athlete.name }}</li> - {% endfor %} - {% else %} - <li>Sorry, no athletes in this list.</li> - {% endif %} - </ul> - -.. templatetag:: if - -if -~~ - -The ``{% if %}`` tag evaluates a variable, and if that variable is "true" (i.e. -exists, is not empty, and is not a false boolean value) the contents of the -block are output:: - - {% if athlete_list %} - Number of athletes: {{ athlete_list|length }} - {% else %} - No athletes. - {% endif %} - -In the above, if ``athlete_list`` is not empty, the number of athletes will be -displayed by the ``{{ athlete_list|length }}`` variable. - -As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that -will be displayed if the test fails. - -Boolean operators -^^^^^^^^^^^^^^^^^ - -``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or -to negate a given variable:: - - {% if athlete_list and coach_list %} - Both athletes and coaches are available. - {% endif %} - - {% if not athlete_list %} - There are no athletes. - {% endif %} - - {% if athlete_list or coach_list %} - There are some athletes or some coaches. - {% endif %} - - {% if not athlete_list or coach_list %} - There are no athletes or there are some coaches (OK, so - writing English translations of boolean logic sounds - stupid; it's not our fault). - {% endif %} - - {% if athlete_list and not coach_list %} - There are some athletes and absolutely no coaches. - {% endif %} - -.. versionchanged:: 1.2 - -Use of both ``and`` and ``or`` clauses within the same tag is allowed, with -``and`` having higher precedence than ``or`` e.g.:: - - {% if athlete_list and coach_list or cheerleader_list %} - -will be interpreted like: - -.. code-block:: python - - if (athlete_list and coach_list) or cheerleader_list - -Use of actual brackets in the ``if`` tag is invalid syntax. If you need them to -indicate precedence, you should use nested ``if`` tags. - -.. versionadded:: 1.2 - - -``if`` tags may also use the operators ``==``, ``!=``, ``<``, ``>``, -``<=``, ``>=`` and ``in`` which work as follows: - - -``==`` operator -^^^^^^^^^^^^^^^ - -Equality. Example:: - - {% if somevar == "x" %} - This appears if variable somevar equals the string "x" - {% endif %} - -``!=`` operator -^^^^^^^^^^^^^^^ - -Inequality. Example:: - - {% if somevar != "x" %} - This appears if variable somevar does not equal the string "x", - or if somevar is not found in the context - {% endif %} - -``<`` operator -^^^^^^^^^^^^^^ - -Less than. Example:: - - {% if somevar < 100 %} - This appears if variable somevar is less than 100. - {% endif %} - -``>`` operator -^^^^^^^^^^^^^^ - -Greater than. Example:: - - {% if somevar > 0 %} - This appears if variable somevar is greater than 0. - {% endif %} - -``<=`` operator -^^^^^^^^^^^^^^^ - -Less than or equal to. Example:: - - {% if somevar <= 100 %} - This appears if variable somevar is less than 100 or equal to 100. - {% endif %} - -``>=`` operator -^^^^^^^^^^^^^^^ - -Greater than or equal to. Example:: - - {% if somevar >= 1 %} - This appears if variable somevar is greater than 1 or equal to 1. - {% endif %} - -``in`` operator -^^^^^^^^^^^^^^^ - -Contained within. This operator is supported by many Python containers to test -whether the given value is in the container. The following are some examples of -how ``x in y`` will be interpreted:: - - {% if "bc" in "abcdef" %} - This appears since "bc" is a substring of "abcdef" - {% endif %} - - {% if "hello" in greetings %} - If greetings is a list or set, one element of which is the string - "hello", this will appear. - {% endif %} - - {% if user in users %} - If users is a QuerySet, this will appear if user is an - instance that belongs to the QuerySet. - {% endif %} - -``not in`` operator -~~~~~~~~~~~~~~~~~~~~ - -Not contained within. This is the negation of the ``in`` operator. - - -The comparison operators cannot be 'chained' like in Python or in mathematical -notation. For example, instead of using:: - - {% if a > b > c %} (WRONG) - -you should use:: - - {% if a > b and b > c %} - - -Filters -^^^^^^^ - -You can also use filters in the ``if`` expression. For example:: - - {% if messages|length >= 100 %} - You have lots of messages today! - {% endif %} - -Complex expressions -^^^^^^^^^^^^^^^^^^^ - -All of the above can be combined to form complex expressions. For such -expressions, it can be important to know how the operators are grouped when the -expression is evaluated - that is, the precedence rules. The precedence of the -operators, from lowest to highest, is as follows: - - * ``or`` - * ``and`` - * ``not`` - * ``in`` - * ``==``, ``!=``, ``<``, ``>``,``<=``, ``>=`` - -(This follows Python exactly). So, for example, the following complex if tag: - - {% if a == b or c == d and e %} - -...will be interpreted as: - -.. code-block:: python - - (a == b) or ((c == d) and e) - -If you need different precedence, you will need to use nested if tags. Sometimes -that is better for clarity anyway, for the sake of those who do not know the -precedence rules. - - -.. templatetag:: ifchanged - -ifchanged -~~~~~~~~~ - -Check if a value has changed from the last iteration of a loop. - -The 'ifchanged' block tag is used within a loop. It has two possible uses. - -1. Checks its own rendered contents against its previous state and only - displays the content if it has changed. For example, this displays a list of - days, only displaying the month if it changes:: - - <h1>Archive for {{ year }}</h1> - - {% for date in days %} - {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %} - <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a> - {% endfor %} - -2. If given a variable, check whether that variable has changed. For - example, the following shows the date every time it changes, but - only shows the hour if both the hour and the date has changed:: - - {% for date in days %} - {% ifchanged date.date %} {{ date.date }} {% endifchanged %} - {% ifchanged date.hour date.date %} - {{ date.hour }} - {% endifchanged %} - {% endfor %} - -The ``ifchanged`` tag can also take an optional ``{% else %}`` clause that -will be displayed if the value has not changed:: - - {% for match in matches %} - <div style="background-color: - {% ifchanged match.ballot_id %} - {% cycle "red" "blue" %} - {% else %} - grey - {% endifchanged %} - ">{{ match }}</div> - {% endfor %} - -.. templatetag:: ifequal - -ifequal -~~~~~~~ - -Output the contents of the block if the two arguments equal each other. - -Example:: - - {% ifequal user.id comment.user_id %} - ... - {% endifequal %} - -As in the ``{% if %}`` tag, an ``{% else %}`` clause is optional. - -The arguments can be hard-coded strings, so the following is valid:: - - {% ifequal user.username "adrian" %} - ... - {% endifequal %} - -It is only possible to compare an argument to template variables or strings. -You cannot check for equality with Python objects such as ``True`` or -``False``. If you need to test if something is true or false, use the ``if`` -tag instead. - -.. versionadded:: 1.2 - An alternative to the ``ifequal`` tag is to use the :ttag:`if` tag and the ``==`` operator. - -.. templatetag:: ifnotequal - -ifnotequal -~~~~~~~~~~ - -Just like ``ifequal``, except it tests that the two arguments are not equal. - -.. versionadded:: 1.2 - An alternative to the ``ifnotequal`` tag is to use the :ttag:`if` tag and the ``!=`` operator. - -.. templatetag:: include - -include -~~~~~~~ - -Loads a template and renders it with the current context. This is a way of -"including" other templates within a template. - -The template name can either be a variable or a hard-coded (quoted) string, -in either single or double quotes. - -This example includes the contents of the template ``"foo/bar.html"``:: - - {% include "foo/bar.html" %} - -This example includes the contents of the template whose name is contained in -the variable ``template_name``:: - - {% include template_name %} - -An included template is rendered with the context of the template that's -including it. This example produces the output ``"Hello, John"``: - - * Context: variable ``person`` is set to ``"john"``. - * Template:: - - {% include "name_snippet.html" %} - - * The ``name_snippet.html`` template:: - - Hello, {{ person }} - -See also: ``{% ssi %}``. - -.. note:: - The :ttag:`include` tag should be considered as an implementation of - "render this subtemplate and include the HTML", not as "parse this - subtemplate and include its contents as if it were part of the parent". - This means that there is no shared state between included templates -- - each include is a completely independent rendering process. - -.. templatetag:: load - -load -~~~~ - -Load a custom template tag set. - -See :doc:`Custom tag and filter libraries </howto/custom-template-tags>` for more information. - -.. templatetag:: now - -now -~~~ - -Display the current date and/or time, according to the given string. - -Given format can be one of the predefined ones ``DATE_FORMAT``, -``DATETIME_FORMAT``, ``SHORT_DATE_FORMAT`` or ``SHORT_DATETIME_FORMAT``, -or a custom format, same as the :tfilter:`date` filter. Note that predefined -formats may vary depending on the current locale. - -Example:: - - It is {% now "jS F Y H:i" %} - -Note that you can backslash-escape a format string if you want to use the -"raw" value. In this example, "f" is backslash-escaped, because otherwise -"f" is a format string that displays the time. The "o" doesn't need to be -escaped, because it's not a format character:: - - It is the {% now "jS o\f F" %} - -This would display as "It is the 4th of September". - -.. templatetag:: regroup - -regroup -~~~~~~~ - -Regroup a list of alike objects by a common attribute. - -This complex tag is best illustrated by use of an example: say that ``people`` -is a list of people represented by dictionaries with ``first_name``, -``last_name``, and ``gender`` keys: - -.. code-block:: python - - people = [ - {'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'}, - {'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'}, - {'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'}, - {'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'}, - {'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'}, - ] - -...and you'd like to display a hierarchical list that is ordered by gender, -like this: - - * Male: - * George Bush - * Bill Clinton - * Female: - * Margaret Thatcher - * Condoleezza Rice - * Unknown: - * Pat Smith - -You can use the ``{% regroup %}`` tag to group the list of people by gender. -The following snippet of template code would accomplish this:: - - {% regroup people by gender as gender_list %} - - <ul> - {% for gender in gender_list %} - <li>{{ gender.grouper }} - <ul> - {% for item in gender.list %} - <li>{{ item.first_name }} {{ item.last_name }}</li> - {% endfor %} - </ul> - </li> - {% endfor %} - </ul> - -Let's walk through this example. ``{% regroup %}`` takes three arguments: the -list you want to regroup, the attribute to group by, and the name of the -resulting list. Here, we're regrouping the ``people`` list by the ``gender`` -attribute and calling the result ``gender_list``. - -``{% regroup %}`` produces a list (in this case, ``gender_list``) of -**group objects**. Each group object has two attributes: - - * ``grouper`` -- the item that was grouped by (e.g., the string "Male" or - "Female"). - * ``list`` -- a list of all items in this group (e.g., a list of all people - with gender='Male'). - -Note that ``{% regroup %}`` does not order its input! Our example relies on -the fact that the ``people`` list was ordered by ``gender`` in the first place. -If the ``people`` list did *not* order its members by ``gender``, the regrouping -would naively display more than one group for a single gender. For example, -say the ``people`` list was set to this (note that the males are not grouped -together): - -.. code-block:: python - - people = [ - {'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'}, - {'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'}, - {'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'}, - {'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'}, - {'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'}, - ] - -With this input for ``people``, the example ``{% regroup %}`` template code -above would result in the following output: - - * Male: - * Bill Clinton - * Unknown: - * Pat Smith - * Female: - * Margaret Thatcher - * Male: - * George Bush - * Female: - * Condoleezza Rice - -The easiest solution to this gotcha is to make sure in your view code that the -data is ordered according to how you want to display it. - -Another solution is to sort the data in the template using the ``dictsort`` -filter, if your data is in a list of dictionaries:: - - {% regroup people|dictsort:"gender" by gender as gender_list %} - -.. templatetag:: spaceless - -spaceless -~~~~~~~~~ - -Removes whitespace between HTML tags. This includes tab -characters and newlines. - -Example usage:: - - {% spaceless %} - <p> - <a href="foo/">Foo</a> - </p> - {% endspaceless %} - -This example would return this HTML:: - - <p><a href="foo/">Foo</a></p> - -Only space between *tags* is removed -- not space between tags and text. In -this example, the space around ``Hello`` won't be stripped:: - - {% spaceless %} - <strong> - Hello - </strong> - {% endspaceless %} - -.. templatetag:: ssi - -ssi -~~~ - -Output the contents of a given file into the page. - -Like a simple "include" tag, ``{% ssi %}`` includes the contents of another -file -- which must be specified using an absolute path -- in the current -page:: - - {% ssi /home/html/ljworld.com/includes/right_generic.html %} - -If the optional "parsed" parameter is given, the contents of the included -file are evaluated as template code, within the current context:: - - {% ssi /home/html/ljworld.com/includes/right_generic.html parsed %} - -Note that if you use ``{% ssi %}``, you'll need to define -:setting:`ALLOWED_INCLUDE_ROOTS` in your Django settings, as a security measure. - -See also: ``{% include %}``. - -.. templatetag:: templatetag - -templatetag -~~~~~~~~~~~ - -Output one of the syntax characters used to compose template tags. - -Since the template system has no concept of "escaping", to display one of the -bits used in template tags, you must use the ``{% templatetag %}`` tag. - -The argument tells which template bit to output: - - ================== ======= - Argument Outputs - ================== ======= - ``openblock`` ``{%`` - ``closeblock`` ``%}`` - ``openvariable`` ``{{`` - ``closevariable`` ``}}`` - ``openbrace`` ``{`` - ``closebrace`` ``}`` - ``opencomment`` ``{#`` - ``closecomment`` ``#}`` - ================== ======= - -.. templatetag:: url - -url -~~~ - -Returns an absolute path reference (a URL without the domain name) matching a -given view function and optional parameters. This is a way to output links -without violating the DRY principle by having to hard-code URLs in your -templates:: - - {% url path.to.some_view v1 v2 %} - -The first argument is a path to a view function in the format -``package.package.module.function``. Additional arguments are optional and -should be space-separated values that will be used as arguments in the URL. -The example above shows passing positional arguments. Alternatively you may -use keyword syntax:: - - {% url path.to.some_view arg1=v1 arg2=v2 %} - -Do not mix both positional and keyword syntax in a single call. All arguments -required by the URLconf should be present. - -For example, suppose you have a view, ``app_views.client``, whose URLconf -takes a client ID (here, ``client()`` is a method inside the views file -``app_views.py``). The URLconf line might look like this: - -.. code-block:: python - - ('^client/(\d+)/$', 'app_views.client') - -If this app's URLconf is included into the project's URLconf under a path -such as this: - -.. code-block:: python - - ('^clients/', include('project_name.app_name.urls')) - -...then, in a template, you can create a link to this view like this:: - - {% url app_views.client client.id %} - -The template tag will output the string ``/clients/client/123/``. - -.. versionadded:: 1.0 - -If you're using :ref:`named URL patterns <naming-url-patterns>`, you can -refer to the name of the pattern in the ``url`` tag instead of using the -path to the view. - -Note that if the URL you're reversing doesn't exist, you'll get an -:exc:`NoReverseMatch` exception raised, which will cause your site to display an -error page. - -.. versionadded:: 1.0 - -If you'd like to retrieve a URL without displaying it, you can use a slightly -different call:: - - - {% url path.to.view arg arg2 as the_url %} - - <a href="{{ the_url }}">I'm linking to {{ the_url }}</a> - -This ``{% url ... as var %}`` syntax will *not* cause an error if the view is -missing. In practice you'll use this to link to views that are optional:: - - {% url path.to.view as the_url %} - {% if the_url %} - <a href="{{ the_url }}">Link to optional stuff</a> - {% endif %} - -.. versionadded:: 1.1 - -If you'd like to retrieve a namespaced URL, specify the fully qualified name:: - - {% url myapp:view-name %} - -This will follow the normal :ref:`namespaced URL resolution strategy -<topics-http-reversing-url-namespaces>`, including using any hints provided -by the context as to the current application. - -.. versionchanged:: 1.2 - -For backwards compatibility, the ``{% url %}`` tag also supports the -use of commas to separate arguments. You shouldn't use this in any new -projects, but for the sake of the people who are still using it, -here's what it looks like:: - - {% url path.to.view arg,arg2 %} - {% url path.to.view arg, arg2 %} - -This syntax doesn't support the use of literal commas, or or equals -signs. Did we mention you shouldn't use this syntax in any new -projects? - -.. templatetag:: widthratio - -widthratio -~~~~~~~~~~ - -For creating bar charts and such, this tag calculates the ratio of a given value -to a maximum value, and then applies that ratio to a constant. - -For example:: - - <img src="bar.gif" height="10" width="{% widthratio this_value max_value 100 %}" /> - -Above, if ``this_value`` is 175 and ``max_value`` is 200, the image in the -above example will be 88 pixels wide (because 175/200 = .875; .875 * 100 = 87.5 -which is rounded up to 88). - -.. templatetag:: with - -with -~~~~ - -.. versionadded:: 1.0 - -Caches a complex variable under a simpler name. This is useful when accessing -an "expensive" method (e.g., one that hits the database) multiple times. - -For example:: - - {% with business.employees.count as total %} - {{ total }} employee{{ total|pluralize }} - {% endwith %} - -The populated variable (in the example above, ``total``) is only available -between the ``{% with %}`` and ``{% endwith %}`` tags. - -.. _ref-templates-builtins-filters: - -Built-in filter reference -------------------------- - -.. templatefilter:: add - -add -~~~ - -Adds the argument to the value. - -For example:: - - {{ value|add:"2" }} - -If ``value`` is ``4``, then the output will be ``6``. - -.. versionchanged:: 1.2 - The following behavior didn't exist in previous Django versions. - -This filter will first try to coerce both values to integers. If this fails, -it'll attempt to add the values together anyway. This will work on some data -types (strings, list, etc.) and fail on others. If it fails, the result will -be an empty string. - -For example, if we have:: - - {{ first|add:second }} - -and ``first`` is ``[1, 2, 3]`` and ``second`` is ``[4, 5, 6]``, then the -output will be ``[1, 2, 3, 4, 5, 6]``. - -.. warning:: - - Strings that can be coerced to integers will be **summed**, not - concatenated, as in the first example above. - -.. templatefilter:: addslashes - -addslashes -~~~~~~~~~~ - -Adds slashes before quotes. Useful for escaping strings in CSV, for example. - -For example:: - - {{ value|addslashes }} - -If ``value`` is ``"I'm using Django"``, the output will be ``"I\'m using Django"``. - -.. templatefilter:: capfirst - -capfirst -~~~~~~~~ - -Capitalizes the first character of the value. - -For example:: - - {{ value|capfirst }} - -If ``value`` is ``"django"``, the output will be ``"Django"``. - -.. templatefilter:: center - -center -~~~~~~ - -Centers the value in a field of a given width. - -For example:: - - "{{ value|center:"15" }}" - -If ``value`` is ``"Django"``, the output will be ``" Django "``. - -.. templatefilter:: cut - -cut -~~~ - -Removes all values of arg from the given string. - -For example:: - - {{ value|cut:" "}} - -If ``value`` is ``"String with spaces"``, the output will be ``"Stringwithspaces"``. - -.. templatefilter:: date - -date -~~~~ - -Formats a date according to the given format. - -Uses the same format as PHP's ``date()`` function (http://php.net/date) -with some custom extensions. - -Available format strings: - - ================ ======================================== ===================== - Format character Description Example output - ================ ======================================== ===================== - a ``'a.m.'`` or ``'p.m.'`` (Note that ``'a.m.'`` - this is slightly different than PHP's - output, because this includes periods - to match Associated Press style.) - A ``'AM'`` or ``'PM'``. ``'AM'`` - b Month, textual, 3 letters, lowercase. ``'jan'`` - B Not implemented. - c ISO 8601 Format. ``2008-01-02T10:30:00.000123`` - d Day of the month, 2 digits with ``'01'`` to ``'31'`` - leading zeros. - D Day of the week, textual, 3 letters. ``'Fri'`` - f Time, in 12-hour hours and minutes, ``'1'``, ``'1:30'`` - with minutes left off if they're zero. - Proprietary extension. - F Month, textual, long. ``'January'`` - g Hour, 12-hour format without leading ``'1'`` to ``'12'`` - zeros. - G Hour, 24-hour format without leading ``'0'`` to ``'23'`` - zeros. - h Hour, 12-hour format. ``'01'`` to ``'12'`` - H Hour, 24-hour format. ``'00'`` to ``'23'`` - i Minutes. ``'00'`` to ``'59'`` - I Not implemented. - j Day of the month without leading ``'1'`` to ``'31'`` - zeros. - l Day of the week, textual, long. ``'Friday'`` - L Boolean for whether it's a leap year. ``True`` or ``False`` - m Month, 2 digits with leading zeros. ``'01'`` to ``'12'`` - M Month, textual, 3 letters. ``'Jan'`` - n Month without leading zeros. ``'1'`` to ``'12'`` - N Month abbreviation in Associated Press ``'Jan.'``, ``'Feb.'``, ``'March'``, ``'May'`` - style. Proprietary extension. - O Difference to Greenwich time in hours. ``'+0200'`` - P Time, in 12-hour hours, minutes and ``'1 a.m.'``, ``'1:30 p.m.'``, ``'midnight'``, ``'noon'``, ``'12:30 p.m.'`` - 'a.m.'/'p.m.', with minutes left off - if they're zero and the special-case - strings 'midnight' and 'noon' if - appropriate. Proprietary extension. - r RFC 2822 formatted date. ``'Thu, 21 Dec 2000 16:01:07 +0200'`` - s Seconds, 2 digits with leading zeros. ``'00'`` to ``'59'`` - S English ordinal suffix for day of the ``'st'``, ``'nd'``, ``'rd'`` or ``'th'`` - month, 2 characters. - t Number of days in the given month. ``28`` to ``31`` - T Time zone of this machine. ``'EST'``, ``'MDT'`` - u Microseconds. ``0`` to ``999999`` - U Seconds since the Unix Epoch - (January 1 1970 00:00:00 UTC). - w Day of the week, digits without ``'0'`` (Sunday) to ``'6'`` (Saturday) - leading zeros. - W ISO-8601 week number of year, with ``1``, ``53`` - weeks starting on Monday. - y Year, 2 digits. ``'99'`` - Y Year, 4 digits. ``'1999'`` - z Day of the year. ``0`` to ``365`` - Z Time zone offset in seconds. The ``-43200`` to ``43200`` - offset for timezones west of UTC is - always negative, and for those east of - UTC is always positive. - ================ ======================================== ===================== - -.. versionadded:: 1.2 - -The ``c`` and ``u`` format specification characters were added in Django 1.2. - -For example:: - - {{ value|date:"D d M Y" }} - -If ``value`` is a ``datetime`` object (e.g., the result of -``datetime.datetime.now()``), the output will be the string -``'Wed 09 Jan 2008'``. - -The format passed can be one of the predefined ones ``DATE_FORMAT``, -``DATETIME_FORMAT``, ``SHORT_DATE_FORMAT`` or ``SHORT_DATETIME_FORMAT``, or a -custom format that uses the format specifiers shown in the table above. Note -that predefined formats may vary depending on the current locale. - -Assuming that :setting:`USE_L10N` is ``True`` and :setting:`LANGUAGE_CODE` is, -for example, ``"es"``, then for:: - - {{ value|date:"SHORT_DATE_FORMAT" }} - -the output would be the string ``"09/01/2008"`` (the ``"SHORT_DATE_FORMAT"`` -format specifier for the ``es`` locale as shipped with Django is ``"d/m/Y"``). - -When used without a format string:: - - {{ value|date }} - -...the formatting string defined in the :setting:`DATE_FORMAT` setting will be -used, without applying any localization. - -.. versionchanged:: 1.2 - Predefined formats can now be influenced by the current locale. - -.. templatefilter:: default - -default -~~~~~~~ - -If value evaluates to ``False``, use given default. Otherwise, use the value. - -For example:: - - {{ value|default:"nothing" }} - -If ``value`` is ``""`` (the empty string), the output will be ``nothing``. - -.. templatefilter:: default_if_none - -default_if_none -~~~~~~~~~~~~~~~ - -If (and only if) value is ``None``, use given default. Otherwise, use the -value. - -Note that if an empty string is given, the default value will *not* be used. -Use the ``default`` filter if you want to fallback for empty strings. - -For example:: - - {{ value|default_if_none:"nothing" }} - -If ``value`` is ``None``, the output will be the string ``"nothing"``. - -.. templatefilter:: dictsort - -dictsort -~~~~~~~~ - -Takes a list of dictionaries and returns that list sorted by the key given in -the argument. - -For example:: - - {{ value|dictsort:"name" }} - -If ``value`` is: - -.. code-block:: python - - [ - {'name': 'zed', 'age': 19}, - {'name': 'amy', 'age': 22}, - {'name': 'joe', 'age': 31}, - ] - -then the output would be: - -.. code-block:: python - - [ - {'name': 'amy', 'age': 22}, - {'name': 'joe', 'age': 31}, - {'name': 'zed', 'age': 19}, - ] - -.. templatefilter:: dictsortreversed - -dictsortreversed -~~~~~~~~~~~~~~~~ - -Takes a list of dictionaries and returns that list sorted in reverse order by -the key given in the argument. This works exactly the same as the above filter, -but the returned value will be in reverse order. - -.. templatefilter:: divisibleby - -divisibleby -~~~~~~~~~~~ - -Returns ``True`` if the value is divisible by the argument. - -For example:: - - {{ value|divisibleby:"3" }} - -If ``value`` is ``21``, the output would be ``True``. - -.. templatefilter:: escape - -escape -~~~~~~ - -Escapes a string's HTML. Specifically, it makes these replacements: - - * ``<`` is converted to ``<`` - * ``>`` is converted to ``>`` - * ``'`` (single quote) is converted to ``'`` - * ``"`` (double quote) is converted to ``"`` - * ``&`` is converted to ``&`` - -The escaping is only applied when the string is output, so it does not matter -where in a chained sequence of filters you put ``escape``: it will always be -applied as though it were the last filter. If you want escaping to be applied -immediately, use the ``force_escape`` filter. - -Applying ``escape`` to a variable that would normally have auto-escaping -applied to the result will only result in one round of escaping being done. So -it is safe to use this function even in auto-escaping environments. If you want -multiple escaping passes to be applied, use the ``force_escape`` filter. - -.. versionchanged:: 1.0 - Due to auto-escaping, the behavior of this filter has changed slightly. - The replacements are only made once, after - all other filters are applied -- including filters before and after it. - -.. templatefilter:: escapejs - -escapejs -~~~~~~~~ - -.. versionadded:: 1.0 - -Escapes characters for use in JavaScript strings. This does *not* make the -string safe for use in HTML, but does protect you from syntax errors when using -templates to generate JavaScript/JSON. - -For example:: - - {{ value|escapejs }} - -If ``value`` is ``"testing\r\njavascript \'string" <b>escaping</b>"``, -the output will be ``"testing\\u000D\\u000Ajavascript \\u0027string\\u0022 \\u003Cb\\u003Eescaping\\u003C/b\\u003E"``. - -.. templatefilter:: filesizeformat - -filesizeformat -~~~~~~~~~~~~~~ - -Format the value like a 'human-readable' file size (i.e. ``'13 KB'``, -``'4.1 MB'``, ``'102 bytes'``, etc). - -For example:: - - {{ value|filesizeformat }} - -If ``value`` is 123456789, the output would be ``117.7 MB``. - -.. templatefilter:: first - -first -~~~~~ - -Returns the first item in a list. - -For example:: - - {{ value|first }} - -If ``value`` is the list ``['a', 'b', 'c']``, the output will be ``'a'``. - -.. templatefilter:: fix_ampersands - -fix_ampersands -~~~~~~~~~~~~~~ - -.. versionchanged:: 1.0 - This is rarely useful as ampersands are now automatically escaped. See escape_ for more information. - -Replaces ampersands with ``&`` entities. - -For example:: - - {{ value|fix_ampersands }} - -If ``value`` is ``Tom & Jerry``, the output will be ``Tom & Jerry``. - -.. templatefilter:: floatformat - -floatformat -~~~~~~~~~~~ - -When used without an argument, rounds a floating-point number to one decimal -place -- but only if there's a decimal part to be displayed. For example: - -============ =========================== ======== -``value`` Template Output -============ =========================== ======== -``34.23234`` ``{{ value|floatformat }}`` ``34.2`` -``34.00000`` ``{{ value|floatformat }}`` ``34`` -``34.26000`` ``{{ value|floatformat }}`` ``34.3`` -============ =========================== ======== - -If used with a numeric integer argument, ``floatformat`` rounds a number to -that many decimal places. For example: - -============ ============================= ========== -``value`` Template Output -============ ============================= ========== -``34.23234`` ``{{ value|floatformat:3 }}`` ``34.232`` -``34.00000`` ``{{ value|floatformat:3 }}`` ``34.000`` -``34.26000`` ``{{ value|floatformat:3 }}`` ``34.260`` -============ ============================= ========== - -If the argument passed to ``floatformat`` is negative, it will round a number -to that many decimal places -- but only if there's a decimal part to be -displayed. For example: - -============ ================================ ========== -``value`` Template Output -============ ================================ ========== -``34.23234`` ``{{ value|floatformat:"-3" }}`` ``34.232`` -``34.00000`` ``{{ value|floatformat:"-3" }}`` ``34`` -``34.26000`` ``{{ value|floatformat:"-3" }}`` ``34.260`` -============ ================================ ========== - -Using ``floatformat`` with no argument is equivalent to using ``floatformat`` -with an argument of ``-1``. - -.. templatefilter:: force_escape - -force_escape -~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -Applies HTML escaping to a string (see the ``escape`` filter for details). -This filter is applied *immediately* and returns a new, escaped string. This -is useful in the rare cases where you need multiple escaping or want to apply -other filters to the escaped results. Normally, you want to use the ``escape`` -filter. - -.. templatefilter:: get_digit - -get_digit -~~~~~~~~~ - -Given a whole number, returns the requested digit, where 1 is the right-most -digit, 2 is the second-right-most digit, etc. Returns the original value for -invalid input (if input or argument is not an integer, or if argument is less -than 1). Otherwise, output is always an integer. - -For example:: - - {{ value|get_digit:"2" }} - -If ``value`` is ``123456789``, the output will be ``8``. - -.. templatefilter:: iriencode - -iriencode -~~~~~~~~~ - -Converts an IRI (Internationalized Resource Identifier) to a string that is -suitable for including in a URL. This is necessary if you're trying to use -strings containing non-ASCII characters in a URL. - -It's safe to use this filter on a string that has already gone through the -``urlencode`` filter. - -For example:: - - {{ value|iriencode }} - -If ``value`` is ``"?test=1&me=2"``, the output will be ``"?test=1&me=2"``. - -.. templatefilter:: join - -join -~~~~ - -Joins a list with a string, like Python's ``str.join(list)`` - -For example:: - - {{ value|join:" // " }} - -If ``value`` is the list ``['a', 'b', 'c']``, the output will be the string -``"a // b // c"``. - -.. templatefilter:: last - -last -~~~~ - -.. versionadded:: 1.0 - -Returns the last item in a list. - -For example:: - - {{ value|last }} - -If ``value`` is the list ``['a', 'b', 'c', 'd']``, the output will be the string -``"d"``. - -.. templatefilter:: length - -length -~~~~~~ - -Returns the length of the value. This works for both strings and lists. - -For example:: - - {{ value|length }} - -If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``4``. - -.. templatefilter:: length_is - -length_is -~~~~~~~~~ - -Returns ``True`` if the value's length is the argument, or ``False`` otherwise. - -For example:: - - {{ value|length_is:"4" }} - -If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``True``. - -.. templatefilter:: linebreaks - -linebreaks -~~~~~~~~~~ - -Replaces line breaks in plain text with appropriate HTML; a single -newline becomes an HTML line break (``<br />``) and a new line -followed by a blank line becomes a paragraph break (``</p>``). - -For example:: - - {{ value|linebreaks }} - -If ``value`` is ``Joel\nis a slug``, the output will be ``<p>Joel<br />is a -slug</p>``. - -.. templatefilter:: linebreaksbr - -linebreaksbr -~~~~~~~~~~~~ - -Converts all newlines in a piece of plain text to HTML line breaks -(``<br />``). - -For example:: - - {{ value|linebreaksbr }} - -If ``value`` is ``Joel\nis a slug``, the output will be ``Joel<br />is a -slug``. - -.. templatefilter:: linenumbers - -linenumbers -~~~~~~~~~~~ - -Displays text with line numbers. - -For example:: - - {{ value|linenumbers }} - -If ``value`` is:: - - one - two - three - -the output will be:: - - 1. one - 2. two - 3. three - -.. templatefilter:: ljust - -ljust -~~~~~ - -Left-aligns the value in a field of a given width. - -**Argument:** field size - -For example:: - - "{{ value|ljust:"10" }}" - -If ``value`` is ``Django``, the output will be ``"Django "``. - -.. templatefilter:: lower - -lower -~~~~~ - -Converts a string into all lowercase. - -For example:: - - {{ value|lower }} - -If ``value`` is ``Still MAD At Yoko``, the output will be ``still mad at yoko``. - -.. templatefilter:: make_list - -make_list -~~~~~~~~~ - -Returns the value turned into a list. For an integer, it's a list of -digits. For a string, it's a list of characters. - -For example:: - - {{ value|make_list }} - -If ``value`` is the string ``"Joel"``, the output would be the list -``[u'J', u'o', u'e', u'l']``. If ``value`` is ``123``, the output will be the -list ``[1, 2, 3]``. - -.. templatefilter:: phone2numeric - -phone2numeric -~~~~~~~~~~~~~ - -Converts a phone number (possibly containing letters) to its numerical -equivalent. - -The input doesn't have to be a valid phone number. This will happily convert -any string. - -For example:: - - {{ value|phone2numeric }} - -If ``value`` is ``800-COLLECT``, the output will be ``800-2655328``. - -.. templatefilter:: pluralize - -pluralize -~~~~~~~~~ - -Returns a plural suffix if the value is not 1. By default, this suffix is ``'s'``. - -Example:: - - You have {{ num_messages }} message{{ num_messages|pluralize }}. - -If ``num_messages`` is ``1``, the output will be ``You have 1 message.`` -If ``num_messages`` is ``2`` the output will be ``You have 2 messages.`` - -For words that require a suffix other than ``'s'``, you can provide an alternate -suffix as a parameter to the filter. - -Example:: - - You have {{ num_walruses }} walrus{{ num_walruses|pluralize:"es" }}. - -For words that don't pluralize by simple suffix, you can specify both a -singular and plural suffix, separated by a comma. - -Example:: - - You have {{ num_cherries }} cherr{{ num_cherries|pluralize:"y,ies" }}. - -.. templatefilter:: pprint - -pprint -~~~~~~ - -A wrapper around `pprint.pprint`__ -- for debugging, really. - -__ http://docs.python.org/library/pprint.html - -.. templatefilter:: random - -random -~~~~~~ - -Returns a random item from the given list. - -For example:: - - {{ value|random }} - -If ``value`` is the list ``['a', 'b', 'c', 'd']``, the output could be ``"b"``. - -.. templatefilter:: removetags - -removetags -~~~~~~~~~~ - -Removes a space-separated list of [X]HTML tags from the output. - -For example:: - - {{ value|removetags:"b span"|safe }} - -If ``value`` is ``"<b>Joel</b> <button>is</button> a <span>slug</span>"`` the -output will be ``"Joel <button>is</button> a slug"``. - -Note that this filter is case-sensitive. - -If ``value`` is ``"<B>Joel</B> <button>is</button> a <span>slug</span>"`` the -output will be ``"<B>Joel</B> <button>is</button> a slug"``. - -.. templatefilter:: rjust - -rjust -~~~~~ - -Right-aligns the value in a field of a given width. - -**Argument:** field size - -For example:: - - "{{ value|rjust:"10" }}" - -If ``value`` is ``Django``, the output will be ``" Django"``. - -.. templatefilter:: safe - -safe -~~~~ - -Marks a string as not requiring further HTML escaping prior to output. When -autoescaping is off, this filter has no effect. - -.. note:: - - If you are chaining filters, a filter applied after ``safe`` can - make the contents unsafe again. For example, the following code - prints the variable as is, unescaped: - - .. code-block:: html+django - - {{ var|safe|escape }} - -.. templatefilter:: safeseq - -safeseq -~~~~~~~ - -Applies the :tfilter:`safe` filter to each element of a sequence. Useful in -conjunction with other filters that operate on sequences, such as -:tfilter:`join`. For example:: - - {{ some_list|safeseq|join:", " }} - -You couldn't use the :tfilter:`safe` filter directly in this case, as it would -first convert the variable into a string, rather than working with the -individual elements of the sequence. - -.. templatefilter:: slice - -slice -~~~~~ - -Returns a slice of the list. - -Uses the same syntax as Python's list slicing. See -http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice -for an introduction. - -Example:: - - {{ some_list|slice:":2" }} - -If ``some_list`` is ``['a', 'b', 'c']``, the output will be ``['a', 'b']``. - -.. templatefilter:: slugify - -slugify -~~~~~~~ - -Converts to lowercase, removes non-word characters (alphanumerics and -underscores) and converts spaces to hyphens. Also strips leading and trailing -whitespace. - -For example:: - - {{ value|slugify }} - -If ``value`` is ``"Joel is a slug"``, the output will be ``"joel-is-a-slug"``. - -.. templatefilter:: stringformat - -stringformat -~~~~~~~~~~~~ - -Formats the variable according to the argument, a string formatting specifier. -This specifier uses Python string formatting syntax, with the exception that -the leading "%" is dropped. - -See http://docs.python.org/library/stdtypes.html#string-formatting-operations -for documentation of Python string formatting - -For example:: - - {{ value|stringformat:"s" }} - -If ``value`` is ``"Joel is a slug"``, the output will be ``"Joel is a slug"``. - -.. templatefilter:: striptags - -striptags -~~~~~~~~~ - -Strips all [X]HTML tags. - -For example:: - - {{ value|striptags }} - -If ``value`` is ``"<b>Joel</b> <button>is</button> a <span>slug</span>"``, the -output will be ``"Joel is a slug"``. - -.. templatefilter:: time - -time -~~~~ - -Formats a time according to the given format. - -Given format can be the predefined one ``TIME_FORMAT``, or a custom format, -same as the :tfilter:`date` filter. Note that the predefined format is locale- -dependant. - -The time filter will only accept parameters in the format string that relate -to the time of day, not the date (for obvious reasons). If you need to -format a date, use the :tfilter:`date` filter. - -For example:: - - {{ value|time:"H:i" }} - -If ``value`` is equivalent to ``datetime.datetime.now()``, the output will be -the string ``"01:23"``. - -Another example: - -Assuming that :setting:`USE_L10N` is ``True`` and :setting:`LANGUAGE_CODE` is, -for example, ``"de"``, then for:: - - {{ value|time:"TIME_FORMAT" }} - -the output will be the string ``"01:23:00"`` (The ``"TIME_FORMAT"`` format -specifier for the ``de`` locale as shipped with Django is ``"H:i:s"``). - -When used without a format string:: - - {{ value|time }} - -...the formatting string defined in the :setting:`TIME_FORMAT` setting will be -used, without applying any localization. - -.. versionchanged:: 1.2 - Predefined formats can now be influenced by the current locale. - -.. templatefilter:: timesince - -timesince -~~~~~~~~~ - -Formats a date as the time since that date (e.g., "4 days, 6 hours"). - -Takes an optional argument that is a variable containing the date to use as -the comparison point (without the argument, the comparison point is *now*). -For example, if ``blog_date`` is a date instance representing midnight on 1 -June 2006, and ``comment_date`` is a date instance for 08:00 on 1 June 2006, -then ``{{ blog_date|timesince:comment_date }}`` would return "8 hours". - -Comparing offset-naive and offset-aware datetimes will return an empty string. - -Minutes is the smallest unit used, and "0 minutes" will be returned for any -date that is in the future relative to the comparison point. - -.. templatefilter:: timeuntil - -timeuntil -~~~~~~~~~ - -Similar to ``timesince``, except that it measures the time from now until the -given date or datetime. For example, if today is 1 June 2006 and -``conference_date`` is a date instance holding 29 June 2006, then -``{{ conference_date|timeuntil }}`` will return "4 weeks". - -Takes an optional argument that is a variable containing the date to use as -the comparison point (instead of *now*). If ``from_date`` contains 22 June -2006, then ``{{ conference_date|timeuntil:from_date }}`` will return "1 week". - -Comparing offset-naive and offset-aware datetimes will return an empty string. - -Minutes is the smallest unit used, and "0 minutes" will be returned for any -date that is in the past relative to the comparison point. - -.. templatefilter:: title - -title -~~~~~ - -Converts a string into titlecase. - -For example:: - - {{ value|title }} - -If ``value`` is ``"my first post"``, the output will be ``"My First Post"``. - -.. templatefilter:: truncatewords - -truncatewords -~~~~~~~~~~~~~ - -Truncates a string after a certain number of words. - -**Argument:** Number of words to truncate after - -For example:: - - {{ value|truncatewords:2 }} - -If ``value`` is ``"Joel is a slug"``, the output will be ``"Joel is ..."``. - -Newlines within the string will be removed. - -.. templatefilter:: truncatewords_html - -truncatewords_html -~~~~~~~~~~~~~~~~~~ - -Similar to ``truncatewords``, except that it is aware of HTML tags. Any tags -that are opened in the string and not closed before the truncation point, are -closed immediately after the truncation. - -This is less efficient than ``truncatewords``, so should only be used when it -is being passed HTML text. - -For example:: - - {{ value|truncatewords_html:2 }} - -If ``value`` is ``"<p>Joel is a slug</p>"``, the output will be -``"<p>Joel is ...</p>"``. - -Newlines in the HTML content will be preserved. - -.. templatefilter:: unordered_list - -unordered_list -~~~~~~~~~~~~~~ - -Recursively takes a self-nested list and returns an HTML unordered list -- -WITHOUT opening and closing <ul> tags. - -.. versionchanged:: 1.0 - The format accepted by ``unordered_list`` has changed to be easier to understand. - -The list is assumed to be in the proper format. For example, if ``var`` contains -``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``, then -``{{ var|unordered_list }}`` would return:: - - <li>States - <ul> - <li>Kansas - <ul> - <li>Lawrence</li> - <li>Topeka</li> - </ul> - </li> - <li>Illinois</li> - </ul> - </li> - -Note: the previous more restrictive and verbose format is still supported: -``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``, - -.. templatefilter:: upper - -upper -~~~~~ - -Converts a string into all uppercase. - -For example:: - - {{ value|upper }} - -If ``value`` is ``"Joel is a slug"``, the output will be ``"JOEL IS A SLUG"``. - -.. templatefilter:: urlencode - -urlencode -~~~~~~~~~ - -Escapes a value for use in a URL. - -For example:: - - {{ value|urlencode }} - -If ``value`` is ``"http://www.example.org/foo?a=b&c=d"``, the output will be -``"http%3A//www.example.org/foo%3Fa%3Db%26c%3Dd"``. - -.. templatefilter:: urlize - -urlize -~~~~~~ - -Converts URLs in plain text into clickable links. - -Note that if ``urlize`` is applied to text that already contains HTML markup, -things won't work as expected. Apply this filter only to *plain* text. - -For example:: - - {{ value|urlize }} - -If ``value`` is ``"Check out www.djangoproject.com"``, the output will be -``"Check out <a -href="http://www.djangoproject.com">www.djangoproject.com</a>"``. - -.. templatefilter:: urlizetrunc - -urlizetrunc -~~~~~~~~~~~ - -Converts URLs into clickable links, truncating URLs longer than the given -character limit. - -As with urlize_, this filter should only be applied to *plain* text. - -**Argument:** Length to truncate URLs to - -For example:: - - {{ value|urlizetrunc:15 }} - -If ``value`` is ``"Check out www.djangoproject.com"``, the output would be -``'Check out <a -href="http://www.djangoproject.com">www.djangopr...</a>'``. - -.. templatefilter:: wordcount - -wordcount -~~~~~~~~~ - -Returns the number of words. - -For example:: - - {{ value|wordcount }} - -If ``value`` is ``"Joel is a slug"``, the output will be ``4``. - -.. templatefilter:: wordwrap - -wordwrap -~~~~~~~~ - -Wraps words at specified line length. - -**Argument:** number of characters at which to wrap the text - -For example:: - - {{ value|wordwrap:5 }} - -If ``value`` is ``Joel is a slug``, the output would be:: - - Joel - is a - slug - -.. templatefilter:: yesno - -yesno -~~~~~ - -Given a string mapping values for true, false and (optionally) None, -returns one of those strings according to the value: - -For example:: - - {{ value|yesno:"yeah,no,maybe" }} - -========== ====================== ================================== -Value Argument Outputs -========== ====================== ================================== -``True`` ``"yeah,no,maybe"`` ``yeah`` -``False`` ``"yeah,no,maybe"`` ``no`` -``None`` ``"yeah,no,maybe"`` ``maybe`` -``None`` ``"yeah,no"`` ``"no"`` (converts None to False - if no mapping for None is given) -========== ====================== ================================== - -Other tags and filter libraries -------------------------------- - -Django comes with a couple of other template-tag libraries that you have to -enable explicitly in your ``INSTALLED_APPS`` setting and enable in your -template with the ``{% load %}`` tag. - -django.contrib.humanize -~~~~~~~~~~~~~~~~~~~~~~~ - -A set of Django template filters useful for adding a "human touch" to data. See -:doc:`/ref/contrib/humanize`. - -django.contrib.markup -~~~~~~~~~~~~~~~~~~~~~ - -A collection of template filters that implement these common markup languages: - - * Textile - * Markdown - * reST (reStructuredText) - -See the :doc:`markup documentation </ref/contrib/markup>`. - -django.contrib.webdesign -~~~~~~~~~~~~~~~~~~~~~~~~ - -A collection of template tags that can be useful while designing a Web site, -such as a generator of Lorem Ipsum text. See :doc:`/ref/contrib/webdesign`. - -i18n -~~~~ - -Provides a couple of templatetags that allow specifying translatable text in -Django templates. It is slightly different from the libraries described -above because you don't need to add any application to the ``INSTALLED_APPS`` -setting but rather set :setting:`USE_I18N` to True, then loading it with -``{% load i18n %}``. See :ref:`specifying-translation-strings-in-template-code`. diff --git a/parts/django/docs/ref/templates/index.txt b/parts/django/docs/ref/templates/index.txt deleted file mode 100644 index 0aa4798..0000000 --- a/parts/django/docs/ref/templates/index.txt +++ /dev/null @@ -1,19 +0,0 @@ -========= -Templates -========= - -Django's template engine provides a powerful mini-language for defining the -user-facing layer of your application, encouraging a clean separation of -application and presentation logic. Templates can be maintained by anyone with -an understanding of HTML; no knowledge of Python is required. - -.. toctree:: - :maxdepth: 2 - - builtins - api - -.. seealso:: - - For information on writing your own custom tags and filters, see - :doc:`/howto/custom-template-tags`. diff --git a/parts/django/docs/ref/unicode.txt b/parts/django/docs/ref/unicode.txt deleted file mode 100644 index 8e110af..0000000 --- a/parts/django/docs/ref/unicode.txt +++ /dev/null @@ -1,362 +0,0 @@ -============ -Unicode data -============ - -.. versionadded:: 1.0 - -Django natively supports Unicode data everywhere. Providing your database can -somehow store the data, you can safely pass around Unicode strings to -templates, models and the database. - -This document tells you what you need to know if you're writing applications -that use data or templates that are encoded in something other than ASCII. - -Creating the database -===================== - -Make sure your database is configured to be able to store arbitrary string -data. Normally, this means giving it an encoding of UTF-8 or UTF-16. If you use -a more restrictive encoding -- for example, latin1 (iso8859-1) -- you won't be -able to store certain characters in the database, and information will be lost. - - * MySQL users, refer to the `MySQL manual`_ (section 9.1.3.2 for MySQL 5.1) - for details on how to set or alter the database character set encoding. - - * PostgreSQL users, refer to the `PostgreSQL manual`_ (section 21.2.2 in - PostgreSQL 8) for details on creating databases with the correct encoding. - - * SQLite users, there is nothing you need to do. SQLite always uses UTF-8 - for internal encoding. - -.. _MySQL manual: http://dev.mysql.com/doc/refman/5.1/en/charset-database.html -.. _PostgreSQL manual: http://www.postgresql.org/docs/8.2/static/multibyte.html#AEN24104 - -All of Django's database backends automatically convert Unicode strings into -the appropriate encoding for talking to the database. They also automatically -convert strings retrieved from the database into Python Unicode strings. You -don't even need to tell Django what encoding your database uses: that is -handled transparently. - -For more, see the section "The database API" below. - -General string handling -======================= - -Whenever you use strings with Django -- e.g., in database lookups, template -rendering or anywhere else -- you have two choices for encoding those strings. -You can use Unicode strings, or you can use normal strings (sometimes called -"bytestrings") that are encoded using UTF-8. - -.. admonition:: Warning - - A bytestring does not carry any information with it about its encoding. - For that reason, we have to make an assumption, and Django assumes that all - bytestrings are in UTF-8. - - If you pass a string to Django that has been encoded in some other format, - things will go wrong in interesting ways. Usually, Django will raise a - ``UnicodeDecodeError`` at some point. - -If your code only uses ASCII data, it's safe to use your normal strings, -passing them around at will, because ASCII is a subset of UTF-8. - -Don't be fooled into thinking that if your :setting:`DEFAULT_CHARSET` setting is set -to something other than ``'utf-8'`` you can use that other encoding in your -bytestrings! :setting:`DEFAULT_CHARSET` only applies to the strings generated as -the result of template rendering (and e-mail). Django will always assume UTF-8 -encoding for internal bytestrings. The reason for this is that the -:setting:`DEFAULT_CHARSET` setting is not actually under your control (if you are the -application developer). It's under the control of the person installing and -using your application -- and if that person chooses a different setting, your -code must still continue to work. Ergo, it cannot rely on that setting. - -In most cases when Django is dealing with strings, it will convert them to -Unicode strings before doing anything else. So, as a general rule, if you pass -in a bytestring, be prepared to receive a Unicode string back in the result. - -Translated strings ------------------- - -Aside from Unicode strings and bytestrings, there's a third type of string-like -object you may encounter when using Django. The framework's -internationalization features introduce the concept of a "lazy translation" -- -a string that has been marked as translated but whose actual translation result -isn't determined until the object is used in a string. This feature is useful -in cases where the translation locale is unknown until the string is used, even -though the string might have originally been created when the code was first -imported. - -Normally, you won't have to worry about lazy translations. Just be aware that -if you examine an object and it claims to be a -``django.utils.functional.__proxy__`` object, it is a lazy translation. -Calling ``unicode()`` with the lazy translation as the argument will generate a -Unicode string in the current locale. - -For more details about lazy translation objects, refer to the -:doc:`internationalization </topics/i18n/index>` documentation. - -Useful utility functions ------------------------- - -Because some string operations come up again and again, Django ships with a few -useful functions that should make working with Unicode and bytestring objects -a bit easier. - -Conversion functions -~~~~~~~~~~~~~~~~~~~~ - -The ``django.utils.encoding`` module contains a few functions that are handy -for converting back and forth between Unicode and bytestrings. - - * ``smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict')`` - converts its input to a Unicode string. The ``encoding`` parameter - specifies the input encoding. (For example, Django uses this internally - when processing form input data, which might not be UTF-8 encoded.) The - ``strings_only`` parameter, if set to True, will result in Python - numbers, booleans and ``None`` not being converted to a string (they keep - their original types). The ``errors`` parameter takes any of the values - that are accepted by Python's ``unicode()`` function for its error - handling. - - If you pass ``smart_unicode()`` an object that has a ``__unicode__`` - method, it will use that method to do the conversion. - - * ``force_unicode(s, encoding='utf-8', strings_only=False, - errors='strict')`` is identical to ``smart_unicode()`` in almost all - cases. The difference is when the first argument is a :ref:`lazy - translation <lazy-translations>` instance. While ``smart_unicode()`` - preserves lazy translations, ``force_unicode()`` forces those objects to a - Unicode string (causing the translation to occur). Normally, you'll want - to use ``smart_unicode()``. However, ``force_unicode()`` is useful in - template tags and filters that absolutely *must* have a string to work - with, not just something that can be converted to a string. - - * ``smart_str(s, encoding='utf-8', strings_only=False, errors='strict')`` - is essentially the opposite of ``smart_unicode()``. It forces the first - argument to a bytestring. The ``strings_only`` parameter has the same - behavior as for ``smart_unicode()`` and ``force_unicode()``. This is - slightly different semantics from Python's builtin ``str()`` function, - but the difference is needed in a few places within Django's internals. - -Normally, you'll only need to use ``smart_unicode()``. Call it as early as -possible on any input data that might be either Unicode or a bytestring, and -from then on, you can treat the result as always being Unicode. - -URI and IRI handling -~~~~~~~~~~~~~~~~~~~~ - -Web frameworks have to deal with URLs (which are a type of IRI_). One -requirement of URLs is that they are encoded using only ASCII characters. -However, in an international environment, you might need to construct a -URL from an IRI_ -- very loosely speaking, a URI that can contain Unicode -characters. Quoting and converting an IRI to URI can be a little tricky, so -Django provides some assistance. - - * The function ``django.utils.encoding.iri_to_uri()`` implements the - conversion from IRI to URI as required by the specification (`RFC - 3987`_). - - * The functions ``django.utils.http.urlquote()`` and - ``django.utils.http.urlquote_plus()`` are versions of Python's standard - ``urllib.quote()`` and ``urllib.quote_plus()`` that work with non-ASCII - characters. (The data is converted to UTF-8 prior to encoding.) - -These two groups of functions have slightly different purposes, and it's -important to keep them straight. Normally, you would use ``urlquote()`` on the -individual portions of the IRI or URI path so that any reserved characters -such as '&' or '%' are correctly encoded. Then, you apply ``iri_to_uri()`` to -the full IRI and it converts any non-ASCII characters to the correct encoded -values. - -.. note:: - Technically, it isn't correct to say that ``iri_to_uri()`` implements the - full algorithm in the IRI specification. It doesn't (yet) perform the - international domain name encoding portion of the algorithm. - -The ``iri_to_uri()`` function will not change ASCII characters that are -otherwise permitted in a URL. So, for example, the character '%' is not -further encoded when passed to ``iri_to_uri()``. This means you can pass a -full URL to this function and it will not mess up the query string or anything -like that. - -An example might clarify things here:: - - >>> urlquote(u'Paris & Orléans') - u'Paris%20%26%20Orl%C3%A9ans' - >>> iri_to_uri(u'/favorites/François/%s' % urlquote(u'Paris & Orléans')) - '/favorites/Fran%C3%A7ois/Paris%20%26%20Orl%C3%A9ans' - -If you look carefully, you can see that the portion that was generated by -``urlquote()`` in the second example was not double-quoted when passed to -``iri_to_uri()``. This is a very important and useful feature. It means that -you can construct your IRI without worrying about whether it contains -non-ASCII characters and then, right at the end, call ``iri_to_uri()`` on the -result. - -The ``iri_to_uri()`` function is also idempotent, which means the following is -always true:: - - iri_to_uri(iri_to_uri(some_string)) = iri_to_uri(some_string) - -So you can safely call it multiple times on the same IRI without risking -double-quoting problems. - -.. _URI: http://www.ietf.org/rfc/rfc2396.txt -.. _IRI: http://www.ietf.org/rfc/rfc3987.txt -.. _RFC 3987: IRI_ - -Models -====== - -Because all strings are returned from the database as Unicode strings, model -fields that are character based (CharField, TextField, URLField, etc) will -contain Unicode values when Django retrieves data from the database. This -is *always* the case, even if the data could fit into an ASCII bytestring. - -You can pass in bytestrings when creating a model or populating a field, and -Django will convert it to Unicode when it needs to. - -Choosing between ``__str__()`` and ``__unicode__()`` ----------------------------------------------------- - -One consequence of using Unicode by default is that you have to take some care -when printing data from the model. - -In particular, rather than giving your model a ``__str__()`` method, we -recommended you implement a ``__unicode__()`` method. In the ``__unicode__()`` -method, you can quite safely return the values of all your fields without -having to worry about whether they fit into a bytestring or not. (The way -Python works, the result of ``__str__()`` is *always* a bytestring, even if you -accidentally try to return a Unicode object). - -You can still create a ``__str__()`` method on your models if you want, of -course, but you shouldn't need to do this unless you have a good reason. -Django's ``Model`` base class automatically provides a ``__str__()`` -implementation that calls ``__unicode__()`` and encodes the result into UTF-8. -This means you'll normally only need to implement a ``__unicode__()`` method -and let Django handle the coercion to a bytestring when required. - -Taking care in ``get_absolute_url()`` -------------------------------------- - -URLs can only contain ASCII characters. If you're constructing a URL from -pieces of data that might be non-ASCII, be careful to encode the results in a -way that is suitable for a URL. The ``django.db.models.permalink()`` decorator -handles this for you automatically. - -If you're constructing a URL manually (i.e., *not* using the ``permalink()`` -decorator), you'll need to take care of the encoding yourself. In this case, -use the ``iri_to_uri()`` and ``urlquote()`` functions that were documented -above_. For example:: - - from django.utils.encoding import iri_to_uri - from django.utils.http import urlquote - - def get_absolute_url(self): - url = u'/person/%s/?x=0&y=0' % urlquote(self.location) - return iri_to_uri(url) - -This function returns a correctly encoded URL even if ``self.location`` is -something like "Jack visited Paris & Orléans". (In fact, the ``iri_to_uri()`` -call isn't strictly necessary in the above example, because all the -non-ASCII characters would have been removed in quoting in the first line.) - -.. _above: `URI and IRI handling`_ - -The database API -================ - -You can pass either Unicode strings or UTF-8 bytestrings as arguments to -``filter()`` methods and the like in the database API. The following two -querysets are identical:: - - qs = People.objects.filter(name__contains=u'Å') - qs = People.objects.filter(name__contains='\xc3\x85') # UTF-8 encoding of Å - -Templates -========= - -You can use either Unicode or bytestrings when creating templates manually:: - - from django.template import Template - t1 = Template('This is a bytestring template.') - t2 = Template(u'This is a Unicode template.') - -But the common case is to read templates from the filesystem, and this creates -a slight complication: not all filesystems store their data encoded as UTF-8. -If your template files are not stored with a UTF-8 encoding, set the :setting:`FILE_CHARSET` -setting to the encoding of the files on disk. When Django reads in a template -file, it will convert the data from this encoding to Unicode. (:setting:`FILE_CHARSET` -is set to ``'utf-8'`` by default.) - -The :setting:`DEFAULT_CHARSET` setting controls the encoding of rendered templates. -This is set to UTF-8 by default. - -Template tags and filters -------------------------- - -A couple of tips to remember when writing your own template tags and filters: - - * Always return Unicode strings from a template tag's ``render()`` method - and from template filters. - - * Use ``force_unicode()`` in preference to ``smart_unicode()`` in these - places. Tag rendering and filter calls occur as the template is being - rendered, so there is no advantage to postponing the conversion of lazy - translation objects into strings. It's easier to work solely with Unicode - strings at that point. - -E-mail -====== - -Django's e-mail framework (in ``django.core.mail``) supports Unicode -transparently. You can use Unicode data in the message bodies and any headers. -However, you're still obligated to respect the requirements of the e-mail -specifications, so, for example, e-mail addresses should use only ASCII -characters. - -The following code example demonstrates that everything except e-mail addresses -can be non-ASCII:: - - from django.core.mail import EmailMessage - - subject = u'My visit to Sør-Trøndelag' - sender = u'Arnbjörg Ráðormsdóttir <arnbjorg@example.com>' - recipients = ['Fred <fred@example.com'] - body = u'...' - EmailMessage(subject, body, sender, recipients).send() - -Form submission -=============== - -HTML form submission is a tricky area. There's no guarantee that the -submission will include encoding information, which means the framework might -have to guess at the encoding of submitted data. - -Django adopts a "lazy" approach to decoding form data. The data in an -``HttpRequest`` object is only decoded when you access it. In fact, most of -the data is not decoded at all. Only the ``HttpRequest.GET`` and -``HttpRequest.POST`` data structures have any decoding applied to them. Those -two fields will return their members as Unicode data. All other attributes and -methods of ``HttpRequest`` return data exactly as it was submitted by the -client. - -By default, the :setting:`DEFAULT_CHARSET` setting is used as the assumed encoding -for form data. If you need to change this for a particular form, you can set -the ``encoding`` attribute on an ``HttpRequest`` instance. For example:: - - def some_view(request): - # We know that the data must be encoded as KOI8-R (for some reason). - request.encoding = 'koi8-r' - ... - -You can even change the encoding after having accessed ``request.GET`` or -``request.POST``, and all subsequent accesses will use the new encoding. - -Most developers won't need to worry about changing form encoding, but this is -a useful feature for applications that talk to legacy systems whose encoding -you cannot control. - -Django does not decode the data of file uploads, because that data is normally -treated as collections of bytes, rather than strings. Any automatic decoding -there would alter the meaning of the stream of bytes. diff --git a/parts/django/docs/ref/utils.txt b/parts/django/docs/ref/utils.txt deleted file mode 100644 index e4ce7c4..0000000 --- a/parts/django/docs/ref/utils.txt +++ /dev/null @@ -1,504 +0,0 @@ -============ -Django Utils -============ - -.. module:: django.utils - :synopsis: Django's built-in utilities. - -This document covers all stable modules in ``django.utils``. Most of the -modules in ``django.utils`` are designed for internal use and only the -following parts can be considered stable and thus backwards compatible as per -the :ref:`internal release deprecation policy <internal-release-deprecation-policy>`. - -``django.utils.cache`` -====================== - -.. module:: django.utils.cache - :synopsis: Helper functions for controlling caching. - -This module contains helper functions for controlling caching. It does so by -managing the ``Vary`` header of responses. It includes functions to patch the -header of response objects directly and decorators that change functions to do -that header-patching themselves. - -For information on the ``Vary`` header, see `RFC 2616 section 14.44`_. - -.. _RFC 2616 section 14.44: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44 - -Essentially, the ``Vary`` HTTP header defines which headers a cache should take -into account when building its cache key. Requests with the same path but -different header content for headers named in ``Vary`` need to get different -cache keys to prevent delivery of wrong content. - -For example, :doc:`internationalization </topics/i18n/index>` middleware would need -to distinguish caches by the ``Accept-language`` header. - -.. function:: patch_cache_control(response, **kwargs) - -This function patches the ``Cache-Control`` header by adding all keyword -arguments to it. The transformation is as follows: - - * All keyword parameter names are turned to lowercase, and underscores - are converted to hyphens. - * If the value of a parameter is ``True`` (exactly ``True``, not just a - true value), only the parameter name is added to the header. - * All other parameters are added with their value, after applying - ``str()`` to it. - -.. function:: get_max_age(response) - -Returns the max-age from the response Cache-Control header as an integer (or -``None`` if it wasn't found or wasn't an integer). - -.. function:: patch_response_headers(response, cache_timeout=None) - -Adds some useful headers to the given ``HttpResponse`` object: - - * ``ETag`` - * ``Last-Modified`` - * ``Expires`` - * ``Cache-Control`` - -Each header is only added if it isn't already set. - -``cache_timeout`` is in seconds. The ``CACHE_MIDDLEWARE_SECONDS`` setting is -used by default. - -.. function:: add_never_cache_headers(response) - -Adds headers to a response to indicate that a page should never be cached. - -.. function:: patch_vary_headers(response, newheaders) - -Adds (or updates) the ``Vary`` header in the given ``HttpResponse`` object. -``newheaders`` is a list of header names that should be in ``Vary``. Existing -headers in ``Vary`` aren't removed. - -.. function:: get_cache_key(request, key_prefix=None) - -Returns a cache key based on the request path. It can be used in the request -phase because it pulls the list of headers to take into account from the -global path registry and uses those to build a cache key to check against. - -If there is no headerlist stored, the page needs to be rebuilt, so this -function returns ``None``. - -.. function:: learn_cache_key(request, response, cache_timeout=None, key_prefix=None) - -Learns what headers to take into account for some request path from the -response object. It stores those headers in a global path registry so that -later access to that path will know what headers to take into account without -building the response object itself. The headers are named in the ``Vary`` -header of the response, but we want to prevent response generation. - -The list of headers to use for cache key generation is stored in the same cache -as the pages themselves. If the cache ages some data out of the cache, this -just means that we have to build the response once to get at the Vary header -and so at the list of headers to use for the cache key. - -SortedDict -========== - -.. module:: django.utils.datastructures - :synopsis: A dictionary that keeps its keys in the order in which they're inserted. - -.. class:: django.utils.datastructures.SortedDict - -Methods -------- - -Extra methods that ``SortedDict`` adds to the standard Python ``dict`` class. - -.. method:: insert(index, key, value) - -Inserts the key, value pair before the item with the given index. - -.. method:: value_for_index(index) - -Returns the value of the item at the given zero-based index. - -Creating new SortedDict ------------------------ - -Creating a new ``SortedDict`` must be done in a way where ordering is -guaranteed. For example:: - - SortedDict({'b': 1, 'a': 2, 'c': 3}) - -will not work. Passing in a basic Python ``dict`` could produce unreliable -results. Instead do:: - - SortedDict([('b', 1), ('a', 2), ('c', 3)]) - -``django.utils.encoding`` -========================= - -.. module:: django.utils.encoding - :synopsis: A series of helper classes and function to manage character encoding. - -.. class:: StrAndUnicode - -A class whose ``__str__`` returns its ``__unicode__`` as a UTF-8 bytestring. -Useful as a mix-in. - -.. function:: smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict') - -Returns a ``unicode`` object representing ``s``. Treats bytestrings using the -'encoding' codec. - -If ``strings_only`` is ``True``, don't convert (some) non-string-like objects. - -.. function:: is_protected_type(obj) - -Determine if the object instance is of a protected type. - -Objects of protected types are preserved as-is when passed to -``force_unicode(strings_only=True)``. - -.. function:: force_unicode(s, encoding='utf-8', strings_only=False, errors='strict') - -Similar to ``smart_unicode``, except that lazy instances are resolved to strings, -rather than kept as lazy objects. - -If ``strings_only`` is ``True``, don't convert (some) non-string-like objects. - -.. function:: smart_str(s, encoding='utf-8', strings_only=False, errors='strict') - -Returns a bytestring version of ``s``, encoded as specified in ``encoding``. - -If ``strings_only`` is ``True``, don't convert (some) non-string-like objects. - -.. function:: iri_to_uri(iri) - -Convert an Internationalized Resource Identifier (IRI) portion to a URI portion -that is suitable for inclusion in a URL. - -This is the algorithm from section 3.1 of `RFC 3987`_. However, since we are -assuming input is either UTF-8 or unicode already, we can simplify things a -little from the full method. - -.. _RFC 3987: http://www.ietf.org/rfc/rfc3987.txt - -Returns an ASCII string containing the encoded result. - -``django.utils.feedgenerator`` -============================== - -.. module:: django.utils.feedgenerator - :synopsis: Syndication feed generation library -- used for generating RSS, etc. - -Sample usage:: - - >>> from django.utils import feedgenerator - >>> feed = feedgenerator.Rss201rev2Feed( - ... title=u"Poynter E-Media Tidbits", - ... link=u"http://www.poynter.org/column.asp?id=31", - ... description=u"A group Weblog by the sharpest minds in online media/journalism/publishing.", - ... language=u"en", - ... ) - >>> feed.add_item( - ... title="Hello", - ... link=u"http://www.holovaty.com/test/", - ... description="Testing." - ... ) - >>> fp = open('test.rss', 'w') - >>> feed.write(fp, 'utf-8') - >>> fp.close() - -For simplifying the selection of a generator use ``feedgenerator.DefaultFeed`` -which is currently ``Rss201rev2Feed`` - -For definitions of the different versions of RSS, see: -http://diveintomark.org/archives/2004/02/04/incompatible-rss - -.. function:: get_tag_uri(url, date) - -Creates a TagURI. - -See http://diveintomark.org/archives/2004/05/28/howto-atom-id - -SyndicationFeed ---------------- - -.. class:: SyndicationFeed - -Base class for all syndication feeds. Subclasses should provide write(). - -Methods -~~~~~~~ - -.. method:: add_item(title, link, description, [author_email=None, author_name=None, author_link=None, pubdate=None, comments=None, unique_id=None, enclosure=None, categories=(), item_copyright=None, ttl=None, **kwargs]) - -Adds an item to the feed. All args are expected to be Python ``unicode`` -objects except ``pubdate``, which is a ``datetime.datetime`` object, and -``enclosure``, which is an instance of the ``Enclosure`` class. - -.. method:: num_items() - -.. method:: root_attributes() - -Return extra attributes to place on the root (i.e. feed/channel) element. -Called from write(). - -.. method:: add_root_elements(handler) - -Add elements in the root (i.e. feed/channel) element. Called from write(). - -.. method:: item_attributes(item) - -Return extra attributes to place on each item (i.e. item/entry) element. - -.. method:: add_item_elements(handler, item) - -Add elements on each item (i.e. item/entry) element. - -.. method:: write(outfile, encoding) - -Outputs the feed in the given encoding to ``outfile``, which is a file-like -object. Subclasses should override this. - -.. method:: writeString(encoding) - -Returns the feed in the given encoding as a string. - -.. method:: latest_post_date() - -Returns the latest item's ``pubdate``. If none of them have a ``pubdate``, -this returns the current date/time. - -Enclosure ---------- - -.. class:: Enclosure - -Represents an RSS enclosure - -RssFeed -------- - -.. class:: RssFeed(SyndicationFeed) - -Rss201rev2Feed --------------- - -.. class:: Rss201rev2Feed(RssFeed) - -Spec: http://blogs.law.harvard.edu/tech/rss - -Atom1Feed ---------- - -.. class:: Atom1Feed(SyndicationFeed) - -Spec: http://atompub.org/2005/07/11/draft-ietf-atompub-format-10.html - -``django.utils.http`` -===================== - -.. module:: django.utils.http - :synopsis: HTTP helper functions. (URL encoding, cookie handling, ...) - -.. function:: urlquote(url, safe='/') - -A version of Python's ``urllib.quote()`` function that can operate on unicode -strings. The url is first UTF-8 encoded before quoting. The returned string -can safely be used as part of an argument to a subsequent ``iri_to_uri()`` -call without double-quoting occurring. Employs lazy execution. - -.. function:: urlquote_plus(url, safe='') - -A version of Python's urllib.quote_plus() function that can operate on unicode -strings. The url is first UTF-8 encoded before quoting. The returned string can -safely be used as part of an argument to a subsequent iri_to_uri() call without -double-quoting occurring. Employs lazy execution. - -.. function:: urlencode(query, doseq=0) - -A version of Python's urllib.urlencode() function that can operate on unicode -strings. The parameters are first case to UTF-8 encoded strings and then -encoded as per normal. - -.. function:: cookie_date(epoch_seconds=None) - -Formats the time to ensure compatibility with Netscape's cookie standard. - -Accepts a floating point number expressed in seconds since the epoch, in UTC - -such as that outputted by ``time.time()``. If set to ``None``, defaults to the current -time. - -Outputs a string in the format ``Wdy, DD-Mon-YYYY HH:MM:SS GMT``. - -.. function:: http_date(epoch_seconds=None) - -Formats the time to match the RFC 1123 date format as specified by HTTP -`RFC 2616`_ section 3.3.1. - -.. _RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616.txt - -Accepts a floating point number expressed in seconds since the epoch, in UTC - -such as that outputted by ``time.time()``. If set to ``None``, defaults to the current -time. - -Outputs a string in the format ``Wdy, DD Mon YYYY HH:MM:SS GMT``. - -.. function:: base36_to_int(s) - -Converted a base 36 string to an integer - -.. function:: int_to_base36(i) - -Converts an integer to a base36 string - -``django.utils.safestring`` -=========================== - -.. module:: django.utils.safestring - :synopsis: Functions and classes for working with strings that can be displayed safely without further escaping in HTML. - -Functions and classes for working with "safe strings": strings that can be -displayed safely without further escaping in HTML. Marking something as a "safe -string" means that the producer of the string has already turned characters -that should not be interpreted by the HTML engine (e.g. '<') into the -appropriate entities. - -.. class:: SafeString - -A string subclass that has been specifically marked as "safe" (requires no -further escaping) for HTML output purposes. - -.. class:: SafeUnicode - -A unicode subclass that has been specifically marked as "safe" for HTML output -purposes. - -.. function:: mark_safe(s) - -Explicitly mark a string as safe for (HTML) output purposes. The returned -object can be used everywhere a string or unicode object is appropriate. - -Can be called multiple times on a single string. - -.. function:: mark_for_escaping(s) - -Explicitly mark a string as requiring HTML escaping upon output. Has no effect -on ``SafeData`` subclasses. - -Can be called multiple times on a single string (the resulting escaping is only -applied once). - -``django.utils.translation`` -============================ - -.. module:: django.utils.translation - :synopsis: Internationalization support. - -For a complete discussion on the usage of the following see the -:doc:`Internationalization documentation </topics/i18n/internationalization>`. - -.. function:: gettext(message) - -Translates ``message`` and returns it in a UTF-8 bytestring - -.. function:: ugettext(message) - -Translates ``message`` and returns it in a unicode string - -.. function:: gettext_lazy(message) -.. function:: ugettext_lazy(message) - -Same as the non-lazy versions above, but using lazy execution. - -See :ref:`lazy translations documentation <lazy-translations>`. - -.. function:: gettext_noop(message) - -Marks strings for translation but doesn't translate them now. This can be used -to store strings in global variables that should stay in the base language -(because they might be used externally) and will be translated later. - -.. function:: ngettext(singular, plural, number) - -Translates ``singular`` and ``plural`` and returns the appropriate string -based on ``number`` in a UTF-8 bytestring - -.. function:: ungettext(singular, plural, number) - -Translates ``singular`` and ``plural`` and returns the appropriate string based -on ``number`` in a unicode string - -.. function:: ngettext_lazy(singular, plural, number) -.. function:: ungettext_lazy(singular, plural, number) - -Same as the non-lazy versions above, but using lazy execution. - -See :ref:`lazy translations documentation <lazy-translations>`. - -.. function:: string_concat(*strings) - -Lazy variant of string concatenation, needed for translations that are -constructed from multiple parts. - -.. function:: activate(language) - -Fetches the translation object for a given tuple of application name and -language and installs it as the current translation object for the current -thread. - -.. function:: deactivate() - -De-installs the currently active translation object so that further _ calls will -resolve against the default translation object, again. - -.. function:: deactivate_all() - -Makes the active translation object a NullTranslations() instance. This is -useful when we want delayed translations to appear as the original string for -some reason. - -.. function:: get_language() - -Returns the currently selected language code. - -.. function:: get_language_bidi() - -Returns selected language's BiDi layout: - - * ``False`` = left-to-right layout - * ``True`` = right-to-left layout - -.. function:: get_date_formats() - -Checks whether translation files provide a translation for some technical -message ID to store date and time formats. If it doesn't contain one, the -formats provided in the settings will be used. - -.. function:: get_language_from_request(request) - -Analyzes the request to find what language the user wants the system to show. -Only languages listed in settings.LANGUAGES are taken into account. If the user -requests a sublanguage where we have a main language, we send out the main -language. - -.. function:: to_locale(language) - -Turns a language name (en-us) into a locale name (en_US). - -.. function:: templatize(src) - -Turns a Django template into something that is understood by xgettext. It does -so by translating the Django translation tags into standard gettext function -invocations. - -``django.utils.tzinfo`` -======================= - -.. module:: django.utils.tzinfo - :synopsis: Implementation of ``tzinfo`` classes for use with ``datetime.datetime``. - -.. class:: FixedOffset - -Fixed offset in minutes east from UTC. - -.. class:: LocalTimezone - -Proxy timezone information from time module. diff --git a/parts/django/docs/ref/validators.txt b/parts/django/docs/ref/validators.txt deleted file mode 100644 index 0451f65..0000000 --- a/parts/django/docs/ref/validators.txt +++ /dev/null @@ -1,158 +0,0 @@ -========== -Validators -========== - -.. versionadded:: 1.2 -.. module:: django.core.validators - :synopsis: Validation utilities and base classes - -Writing validators -================== - -A validator is a callable that takes a value and raises a -:exc:`~django.core.exceptions.ValidationError` if it doesn't meet some -criteria. Validators can be useful for re-using validation logic between -different types of fields. - -For example, here's a validator that only allows even numbers:: - - from django.core.exceptions import ValidationError - - def validate_even(value): - if value % 2 != 0: - raise ValidationError(u'%s is not an even number' % value) - -You can add this to a model field via the field's :attr:`~django.db.models.Field.validators` -argument:: - - from django.db import models - - class MyModel(models.Model): - even_field = models.IntegerField(validators=[validate_even]) - -Because values are converted to Python before validators are run, you can even -use the same validator with forms:: - - from django import forms - - class MyForm(forms.Form): - even_field = forms.IntegerField(validators=[validate_even]) - -How validators are run -====================== - -See the :doc:`form validation </ref/forms/validation>` for more information on -how validators are run in forms, and :ref:`Validating objects -<validating-objects>` for how they're run in models. Note that validators will -not be run automatically when you save a model, but if you are using a -:class:`~django.forms.ModelForm`, it will run your validators on any fields -that are included in your form. See the -:doc:`ModelForm documentation </topics/forms/modelforms>` for information on -how model validation interacts with forms. - -Built-in validators -=================== - -The :mod:`django.core.validators` module contains a collection of callable -validators for use with model and form fields. They're used internally but -are available for use with your own fields, too. They can be used in addition -to, or in lieu of custom ``field.clean()`` methods. - -``RegexValidator`` ------------------- -.. class:: RegexValidator(regex, [message=None, code=None]) - - .. attribute:: regex - - The regular expression pattern to search for the provided ``value``, - or a pre-compiled regular expression. Raises a - :exc:`~django.core.exceptions.ValidationError` with :attr:`.message` - and :attr:`.code` if no match is found. - - .. attribute:: message - - The error message used by :exc:`~django.core.exceptions.ValidationError` - if validation fails. If no :attr:`.message` is specified, a generic - ``"Enter a valid value"`` message is used. Default value: ``None``. - - .. attribute:: code - - The error code used by :exc:`~django.core.exceptions.ValidationError` - if validation fails. If :attr:`.code` is not specified, ``"invalid"`` - is used. Default value: ``None``. - -``URLValidator`` ----------------- -.. class:: URLValidator([verify_exists=False, validator_user_agent=URL_VALIDATOR_USER_AGENT]) - - A :class:`RegexValidator` that ensures a value looks like a URL and - optionally verifies that the URL actually exists (i.e., doesn't return a - 404 status code). Raises an error code of ``'invalid'`` if it doesn't look - like a URL, and a code of ``'invalid_link'`` if it doesn't exist. - - .. attribute:: verify_exists - - Default value: ``False``. If set to ``True``, this validator checks - that the URL actually exists. - - .. attribute:: validator_user_agent - - If :attr:`.verify_exists` is ``True``, Django uses the value of - :attr:`.validator_user_agent` as the "User-agent" for the request. This - defaults to :setting:`settings.URL_VALIDATOR_USER_AGENT <URL_VALIDATOR_USER_AGENT>`. - -``validate_email`` ------------------- -.. data:: validate_email - - A :class:`RegexValidator` instance that ensures a value looks like an - e-mail address. - -``validate_slug`` ------------------ -.. data:: validate_slug - - A :class:`RegexValidator` instance that ensures a value consists of only - letters, numbers, underscores or hyphens. - -``validate_ipv4_address`` -------------------------- -.. data:: validate_ipv4_address - - A :class:`RegexValidator` instance that ensures a value looks like an IPv4 - address. - -``validate_comma_separated_integer_list`` ------------------------------------------ -.. data:: validate_comma_separated_integer_list - - A :class:`RegexValidator` instance that ensures a value is a - comma-separated list of integers. - -``MaxValueValidator`` ---------------------- -.. class:: MaxValueValidator(max_value) - - Raises a :exc:`~django.core.exceptions.ValidationError` with a code of - ``'max_value'`` if ``value`` is greater than ``max_value``. - -``MinValueValidator`` ---------------------- -.. class:: MinValueValidator(min_value) - - Raises a :exc:`~django.core.exceptions.ValidationError` with a code of - ``'min_value'`` if ``value`` is less than ``min_value``. - -``MaxLengthValidator`` ----------------------- -.. class:: MaxLengthValidator(max_length) - - Raises a :exc:`~django.core.exceptions.ValidationError` with a code of - ``'max_length'`` if the length of ``value`` is greater than ``max_length``. - -``MinLengthValidator`` ----------------------- -.. class:: MinLengthValidator(min_length) - - Raises a :exc:`~django.core.exceptions.ValidationError` with a code of - ``'min_length'`` if the length of ``value`` is less than ``min_length``. diff --git a/parts/django/docs/releases/0.95.txt b/parts/django/docs/releases/0.95.txt deleted file mode 100644 index 7409bff..0000000 --- a/parts/django/docs/releases/0.95.txt +++ /dev/null @@ -1,124 +0,0 @@ -================================= -Django version 0.95 release notes -================================= - -Welcome to the Django 0.95 release. - -This represents a significant advance in Django development since the 0.91 -release in January 2006. The details of every change in this release would be -too extensive to list in full, but a summary is presented below. - -Suitability and API stability -============================= - -This release is intended to provide a stable reference point for developers -wanting to work on production-level applications that use Django. - -However, it's not the 1.0 release, and we'll be introducing further changes -before 1.0. For a clear look at which areas of the framework will change (and -which ones will *not* change) before 1.0, see the api-stability.txt file, which -lives in the docs/ directory of the distribution. - -You may have a need to use some of the features that are marked as -"subject to API change" in that document, but that's OK with us as long as it's -OK with you, and as long as you understand APIs may change in the future. - -Fortunately, most of Django's core APIs won't be changing before version 1.0. -There likely won't be as big of a change between 0.95 and 1.0 versions as there -was between 0.91 and 0.95. - -Changes and new features -======================== - -The major changes in this release (for developers currently using the 0.91 -release) are a result of merging the 'magic-removal' branch of development. -This branch removed a number of constraints in the way Django code had to be -written that were a consequence of decisions made in the early days of Django, -prior to its open-source release. It's now possible to write more natural, -Pythonic code that works as expected, and there's less "black magic" happening -behind the scenes. - -Aside from that, another main theme of this release is a dramatic increase in -usability. We've made countless improvements in error messages, documentation, -etc., to improve developers' quality of life. - -The new features and changes introduced in 0.95 include: - - * Django now uses a more consistent and natural filtering interface for - retrieving objects from the database. - - * User-defined models, functions and constants now appear in the module - namespace they were defined in. (Previously everything was magically - transferred to the django.models.* namespace.) - - * Some optional applications, such as the FlatPage, Sites and Redirects - apps, have been decoupled and moved into django.contrib. If you don't - want to use these applications, you no longer have to install their - database tables. - - * Django now has support for managing database transactions. - - * We've added the ability to write custom authentication and authorization - backends for authenticating users against alternate systems, such as - LDAP. - - * We've made it easier to add custom table-level functions to models, - through a new "Manager" API. - - * It's now possible to use Django without a database. This simply means - that the framework no longer requires you to have a working database set - up just to serve dynamic pages. In other words, you can just use - URLconfs/views on their own. Previously, the framework required that a - database be configured, regardless of whether you actually used it. - - * It's now more explicit and natural to override save() and delete() - methods on models, rather than needing to hook into the pre_save() and - post_save() method hooks. - - * Individual pieces of the framework now can be configured without - requiring the setting of an environment variable. This permits use of, - for example, the Django templating system inside other applications. - - * More and more parts of the framework have been internationalized, as - we've expanded internationalization (i18n) support. The Django - codebase, including code and templates, has now been translated, at least - in part, into 31 languages. From Arabic to Chinese to Hungarian to Welsh, - it is now possible to use Django's admin site in your native language. - -The number of changes required to port from 0.91-compatible code to the 0.95 -code base are significant in some cases. However, they are, for the most part, -reasonably routine and only need to be done once. A list of the necessary -changes is described in the `Removing The Magic`_ wiki page. There is also an -easy checklist_ for reference when undertaking the porting operation. - -.. _Removing The Magic: http://code.djangoproject.com/wiki/RemovingTheMagic -.. _checklist: http://code.djangoproject.com/wiki/MagicRemovalCheatSheet1 - -Problem reports and getting help -================================ - -Need help resolving a problem with Django? The documentation in the distribution -is also available online_ at the `Django Web site`_. The :doc:`FAQ </faq/index>` -document is especially recommended, as it contains a number of issues that come -up time and again. - -For more personalized help, the `django-users`_ mailing list is a very active -list, with more than 2,000 subscribers who can help you solve any sort of -Django problem. We recommend you search the archives first, though, because -many common questions appear with some regularity, and any particular problem -may already have been answered. - -Finally, for those who prefer the more immediate feedback offered by IRC, -there's a #django channel on irc.freenode.net that is regularly populated by -Django users and developers from around the world. Friendly people are usually -available at any hour of the day -- to help, or just to chat. - -.. _online: http://www.djangoproject.com/documentation/0.95/ -.. _Django Web site: http://www.djangoproject.com/ -.. _django-users: http://groups.google.com/group/django-users - -Thanks for using Django! - -The Django Team -July 2006 - diff --git a/parts/django/docs/releases/0.96.txt b/parts/django/docs/releases/0.96.txt deleted file mode 100644 index 1224360..0000000 --- a/parts/django/docs/releases/0.96.txt +++ /dev/null @@ -1,264 +0,0 @@ -================================= -Django version 0.96 release notes -================================= - -Welcome to Django 0.96! - -The primary goal for 0.96 is a cleanup and stabilization of the features -introduced in 0.95. There have been a few small `backwards-incompatible -changes`_ since 0.95, but the upgrade process should be fairly simple -and should not require major changes to existing applications. - -However, we're also releasing 0.96 now because we have a set of -backwards-incompatible changes scheduled for the near future. Once -completed, they will involve some code changes for application -developers, so we recommend that you stick with Django 0.96 until the -next official release; then you'll be able to upgrade in one step -instead of needing to make incremental changes to keep up with the -development version of Django. - -Backwards-incompatible changes -============================== - -The following changes may require you to update your code when you switch from -0.95 to 0.96: - -``MySQLdb`` version requirement -------------------------------- - -Due to a bug in older versions of the ``MySQLdb`` Python module (which -Django uses to connect to MySQL databases), Django's MySQL backend now -requires version 1.2.1p2 or higher of ``MySQLdb``, and will raise -exceptions if you attempt to use an older version. - -If you're currently unable to upgrade your copy of ``MySQLdb`` to meet -this requirement, a separate, backwards-compatible backend, called -"mysql_old", has been added to Django. To use this backend, change -the :setting:`DATABASE_ENGINE` setting in your Django settings file from -this:: - - DATABASE_ENGINE = "mysql" - -to this:: - - DATABASE_ENGINE = "mysql_old" - -However, we strongly encourage MySQL users to upgrade to a more recent -version of ``MySQLdb`` as soon as possible, The "mysql_old" backend is -provided only to ease this transition, and is considered deprecated; -aside from any necessary security fixes, it will not be actively -maintained, and it will be removed in a future release of Django. - -Also, note that some features, like the new :setting:`DATABASE_OPTIONS` -setting (see the `databases documentation`_ for details), are only -available on the "mysql" backend, and will not be made available for -"mysql_old". - -.. _databases documentation: http://www.djangoproject.com/documentation/0.96/databases/ - -Database constraint names changed ---------------------------------- - -The format of the constraint names Django generates for foreign key -references have changed slightly. These names are generally only used -when it is not possible to put the reference directly on the affected -column, so they are not always visible. - -The effect of this change is that running ``manage.py reset`` and -similar commands against an existing database may generate SQL with -the new form of constraint name, while the database itself contains -constraints named in the old form; this will cause the database server -to raise an error message about modifying non-existent constraints. - -If you need to work around this, there are two methods available: - - 1. Redirect the output of ``manage.py`` to a file, and edit the - generated SQL to use the correct constraint names before - executing it. - - 2. Examine the output of ``manage.py sqlall`` to see the new-style - constraint names, and use that as a guide to rename existing - constraints in your database. - -Name changes in ``manage.py`` ------------------------------ - -A few of the options to ``manage.py`` have changed with the addition of fixture -support: - - * There are new ``dumpdata`` and ``loaddata`` commands which, as - you might expect, will dump and load data to/from the - database. These commands can operate against any of Django's - supported serialization formats. - - * The ``sqlinitialdata`` command has been renamed to ``sqlcustom`` to - emphasize that ``loaddata`` should be used for data (and ``sqlcustom`` for - other custom SQL -- views, stored procedures, etc.). - - * The vestigial ``install`` command has been removed. Use ``syncdb``. - -Backslash escaping changed --------------------------- - -The Django database API now escapes backslashes given as query parameters. If -you have any database API code that matches backslashes, and it was working before -(despite the lack of escaping), you'll have to change your code to "unescape" the -slashes one level. - -For example, this used to work:: - - # Find text containing a single backslash - MyModel.objects.filter(text__contains='\\\\') - -The above is now incorrect, and should be rewritten as:: - - # Find text containing a single backslash - MyModel.objects.filter(text__contains='\\') - -Removed ENABLE_PSYCO setting ----------------------------- - -The ``ENABLE_PSYCO`` setting no longer exists. If your settings file includes -``ENABLE_PSYCO`` it will have no effect; to use Psyco_, we recommend -writing a middleware class to activate it. - -.. _psyco: http://psyco.sourceforge.net/ - -What's new in 0.96? -=================== - -This revision represents over a thousand source commits and over four hundred -bug fixes, so we can't possibly catalog all the changes. Here, we describe the -most notable changes in this release. - -New forms library ------------------ - -``django.newforms`` is Django's new form-handling library. It's a -replacement for ``django.forms``, the old form/manipulator/validation -framework. Both APIs are available in 0.96, but over the next two -releases we plan to switch completely to the new forms system, and -deprecate and remove the old system. - -There are three elements to this transition: - - * We've copied the current ``django.forms`` to - ``django.oldforms``. This allows you to upgrade your code *now* - rather than waiting for the backwards-incompatible change and - rushing to fix your code after the fact. Just change your - import statements like this:: - - from django import forms # 0.95-style - from django import oldforms as forms # 0.96-style - - * The next official release of Django will move the current - ``django.newforms`` to ``django.forms``. This will be a - backwards-incompatible change, and anyone still using the old - version of ``django.forms`` at that time will need to change - their import statements as described above. - - * The next release after that will completely remove - ``django.oldforms``. - -Although the ``newforms`` library will continue to evolve, it's ready for use -for most common cases. We recommend that anyone new to form handling skip the -old forms system and start with the new. - -For more information about ``django.newforms``, read the `newforms -documentation`_. - -.. _newforms documentation: http://www.djangoproject.com/documentation/0.96/newforms/ - -URLconf improvements --------------------- - -You can now use any callable as the callback in URLconfs (previously, only -strings that referred to callables were allowed). This allows a much more -natural use of URLconfs. For example, this URLconf:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - ('^myview/$', 'mysite.myapp.views.myview') - ) - -can now be rewritten as:: - - from django.conf.urls.defaults import * - from mysite.myapp.views import myview - - urlpatterns = patterns('', - ('^myview/$', myview) - ) - -One useful application of this can be seen when using decorators; this -change allows you to apply decorators to views *in your -URLconf*. Thus, you can make a generic view require login very -easily:: - - from django.conf.urls.defaults import * - from django.contrib.auth.decorators import login_required - from django.views.generic.list_detail import object_list - from mysite.myapp.models import MyModel - - info = { - "queryset" : MyModel.objects.all(), - } - - urlpatterns = patterns('', - ('^myview/$', login_required(object_list), info) - ) - -Note that both syntaxes (strings and callables) are valid, and will continue to -be valid for the foreseeable future. - -The test framework ------------------- - -Django now includes a test framework so you can start transmuting fear into -boredom (with apologies to Kent Beck). You can write tests based on doctest_ -or unittest_ and test your views with a simple test client. - -There is also new support for "fixtures" -- initial data, stored in any of the -supported `serialization formats`_, that will be loaded into your database at the -start of your tests. This makes testing with real data much easier. - -See `the testing documentation`_ for the full details. - -.. _doctest: http://docs.python.org/library/doctest.html -.. _unittest: http://docs.python.org/library/unittest.html -.. _the testing documentation: http://www.djangoproject.com/documentation/0.96/testing/ -.. _serialization formats: http://www.djangoproject.com/documentation/0.96/serialization/ - -Improvements to the admin interface ------------------------------------ - -A small change, but a very nice one: dedicated views for adding and -updating users have been added to the admin interface, so you no -longer need to worry about working with hashed passwords in the admin. - -Thanks -====== - -Since 0.95, a number of people have stepped forward and taken a major -new role in Django's development. We'd like to thank these people for -all their hard work: - - * Russell Keith-Magee and Malcolm Tredinnick for their major code - contributions. This release wouldn't have been possible without them. - - * Our new release manager, James Bennett, for his work in getting out - 0.95.1, 0.96, and (hopefully) future release. - - * Our ticket managers Chris Beaven (aka SmileyChris), Simon Greenhill, - Michael Radziej, and Gary Wilson. They agreed to take on the monumental - task of wrangling our tickets into nicely cataloged submission. Figuring - out what to work on is now about a million times easier; thanks again, - guys. - - * Everyone who submitted a bug report, patch or ticket comment. We can't - possibly thank everyone by name -- over 200 developers submitted patches - that went into 0.96 -- but everyone who's contributed to Django is listed - in AUTHORS_. - -.. _AUTHORS: http://code.djangoproject.com/browser/django/trunk/AUTHORS diff --git a/parts/django/docs/releases/1.0-alpha-1.txt b/parts/django/docs/releases/1.0-alpha-1.txt deleted file mode 100644 index 82846be..0000000 --- a/parts/django/docs/releases/1.0-alpha-1.txt +++ /dev/null @@ -1,161 +0,0 @@ -================================ -Django 1.0 alpha release notes -================================ - -Welcome to Django 1.0 alpha! - -This is the first in a series of preview/development releases leading -up to the eventual release of Django 1.0, currently scheduled to take -place in early September 2008. This release is primarily targeted at -developers who are interested in testing the Django codebase and -helping to identify and resolve bugs prior to the final 1.0 release. - -As such, this release is *not* intended for production use, and any -such use is strongly discouraged. - - -What's new in Django 1.0 alpha -============================== - -Django's development trunk has been the site of nearly constant -activity over the past year, with several major new features landing -since the 0.96 release. Some of the highlights include: - -Refactored admin application (newforms-admin) - The Django administrative interface (``django.contrib.admin``) has - been completely refactored; admin definitions are now completely - decoupled from model definitions (no more ``class Admin`` - declaration in models!), rewritten to use Django's new - form-handling library (introduced in the 0.96 release as - ``django.newforms``, and now available as simply ``django.forms``) - and redesigned with extensibility and customization in mind. Full - documentation for the admin application is available online in the - official Django documentation: - - :doc:`admin reference </ref/contrib/admin/index>` - -Improved Unicode handling - Django's internals have been refactored to use Unicode throughout; - this drastically simplifies the task of dealing with - non-Western-European content and data in Django. Additionally, - utility functions have been provided to ease interoperability with - third-party libraries and systems which may or may not handle - Unicode gracefully. Details are available in Django's - Unicode-handling documentation: - - :doc:`unicode reference </ref/unicode>` - -An improved Django ORM - Django's object-relational mapper -- the component which provides - the mapping between Django model classes and your database, and - which mediates your database queries -- has been dramatically - improved by a massive refactoring. For most users of Django this - is backwards-compatible; the public-facing API for database - querying underwent a few minor changes, but most of the updates - took place in the ORM's internals. A guide to the changes, - including backwards-incompatible modifications and mentions of new - features opened up by this refactoring, is available on the Django - wiki: - - http://code.djangoproject.com/wiki/QuerysetRefactorBranch - -Automatic escaping of template variables - To provide improved security against cross-site scripting (XSS) - vulnerabilities, Django's template system now automatically - escapes the output of variables. This behavior is configurable, - and allows both variables and larger template constructs to be - marked as safe (requiring no escaping) or unsafe (requiring - escaping). A full guide to this feature is in the documentation - for the :ttag:`autoescape` tag. - -There are many more new features, many bugfixes and many enhancements -to existing features from previous releases. The ``newforms`` library, -for example, has undergone massive improvements including several -useful add-ons in ``django.contrib`` which complement and build on -Django's form-handling capabilities, and Django's file-uploading -handlers have been refactored to allow finer-grained control over the -uploading process as well as streaming uploads of large files. - -Along with these improvements and additions, we've made a number of -of backwards-incompatible changes to the framework, as features have been -fleshed out and APIs have been finalized for the 1.0 release. A -complete guide to these changes will be available as part of the final -Django 1.0 release, and a comprehensive list of backwards-incompatible -changes is also available on the Django wiki for those who want to -begin developing and testing their upgrade process: - - http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges - - -The Django 1.0 roadmap -====================== - -One of the primary goals of this alpha release is to focus attention -on the remaining features to be implemented for Django 1.0, and on the -bugs that need to be resolved before the final release. Following -this release, we'll be conducting a series of sprints building up to a -series of beta releases and a release-candidate stage, followed soon -after by Django 1.0. The timeline is projected to be: - -* August 1, 2008: Sprint (based in Washington, DC, and online). - -* August 5, 2008: Django 1.0 beta 1 release. This will also constitute - the feature freeze for 1.0. Any feature to be included in 1.0 must - be completed and in trunk by this time. - -* August 8, 2008: Sprint (based in Lawrence, KS, and online). - -* August 12, 2008: Django 1.0 beta 2 release. - -* August 15, 2008: Sprint (based in Austin, TX, and online). - -* August 19, 2008: Django 1.0 release candidate 1. - -* August 22, 2008: Sprint (based in Portland, OR, and online). - -* August 26, 2008: Django 1.0 release candidate 2. - -* September 2, 2008: Django 1.0 final release. The official Django 1.0 - release party will take place during the first-ever DjangoCon, to be - held in Mountain View, CA, September 6-7. - -Of course, like any estimated timeline, this is subject to change as -requirements dictate. The latest information will always be available -on the Django project wiki: - - http://code.djangoproject.com/wiki/VersionOneRoadmap - - -What you can do to help -======================= - -In order to provide a high-quality 1.0 release, we need your -help. Although this alpha release is, again, *not* intended for -production use, you can help the Django team by trying out the alpha -codebase in a safe test environment and reporting any bugs or issues -you encounter. The Django ticket tracker is the central place to -search for open issues: - - http://code.djangoproject.com/timeline - -Please open new tickets if no existing ticket corresponds to a problem -you're running into. - -Additionally, discussion of Django development, including progress -toward the 1.0 release, takes place daily on the django-developers -mailing list: - - http://groups.google.com/group/django-developers - -...and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If -you're interested in helping out with Django's development, feel free -to join the discussions there. - -Django's online documentation also includes pointers on how to -contribute to Django: - - :doc:`contributing to Django </internals/contributing>` - -Contributions on any level -- developing code, writing -documentation or simply triaging tickets and helping to test proposed -bugfixes -- are always welcome and appreciated. diff --git a/parts/django/docs/releases/1.0-alpha-2.txt b/parts/django/docs/releases/1.0-alpha-2.txt deleted file mode 100644 index 83e2e2e..0000000 --- a/parts/django/docs/releases/1.0-alpha-2.txt +++ /dev/null @@ -1,136 +0,0 @@ -================================ -Django 1.0 alpha 2 release notes -================================ - -Welcome to Django 1.0 alpha 2! - -This is the second in a series of preview/development releases leading -up to the eventual release of Django 1.0, currently scheduled to take -place in early September 2008. This releases is primarily targeted at -developers who are interested in testing the Django codebase and -helping to identify and resolve bugs prior to the final 1.0 release. - -As such, this release is *not* intended for production use, and any -such use is strongly discouraged. - - -What's new in Django 1.0 alpha 2 -================================ - -Django's development trunk has been the site of nearly constant activity over -the past year, with several major new features landing since the 0.96 release. -For features which were new as of Django 1.0 alpha 1, see :doc:`the 1.0 alpha 1 -release notes </releases/1.0-alpha-1>`. Since the 1.0 alpha 1 release several new -features have landed, including: - -``django.contrib.gis`` (`GeoDjango`_) - A project over a year in the making, this adds world-class GIS - (`Geographic Information Systems`_) support to Django, in the form - of a ``contrib`` application. `Its documentation`_ is currently - being maintained externally, and will be merged into the main - Django documentation prior to the final 1.0 release. Huge thanks - go to Justin Bronn, Jeremy Dunck, Brett Hoerner and Travis Pinney - for their efforts in creating and completing this feature. - -Pluggable file storage - Django's built-in ``FileField`` and ``ImageField`` now can take advantage of - pluggable file-storage backends, allowing extensive customization of where - and how uploaded files get stored by Django. For details, see :doc:`the - files documentation </topics/files>`; big thanks go to Marty Alchin for - putting in the hard work to get this completed. - -Jython compatibility - Thanks to a lot of work from Leo Soto during a Google Summer of - Code project, Django's codebase has been refactored to remove - incompatibilities with `Jython`_, an implementation of Python - written in Java, which runs Python code on the Java Virtual - Machine. Django is now compatible with the forthcoming Jython 2.5 - release. - -There are many other new features and improvements in this release, including -two major performance boosts: strings marked for translation using -:doc:`Django's internationalization system </topics/i18n/index>` now consume far less -memory, and Django's internal dispatcher -- which is invoked frequently during -request/response processing and when working with Django's object-relational -mapper -- is now significantly faster. - -.. _GeoDjango: http://geodjango.org/ -.. _Geographic Information Systems: http://en.wikipedia.org/wiki/Geographic_information_system -.. _Its documentation: http://geodjango.org/docs/ -.. _Jython: http://www.jython.org/ - - -The Django 1.0 roadmap -====================== - -One of the primary goals of this alpha release is to focus attention -on the remaining features to be implemented for Django 1.0, and on the -bugs that need to be resolved before the final release. Following this -release, we'll be conducting a series of development sprints building -up to the beta and release-candidate stages, followed soon after by -Django 1.0. The timeline is projected to be: - -* **August 14, 2008: Django 1.0 beta release.** Past this point Django - will be in a "feature freeze" for the 1.0 release; after Django 1.0 - beta, the development focus will be solely on bug fixes and - stabilization. - -* August 15, 2008: Sprint (based in Austin, Texas, USA, and online). - -* August 17, 2008: Sprint (based in Tel Aviv, Israel, and online). - -* **August 21, 2008: Django 1.0 release candidate 1.** At this point, - all strings marked for translation within Django's codebase will be - frozen, to provide contributors time to check and finalize all of - Django's bundled translation files prior to the final 1.0 release. - -* August 22, 2008: Sprint (based in Portland, Oregon, USA, and online). - -* **August 26, 2008: Django 1.0 release candidate 2.** - -* August 30, 2008: Sprint (based in London, England, UK, and online). - -* **September 2, 2008: Django 1.0 final release.** The official Django - 1.0 release party will take place during the first-ever DjangoCon, - to be held in Mountain View, California, USA, September 6-7. - -Of course, like any estimated timeline, this is subject to change as -requirements dictate. The latest information will always be available -on the Django project wiki: - - http://code.djangoproject.com/wiki/VersionOneRoadmap - - -What you can do to help -======================= - -In order to provide a high-quality 1.0 release, we need your -help. Although this alpha release is, again, *not* intended for -production use, you can help the Django team by trying out the alpha -codebase in a safe test environment and reporting any bugs or issues -you encounter. The Django ticket tracker is the central place to -search for open issues: - - http://code.djangoproject.com/timeline - -Please open new tickets if no existing ticket corresponds to a problem -you're running into. - -Additionally, discussion of Django development, including progress -toward the 1.0 release, takes place daily on the django-developers -mailing list: - - http://groups.google.com/group/django-developers - -...and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If -you're interested in helping out with Django's development, feel free -to join the discussions there. - -Django's online documentation also includes pointers on how to -contribute to Django: - - :doc:`contributing to Django </internals/contributing>` - -Contributions on any level -- developing code, writing -documentation or simply triaging tickets and helping to test proposed -bugfixes -- are always welcome and appreciated. diff --git a/parts/django/docs/releases/1.0-beta-2.txt b/parts/django/docs/releases/1.0-beta-2.txt deleted file mode 100644 index eabd6b7..0000000 --- a/parts/django/docs/releases/1.0-beta-2.txt +++ /dev/null @@ -1,119 +0,0 @@ -=============================== -Django 1.0 beta 2 release notes -=============================== - -Welcome to Django 1.0 beta 2! - -This is the fourth in a series of preview/development releases leading -up to the eventual release of Django 1.0, currently scheduled to take -place in early September 2008. This releases is primarily targeted at -developers who are interested in testing the Django codebase and -helping to identify and resolve bugs prior to the final 1.0 release. - -As such, this release is *not* intended for production use, and any -such use is discouraged. - -What's new in Django 1.0 beta 2 -=============================== - -Django's development trunk has been the site of nearly constant -activity over the past year, with several major new features landing -since the 0.96 release. For features which were new as of Django 1.0 -alpha 1, see :doc:`the 1.0 alpha 1 release notes -</releases/1.0-alpha-1>`. For features which were new as of Django 1.0 -alpha 2, see :doc:`the 1.0 alpha 2 release notes -</releases/1.0-alpha-2>`. For features which were new as of Django 1.0 -beta 1, see :doc:`the 1.0 beta 1 release notes </releases/1.0-beta>`. - -This beta release includes two major features: - -Refactored ``django.contrib.comments`` - As part of a Google Summer of Code project, Thejaswi Puthraya - carried out a major rewrite and refactoring of Django's bundled - comment system, greatly increasing its flexibility and - customizability. :doc:`Full documentation - </ref/contrib/comments/index>` is available, as well as :doc:`an - upgrade guide </ref/contrib/comments/upgrade>` if you were using - the previous incarnation of the comments application.. - -Refactored documentation - Django's bundled and online documentation has also been - significantly refactored; the new documentation system uses - `Sphinx`_ to build the docs and handle such niceties as topical - indexes, reference documentation and cross-references within the - docs. You can check out the new documentation `online`_ or, if you - have Sphinx installed, build the HTML yourself from the - documentation files bundled with Django. - -.. _Sphinx: http://sphinx.pocoo.org/ -.. _online: http://docs.djangoproject.com/en/dev/ - -Along with these new features, the Django team has also been hard at -work polishing Django's codebase for the final 1.0 release; this beta -release contains a large number of smaller improvements and bugfixes -from the ongoing push to 1.0. - -Also, as part of its ongoing deprecation process, Django's old -form-handling system has been removed; this means ``django.oldforms`` -no longer exists, and its various API hooks (such as automatic -manipulators) are no longer present in Django. This system has been -completely replaced by :doc:`the new form-handling system -</topics/forms/index>` in ``django.forms``. - - -The Django 1.0 roadmap -====================== - -One of the primary goals of this beta release is to focus attention on -the remaining features to be implemented for Django 1.0, and on the -bugs that need to be resolved before the final release. As of this -beta release, Django is in its final "feature freeze" for 1.0; feature -requests will be deferred to later releases, and the development -effort will be focused solely on bug-fixing and stability. Django is -also now in a "string freeze"; translatable strings (labels, error -messages, etc.) in Django's codebase will not be changed prior to the -release, in order to allow our translators to produce the final 1.0 -version of Django's translation files. - -Following this release, we'll be conducting a final development sprint -on August 30, 2008, based in London and coordinated online; the goal -of this sprint will be to squash as many bugs as possible in -anticipation of the final 1.0 release, which is currently targeted for -**September 2, 2008**. The official Django 1.0 release party will take -place during the first-ever DjangoCon, to be held in Mountain View, -California, USA, September 6-7. - - -What you can do to help -======================= - -In order to provide a high-quality 1.0 release, we need your -help. Although this beta release is, again, *not* intended for -production use, you can help the Django team by trying out the beta -codebase in a safe test environment and reporting any bugs or issues -you encounter. The Django ticket tracker is the central place to -search for open issues: - - http://code.djangoproject.com/timeline - -Please open new tickets if no existing ticket corresponds to a problem -you're running into. - -Additionally, discussion of Django development, including progress -toward the 1.0 release, takes place daily on the django-developers -mailing list: - - http://groups.google.com/group/django-developers - -...and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If -you're interested in helping out with Django's development, feel free -to join the discussions there. - -Django's online documentation also includes pointers on how to -contribute to Django: - - :doc:`contributing to Django </internals/contributing>` - -Contributions on any level -- developing code, writing -documentation or simply triaging tickets and helping to test proposed -bugfixes -- are always welcome and appreciated. diff --git a/parts/django/docs/releases/1.0-beta.txt b/parts/django/docs/releases/1.0-beta.txt deleted file mode 100644 index 9e07e6c..0000000 --- a/parts/django/docs/releases/1.0-beta.txt +++ /dev/null @@ -1,153 +0,0 @@ -=============================== -Django 1.0 beta 1 release notes -=============================== - -Welcome to Django 1.0 beta 1! - -This is the third in a series of preview/development releases leading -up to the eventual release of Django 1.0, currently scheduled to take -place in early September 2008. This releases is primarily targeted at -developers who are interested in testing the Django codebase and -helping to identify and resolve bugs prior to the final 1.0 release. - -As such, this release is *not* intended for production use, and any -such use is discouraged. - -What's new in Django 1.0 beta 1 -=============================== - -Django's development trunk has been the site of nearly constant activity over -the past year, with several major new features landing since the 0.96 release. -For features which were new as of Django 1.0 alpha 1, see :doc:`the 1.0 alpha 1 -release notes </releases/1.0-alpha-1>`. For features which were new as of Django -1.0 alpha 2, see :doc:`the 1.0 alpha 2 release notes </releases/1.0-alpha-2>`. - -This beta release does not contain any major new features, but does -include several smaller updates and improvements to Django: - -Generic relations in forms and admin - Classes are now included in ``django.contrib.contenttypes`` which - can be used to support generic relations in both the admin - interface and in end-user forms. See :ref:`the documentation for - generic relations <generic-relations>` for details. - -Improved flexibility in the admin - Following up on the refactoring of Django's administrative - interface (``django.contrib.admin``), introduced in Django 1.0 - alpha 1, two new hooks have been added to allow customized pre- - and post-save handling of model instances in the admin. Full - details are in :doc:`the admin documentation </ref/contrib/admin/index>`. - -``INSERT``/``UPDATE`` distinction - Although Django's default behavior of having a model's ``save()`` - method automatically determine whether to perform an ``INSERT`` or - an ``UPDATE`` at the SQL level is suitable for the majority of - cases, there are occasional situations where forcing one or the - other is useful. As a result, models can now support an additional - parameter to ``save()`` which can force a specific - operation. Consult the database API documentation for details - and important notes about appropriate use of this parameter. - -Split ``CacheMiddleware`` - Django's ``CacheMiddleware`` has been split into three classes: - ``CacheMiddleware`` itself still exists and retains all of its - previous functionality, but it is now built from two separate - middleware classes which handle the two parts of caching (inserting - into and reading from the cache) separately, offering additional - flexibility for situations where combining these functions into a - single middleware posed problems. Full details, including updated - notes on appropriate use, are in - :doc:`the caching documentation </topics/cache>`. - -Removal of deprecated features - A number of features and methods which had previously been marked - as deprecated, and which were scheduled for removal prior to the - 1.0 release, are no longer present in Django. These include - imports of the form library from ``django.newforms`` (now located - simply at ``django.forms``), the ``form_for_model`` and - ``form_for_instance`` helper functions (which have been replaced - by ``ModelForm``) and a number of deprecated features which were - replaced by the dispatcher, file-uploading and file-storage - refactorings introduced in the Django 1.0 alpha releases. A full - list of these and all other backwards-incompatible changes is - available on `the Django wiki`_. - -A number of other improvements and bugfixes have also been included: -some tricky cases involving case-sensitivity in differing MySQL -collations have been resolved, Windows packaging and installation has -been improved and the method by which Django generates unique session -identifiers has been made much more robust. - -.. _the documentation for generic relations: ../contenttypes/#generic-relations -.. _the Django wiki: http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Removedseveralmoredeprecatedfeaturesfor1.0 - - -The Django 1.0 roadmap -====================== - -One of the primary goals of this beta release is to focus attention on -the remaining features to be implemented for Django 1.0, and on the -bugs that need to be resolved before the final release. Following this -release, we'll be conducting a series of development sprints building -up to the release-candidate stage, followed soon after by Django -1.0. The timeline is projected to be: - -* August 15, 2008: Sprint (based in Austin, Texas, USA, and online). - -* August 17, 2008: Sprint (based in Tel Aviv, Israel, and online). - -* **August 21, 2008: Django 1.0 release candidate 1.** At this point, - all strings marked for translation within Django's codebase will be - frozen, to provide contributors time to check and finalize all of - Django's bundled translation files prior to the final 1.0 release. - -* August 22, 2008: Sprint (based in Portland, Oregon, USA, and online). - -* **August 26, 2008: Django 1.0 release candidate 2.** - -* August 30, 2008: Sprint (based in London, England, UK, and online). - -* **September 2, 2008: Django 1.0 final release.** The official Django - 1.0 release party will take place during the first-ever DjangoCon, - to be held in Mountain View, California, USA, September 6-7. - -Of course, like any estimated timeline, this is subject to change as -requirements dictate. The latest information will always be available -on the Django project wiki: - - http://code.djangoproject.com/wiki/VersionOneRoadmap - - -What you can do to help -======================= - -In order to provide a high-quality 1.0 release, we need your -help. Although this beta release is, again, *not* intended for -production use, you can help the Django team by trying out the beta -codebase in a safe test environment and reporting any bugs or issues -you encounter. The Django ticket tracker is the central place to -search for open issues: - - http://code.djangoproject.com/timeline - -Please open new tickets if no existing ticket corresponds to a problem -you're running into. - -Additionally, discussion of Django development, including progress -toward the 1.0 release, takes place daily on the django-developers -mailing list: - - http://groups.google.com/group/django-developers - -...and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If -you're interested in helping out with Django's development, feel free -to join the discussions there. - -Django's online documentation also includes pointers on how to -contribute to Django: - - :doc:`contributing to Django </internals/contributing>` - -Contributions on any level -- developing code, writing -documentation or simply triaging tickets and helping to test proposed -bugfixes -- are always welcome and appreciated. diff --git a/parts/django/docs/releases/1.0-porting-guide.txt b/parts/django/docs/releases/1.0-porting-guide.txt deleted file mode 100644 index e12b34e..0000000 --- a/parts/django/docs/releases/1.0-porting-guide.txt +++ /dev/null @@ -1,772 +0,0 @@ -========================================= -Porting your apps from Django 0.96 to 1.0 -========================================= - -.. highlight:: python - -Django 1.0 breaks compatibility with 0.96 in some areas. - -This guide will help you port 0.96 projects and apps to 1.0. The first part of -this document includes the common changes needed to run with 1.0. If after going -through the first part your code still breaks, check the section `Less-common -Changes`_ for a list of a bunch of less-common compatibility issues. - -.. seealso:: - - The :doc:`1.0 release notes </releases/1.0>`. That document explains the new - features in 1.0 more deeply; the porting guide is more concerned with - helping you quickly update your code. - -Common changes -============== - -This section describes the changes between 0.96 and 1.0 that most users will -need to make. - -Use Unicode ------------ - -Change string literals (``'foo'``) into Unicode literals (``u'foo'``). Django -now uses Unicode strings throughout. In most places, raw strings will continue -to work, but updating to use Unicode literals will prevent some obscure -problems. - -See :doc:`/ref/unicode` for full details. - -Models ------- - -Common changes to your models file: - -Rename ``maxlength`` to ``max_length`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Rename your ``maxlength`` argument to ``max_length`` (this was changed to be -consistent with form fields): - -Replace ``__str__`` with ``__unicode__`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Replace your model's ``__str__`` function with a ``__unicode__`` method, and -make sure you `use Unicode`_ (``u'foo'``) in that method. - -Remove ``prepopulated_from`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Remove the ``prepopulated_from`` argument on model fields. It's no longer valid -and has been moved to the ``ModelAdmin`` class in ``admin.py``. See `the -admin`_, below, for more details about changes to the admin. - -Remove ``core`` -~~~~~~~~~~~~~~~ - -Remove the ``core`` argument from your model fields. It is no longer -necessary, since the equivalent functionality (part of :ref:`inline editing -<admin-inlines>`) is handled differently by the admin interface now. You don't -have to worry about inline editing until you get to `the admin`_ section, -below. For now, remove all references to ``core``. - -Replace ``class Admin:`` with ``admin.py`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Remove all your inner ``class Admin`` declarations from your models. They won't -break anything if you leave them, but they also won't do anything. To register -apps with the admin you'll move those declarations to an ``admin.py`` file; -see `the admin`_ below for more details. - -.. seealso:: - - A contributor to djangosnippets__ has written a script that'll `scan your - models.py and generate a corresponding admin.py`__. - - __ http://www.djangosnippets.org/ - __ http://www.djangosnippets.org/snippets/603/ - -Example -~~~~~~~ - -Below is an example ``models.py`` file with all the changes you'll need to make: - -Old (0.96) ``models.py``:: - - class Author(models.Model): - first_name = models.CharField(maxlength=30) - last_name = models.CharField(maxlength=30) - slug = models.CharField(maxlength=60, prepopulate_from=('first_name', 'last_name')) - - class Admin: - list_display = ['first_name', 'last_name'] - - def __str__(self): - return '%s %s' % (self.first_name, self.last_name) - -New (1.0) ``models.py``:: - - class Author(models.Model): - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=30) - slug = models.CharField(max_length=60) - - def __unicode__(self): - return u'%s %s' % (self.first_name, self.last_name) - -New (1.0) ``admin.py``:: - - from django.contrib import admin - from models import Author - - class AuthorAdmin(admin.ModelAdmin): - list_display = ['first_name', 'last_name'] - prepopulated_fields = { - 'slug': ('first_name', 'last_name') - } - - admin.site.register(Author, AuthorAdmin) - -The Admin ---------- - -One of the biggest changes in 1.0 is the new admin. The Django administrative -interface (``django.contrib.admin``) has been completely refactored; admin -definitions are now completely decoupled from model definitions, the framework -has been rewritten to use Django's new form-handling library and redesigned with -extensibility and customization in mind. - -Practically, this means you'll need to rewrite all of your ``class Admin`` -declarations. You've already seen in `models`_ above how to replace your ``class -Admin`` with a ``admin.site.register()`` call in an ``admin.py`` file. Below are -some more details on how to rewrite that ``Admin`` declaration into the new -syntax. - -Use new inline syntax -~~~~~~~~~~~~~~~~~~~~~ - -The new ``edit_inline`` options have all been moved to ``admin.py``. Here's an -example: - -Old (0.96):: - - class Parent(models.Model): - ... - - class Child(models.Model): - parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3) - - -New (1.0):: - - class ChildInline(admin.StackedInline): - model = Child - extra = 3 - - class ParentAdmin(admin.ModelAdmin): - model = Parent - inlines = [ChildInline] - - admin.site.register(Parent, ParentAdmin) - -See :ref:`admin-inlines` for more details. - -Simplify ``fields``, or use ``fieldsets`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The old ``fields`` syntax was quite confusing, and has been simplified. The old -syntax still works, but you'll need to use ``fieldsets`` instead. - -Old (0.96):: - - class ModelOne(models.Model): - ... - - class Admin: - fields = ( - (None, {'fields': ('foo','bar')}), - ) - - class ModelTwo(models.Model): - ... - - class Admin: - fields = ( - ('group1', {'fields': ('foo','bar'), 'classes': 'collapse'}), - ('group2', {'fields': ('spam','eggs'), 'classes': 'collapse wide'}), - ) - - -New (1.0):: - - class ModelOneAdmin(admin.ModelAdmin): - fields = ('foo', 'bar') - - class ModelTwoAdmin(admin.ModelAdmin): - fieldsets = ( - ('group1', {'fields': ('foo','bar'), 'classes': 'collapse'}), - ('group2', {'fields': ('spam','eggs'), 'classes': 'collapse wide'}), - ) - - -.. seealso:: - - * More detailed information about the changes and the reasons behind them - can be found on the `NewformsAdminBranch wiki page`__ - - * The new admin comes with a ton of new features; you can read about them in - the :doc:`admin documentation </ref/contrib/admin/index>`. - - __ http://code.djangoproject.com/wiki/NewformsAdminBranch - -URLs ----- - -Update your root ``urls.py`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you're using the admin site, you need to update your root ``urls.py``. - -Old (0.96) ``urls.py``:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^admin/', include('django.contrib.admin.urls')), - - # ... the rest of your URLs here ... - ) - -New (1.0) ``urls.py``:: - - from django.conf.urls.defaults import * - - # The next two lines enable the admin and load each admin.py file: - from django.contrib import admin - admin.autodiscover() - - urlpatterns = patterns('', - (r'^admin/(.*)', admin.site.root), - - # ... the rest of your URLs here ... - ) - -Views ------ - -Use ``django.forms`` instead of ``newforms`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Replace ``django.newforms`` with ``django.forms`` -- Django 1.0 renamed the -``newforms`` module (introduced in 0.96) to plain old ``forms``. The -``oldforms`` module was also removed. - -If you're already using the ``newforms`` library, and you used our recommended -``import`` statement syntax, all you have to do is change your import -statements. - -Old:: - - from django import newforms as forms - -New:: - - from django import forms - -If you're using the old forms system (formerly known as ``django.forms`` and -``django.oldforms``), you'll have to rewrite your forms. A good place to start -is the :doc:`forms documentation </topics/forms/index>` - -Handle uploaded files using the new API -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Replace use of uploaded files -- that is, entries in ``request.FILES`` -- as -simple dictionaries with the new :class:`~django.core.files.UploadedFile`. The -old dictionary syntax no longer works. - -Thus, in a view like:: - - def my_view(request): - f = request.FILES['file_field_name'] - ... - -...you'd need to make the following changes: - -===================== ===================== -Old (0.96) New (1.0) -===================== ===================== -``f['content']`` ``f.read()`` -``f['filename']`` ``f.name`` -``f['content-type']`` ``f.content_type`` -===================== ===================== - -Work with file fields using the new API -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The internal implementation of :class:`django.db.models.FileField` have changed. -A visible result of this is that the way you access special attributes (URL, -filename, image size, etc) of these model fields has changed. You will need to -make the following changes, assuming your model's -:class:`~django.db.models.FileField` is called ``myfile``: - -=================================== ======================== -Old (0.96) New (1.0) -=================================== ======================== -``myfile.get_content_filename()`` ``myfile.content.path`` -``myfile.get_content_url()`` ``myfile.content.url`` -``myfile.get_content_size()`` ``myfile.content.size`` -``myfile.save_content_file()`` ``myfile.content.save()`` -``myfile.get_content_width()`` ``myfile.content.width`` -``myfile.get_content_height()`` ``myfile.content.height`` -=================================== ======================== - -Note that the ``width`` and ``height`` attributes only make sense for -:class:`~django.db.models.ImageField` fields. More details can be found in the -:doc:`model API </ref/models/fields>` documentation. - -Use ``Paginator`` instead of ``ObjectPaginator`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``ObjectPaginator`` in 0.96 has been removed and replaced with an improved -version, :class:`django.core.paginator.Paginator`. - -Templates ---------- - -Learn to love autoescaping -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default, the template system now automatically HTML-escapes the output of -every variable. To learn more, see :ref:`automatic-html-escaping`. - -To disable auto-escaping for an individual variable, use the :tfilter:`safe` -filter: - -.. code-block:: html+django - - This will be escaped: {{ data }} - This will not be escaped: {{ data|safe }} - -To disable auto-escaping for an entire template, wrap the template (or just a -particular section of the template) in the :ttag:`autoescape` tag: - -.. code-block:: html+django - - {% autoescape off %} - ... unescaped template content here ... - {% endautoescape %} - -Less-common changes -=================== - -The following changes are smaller, more localized changes. They should only -affect more advanced users, but it's probably worth reading through the list and -checking your code for these things. - -Signals -------- - -* Add ``**kwargs`` to any registered signal handlers. - -* Connect, disconnect, and send signals via methods on the - :class:`~django.dispatch.Signal` object instead of through module methods in - ``django.dispatch.dispatcher``. - -* Remove any use of the ``Anonymous`` and ``Any`` sender options; they no longer - exist. You can still receive signals sent by any sender by using - ``sender=None`` - -* Make any custom signals you've declared into instances of - :class:`django.dispatch.Signal` instead of anonymous objects. - -Here's quick summary of the code changes you'll need to make: - -================================================= ====================================== -Old (0.96) New (1.0) -================================================= ====================================== -``def callback(sender)`` ``def callback(sender, **kwargs)`` -``sig = object()`` ``sig = django.dispatch.Signal()`` -``dispatcher.connect(callback, sig)`` ``sig.connect(callback)`` -``dispatcher.send(sig, sender)`` ``sig.send(sender)`` -``dispatcher.connect(callback, sig, sender=Any)`` ``sig.connect(callback, sender=None)`` -================================================= ====================================== - -Comments --------- - -If you were using Django 0.96's ``django.contrib.comments`` app, you'll need to -upgrade to the new comments app introduced in 1.0. See -:doc:`/ref/contrib/comments/upgrade` for details. - -Template tags -------------- - -:ttag:`spaceless` tag -~~~~~~~~~~~~~~~~~~~~~ - -The spaceless template tag now removes *all* spaces between HTML tags, instead -of preserving a single space. - -Local flavors -------------- - -U.S. local flavor -~~~~~~~~~~~~~~~~~ - -``django.contrib.localflavor.usa`` has been renamed to -:mod:`django.contrib.localflavor.us`. This change was made to match the naming -scheme of other local flavors. To migrate your code, all you need to do is -change the imports. - -Sessions --------- - -Getting a new session key -~~~~~~~~~~~~~~~~~~~~~~~~~ - -``SessionBase.get_new_session_key()`` has been renamed to -``_get_new_session_key()``. ``get_new_session_object()`` no longer exists. - -Fixtures --------- - -Loading a row no longer calls ``save()`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Previously, loading a row automatically ran the model's ``save()`` method. This -is no longer the case, so any fields (for example: timestamps) that were -auto-populated by a ``save()`` now need explicit values in any fixture. - -Settings --------- - -Better exceptions -~~~~~~~~~~~~~~~~~ - -The old :exc:`EnvironmentError` has split into an :exc:`ImportError` when -Django fails to find the settings module and a :exc:`RuntimeError` when you try -to reconfigure settings after having already used them - -``LOGIN_URL`` has moved -~~~~~~~~~~~~~~~~~~~~~~~ - -The ``LOGIN_URL`` constant moved from ``django.contrib.auth`` into the -``settings`` module. Instead of using ``from django.contrib.auth import -LOGIN_URL`` refer to :setting:`settings.LOGIN_URL <LOGIN_URL>`. - -:setting:`APPEND_SLASH` behavior has been updated -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In 0.96, if a URL didn't end in a slash or have a period in the final -component of its path, and ``APPEND_SLASH`` was True, Django would redirect -to the same URL, but with a slash appended to the end. Now, Django checks to -see whether the pattern without the trailing slash would be matched by -something in your URL patterns. If so, no redirection takes place, because it -is assumed you deliberately wanted to catch that pattern. - -For most people, this won't require any changes. Some people, though, have URL -patterns that look like this:: - - r'/some_prefix/(.*)$' - -Previously, those patterns would have been redirected to have a trailing -slash. If you always want a slash on such URLs, rewrite the pattern as:: - - r'/some_prefix/(.*/)$' - -Smaller model changes ---------------------- - -Different exception from ``get()`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Managers now return a :exc:`MultipleObjectsReturned` exception -instead of :exc:`AssertionError`: - -Old (0.96):: - - try: - Model.objects.get(...) - except AssertionError: - handle_the_error() - -New (1.0):: - - try: - Model.objects.get(...) - except Model.MultipleObjectsReturned: - handle_the_error() - -``LazyDate`` has been fired -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``LazyDate`` helper class no longer exists. - -Default field values and query arguments can both be callable objects, so -instances of ``LazyDate`` can be replaced with a reference to ``datetime.datetime.now``: - -Old (0.96):: - - class Article(models.Model): - title = models.CharField(maxlength=100) - published = models.DateField(default=LazyDate()) - -New (1.0):: - - import datetime - - class Article(models.Model): - title = models.CharField(max_length=100) - published = models.DateField(default=datetime.datetime.now) - -``DecimalField`` is new, and ``FloatField`` is now a proper float -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Old (0.96):: - - class MyModel(models.Model): - field_name = models.FloatField(max_digits=10, decimal_places=3) - ... - -New (1.0):: - - class MyModel(models.Model): - field_name = models.DecimalField(max_digits=10, decimal_places=3) - ... - -If you forget to make this change, you will see errors about ``FloatField`` -not taking a ``max_digits`` attribute in ``__init__``, because the new -``FloatField`` takes no precision-related arguments. - -If you're using MySQL or PostgreSQL, no further changes are needed. The -database column types for ``DecimalField`` are the same as for the old -``FloatField``. - -If you're using SQLite, you need to force the database to view the -appropriate columns as decimal types, rather than floats. To do this, you'll -need to reload your data. Do this after you have made the change to using -``DecimalField`` in your code and updated the Django code. - -.. warning:: - - **Back up your database first!** - - For SQLite, this means making a copy of the single file that stores the - database (the name of that file is the ``DATABASE_NAME`` in your settings.py - file). - -To upgrade each application to use a ``DecimalField``, you can do the -following, replacing ``<app>`` in the code below with each app's name: - -.. code-block:: bash - - $ ./manage.py dumpdata --format=xml <app> > data-dump.xml - $ ./manage.py reset <app> - $ ./manage.py loaddata data-dump.xml - -Notes: - - 1. It's important that you remember to use XML format in the first step of - this process. We are exploiting a feature of the XML data dumps that makes - porting floats to decimals with SQLite possible. - - 2. In the second step you will be asked to confirm that you are prepared to - lose the data for the application(s) in question. Say yes; we'll restore - this data in the third step, of course. - - 3. ``DecimalField`` is not used in any of the apps shipped with Django prior - to this change being made, so you do not need to worry about performing - this procedure for any of the standard Django models. - -If something goes wrong in the above process, just copy your backed up -database file over the original file and start again. - -Internationalization --------------------- - -:func:`django.views.i18n.set_language` now requires a POST request -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Previously, a GET request was used. The old behavior meant that state (the -locale used to display the site) could be changed by a GET request, which is -against the HTTP specification's recommendations. Code calling this view must -ensure that a POST request is now made, instead of a GET. This means you can -no longer use a link to access the view, but must use a form submission of -some kind (e.g. a button). - -``_()`` is no longer in builtins -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``_()`` (the callable object whose name is a single underscore) is no longer -monkeypatched into builtins -- that is, it's no longer available magically in -every module. - -If you were previously relying on ``_()`` always being present, you should now -explicitly import ``ugettext`` or ``ugettext_lazy``, if appropriate, and alias -it to ``_`` yourself:: - - from django.utils.translation import ugettext as _ - -HTTP request/response objects ------------------------------ - -Dictionary access to ``HttpRequest`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``HttpRequest`` objects no longer directly support dictionary-style -access; previously, both ``GET`` and ``POST`` data were directly -available on the ``HttpRequest`` object (e.g., you could check for a -piece of form data by using ``if 'some_form_key' in request`` or by -reading ``request['some_form_key']``. This is no longer supported; if -you need access to the combined ``GET`` and ``POST`` data, use -``request.REQUEST`` instead. - -It is strongly suggested, however, that you always explicitly look in -the appropriate dictionary for the type of request you expect to -receive (``request.GET`` or ``request.POST``); relying on the combined -``request.REQUEST`` dictionary can mask the origin of incoming data. - -Accessing ``HTTPResponse`` headers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``django.http.HttpResponse.headers`` has been renamed to ``_headers`` and -:class:`~django.http.HttpResponse` now supports containment checking directly. -So use ``if header in response:`` instead of ``if header in response.headers:``. - -Generic relations ------------------ - -Generic relations have been moved out of core -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The generic relation classes -- ``GenericForeignKey`` and ``GenericRelation`` --- have moved into the :mod:`django.contrib.contenttypes` module. - -Testing -------- - -:meth:`django.test.Client.login` has changed -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Old (0.96):: - - from django.test import Client - c = Client() - c.login('/path/to/login','myuser','mypassword') - -New (1.0):: - - # ... same as above, but then: - c.login(username='myuser', password='mypassword') - -Management commands -------------------- - -Running management commands from your code -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:mod:`django.core.management` has been greatly refactored. - -Calls to management services in your code now need to use -``call_command``. For example, if you have some test code that calls flush and -load_data:: - - from django.core import management - management.flush(verbosity=0, interactive=False) - management.load_data(['test_data'], verbosity=0) - -...you'll need to change this code to read:: - - from django.core import management - management.call_command('flush', verbosity=0, interactive=False) - management.call_command('loaddata', 'test_data', verbosity=0) - -Subcommands must now precede options -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``django-admin.py`` and ``manage.py`` now require subcommands to precede -options. So: - -.. code-block:: bash - - $ django-admin.py --settings=foo.bar runserver - -...no longer works and should be changed to: - -.. code-block:: bash - - $ django-admin.py runserver --settings=foo.bar - -Syndication ------------ - -``Feed.__init__`` has changed -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``__init__()`` method of the syndication framework's ``Feed`` class now -takes an ``HttpRequest`` object as its second parameter, instead of the feed's -URL. This allows the syndication framework to work without requiring the sites -framework. This only affects code that subclasses ``Feed`` and overrides the -``__init__()`` method, and code that calls ``Feed.__init__()`` directly. - -Data structures ---------------- - -``SortedDictFromList`` is gone -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``django.newforms.forms.SortedDictFromList`` was removed. -:class:`django.utils.datastructures.SortedDict` can now be instantiated with -a sequence of tuples. - -To update your code: - - 1. Use :class:`django.utils.datastructures.SortedDict` wherever you were - using ``django.newforms.forms.SortedDictFromList``. - - 2. Because :meth:`django.utils.datastructures.SortedDict.copy` doesn't - return a deepcopy as ``SortedDictFromList.copy()`` did, you will need - to update your code if you were relying on a deepcopy. Do this by using - ``copy.deepcopy`` directly. - -Database backend functions --------------------------- - -Database backend functions have been renamed -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Almost *all* of the database backend-level functions have been renamed and/or -relocated. None of these were documented, but you'll need to change your code -if you're using any of these functions, all of which are in :mod:`django.db`: - -======================================= =================================================== -Old (0.96) New (1.0) -======================================= =================================================== -``backend.get_autoinc_sql`` ``connection.ops.autoinc_sql`` -``backend.get_date_extract_sql`` ``connection.ops.date_extract_sql`` -``backend.get_date_trunc_sql`` ``connection.ops.date_trunc_sql`` -``backend.get_datetime_cast_sql`` ``connection.ops.datetime_cast_sql`` -``backend.get_deferrable_sql`` ``connection.ops.deferrable_sql`` -``backend.get_drop_foreignkey_sql`` ``connection.ops.drop_foreignkey_sql`` -``backend.get_fulltext_search_sql`` ``connection.ops.fulltext_search_sql`` -``backend.get_last_insert_id`` ``connection.ops.last_insert_id`` -``backend.get_limit_offset_sql`` ``connection.ops.limit_offset_sql`` -``backend.get_max_name_length`` ``connection.ops.max_name_length`` -``backend.get_pk_default_value`` ``connection.ops.pk_default_value`` -``backend.get_random_function_sql`` ``connection.ops.random_function_sql`` -``backend.get_sql_flush`` ``connection.ops.sql_flush`` -``backend.get_sql_sequence_reset`` ``connection.ops.sequence_reset_sql`` -``backend.get_start_transaction_sql`` ``connection.ops.start_transaction_sql`` -``backend.get_tablespace_sql`` ``connection.ops.tablespace_sql`` -``backend.quote_name`` ``connection.ops.quote_name`` -``backend.get_query_set_class`` ``connection.ops.query_set_class`` -``backend.get_field_cast_sql`` ``connection.ops.field_cast_sql`` -``backend.get_drop_sequence`` ``connection.ops.drop_sequence_sql`` -``backend.OPERATOR_MAPPING`` ``connection.operators`` -``backend.allows_group_by_ordinal`` ``connection.features.allows_group_by_ordinal`` -``backend.allows_unique_and_pk`` ``connection.features.allows_unique_and_pk`` -``backend.autoindexes_primary_keys`` ``connection.features.autoindexes_primary_keys`` -``backend.needs_datetime_string_cast`` ``connection.features.needs_datetime_string_cast`` -``backend.needs_upper_for_iops`` ``connection.features.needs_upper_for_iops`` -``backend.supports_constraints`` ``connection.features.supports_constraints`` -``backend.supports_tablespaces`` ``connection.features.supports_tablespaces`` -``backend.uses_case_insensitive_names`` ``connection.features.uses_case_insensitive_names`` -``backend.uses_custom_queryset`` ``connection.features.uses_custom_queryset`` -======================================= =================================================== - diff --git a/parts/django/docs/releases/1.0.1.txt b/parts/django/docs/releases/1.0.1.txt deleted file mode 100644 index 780dc53..0000000 --- a/parts/django/docs/releases/1.0.1.txt +++ /dev/null @@ -1,65 +0,0 @@ -========================== -Django 1.0.1 release notes -========================== - -Welcome to Django 1.0.1! - -This is the first "bugfix" release in the Django 1.0 series, improving -the stability and performance of the Django 1.0 codebase. As such, -Django 1.0.1 contains no new features (and, pursuant to `our -compatibility policy`_, maintains backwards compatibility with Django -1.0), but does contain a number of fixes and other -improvements. Django 1.0.1 is a recommended upgrade for any -development or deployment currently using or targeting Django 1.0. - - -Fixes and improvements in Django 1.0.1 -====================================== - -Django 1.0.1 contains over two hundred fixes to the original Django -1.0 codebase; full details of every fix are available in `the -Subversion log of the 1.0.X branch`_, but here are some of the -highlights: - -* Several fixes in ``django.contrib.comments``, pertaining to RSS - feeds of comments, default ordering of comments and the XHTML and - internationalization of the default templates for comments. - -* Multiple fixes for Django's support of Oracle databases, including - pagination support for GIS QuerySets, more efficient slicing of - results and improved introspection of existing databases. - -* Several fixes for query support in the Django object-relational - mapper, including repeated setting and resetting of ordering and - fixes for working with ``INSERT``-only queries. - -* Multiple fixes for inline forms in formsets. - -* Multiple fixes for ``unique`` and ``unique_together`` model - constraints in automatically-generated forms. - -* Fixed support for custom callable ``upload_to`` declarations when - handling file uploads through automatically-generated forms. - -* Fixed support for sorting an admin change list based on a callable - attributes in ``list_display``. - -* A fix to the application of autoescaping for literal strings passed - to the ``join`` template filter. Previously, literal strings passed - to ``join`` were automatically escaped, contrary to `the documented - behavior for autoescaping and literal strings`_. Literal strings - passed to ``join`` are no longer automatically escaped, meaning you - must now manually escape them; this is an incompatibility if you - were relying on this bug, but not if you were relying on escaping - behaving as documented. - -* Improved and expanded translation files for many of the languages - Django supports by default. - -* And as always, a large number of improvements to Django's - documentation, including both corrections to existing documents and - expanded and new documentation. - -.. _our compatibility policy: http://docs.djangoproject.com/en/dev/misc/api-stability/ -.. _the Subversion log of the 1.0.X branch: http://code.djangoproject.com/log/django/branches/releases/1.0.X -.. _the documented behavior for autoescaping and literal strings: http://docs.djangoproject.com/en/dev/topics/templates/#string-literals-and-automatic-escaping diff --git a/parts/django/docs/releases/1.0.2.txt b/parts/django/docs/releases/1.0.2.txt deleted file mode 100644 index b34522a..0000000 --- a/parts/django/docs/releases/1.0.2.txt +++ /dev/null @@ -1,51 +0,0 @@ -========================== -Django 1.0.2 release notes -========================== - -Welcome to Django 1.0.2! - -This is the second "bugfix" release in the Django 1.0 series, -improving the stability and performance of the Django 1.0 codebase. As -such, Django 1.0.2 contains no new features (and, pursuant to -:doc:`our compatibility policy </misc/api-stability>`, maintains backwards compatibility with Django -1.0.0), but does contain a number of fixes and other -improvements. Django 1.0.2 is a recommended upgrade for any -development or deployment currently using or targeting Django 1.0. - - -Fixes and improvements in Django 1.0.2 -====================================== - -The primary reason behind this release is to remedy an issue in the -recently-released Django 1.0.1; the packaging scripts used for Django -1.0.1 omitted some directories from the final release package, -including one directory required by ``django.contrib.gis`` and part of -Django's unit-test suite. - -Django 1.0.2 contains updated packaging scripts, and the release -package contains the directories omitted from Django 1.0.1. As such, -this release contains all of the fixes and improvements from Django -1.0.1; see :doc:`the Django 1.0.1 release notes </releases/1.0.1>` for -details. - -Additionally, in the period since Django 1.0.1 was released: - -* Updated Hebrew and Danish translations have been added. - -* The default ``__repr__`` method of Django models has been made more - robust in the face of bad Unicode data coming from the - ``__unicode__`` method; rather than raise an exception in such - cases, ``repr()`` will now contain the string "[Bad Unicode data]" - in place of the invalid Unicode. - -* A bug involving the interaction of Django's ``SafeUnicode`` class - and the MySQL adapter has been resolved; ``SafeUnicode`` instances - (generated, for example, by template rendering) can now be assigned - to model attributes and saved to MySQL without requiring an explicit - intermediate cast to ``unicode``. - -* A bug affecting filtering on a nullable ``DateField`` in SQLite has - been resolved. - -* Several updates and improvements have been made to Django's - documentation. diff --git a/parts/django/docs/releases/1.0.txt b/parts/django/docs/releases/1.0.txt deleted file mode 100644 index a2b6083..0000000 --- a/parts/django/docs/releases/1.0.txt +++ /dev/null @@ -1,246 +0,0 @@ -======================== -Django 1.0 release notes -======================== - -Welcome to Django 1.0! - -We've been looking forward to this moment for over three years, and it's finally -here. Django 1.0 represents a the largest milestone in Django's development to -date: a Web framework that a group of perfectionists can truly be proud of. - -Django 1.0 represents over three years of community development as an Open -Source project. Django's received contributions from hundreds of developers, -been translated into fifty languages, and today is used by developers on every -continent and in every kind of job. - -An interesting historical note: when Django was first released in July 2005, the -initial released version of Django came from an internal repository at revision -number 8825. Django 1.0 represents revision 8961 of our public repository. It -seems fitting that our 1.0 release comes at the moment where community -contributions overtake those made privately. - -Stability and forwards-compatibility -==================================== - -:doc:`The release of Django 1.0 </releases/1.0>` comes with a promise of API -stability and forwards-compatibility. In a nutshell, this means that code you -develop against Django 1.0 will continue to work against 1.1 unchanged, and you -should need to make only minor changes for any 1.X release. - -See the :doc:`API stability guide </misc/api-stability>` for full details. - -Backwards-incompatible changes -============================== - -Django 1.0 has a number of backwards-incompatible changes from Django 0.96. If -you have apps written against Django 0.96 that you need to port, see our -detailed porting guide: - -.. toctree:: - :maxdepth: 1 - - 1.0-porting-guide - -A complete list of backwards-incompatible changes can be found at -http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges. - -What's new in Django 1.0 -======================== - -A *lot*! - -Since Django 0.96, we've made over 4,000 code commits, fixed more than 2,000 -bugs, and edited, added, or removed around 350,000 lines of code. We've also -added 40,000 lines of new documentation, and greatly improved what was already -there. - -In fact, new documentation is one of our favorite features of Django 1.0, so we -might as well start there. First, there's a new documentation site: - - http://docs.djangoproject.com/ - -The documentation has been greatly improved, cleaned up, and generally made -awesome. There's now dedicated search, indexes, and more. - -We can't possibly document everything that's new in 1.0, but the documentation -will be your definitive guide. Anywhere you see something like: - -.. versionadded:: 1.0 - This feature is new in Django 1.0 - -You'll know that you're looking at something new or changed. - -The other major highlights of Django 1.0 are: - -Re-factored admin application ------------------------------ - -The Django administrative interface (``django.contrib.admin``) has been -completely refactored; admin definitions are now completely decoupled from model -definitions (no more ``class Admin`` declaration in models!), rewritten to use -Django's new form-handling library (introduced in the 0.96 release as -``django.newforms``, and now available as simply ``django.forms``) and -redesigned with extensibility and customization in mind. Full documentation for -the admin application is available online in the official Django documentation: - -See the :doc:`admin reference </ref/contrib/admin/index>` for details - -Improved Unicode handling -------------------------- - -Django's internals have been refactored to use Unicode throughout; this -drastically simplifies the task of dealing with non-Western-European content and -data in Django. Additionally, utility functions have been provided to ease -interoperability with third-party libraries and systems which may or may not -handle Unicode gracefully. Details are available in Django's Unicode-handling -documentation. - -See :doc:`/ref/unicode`. - -An improved ORM ---------------- - -Django's object-relational mapper -- the component which provides the mapping -between Django model classes and your database, and which mediates your database -queries -- has been dramatically improved by a massive refactoring. For most -users of Django this is backwards-compatible; the public-facing API for database -querying underwent a few minor changes, but most of the updates took place in -the ORM's internals. A guide to the changes, including backwards-incompatible -modifications and mentions of new features opened up by this refactoring, is -`available on the Django wiki`__. - -__ http://code.djangoproject.com/wiki/QuerysetRefactorBranch - -Automatic escaping of template variables ----------------------------------------- - -To provide improved security against cross-site scripting (XSS) vulnerabilities, -Django's template system now automatically escapes the output of variables. This -behavior is configurable, and allows both variables and larger template -constructs to be marked as safe (requiring no escaping) or unsafe (requiring -escaping). A full guide to this feature is in the documentation for the -:ttag:`autoescape` tag. - -``django.contrib.gis`` (GeoDjango) ----------------------------------- - -A project over a year in the making, this adds world-class GIS (`Geographic -Information Systems`_) support to Django, in the form of a ``contrib`` -application. Its documentation is currently being maintained externally, and -will be merged into the main Django documentation shortly. Huge thanks go to -Justin Bronn, Jeremy Dunck, Brett Hoerner and Travis Pinney for their efforts in -creating and completing this feature. - -See http://geodjango.org/ for details. - -.. _Geographic Information Systems: http://en.wikipedia.org/wiki/Geographic_information_system - -Pluggable file storage ----------------------- - -Django's built-in ``FileField`` and ``ImageField`` now can take advantage of -pluggable file-storage backends, allowing extensive customization of where and -how uploaded files get stored by Django. For details, see :doc:`the files -documentation </topics/files>`; big thanks go to Marty Alchin for putting in the -hard work to get this completed. - -Jython compatibility --------------------- - -Thanks to a lot of work from Leo Soto during a Google Summer of Code project, -Django's codebase has been refactored to remove incompatibilities with -`Jython`_, an implementation of Python written in Java, which runs Python code -on the Java Virtual Machine. Django is now compatible with the forthcoming -Jython 2.5 release. - -See :doc:`/howto/jython`. - -.. _Jython: http://www.jython.org/ - -Generic relations in forms and admin ------------------------------------- - -Classes are now included in ``django.contrib.contenttypes`` which can be used to -support generic relations in both the admin interface and in end-user forms. See -:ref:`the documentation for generic relations <generic-relations>` for details. - -``INSERT``/``UPDATE`` distinction ---------------------------------- - -Although Django's default behavior of having a model's ``save()`` method -automatically determine whether to perform an ``INSERT`` or an ``UPDATE`` at the -SQL level is suitable for the majority of cases, there are occasional situations -where forcing one or the other is useful. As a result, models can now support an -additional parameter to ``save()`` which can force a specific operation. - -See :ref:`ref-models-force-insert` for details. - -Split ``CacheMiddleware`` -------------------------- - -Django's ``CacheMiddleware`` has been split into three classes: -``CacheMiddleware`` itself still exists and retains all of its previous -functionality, but it is now built from two separate middleware classes which -handle the two parts of caching (inserting into and reading from the cache) -separately, offering additional flexibility for situations where combining these -functions into a single middleware posed problems. - -Full details, including updated notes on appropriate use, are in :doc:`the -caching documentation </topics/cache>`. - -Refactored ``django.contrib.comments`` --------------------------------------- - -As part of a Google Summer of Code project, Thejaswi Puthraya carried out a -major rewrite and refactoring of Django's bundled comment system, greatly -increasing its flexibility and customizability. :doc:`Full documentation -</ref/contrib/comments/index>` is available, as well as :doc:`an upgrade guide -</ref/contrib/comments/upgrade>` if you were using the previous incarnation of -the comments application. - -Removal of deprecated features ------------------------------- - -A number of features and methods which had previously been marked as deprecated, -and which were scheduled for removal prior to the 1.0 release, are no longer -present in Django. These include imports of the form library from -``django.newforms`` (now located simply at ``django.forms``), the -``form_for_model`` and ``form_for_instance`` helper functions (which have been -replaced by ``ModelForm``) and a number of deprecated features which were -replaced by the dispatcher, file-uploading and file-storage refactorings -introduced in the Django 1.0 alpha releases. - -Known issues -============ - -We've done our best to make Django 1.0 as solid as possible, but unfortunately -there are a couple of issues that we know about in the release. - -Multi-table model inheritance with ``to_field`` ------------------------------------------------ - -If you're using :ref:`multiple table model inheritance -<multi-table-inheritance>`, be aware of this caveat: child models using a custom -``parent_link`` and ``to_field`` will cause database integrity errors. A set of -models like the following are **not valid**:: - - class Parent(models.Model): - name = models.CharField(max_length=10) - other_value = models.IntegerField(unique=True) - - class Child(Parent): - father = models.OneToOneField(Parent, primary_key=True, to_field="other_value", parent_link=True) - value = models.IntegerField() - -This bug will be fixed in the next release of Django. - -Caveats with support of certain databases ------------------------------------------ - -Django attempts to support as many features as possible on all database -backends. However, not all database backends are alike, and in particular many of the supported database differ greatly from version to version. It's a good idea to checkout our :doc:`notes on supported database </ref/databases>`: - - - :ref:`mysql-notes` - - :ref:`sqlite-notes` - - :ref:`oracle-notes` - diff --git a/parts/django/docs/releases/1.1-alpha-1.txt b/parts/django/docs/releases/1.1-alpha-1.txt deleted file mode 100644 index b15a2a4..0000000 --- a/parts/django/docs/releases/1.1-alpha-1.txt +++ /dev/null @@ -1,163 +0,0 @@ -================================ -Django 1.1 alpha 1 release notes -================================ - -February 23, 2009 - -Welcome to Django 1.1 alpha 1! - -This is the first in a series of preview/development releases leading up to the -eventual release of Django 1.1, currently scheduled to take place in April 2009. -This release is primarily targeted at developers who are interested in trying -out new features and testing the Django codebase to help identify and resolve -bugs prior to the final 1.1 release. - -As such, this release is *not* intended for production use, and any such use is -discouraged. - -What's new in Django 1.1 alpha 1 -================================ - -ORM improvements ----------------- - -Two major enhancements have been added to Django's object-relational mapper -(ORM): - -Aggregate support -~~~~~~~~~~~~~~~~~ - -.. currentmodule:: django.db.models - -It's now possible to run SQL aggregate queries (i.e. ``COUNT()``, ``MAX()``, -``MIN()``, etc.) from within Django's ORM. You can choose to either return the -results of the aggregate directly, or else annotate the objects in a -:class:`QuerySet` with the results of the aggregate query. - -This feature is available as new :meth:`QuerySet.aggregate()`` and -:meth:`QuerySet.annotate()`` methods, and is covered in detail in :doc:`the ORM -aggregation documentation </topics/db/aggregation>` - -Query expressions -~~~~~~~~~~~~~~~~~ - -Queries can now refer to a another field on the query and can traverse -relationships to refer to fields on related models. This is implemented in the -new :class:`F` object; for full details, including examples, consult the -:ref:`documentation for F expressions <query-expressions>`. - -Performance improvements ------------------------- - -.. currentmodule:: django.test - -Tests written using Django's :doc:`testing framework </topics/testing>` now run -dramatically faster (as much as 10 times faster in many cases). - -This was accomplished through the introduction of transaction-based tests: when -using :class:`django.test.TestCase`, your tests will now be run in a transaction -which is rolled back when finished, instead of by flushing and re-populating the -database. This results in an immense speedup for most types of unit tests. See -the documentation for :class:`TestCase` and :class:`TransactionTestCase` for a -full description, and some important notes on database support. - -Other improvements ------------------- - -Other new features and changes introduced since Django 1.0 include: - -* The :doc:`CSRF protection middleware </ref/contrib/csrf>` has been split into - two classes -- ``CsrfViewMiddleware`` checks incoming requests, and - ``CsrfResponseMiddleware`` processes outgoing responses. The combined - ``CsrfMiddleware`` class (which does both) remains for - backwards-compatibility, but using the split classes is now recommended in - order to allow fine-grained control of when and where the CSRF processing - takes place. - -* :func:`~django.core.urlresolvers.reverse` and code which uses it (e.g., the - ``{% url %}`` template tag) now works with URLs in Django's administrative - site, provided that the admin URLs are set up via ``include(admin.site.urls)`` - (sending admin requests to the ``admin.site.root`` view still works, but URLs - in the admin will not be "reversible" when configured this way). - -* The ``include()`` function in Django URLconf modules can now accept sequences - of URL patterns (generated by ``patterns()``) in addition to module names. - -* Instances of Django forms (see :doc:`the forms overview </topics/forms/index>`) - now have two additional methods, ``hidden_fields()`` and ``visible_fields()``, - which return the list of hidden -- i.e., ``<input type="hidden">`` -- and - visible fields on the form, respectively. - -* The ``redirect_to`` generic view (see :doc:`the generic views documentation - </ref/generic-views>`) now accepts an additional keyword argument - ``permanent``. If ``permanent`` is ``True``, the view will emit an HTTP - permanent redirect (status code 301). If ``False``, the view will emit an HTTP - temporary redirect (status code 302). - -* A new database lookup type -- ``week_day`` -- has been added for ``DateField`` - and ``DateTimeField``. This type of lookup accepts a number between 1 (Sunday) - and 7 (Saturday), and returns objects where the field value matches that day - of the week. See :ref:`the full list of lookup types <field-lookups>` for - details. - -* The ``{% for %}`` tag in Django's template language now accepts an optional - ``{% empty %}`` clause, to be displayed when ``{% for %}`` is asked to loop - over an empty sequence. See :doc:`the list of built-in template tags - </ref/templates/builtins>` for examples of this. - -The Django 1.1 roadmap -====================== - -Before Django 1.1 goes final, several other preview/development releases will be -made available. The current schedule consists of at least the following: - -* Week of *March 20, 2009:* Django 1.1 beta 1, at which point Django 1.1 will - be in "feature freeze": no new features will be implemented for 1.1 - past that point, and all new feature work will be deferred to - Django 1.2. - -* Week of *April 2, 2009:* Django 1.1 release candidate. At this point all - strings marked for translation must freeze to allow translations to - be submitted in advance of the final release. - -* Week of *April 13, 2009:* Django 1.1 final. - -If deemed necessary, additional alpha, beta or release candidate packages will -be issued prior to the final 1.1 release. - -What you can do to help -======================= - -In order to provide a high-quality 1.1 release, we need your help. Although this -alpha release is, again, *not* intended for production use, you can help the -Django team by trying out the alpha codebase in a safe test environment and -reporting any bugs or issues you encounter. The Django ticket tracker is the -central place to search for open issues: - - * http://code.djangoproject.com/timeline - -Please open new tickets if no existing ticket corresponds to a problem you're -running into. - -Additionally, discussion of Django development, including progress toward the -1.1 release, takes place daily on the django-developers mailing list: - - * http://groups.google.com/group/django-developers - -... and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If you're -interested in helping out with Django's development, feel free to join the -discussions there. - -Django's online documentation also includes pointers on how to contribute to -Django: - - * :doc:`How to contribute to Django </internals/contributing>` - -Contributions on any level -- developing code, writing documentation or simply -triaging tickets and helping to test proposed bugfixes -- are always welcome and -appreciated. - -Development sprints for Django 1.1 will also be taking place at PyCon US 2009, -on the dedicated sprint days (March 30 through April 2), and anyone who wants to -help out is welcome to join in, either in person at PyCon or virtually in the -IRC channel or on the mailing list. diff --git a/parts/django/docs/releases/1.1-beta-1.txt b/parts/django/docs/releases/1.1-beta-1.txt deleted file mode 100644 index 535f818..0000000 --- a/parts/django/docs/releases/1.1-beta-1.txt +++ /dev/null @@ -1,208 +0,0 @@ -=============================== -Django 1.1 beta 1 release notes -=============================== - -March 23, 2009 - -Welcome to Django 1.1 beta 1! - -This is the second in a series of preview/development releases leading up to -the eventual release of Django 1.1, currently scheduled to take place in April -2009. This release is primarily targeted at developers who are interested in -trying out new features and testing the Django codebase to help identify and -resolve bugs prior to the final 1.1 release. - -As such, this release is *not* intended for production use, and any such use -is discouraged. - -What's new in Django 1.1 beta 1 -=============================== - -.. seealso:: - - The :doc:`1.1 alpha release notes </releases/1.1-alpha-1>`, which has a - list of everything new between Django 1.0 and Django 1.1 alpha. - -Model improvements ------------------- - -.. currentmodule:: django.db.models - -A number of features have been added to Django's model layer: - -"Unmanaged" models -~~~~~~~~~~~~~~~~~~ - -You can now control whether or not Django creates database tables for a model -using the :attr:`~Options.managed` model option. This defaults to ``True``, -meaning that Django will create the appropriate database tables in -:djadmin:`syncdb` and remove them as part of :djadmin:`reset` command. That -is, Django *manages* the database table's lifecycle. - -If you set this to ``False``, however, no database table creating or deletion -will be automatically performed for this model. This is useful if the model -represents an existing table or a database view that has been created by some -other means. - -For more details, see the documentation for the :attr:`~Options.managed` -option. - -Proxy models -~~~~~~~~~~~~ - -You can now create :ref:`proxy models <proxy-models>`: subclasses of existing -models that only add Python behavior and aren't represented by a new table. -That is, the new model is a *proxy* for some underlying model, which stores -all the real data. - -All the details can be found in the :ref:`proxy models documentation -<proxy-models>`. This feature is similar on the surface to unmanaged models, -so the documentation has an explanation of :ref:`how proxy models differ from -unmanaged models <proxy-vs-unmanaged-models>`. - -Deferred fields -~~~~~~~~~~~~~~~ - -In some complex situations, your models might contain fields which could -contain a lot of data (for example, large text fields), or require expensive -processing to convert them to Python objects. If you know you don't need those -particular fields, you can now tell Django not to retrieve them from the -database. - -You'll do this with the new queryset methods -:meth:`~django.db.models.QuerySet.defer` and -:meth:`~django.db.models.QuerySet.only`. - -New admin features ------------------- - -Since 1.1 alpha, a couple of new features have been added to Django's admin -application: - -Editable fields on the change list -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can now make fields editable on the admin list views via the new -:ref:`list_editable <admin-list-editable>` admin option. These fields will show -up as form widgets on the list pages, and can be edited and saved in bulk. - -Admin "actions" -~~~~~~~~~~~~~~~ - -You can now define :doc:`admin actions </ref/contrib/admin/actions>` that can perform -some action to a group of models in bulk. Users will be able to select objects on -the change list page and then apply these bulk actions to all selected objects. - -Django ships with one pre-defined admin action to delete a group of objects in -one fell swoop. - -Testing improvements --------------------- - -.. currentmodule:: django.test.client - -A couple of small but very useful improvements have been made to the -:doc:`testing framework </topics/testing>`: - - * The test :class:`Client` now can automatically follow redirects with the - ``follow`` argument to :meth:`Client.get` and :meth:`Client.post`. This - makes testing views that issue redirects simpler. - - * It's now easier to get at the template context in the response returned - the test client: you'll simply access the context as - ``request.context[key]``. The old way, which treats ``request.context`` - as a list of contexts, one for each rendered template, is still - available if you need it. - -Conditional view processing ---------------------------- - -Django now has much better support for :doc:`conditional view processing -</topics/conditional-view-processing>` using the standard ``ETag`` and -``Last-Modified`` HTTP headers. This means you can now easily short-circuit -view processing by testing less-expensive conditions. For many views this can -lead to a serious improvement in speed and reduction in bandwidth. - -Other improvements ------------------- - -Finally, a grab-bag of other neat features made their way into this beta -release, including: - - * The :djadmin:`dumpdata` management command now accepts individual - model names as arguments, allowing you to export the data just from - particular models. - - * There's a new :tfilter:`safeseq` template filter which works just like - :tfilter:`safe` for lists, marking each item in the list as safe. - - * :doc:`Cache backends </topics/cache>` now support ``incr()`` and - ``decr()`` commands to increment and decrement the value of a cache key. - On cache backends that support atomic increment/decrement -- most - notably, the memcached backend -- these operations will be atomic, and - quite fast. - - * Django now can :doc:`easily delegate authentication to the Web server - </howto/auth-remote-user>` via a new authentication backend that supports - the standard ``REMOTE_USER`` environment variable used for this purpose. - - * There's a new :func:`django.shortcuts.redirect` function that makes it - easier to issue redirects given an object, a view name, or a URL. - - * The ``postgresql_psycopg2`` backend now supports :ref:`native PostgreSQL - autocommit <postgresql-notes>`. This is an advanced, PostgreSQL-specific - feature, that can make certain read-heavy applications a good deal - faster. - -The Django 1.1 roadmap -====================== - -Before Django 1.1 goes final, at least one other preview/development release -will be made available. The current schedule consists of at least the -following: - -* Week of *April 2, 2009:* Django 1.1 release candidate. At this point all - strings marked for translation must freeze to allow translations to - be submitted in advance of the final release. - -* Week of *April 13, 2009:* Django 1.1 final. - -If deemed necessary, additional beta or release candidate packages will be -issued prior to the final 1.1 release. - -What you can do to help -======================= - -In order to provide a high-quality 1.1 release, we need your help. Although this -beta release is, again, *not* intended for production use, you can help the -Django team by trying out the beta codebase in a safe test environment and -reporting any bugs or issues you encounter. The Django ticket tracker is the -central place to search for open issues: - - * http://code.djangoproject.com/timeline - -Please open new tickets if no existing ticket corresponds to a problem you're -running into. - -Additionally, discussion of Django development, including progress toward the -1.1 release, takes place daily on the django-developers mailing list: - - * http://groups.google.com/group/django-developers - -... and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If you're -interested in helping out with Django's development, feel free to join the -discussions there. - -Django's online documentation also includes pointers on how to contribute to -Django: - - * :doc:`How to contribute to Django </internals/contributing>` - -Contributions on any level -- developing code, writing documentation or simply -triaging tickets and helping to test proposed bugfixes -- are always welcome and -appreciated. - -Development sprints for Django 1.1 will also be taking place at PyCon US 2009, -on the dedicated sprint days (March 30 through April 2), and anyone who wants to -help out is welcome to join in, either in person at PyCon or virtually in the -IRC channel or on the mailing list. diff --git a/parts/django/docs/releases/1.1-rc-1.txt b/parts/django/docs/releases/1.1-rc-1.txt deleted file mode 100644 index f74444f..0000000 --- a/parts/django/docs/releases/1.1-rc-1.txt +++ /dev/null @@ -1,109 +0,0 @@ -============================= -Django 1.1 RC 1 release notes -============================= - - -July 21, 2009 - -Welcome to the first Django 1.1 release candidate! - -This is the third -- and likely last -- in a series of -preview/development releases leading up to the eventual release of -Django 1.1, currently scheduled to take place approximately one week -after this release candidate. This release is targeted primarily at -developers who are interested in trying out new features and testing -the Django codebase to help identify and resolve any critical bugs -prior to the final 1.1 release. - -As such, this release is not yet intended for production use, and any -such use is discouraged. - - -What's new in Django 1.1 RC 1 -============================= - -The Django codebase has -- with one exception -- been in feature -freeze since the first 1.1 beta release, and so this release candidate -contains only one new feature (see below); work leading up to this -release candidate has instead been focused on bugfixing, particularly -on the new features introduced prior to the 1.1 beta. - -For an overview of those features, consult :doc:`the Django 1.1 beta -release notes </releases/1.1-beta-1>`. - - -URL namespaces --------------- - -The 1.1 beta release introduced the ability to use reverse URL -resolution with Django's admin application, which exposed a set of -:ref:`named URLs <naming-url-patterns>`. Unfortunately, achieving -consistent and correct reverse resolution for admin URLs proved -extremely difficult, and so one additional feature was added to Django -to resolve this issue: URL namespaces. - -In short, this feature allows the same group of URLs, from the same -application, to be included in a Django URLConf multiple times, with -varying (and potentially nested) named prefixes which will be used -when performing reverse resolution. For full details, see :ref:`the -documentation on defining URL namespaces -<topics-http-defining-url-namespaces>`. - -Due to the changes needed to support this feature, the URL pattern -names used when reversing admin URLs have changed since the 1.1 beta -release; if you were developing applications which took advantage of -this new feature, you will need to update your code to reflect the new -names (for most purposes, changing ``admin_`` to ``admin:`` in names -to be reversed will suffice). For a full list of URL pattern names -used by the admin and information on how namespaces are applied to -them, consult the documentation on :ref:`reversing admin URLs -<admin-reverse-urls>`. - - -The Django 1.1 roadmap -====================== - -As of this release candidate, Django 1.1 is in both feature freeze and -"string freeze" -- all strings marked for translation in the Django -codebase will retain their current form in the final Django 1.1 -release. Only critical release-blocking bugs will receive attention -between now and the final 1.1 release. - -If no such bugs are discovered, Django 1.1 will be released -approximately one week after this release candidate, on or about July -28, 2009. - - -What you can do to help -======================= - -In order to provide a high-quality 1.1 release, we need your -help. Although this release candidate is, again, *not* intended for -production use, you can help the Django team by trying out this -release candidate in a safe testing environment and reporting any bugs -or issues you encounter. The Django ticket tracker is the central -place to search for open issues: - - * http://code.djangoproject.com/timeline - -Please open a new ticket only if no existing ticket corresponds to a -problem you're running into. - -Additionally, discussion of Django development, including progress -toward the 1.1 release, takes place daily on the django-developers -mailing list: - - * http://groups.google.com/group/django-developers - -... and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If you're -interested in helping out with Django's development, feel free to join the -discussions there. - -Django's online documentation also includes pointers on how to contribute to -Django: - - * :doc:`How to contribute to Django </internals/contributing>` - -Contributions on any level -- developing code, writing documentation or simply -triaging tickets and helping to test proposed bugfixes -- are always welcome and -appreciated. diff --git a/parts/django/docs/releases/1.1.2.txt b/parts/django/docs/releases/1.1.2.txt deleted file mode 100644 index 90a6975..0000000 --- a/parts/django/docs/releases/1.1.2.txt +++ /dev/null @@ -1,56 +0,0 @@ -========================== -Django 1.1.2 release notes -========================== - -Welcome to Django 1.1.2! - -This is the second "bugfix" release in the Django 1.1 series, -improving the stability and performance of the Django 1.1 codebase. - -Django 1.1.2 maintains backwards compatibility with Django -1.1.0, but contain a number of fixes and other -improvements. Django 1.1.2 is a recommended upgrade for any -development or deployment currently using or targeting Django 1.1. - -For full details on the new features, backwards incompatibilities, and -deprecated features in the 1.1 branch, see the :doc:`/releases/1.1`. - -Backwards-incompatible changes in 1.1.2 -======================================= - -Test runner exit status code ----------------------------- - -The exit status code of the test runners (``tests/runtests.py`` and ``python -manage.py test``) no longer represents the number of failed tests, since a -failure of 256 or more tests resulted in a wrong exit status code. The exit -status code for the test runner is now 0 for success (no failing tests) and 1 -for any number of test failures. If needed, the number of test failures can be -found at the end of the test runner's output. - -Cookie encoding ---------------- - -To fix bugs with cookies in Internet Explorer, Safari, and possibly other -browsers, our encoding of cookie values was changed so that the characters -comma and semi-colon are treated as non-safe characters, and are therefore -encoded as ``\054`` and ``\073`` respectively. This could produce backwards -incompatibilities, especially if you are storing comma or semi-colon in -cookies and have javascript code that parses and manipulates cookie values -client-side. - -One new feature -=============== - -Ordinarily, a point release would not include new features, but in the -case of Django 1.1.2, we have made an exception to this rule. Django -1.2 (the next major release of Django) will contain a feature that -will improve protection against Cross-Site Request Forgery (CSRF) -attacks. This feature requires the use of a new :ttag:`csrf_token` -template tag in all forms that Django renders. - -To make it easier to support both 1.1.X and 1.2.X versions of Django with -the same templates, we have decided to introduce the :ttag:`csrf_token` template -tag to the 1.1.X branch. In the 1.1.X branch, :ttag:`csrf_token` does nothing - -it has no effect on templates or form processing. However, it means that the -same template will work with Django 1.2. diff --git a/parts/django/docs/releases/1.1.txt b/parts/django/docs/releases/1.1.txt deleted file mode 100644 index 3ca8344..0000000 --- a/parts/django/docs/releases/1.1.txt +++ /dev/null @@ -1,463 +0,0 @@ -======================== -Django 1.1 release notes -======================== - - -July 29, 2009 - -Welcome to Django 1.1! - -Django 1.1 includes a number of nifty `new features`_, lots of bug -fixes, and an easy upgrade path from Django 1.0. - -.. _new features: `What's new in Django 1.1`_ - -.. _backwards-incompatible-changes-1.1: - -Backwards-incompatible changes in 1.1 -===================================== - -Django has a policy of :doc:`API stability </misc/api-stability>`. This means -that, in general, code you develop against Django 1.0 should continue to work -against 1.1 unchanged. However, we do sometimes make backwards-incompatible -changes if they're necessary to resolve bugs, and there are a handful of such -(minor) changes between Django 1.0 and Django 1.1. - -Before upgrading to Django 1.1 you should double-check that the following -changes don't impact you, and upgrade your code if they do. - -Changes to constraint names ---------------------------- - -Django 1.1 modifies the method used to generate database constraint names so -that names are consistent regardless of machine word size. This change is -backwards incompatible for some users. - -If you are using a 32-bit platform, you're off the hook; you'll observe no -differences as a result of this change. - -However, **users on 64-bit platforms may experience some problems** using the -:djadmin:`reset` management command. Prior to this change, 64-bit platforms -would generate a 64-bit, 16 character digest in the constraint name; for -example:: - - ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_5e8f10c132091d1e FOREIGN KEY ... - -Following this change, all platforms, regardless of word size, will generate a -32-bit, 8 character digest in the constraint name; for example:: - - ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_32091d1e FOREIGN KEY ... - -As a result of this change, you will not be able to use the :djadmin:`reset` -management command on any table made by a 64-bit machine. This is because the -the new generated name will not match the historically generated name; as a -result, the SQL constructed by the reset command will be invalid. - -If you need to reset an application that was created with 64-bit constraints, -you will need to manually drop the old constraint prior to invoking -:djadmin:`reset`. - -Test cases are now run in a transaction ---------------------------------------- - -Django 1.1 runs tests inside a transaction, allowing better test performance -(see `test performance improvements`_ for details). - -This change is slightly backwards incompatible if existing tests need to test -transactional behavior, if they rely on invalid assumptions about the test -environment, or if they require a specific test case ordering. - -For these cases, :class:`~django.test.TransactionTestCase` can be used instead. -This is a just a quick fix to get around test case errors revealed by the new -rollback approach; in the long-term tests should be rewritten to correct the -test case. - -.. _removed-setremoteaddrfromforwardedfor-middleware: - -Removed ``SetRemoteAddrFromForwardedFor`` middleware ----------------------------------------------------- - -For convenience, Django 1.0 included an optional middleware class -- -``django.middleware.http.SetRemoteAddrFromForwardedFor`` -- which updated the -value of ``REMOTE_ADDR`` based on the HTTP ``X-Forwarded-For`` header commonly -set by some proxy configurations. - -It has been demonstrated that this mechanism cannot be made reliable enough for -general-purpose use, and that (despite documentation to the contrary) its -inclusion in Django may lead application developers to assume that the value of -``REMOTE_ADDR`` is "safe" or in some way reliable as a source of authentication. - -While not directly a security issue, we've decided to remove this middleware -with the Django 1.1 release. It has been replaced with a class that does nothing -other than raise a ``DeprecationWarning``. - -If you've been relying on this middleware, the easiest upgrade path is: - - * Examine `the code as it existed before it was removed`__. - - * Verify that it works correctly with your upstream proxy, modifying - it to support your particular proxy (if necessary). - - * Introduce your modified version of ``SetRemoteAddrFromForwardedFor`` as a - piece of middleware in your own project. - -__ http://code.djangoproject.com/browser/django/trunk/django/middleware/http.py?rev=11000#L33 - -Names of uploaded files are available later -------------------------------------------- - -.. currentmodule:: django.db.models - -In Django 1.0, files uploaded and stored in a model's :class:`FileField` were -saved to disk before the model was saved to the database. This meant that the -actual file name assigned to the file was available before saving. For example, -it was available in a model's pre-save signal handler. - -In Django 1.1 the file is saved as part of saving the model in the database, so -the actual file name used on disk cannot be relied on until *after* the model -has been saved. - -Changes to how model formsets are saved ---------------------------------------- - -.. currentmodule:: django.forms.models - -In Django 1.1, :class:`BaseModelFormSet` now calls :meth:`ModelForm.save()`. - -This is backwards-incompatible if you were modifying ``self.initial`` in a model -formset's ``__init__``, or if you relied on the internal ``_total_form_count`` -or ``_initial_form_count`` attributes of BaseFormSet. Those attributes are now -public methods. - -Fixed the ``join`` filter's escaping behavior ---------------------------------------------- - -The :ttag:`join` filter no longer escapes the literal value that is -passed in for the connector. - -This is backwards incompatible for the special situation of the literal string -containing one of the five special HTML characters. Thus, if you were writing -``{{ foo|join:"&" }}``, you now have to write ``{{ foo|join:"&" }}``. - -The previous behavior was a bug and contrary to what was documented -and expected. - -Permanent redirects and the ``redirect_to()`` generic view ----------------------------------------------------------- - -Django 1.1 adds a ``permanent`` argument to the -:func:`django.views.generic.simple.redirect_to()` view. This is technically -backwards-incompatible if you were using the ``redirect_to`` view with a -format-string key called 'permanent', which is highly unlikely. - -.. _deprecated-features-1.1: - -Features deprecated in 1.1 -========================== - -One feature has been marked as deprecated in Django 1.1: - - * You should no longer use ``AdminSite.root()`` to register that admin - views. That is, if your URLconf contains the line:: - - (r'^admin/(.*)', admin.site.root), - - You should change it to read:: - - (r'^admin/', include(admin.site.urls)), - -You should begin to remove use of this feature from your code immediately. - -``AdminSite.root`` will raise a ``PendingDeprecationWarning`` if used in -Django 1.1. This warning is hidden by default. In Django 1.2, this warning will -be upgraded to a ``DeprecationWarning``, which will be displayed loudly. Django -1.3 will remove ``AdminSite.root()`` entirely. - -For more details on our deprecation policies and strategy, see -:doc:`/internals/release-process`. - -What's new in Django 1.1 -======================== - -Quite a bit: since Django 1.0, we've made 1,290 code commits, fixed 1,206 bugs, -and added roughly 10,000 lines of documentation. - -The major new features in Django 1.1 are: - -ORM improvements ----------------- - -.. currentmodule:: django.db.models - -Two major enhancements have been added to Django's object-relational mapper -(ORM): aggregate support, and query expressions. - -Aggregate support -~~~~~~~~~~~~~~~~~ - -It's now possible to run SQL aggregate queries (i.e. ``COUNT()``, ``MAX()``, -``MIN()``, etc.) from within Django's ORM. You can choose to either return the -results of the aggregate directly, or else annotate the objects in a -:class:`QuerySet` with the results of the aggregate query. - -This feature is available as new :meth:`QuerySet.aggregate()`` and -:meth:`QuerySet.annotate()`` methods, and is covered in detail in :doc:`the ORM -aggregation documentation </topics/db/aggregation>`. - -Query expressions -~~~~~~~~~~~~~~~~~ - -Queries can now refer to a another field on the query and can traverse -relationships to refer to fields on related models. This is implemented in the -new :class:`F` object; for full details, including examples, consult the -:ref:`documentation for F expressions <query-expressions>`. - -Model improvements ------------------- - -A number of features have been added to Django's model layer: - -"Unmanaged" models -~~~~~~~~~~~~~~~~~~ - -You can now control whether or not Django manages the life-cycle of the database -tables for a model using the :attr:`~Options.managed` model option. This -defaults to ``True``, meaning that Django will create the appropriate database -tables in :djadmin:`syncdb` and remove them as part of the :djadmin:`reset` -command. That is, Django *manages* the database table's lifecycle. - -If you set this to ``False``, however, no database table creating or deletion -will be automatically performed for this model. This is useful if the model -represents an existing table or a database view that has been created by some -other means. - -For more details, see the documentation for the :attr:`~Options.managed` -option. - -Proxy models -~~~~~~~~~~~~ - -You can now create :ref:`proxy models <proxy-models>`: subclasses of existing -models that only add Python-level (rather than database-level) behavior and -aren't represented by a new table. That is, the new model is a *proxy* for some -underlying model, which stores all the real data. - -All the details can be found in the :ref:`proxy models documentation -<proxy-models>`. This feature is similar on the surface to unmanaged models, -so the documentation has an explanation of :ref:`how proxy models differ from -unmanaged models <proxy-vs-unmanaged-models>`. - -Deferred fields -~~~~~~~~~~~~~~~ - -In some complex situations, your models might contain fields which could -contain a lot of data (for example, large text fields), or require expensive -processing to convert them to Python objects. If you know you don't need those -particular fields, you can now tell Django not to retrieve them from the -database. - -You'll do this with the new queryset methods -:meth:`~django.db.models.QuerySet.defer` and -:meth:`~django.db.models.QuerySet.only`. - -Testing improvements --------------------- - -A few notable improvements have been made to the :doc:`testing framework -</topics/testing>`. - -Test performance improvements -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. currentmodule:: django.test - -Tests written using Django's :doc:`testing framework </topics/testing>` now run -dramatically faster (as much as 10 times faster in many cases). - -This was accomplished through the introduction of transaction-based tests: when -using :class:`django.test.TestCase`, your tests will now be run in a transaction -which is rolled back when finished, instead of by flushing and re-populating the -database. This results in an immense speedup for most types of unit tests. See -the documentation for :class:`TestCase` and :class:`TransactionTestCase` for a -full description, and some important notes on database support. - -Test client improvements ------------------------- - -.. currentmodule:: django.test.client - -A couple of small -- but highly useful -- improvements have been made to the -test client: - - * The test :class:`Client` now can automatically follow redirects with the - ``follow`` argument to :meth:`Client.get` and :meth:`Client.post`. This - makes testing views that issue redirects simpler. - - * It's now easier to get at the template context in the response returned - the test client: you'll simply access the context as - ``request.context[key]``. The old way, which treats ``request.context`` as - a list of contexts, one for each rendered template in the inheritance - chain, is still available if you need it. - -New admin features ------------------- - -Django 1.1 adds a couple of nifty new features to Django's admin interface: - -Editable fields on the change list -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can now make fields editable on the admin list views via the new -:ref:`list_editable <admin-list-editable>` admin option. These fields will show -up as form widgets on the list pages, and can be edited and saved in bulk. - -Admin "actions" -~~~~~~~~~~~~~~~ - -You can now define :doc:`admin actions </ref/contrib/admin/actions>` that can -perform some action to a group of models in bulk. Users will be able to select -objects on the change list page and then apply these bulk actions to all -selected objects. - -Django ships with one pre-defined admin action to delete a group of objects in -one fell swoop. - -Conditional view processing ---------------------------- - -Django now has much better support for :doc:`conditional view processing -</topics/conditional-view-processing>` using the standard ``ETag`` and -``Last-Modified`` HTTP headers. This means you can now easily short-circuit -view processing by testing less-expensive conditions. For many views this can -lead to a serious improvement in speed and reduction in bandwidth. - -URL namespaces --------------- - -Django 1.1 improves :ref:`named URL patterns <naming-url-patterns>` with the -introduction of URL "namespaces." - -In short, this feature allows the same group of URLs, from the same application, -to be included in a Django URLConf multiple times, with varying (and potentially -nested) named prefixes which will be used when performing reverse resolution. In -other words, reusable applications like Django's admin interface may be -registered multiple times without URL conflicts. - -For full details, see :ref:`the documentation on defining URL namespaces -<topics-http-defining-url-namespaces>`. - -GeoDjango ---------- - -In Django 1.1, GeoDjango_ (i.e. ``django.contrib.gis``) has several new -features: - - * Support for SpatiaLite_ -- a spatial database for SQLite -- as a spatial - backend. - - * Geographic aggregates (``Collect``, ``Extent``, ``MakeLine``, ``Union``) - and ``F`` expressions. - - * New ``GeoQuerySet`` methods: ``collect``, ``geojson``, and - ``snap_to_grid``. - - * A new list interface methods for ``GEOSGeometry`` objects. - -For more details, see the `GeoDjango documentation`_. - -.. _geodjango: http://geodjango.org/ -.. _spatialite: http://www.gaia-gis.it/spatialite/ -.. _geodjango documentation: http://geodjango.org/docs/ - -Other improvements ------------------- - -Other new features and changes introduced since Django 1.0 include: - -* The :doc:`CSRF protection middleware </ref/contrib/csrf>` has been split into - two classes -- ``CsrfViewMiddleware`` checks incoming requests, and - ``CsrfResponseMiddleware`` processes outgoing responses. The combined - ``CsrfMiddleware`` class (which does both) remains for - backwards-compatibility, but using the split classes is now recommended in - order to allow fine-grained control of when and where the CSRF processing - takes place. - -* :func:`~django.core.urlresolvers.reverse` and code which uses it (e.g., the - ``{% url %}`` template tag) now works with URLs in Django's administrative - site, provided that the admin URLs are set up via ``include(admin.site.urls)`` - (sending admin requests to the ``admin.site.root`` view still works, but URLs - in the admin will not be "reversible" when configured this way). - -* The ``include()`` function in Django URLconf modules can now accept sequences - of URL patterns (generated by ``patterns()``) in addition to module names. - -* Instances of Django forms (see :doc:`the forms overview </topics/forms/index>`) - now have two additional methods, ``hidden_fields()`` and ``visible_fields()``, - which return the list of hidden -- i.e., ``<input type="hidden">`` -- and - visible fields on the form, respectively. - -* The ``redirect_to`` generic view (see :doc:`the generic views documentation - </ref/generic-views>`) now accepts an additional keyword argument - ``permanent``. If ``permanent`` is ``True``, the view will emit an HTTP - permanent redirect (status code 301). If ``False``, the view will emit an HTTP - temporary redirect (status code 302). - -* A new database lookup type -- ``week_day`` -- has been added for ``DateField`` - and ``DateTimeField``. This type of lookup accepts a number between 1 (Sunday) - and 7 (Saturday), and returns objects where the field value matches that day - of the week. See :ref:`the full list of lookup types <field-lookups>` for - details. - -* The ``{% for %}`` tag in Django's template language now accepts an optional - ``{% empty %}`` clause, to be displayed when ``{% for %}`` is asked to loop - over an empty sequence. See :doc:`the list of built-in template tags - </ref/templates/builtins>` for examples of this. - -* The :djadmin:`dumpdata` management command now accepts individual - model names as arguments, allowing you to export the data just from - particular models. - -* There's a new :tfilter:`safeseq` template filter which works just like - :tfilter:`safe` for lists, marking each item in the list as safe. - -* :doc:`Cache backends </topics/cache>` now support ``incr()`` and - ``decr()`` commands to increment and decrement the value of a cache key. - On cache backends that support atomic increment/decrement -- most - notably, the memcached backend -- these operations will be atomic, and - quite fast. - -* Django now can :doc:`easily delegate authentication to the Web server - </howto/auth-remote-user>` via a new authentication backend that supports - the standard ``REMOTE_USER`` environment variable used for this purpose. - -* There's a new :func:`django.shortcuts.redirect` function that makes it - easier to issue redirects given an object, a view name, or a URL. - -* The ``postgresql_psycopg2`` backend now supports :ref:`native PostgreSQL - autocommit <postgresql-notes>`. This is an advanced, PostgreSQL-specific - feature, that can make certain read-heavy applications a good deal - faster. - -What's next? -============ - -We'll take a short break, and then work on Django 1.2 will begin -- no rest for -the weary! If you'd like to help, discussion of Django development, including -progress toward the 1.2 release, takes place daily on the django-developers -mailing list: - - * http://groups.google.com/group/django-developers - -... and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. Feel free to -join the discussions! - -Django's online documentation also includes pointers on how to contribute to -Django: - - * :doc:`How to contribute to Django </internals/contributing>` - -Contributions on any level -- developing code, writing documentation or simply -triaging tickets and helping to test proposed bugfixes -- are always welcome and -appreciated. - -And that's the way it is. diff --git a/parts/django/docs/releases/1.2-alpha-1.txt b/parts/django/docs/releases/1.2-alpha-1.txt deleted file mode 100644 index 4144a9a..0000000 --- a/parts/django/docs/releases/1.2-alpha-1.txt +++ /dev/null @@ -1,578 +0,0 @@ -================================ -Django 1.2 alpha 1 release notes -================================ - -January 5, 2010 - -Welcome to Django 1.2 alpha 1! - -This is the first in a series of preview/development releases leading up to the -eventual release of Django 1.2, currently scheduled to take place in March 2010. -This release is primarily targeted at developers who are interested in trying -out new features and testing the Django codebase to help identify and resolve -bugs prior to the final 1.2 release. - -As such, this release is *not* intended for production use, and any such use is -discouraged. - - -Backwards-incompatible changes in 1.2 -===================================== - -CSRF Protection ---------------- - -There have been large changes to the way that CSRF protection works, detailed in -:doc:`the CSRF documentaton </ref/contrib/csrf>`. The following are the major -changes that developers must be aware of: - - * ``CsrfResponseMiddleware`` and ``CsrfMiddleware`` have been deprecated, and - **will be removed completely in Django 1.4**, in favor of a template tag that - should be inserted into forms. - - * All contrib apps use a ``csrf_protect`` decorator to protect the view. This - requires the use of the ``csrf_token`` template tag in the template, so if you - have used custom templates for contrib views, you MUST READ THE :ref:`UPGRADE - INSTRUCTIONS <ref-csrf-upgrading-notes>` to fix those templates. - - * ``CsrfViewMiddleware`` is included in :setting:`MIDDLEWARE_CLASSES` by - default. This turns on CSRF protection by default, so that views that accept - POST requests need to be written to work with the middleware. Instructions - on how to do this are found in the CSRF docs. - - * CSRF-related code has moved from ``contrib`` to ``core`` (with - backwards compatible imports in the old locations, which are - deprecated). - -:ttag:`if` tag changes ----------------------- - -Due to new features in the :ttag:`if` template tag, it no longer accepts 'and', -'or' and 'not' as valid **variable** names. Previously that worked in some -cases even though these strings were normally treated as keywords. Now, the -keyword status is always enforced, and template code like ``{% if not %}`` or -``{% if and %}`` will throw a TemplateSyntaxError. - -``LazyObject`` --------------- - -``LazyObject`` is an undocumented utility class used for lazily wrapping other -objects of unknown type. In Django 1.1 and earlier, it handled introspection in -a non-standard way, depending on wrapped objects implementing a public method -``get_all_members()``. Since this could easily lead to name clashes, it has been -changed to use the standard method, involving ``__members__`` and ``__dir__()``. -If you used ``LazyObject`` in your own code, and implemented the -``get_all_members()`` method for wrapped objects, you need to make the following -changes: - - * If your class does not have special requirements for introspection (i.e. you - have not implemented ``__getattr__()`` or other methods that allow for - attributes not discoverable by normal mechanisms), you can simply remove the - ``get_all_members()`` method. The default implementation on ``LazyObject`` - will do the right thing. - - * If you have more complex requirements for introspection, first rename the - ``get_all_members()`` method to ``__dir__()``. This is the standard method, - from Python 2.6 onwards, for supporting introspection. If you are require - support for Python < 2.6, add the following code to the class:: - - __members__ = property(lambda self: self.__dir__()) - -``__dict__`` on Model instances -------------------------------- - -Historically, the ``__dict__`` attribute of a model instance has only contained -attributes corresponding to the fields on a model. - -In order to support multiple database configurations, Django 1.2 has -added a ``_state`` attribute to object instances. This attribute will -appear in ``__dict__`` for a model instance. If your code relies on -iterating over __dict__ to obtain a list of fields, you must now -filter the ``_state`` attribute of out ``__dict__``. - -``get_db_prep_*()`` methods on Field ------------------------------------- - -Prior to v1.2, a custom field had the option of defining several -functions to support conversion of Python values into -database-compatible values. A custom field might look something like:: - - class CustomModelField(models.Field): - # ... - - def get_db_prep_save(self, value): - # ... - - def get_db_prep_value(self, value): - # ... - - def get_db_prep_lookup(self, lookup_type, value): - # ... - -In 1.2, these three methods have undergone a change in prototype, and -two extra methods have been introduced:: - - class CustomModelField(models.Field): - # ... - - def get_prep_value(self, value): - # ... - - def get_prep_lookup(self, lookup_type, value): - # ... - - def get_db_prep_save(self, value, connection): - # ... - - def get_db_prep_value(self, value, connection, prepared=False): - # ... - - def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False): - # ... - -These changes are required to support multiple databases: -``get_db_prep_*`` can no longer make any assumptions regarding the -database for which it is preparing. The ``connection`` argument now -provides the preparation methods with the specific connection for -which the value is being prepared. - -The two new methods exist to differentiate general data preparation -requirements, and requirements that are database-specific. The -``prepared`` argument is used to indicate to the database preparation -methods whether generic value preparation has been performed. If -an unprepared (i.e., ``prepared=False``) value is provided to the -``get_db_prep_*()`` calls, they should invoke the corresponding -``get_prep_*()`` calls to perform generic data preparation. - -Conversion functions has been provided which will transparently -convert functions adhering to the old prototype into functions -compatible with the new prototype. However, this conversion function -will be removed in Django 1.4, so you should upgrade your Field -definitions to use the new prototype. - -If your ``get_db_prep_*()`` methods made no use of the database -connection, you should be able to upgrade by renaming -``get_db_prep_value()`` to ``get_prep_value()`` and -``get_db_prep_lookup()`` to ``get_prep_lookup()`. If you require -database specific conversions, then you will need to provide an -implementation ``get_db_prep_*`` that uses the ``connection`` -argument to resolve database-specific values. - -Stateful template tags ----------------------- - -Template tags that store rendering state on the node itself may experience -problems if they are used with the new :ref:`cached -template loader<template-loaders>`. - -All of the built-in Django template tags are safe to use with the cached -loader, but if you're using custom template tags that come from third -party packages, or that you wrote yourself, you should ensure that the -``Node`` implementation for each tag is thread-safe. For more -information, see -:ref:`template tag thread safety considerations<template_tag_thread_safety>`. - -Test runner exit status code ----------------------------- - -The exit status code of the test runners (``tests/runtests.py`` and ``python -manage.py test``) no longer represents the number of failed tests, since a -failure of 256 or more tests resulted in a wrong exit status code. The exit -status code for the test runner is now 0 for success (no failing tests) and 1 -for any number of test failures. If needed, the number of test failures can be -found at the end of the test runner's output. - -Features deprecated in 1.2 -========================== - -CSRF response rewriting middleware ----------------------------------- - -``CsrfResponseMiddleware``, the middleware that automatically inserted CSRF -tokens into POST forms in outgoing pages, has been deprecated in favor of a -template tag method (see above), and will be removed completely in Django -1.4. ``CsrfMiddleware``, which includes the functionality of -``CsrfResponseMiddleware`` and ``CsrfViewMiddleware`` has likewise been -deprecated. - -Also, the CSRF module has moved from contrib to core, and the old imports are -deprecated, as described in the :ref:`upgrading notes <ref-csrf-upgrading-notes>`. - -``SMTPConnection`` ------------------- - -The ``SMTPConnection`` class has been deprecated in favor of a generic -E-mail backend API. Old code that explicitly instantiated an instance -of an SMTPConnection:: - - from django.core.mail import SMTPConnection - connection = SMTPConnection() - messages = get_notification_email() - connection.send_messages(messages) - -should now call :meth:`~django.core.mail.get_connection()` to -instantiate a generic e-mail connection:: - - from django.core.mail import get_connection - connection = get_connection() - messages = get_notification_email() - connection.send_messages(messages) - -Depending on the value of the :setting:`EMAIL_BACKEND` setting, this -may not return an SMTP connection. If you explicitly require an SMTP -connection with which to send e-mail, you can explicitly request an -SMTP connection:: - - from django.core.mail import get_connection - connection = get_connection('django.core.mail.backends.smtp.EmailBackend') - messages = get_notification_email() - connection.send_messages(messages) - -If your call to construct an instance of ``SMTPConnection`` required -additional arguments, those arguments can be passed to the -:meth:`~django.core.mail.get_connection()` call:: - - connection = get_connection('django.core.mail.backends.smtp.EmailBackend', hostname='localhost', port=1234) - -Specifying databases --------------------- - -Prior to Django 1.1, Django used a number of settings to control access to a -single database. Django 1.2 introduces support for multiple databases, and as -a result, the way you define database settings has changed. - -**Any existing Django settings file will continue to work as expected -until Django 1.4.** Old-style database settings will be automatically -translated to the new-style format. - -In the old-style (pre 1.2) format, there were a number of -``DATABASE_`` settings at the top level of your settings file. For -example:: - - DATABASE_NAME = 'test_db' - DATABASE_ENGINE = 'postgresql_psycopg2' - DATABASE_USER = 'myusername' - DATABASE_PASSWORD = 's3krit' - -These settings are now contained inside a dictionary named -:setting:`DATABASES`. Each item in the dictionary corresponds to a -single database connection, with the name ``'default'`` describing the -default database connection. The setting names have also been -shortened to reflect the fact that they are stored in a dictionary. -The sample settings given previously would now be stored using:: - - DATABASES = { - 'default': { - 'NAME': 'test_db', - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'USER': 'myusername', - 'PASSWORD': 's3krit', - } - } - -This affects the following settings: - - ========================================= ========================== - Old setting New Setting - ========================================= ========================== - :setting:`DATABASE_ENGINE` :setting:`ENGINE` - :setting:`DATABASE_HOST` :setting:`HOST` - :setting:`DATABASE_NAME` :setting:`NAME` - :setting:`DATABASE_OPTIONS` :setting:`OPTIONS` - :setting:`DATABASE_PASSWORD` :setting:`PASSWORD` - :setting:`DATABASE_PORT` :setting:`PORT` - :setting:`DATABASE_USER` :setting:`USER` - :setting:`TEST_DATABASE_CHARSET` :setting:`TEST_CHARSET` - :setting:`TEST_DATABASE_COLLATION` :setting:`TEST_COLLATION` - :setting:`TEST_DATABASE_NAME` :setting:`TEST_NAME` - ========================================= ========================== - -These changes are also required if you have manually created a database -connection using ``DatabaseWrapper()`` from your database backend of choice. - -In addition to the change in structure, Django 1.2 removes the special -handling for the built-in database backends. All database backends -must now be specified by a fully qualified module name (i.e., -``django.db.backends.postgresql_psycopg2``, rather than just -``postgresql_psycopg2``). - -User Messages API ------------------ - -The API for storing messages in the user ``Message`` model (via -``user.message_set.create``) is now deprecated and will be removed in Django -1.4 according to the standard :doc:`release process </internals/release-process>`. - -To upgrade your code, you need to replace any instances of:: - - user.message_set.create('a message') - -with the following:: - - from django.contrib import messages - messages.add_message(request, messages.INFO, 'a message') - -Additionally, if you make use of the method, you need to replace the -following:: - - for message in user.get_and_delete_messages(): - ... - -with:: - - from django.contrib import messages - for message in messages.get_messages(request): - ... - -For more information, see the full -:doc:`messages documentation </ref/contrib/messages>`. You should begin to -update your code to use the new API immediately. - -Date format helper functions ----------------------------- - -``django.utils.translation.get_date_formats()`` and -``django.utils.translation.get_partial_date_formats()`` have been deprecated -in favor of the appropriate calls to ``django.utils.formats.get_format()`` -which is locale aware when :setting:`USE_L10N` is set to ``True``, and falls -back to default settings if set to ``False``. - -To get the different date formats, instead of writing:: - - from django.utils.translation import get_date_formats - date_format, datetime_format, time_format = get_date_formats() - -use:: - - from django.utils import formats - - date_format = formats.get_format('DATE_FORMAT') - datetime_format = formats.get_format('DATETIME_FORMAT') - time_format = formats.get_format('TIME_FORMAT') - -or, when directly formatting a date value:: - - from django.utils import formats - value_formatted = formats.date_format(value, 'DATETIME_FORMAT') - -The same applies to the globals found in ``django.forms.fields``: - - * ``DEFAULT_DATE_INPUT_FORMATS`` - * ``DEFAULT_TIME_INPUT_FORMATS`` - * ``DEFAULT_DATETIME_INPUT_FORMATS`` - -Use ``django.utils.formats.get_format()`` to get the appropriate formats. - - -What's new in Django 1.2 alpha 1 -================================ - -The following new features are present as of this alpha release; this -release also marks the end of major feature development for the 1.2 -release cycle. Some minor features will continue development until the -1.2 beta release, however. - - -CSRF support ------------- - -Django now has much improved protection against :doc:`Cross-Site -Request Forgery (CSRF) attacks</ref/contrib/csrf>`. This type of attack -occurs when a malicious Web site contains a link, a form button or -some javascript that is intended to perform some action on your Web -site, using the credentials of a logged-in user who visits the -malicious site in their browser. A related type of attack, 'login -CSRF', where an attacking site tricks a user's browser into logging -into a site with someone else's credentials, is also covered. - -E-mail Backends ---------------- - -You can now :ref:`configure the way that Django sends e-mail -<topic-email-backends>`. Instead of using SMTP to send all e-mail, you -can now choose a configurable e-mail backend to send messages. If your -hosting provider uses a sandbox or some other non-SMTP technique for -sending mail, you can now construct an e-mail backend that will allow -Django's standard :doc:`mail sending methods</topics/email>` to use -those facilities. - -This also makes it easier to debug mail sending - Django ships with -backend implementations that allow you to send e-mail to a -:ref:`file<topic-email-file-backend>`, to the -:ref:`console<topic-email-console-backend>`, or to -:ref:`memory<topic-email-memory-backend>` - you can even configure all -e-mail to be :ref:`thrown away<topic-email-dummy-backend>`. - -Messages Framework ------------------- - -Django now includes a robust and configurable :doc:`messages framework -</ref/contrib/messages>` with built-in support for cookie- and session-based -messaging, for both anonymous and authenticated clients. The messages framework -replaces the deprecated user message API and allows you to temporarily store -messages in one request and retrieve them for display in a subsequent request -(usually the next one). - -Support for multiple databases ------------------------------- - -Django 1.2 adds the ability to use :doc:`more than one database -</topics/db/multi-db>` in your Django project. Queries can be -issued at a specific database with the `using()` method on -querysets; individual objects can be saved to a specific database -by providing a ``using`` argument when you save the instance. - -'Smart' if tag --------------- - -The :ttag:`if` tag has been upgraded to be much more powerful. First, support -for comparison operators has been added. No longer will you have to type: - -.. code-block:: html+django - - {% ifnotequal a b %} - ... - {% endifnotequal %} - -...as you can now do: - -.. code-block:: html+django - - {% if a != b %} - ... - {% endif %} - -The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=`` and -``in``, all of which work like the Python operators, in addition to ``and``, -``or`` and ``not`` which were already supported. - -Also, filters may now be used in the ``if`` expression. For example: - -.. code-block:: html+django - - <div - {% if user.email|lower == message.recipient|lower %} - class="highlight" - {% endif %} - >{{ message }}</div> - -Template caching ----------------- - -In previous versions of Django, every time you rendered a template it -would be reloaded from disk. In Django 1.2, you can use a :ref:`cached -template loader <template-loaders>` to load templates once, then use -the cached result for every subsequent render. This can lead to a -significant performance improvement if your templates are broken into -lots of smaller subtemplates (using the ``{% extends %}`` or ``{% -include %}`` tags). - -As a side effect, it is now much easier to support non-Django template -languages. For more details, see the :ref:`notes on supporting -non-Django template languages<topic-template-alternate-language>`. - -Natural keys in fixtures ------------------------- - -Fixtures can refer to remote objects using -:ref:`topics-serialization-natural-keys`. This lookup scheme is an -alternative to the normal primary-key based object references in a -fixture, improving readability, and resolving problems referring to -objects whose primary key value may not be predictable or known. - -``BigIntegerField`` -------------------- - -Models can now use a 64 bit :class:`~django.db.models.BigIntegerField` type. - -Fast Failure for Tests ----------------------- - -The :djadmin:`test` subcommand of ``django-admin.py``, and the ``runtests.py`` -script used to run Django's own test suite, support a new ``--failfast`` option. -When specified, this option causes the test runner to exit after encountering -a failure instead of continuing with the test run. In addition, the handling -of ``Ctrl-C`` during a test run has been improved to trigger a graceful exit -from the test run that reports details of the tests run before the interruption. - -Improved localization ---------------------- - -Django's :doc:`internationalization framework </topics/i18n/index>` has been -expanded by locale aware formatting and form processing. That means, if -enabled, dates and numbers on templates will be displayed using the format -specified for the current locale. Django will also use localized formats -when parsing data in forms. -See :ref:`Format localization <format-localization>` for more details. - -Added ``readonly_fields`` to ``ModelAdmin`` -------------------------------------------- - -:attr:`django.contrib.admin.ModelAdmin.readonly_fields` has been added to -enable non-editable fields in add/change pages for models and inlines. Field -and calculated values can be displayed along side editable fields. - -Customizable syntax highlighting --------------------------------- - -You can now use the ``DJANGO_COLORS`` environment variable to modify -or disable the colors used by ``django-admin.py`` to provide -:ref:`syntax highlighting <syntax-coloring>`. - - -The Django 1.2 roadmap -====================== - -Before the final Django 1.2 release, several other preview/development -releases will be made available. The current schedule consists of at -least the following: - -* Week of **January 26, 2010**: First Django 1.2 beta release. Final - feature freeze for Django 1.2. - -* Week of **March 2, 2010**: First Django 1.2 release - candidate. String freeze for translations. - -* Week of **March 9, 2010**: Django 1.2 final release. - -If necessary, additional alpha, beta or release-candidate packages -will be issued prior to the final 1.2 release. Django 1.2 will be -released approximately one week after the final release candidate. - - -What you can do to help -======================= - -In order to provide a high-quality 1.2 release, we need your help. Although this -alpha release is, again, *not* intended for production use, you can help the -Django team by trying out the alpha codebase in a safe test environment and -reporting any bugs or issues you encounter. The Django ticket tracker is the -central place to search for open issues: - - * http://code.djangoproject.com/timeline - -Please open new tickets if no existing ticket corresponds to a problem you're -running into. - -Additionally, discussion of Django development, including progress toward the -1.2 release, takes place daily on the django-developers mailing list: - - * http://groups.google.com/group/django-developers - -... and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If you're -interested in helping out with Django's development, feel free to join the -discussions there. - -Django's online documentation also includes pointers on how to contribute to -Django: - - * :doc:`How to contribute to Django </internals/contributing>` - -Contributions on any level -- developing code, writing documentation or simply -triaging tickets and helping to test proposed bugfixes -- are always welcome and -appreciated. - -Development sprints for Django 1.2 will also be taking place at PyCon -US 2010, on the dedicated sprint days (February 22 through 25), and -anyone who wants to help out is welcome to join in, either in person -at PyCon or virtually in the IRC channel or on the mailing list. diff --git a/parts/django/docs/releases/1.2-beta-1.txt b/parts/django/docs/releases/1.2-beta-1.txt deleted file mode 100644 index 2a12ef3..0000000 --- a/parts/django/docs/releases/1.2-beta-1.txt +++ /dev/null @@ -1,173 +0,0 @@ -=============================== -Django 1.2 beta 1 release notes -=============================== - -February 5, 2010 - -Welcome to Django 1.2 beta 1! - -This is the second in a series of preview/development releases leading -up to the eventual release of Django 1.2, currently scheduled to take -place in March 2010. This release is primarily targeted at developers -who are interested in trying out new features and testing the Django -codebase to help identify and resolve bugs prior to the final 1.2 -release. - -As such, this release is *not* intended for production use, and any -such use is discouraged. - -This document covers changes since the Django 1.2 alpha release; the -:doc:`1.2 alpha release notes </releases/1.2-alpha-1>` cover new and -updated features in Django between 1.1 and 1.2 alpha. - - -Deprecations and other changes in 1.2 beta -========================================== - -This beta release deprecates two portions of public API, and -introduces a potentially backwards-incompatible change to -another. Under :doc:`our API stability policy </misc/api-stability>`, -deprecation proceeds over multiple release cycles: initially, the -deprecated API will raise ``PendingDeprecationWarning``, followed by -raising ``DeprecationWarning`` in the next release, and finally -removal of the deprecated API in the release after that. APIs -beginning the deprecation process in Django 1.2 will be removed in the -Django 1.4 release. - - -Unit test runners ------------------ - -Django 1.2 changes the test runner tools to use a class-based -approach. Old style function-based test runners will still work, but -should be updated to use the new :ref:`class-based runners -<topics-testing-test_runner>`. - - -Syndication feeds ------------------ - -The :class:`django.contrib.syndication.feeds.Feed` class is being -replaced by the :class:`django.contrib.syndication.views.Feed` class. -The old ``feeds.Feed`` class is deprecated. The new class has an -almost identical API, but allows instances to be used as views. - -Also, in accordance with `RSS best practices`_, RSS feeds will now -include an ``atom:link`` element. You may need to update your tests to -take this into account. - -For more information, see the full :doc:`syndication framework -documentation </ref/contrib/syndication>`. - -.. _RSS best practices: http://www.rssboard.org/rss-profile - - -Cookie encoding ---------------- - -Due to cookie-handling bugs in Internet Explorer, Safari, and possibly -other browsers, Django's encoding of cookie values was changed so that -the characters comma (',') and semi-colon (';') are treated as -non-safe characters, and are therefore encoded as ``\054`` and -``\073`` respectively. This could produce backwards incompatibilities -if you are relying on the ability to set these characters directly in -cookie values. - - -What's new in 1.2 beta -====================== - -This 1.2 beta release marks the final feature freeze for Django 1.2; -while most feature development was completed for 1.2 alpha (which -constituted a freeze on major features), a few other new features were -added afterward and so are new as of 1.2 beta. - - -Object-level permissions ------------------------- - -A foundation for specifying permissions at the per-object level was -added in Django 1.2 alpha but not documented with the alpha release. - -The default authentication backends shipped with Django do not -currently make use of this, but third-party authentication backends -are free to do so. See the :doc:`authentication docs </topics/auth>` -for more information. - - -Permissions for anonymous users -------------------------------- - -If you provide a custom authentication backend with the attribute -``supports_anonymous_user`` set to ``True``, the ``AnonymousUser`` -class will check the backend for permissions, just as the normal -``User`` does. This is intended to help centralize permission -handling; apps can always delegate the question of whether something -is allowed or not to the authorization/authentication system. See the -:doc:`authentication docs </topics/auth>` for more details. - - -``select_related()`` improvements ---------------------------------- - -The ``select_related()`` method of ``QuerySet`` now accepts the -``related_name`` of a reverse one-to-one relation in the list of -fields to select. One-to-one relations will not, however, be traversed -by a depth-based ``select_related()`` call. - - -The Django 1.2 roadmap -====================== - -Before the final Django 1.2 release, at least one additional -preview/development releases will be made available. The current -schedule consists of at least the following: - -* Week of **March 2, 2010**: First Django 1.2 release - candidate. String freeze for translations. - -* Week of **March 9, 2010**: Django 1.2 final release. - -If necessary, additional beta or release-candidate packages will be -issued prior to the final 1.2 release. Django 1.2 will be released -approximately one week after the final release candidate. - - -What you can do to help -======================= - -In order to provide a high-quality 1.2 release, we need your -help. Although this beta release is, again, *not* intended for -production use, you can help the Django team by trying out the beta -codebase in a safe test environment and reporting any bugs or issues -you encounter. The Django ticket tracker is the central place to -search for open issues: - - * http://code.djangoproject.com/timeline - -Please open new tickets if no existing ticket corresponds to a problem -you're running into. - -Additionally, discussion of Django development, including progress -toward the 1.2 release, takes place daily on the django-developers -mailing list: - - * http://groups.google.com/group/django-developers - -... and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If you're -interested in helping out with Django's development, feel free to join the -discussions there. - -Django's online documentation also includes pointers on how to -contribute to Django: - - * :doc:`How to contribute to Django </internals/contributing>` - -Contributions on any level -- developing code, writing documentation -or simply triaging tickets and helping to test proposed bugfixes -- -are always welcome and appreciated. - -Development sprints for Django 1.2 will also be taking place at PyCon -US 2010, on the dedicated sprint days (February 22 through 25), and -anyone who wants to help out is welcome to join in, either in person -at PyCon or virtually in the IRC channel or on the mailing list. diff --git a/parts/django/docs/releases/1.2-rc-1.txt b/parts/django/docs/releases/1.2-rc-1.txt deleted file mode 100644 index b599dcc..0000000 --- a/parts/django/docs/releases/1.2-rc-1.txt +++ /dev/null @@ -1,101 +0,0 @@ -============================= -Django 1.2 RC 1 release notes -============================= - - -May 5, 2010 - -Welcome to the first Django 1.2 release candidate! - -This is the third -- and likely last -- in a series of -preview/development releases leading up to the eventual release of -Django 1.2. This release is targeted primarily at developers who are -interested in trying out new features and testing the Django codebase -to help identify and resolve any critical bugs prior to the final 1.2 -release. - -As such, this release is not yet intended for production use, and any -such use is discouraged. - -Django has been feature frozen since the 1.2 beta release, so this -release candidate contains no new features, only bugfixes; for a -summary of features new to Django 1.2, consult the :doc:`1.2 alpha -</releases/1.2-alpha-1>` and :doc:`1.2 beta </releases/1.2-beta-1>` -release notes. - - -Python compatibility -==================== - -While not a new feature, it's important to note that Django 1.2 -introduces the first shift in our Python compatibility policy since -Django's initial public debut. Previous Django releases were tested -and supported on 2.x Python versions from 2.3 up; Django 1.2, however, -drops official support for Python 2.3. As such, the minimum Python -version required for Django is now 2.4, and Django is tested and -supported on Python 2.4, 2.5 and 2.6, and will be supported on the -as-yet-unreleased Python 2.7. - -This change should affect only a small number of Django users, as most -operating-system vendors today are shipping Python 2.4 or newer as -their default version. If you're still using Python 2.3, however, -you'll need to stick to Django 1.1 until you can upgrade; per -:doc:`our support policy </internals/release-process>`, Django 1.1 will -continue to receive security support until the release of Django 1.3. - -A roadmap for Django's overall 2.x Python support, and eventual -transition to Python 3.x, is currently being developed, and will be -announced prior to the release of Django 1.3. - - -The Django 1.2 roadmap -====================== - -As of this release candidate, Django 1.2 is in both feature freeze and -"string freeze" -- all strings marked for translation in the Django -codebase will retain their current form in the final Django 1.2 -release. Only critical release-blocking bugs, documentation and -updated translation files will receive attention between now and the -final 1.2 release. Note that Django's localization infrastructure has -been expanded for 1.2, and translation packages should now include a -``formats.py`` file containing data for localized formatting of -numbers and dates. - -If no critical bugs are discovered, Django 1.2 will be released -approximately one week after this release candidate, on or about May -12, 2010. - - -What you can do to help -======================= - -In order to provide a high-quality 1.2 release, we need your -help. Although this release candidate is, again, *not* intended for -production use, you can help the Django team by trying out this -release candidate in a safe testing environment and reporting any bugs -or issues you encounter. The Django ticket tracker is the central -place to search for open issues: - - * http://code.djangoproject.com/timeline - -Please open a new ticket only if no existing ticket corresponds to a -problem you're running into. - -Additionally, discussion of Django development, including progress -toward the 1.2 release, takes place daily on the django-developers -mailing list: - - * http://groups.google.com/group/django-developers - -... and in the ``#django-dev`` IRC channel on ``irc.freenode.net``. If you're -interested in helping out with Django's development, feel free to join the -discussions there. - -Django's online documentation also includes pointers on how to contribute to -Django: - - * :doc:`How to contribute to Django </internals/contributing>` - -Contributions on any level -- developing code, writing documentation or simply -triaging tickets and helping to test proposed bugfixes -- are always welcome and -appreciated. diff --git a/parts/django/docs/releases/1.2.2.txt b/parts/django/docs/releases/1.2.2.txt deleted file mode 100644 index 4ae74ab..0000000 --- a/parts/django/docs/releases/1.2.2.txt +++ /dev/null @@ -1,29 +0,0 @@ -========================== -Django 1.2.2 release notes -========================== - -Welcome to Django 1.2.2! - -This is the second "bugfix" release in the Django 1.2 series, -improving the stability and performance of the Django 1.2 codebase. - -Django 1.2.2 maintains backwards compatibility with Django -1.2.1, but contain a number of fixes and other -improvements. Django 1.2.2 is a recommended upgrade for any -development or deployment currently using or targeting Django 1.2. - -For full details on the new features, backwards incompatibilities, and -deprecated features in the 1.2 branch, see the :doc:`/releases/1.2`. - -One new feature -=============== - -Ordinarily, a point release would not include new features, but in the -case of Django 1.2.2, we have made an exception to this rule. - -In order to test a bug fix that forms part of the 1.2.2 release, it -was necessary to add a feature -- the ``enforce_csrf_checks`` flag -- -to the :mod:`test client <django.test.client>`. This flag forces -the test client to perform full CSRF checks on forms. The default -behavior of the test client hasn't changed, but if you want to do -CSRF checks with the test client, it is now possible to do so. diff --git a/parts/django/docs/releases/1.2.4.txt b/parts/django/docs/releases/1.2.4.txt deleted file mode 100644 index 5472a28..0000000 --- a/parts/django/docs/releases/1.2.4.txt +++ /dev/null @@ -1,52 +0,0 @@ -========================== -Django 1.2.4 release notes -========================== - -Welcome to Django 1.2.4! - -This is the fourth "bugfix" release in the Django 1.2 series, -improving the stability and performance of the Django 1.2 codebase. - -Django 1.2.4 maintains backwards compatibility with Django -1.2.3, but contain a number of fixes and other -improvements. Django 1.2.4 is a recommended upgrade for any -development or deployment currently using or targeting Django 1.2. - -For full details on the new features, backwards incompatibilities, and -deprecated features in the 1.2 branch, see the :doc:`/releases/1.2`. - -One new feature -=============== - -Ordinarily, a point release would not include new features, but in the -case of Django 1.2.4, we have made an exception to this rule. - -One of the bugs fixed in Django 1.2.4 involves a set of -circumstances whereby a running a test suite on a multiple database -configuration could cause the original source database (i.e., the -actual production database) to be dropped, causing catastrophic loss -of data. In order to provide a fix for this problem, it was necessary -to introduce a new setting -- :setting:`TEST_DEPENDENCIES` -- that -allows you to define any creation order dependencies in your database -configuration. - -Most users -- even users with multiple-database configurations -- need -not be concerned about the data loss bug, or the manual configuration of -:setting:`TEST_DEPENDENCIES`. See the `original problem report`_ -documentation on :ref:`controlling the creation order of test -databases <topics-testing-creation-dependencies>` for details. - -.. _original problem report: http://code.djangoproject.com/ticket/14415 - -GeoDjango -========= - -The function-based :setting:`TEST_RUNNER` previously used to execute -the GeoDjango test suite, :func:`django.contrib.gis.tests.run_gis_tests`, -was finally deprecated in favor of a class-based test runner, -:class:`django.contrib.gis.tests.GeoDjangoTestSuiteRunner`, added in this -release. - -In addition, the GeoDjango test suite is now included when -:ref:`running the Django test suite <running-unit-tests>` with ``runtests.py`` -and using :ref:`spatial database backends <spatial-backends>`. diff --git a/parts/django/docs/releases/1.2.txt b/parts/django/docs/releases/1.2.txt deleted file mode 100644 index efff2a6..0000000 --- a/parts/django/docs/releases/1.2.txt +++ /dev/null @@ -1,1139 +0,0 @@ -======================== -Django 1.2 release notes -======================== - -*May 17, 2010.* - -Welcome to Django 1.2! - -Nearly a year in the making, Django 1.2 packs an impressive list of `new -features`_ and lots of bug fixes. These release notes cover the new features, -as well as important changes you'll want to be aware of when upgrading from -Django 1.1 or older versions. - -.. _new features: `What's new in Django 1.2`_ - -Overview -======== - -Django 1.2 introduces several large, important new features, including: - - * Support for `multiple database connections`_ in a single Django instance. - - * `Model validation`_ inspired by Django's form validation. - - * Vastly `improved protection against Cross-Site Request Forgery`_ (CSRF). - - * A new `user "messages" framework`_ with support for cookie- and session-based - message for both anonymous and authenticated users. - - * Hooks for `object-level permissions`_, `permissions for anonymous users`_, - and `more flexible username requirements`_. - - * Customization of e-mail sending via `e-mail backends`_. - - * New :ref:`"smart" if template tag <new-in-1.2-smart-if>` which supports - comparison operators. - -.. _multiple database connections: `support for multiple databases`_ -.. _improved protection against Cross-Site Request Forgery: `improved CSRF protection`_ -.. _user "messages" framework: `messages framework`_ -.. _more flexible username requirements: `relaxed requirements for usernames`_ - -These are just the highlights; full details and a complete list of features `may -be found below`_. - -.. _may be found below: `what's new in django 1.2`_ - -.. seealso:: - - `Django Advent`_ covered the release of Django 1.2 with a series of - articles and tutorials that cover some of the new features in depth. - -.. _django advent: http://djangoadvent.com/ - -Wherever possible these features have been introduced in a backwards-compatible -manner per :doc:`our API stability policy </misc/api-stability>` policy. - -However, a handful of features *have* changed in ways that, for some users, will be -backwards-incompatible. The big changes are: - - * Support for Python 2.3 has been dropped. See the full notes - below. - - * The new CSRF protection framework is not backwards-compatible with - the old system. Users of the old system will not be affected until - the old system is removed in Django 1.4. - - However, upgrading to the new CSRF protection framework requires a few - important backwards-incompatible changes, detailed in `CSRF Protection`_, - below. - - * Authors of custom :class:`~django.db.models.Field` subclasses should be - aware that a number of methods have had a change in prototype, detailed - under `get_db_prep_*() methods on Field`_, below. - - * The internals of template tags have changed somewhat; authors of custom - template tags that need to store state (e.g. custom control flow tags) - should ensure that their code follows the new rules for `stateful template - tags`_ - - * The :func:`~django.contrib.auth.decorators.user_passes_test`, - :func:`~django.contrib.auth.decorators.login_required`, and - :func:`~django.contrib.auth.decorators.permission_required`, decorators - from :mod:`django.contrib.auth` only apply to functions and no longer - work on methods. There's a simple one-line fix `detailed below`_. - -.. _detailed below: `user_passes_test, login_required and permission_required`_ - -Again, these are just the big features that will affect the most users. Users -upgrading from previous versions of Django are heavily encouraged to consult -the complete list of :ref:`backwards-incompatible changes -<backwards-incompatible-changes-1.2>` and the list of :ref:`deprecated -features <deprecated-features-1.2>`. - -Python compatibility -==================== - -While not a new feature, it's important to note that Django 1.2 -introduces the first shift in our Python compatibility policy since -Django's initial public debut. Previous Django releases were tested -and supported on 2.x Python versions from 2.3 up; Django 1.2, however, -drops official support for Python 2.3. As such, the minimum Python -version required for Django is now 2.4, and Django is tested and -supported on Python 2.4, 2.5 and 2.6, and will be supported on the -as-yet-unreleased Python 2.7. - -This change should affect only a small number of Django users, as most -operating-system vendors today are shipping Python 2.4 or newer as -their default version. If you're still using Python 2.3, however, -you'll need to stick to Django 1.1 until you can upgrade; per -:doc:`our support policy </internals/release-process>`, Django 1.1 will -continue to receive security support until the release of Django 1.3. - -A roadmap for Django's overall 2.x Python support, and eventual -transition to Python 3.x, is currently being developed, and will be -announced prior to the release of Django 1.3. - -What's new in Django 1.2 -======================== - -Support for multiple databases ------------------------------- - -Django 1.2 adds the ability to use :doc:`more than one database -</topics/db/multi-db>` in your Django project. Queries can be issued at a -specific database with the `using()` method on ``QuerySet`` objects. Individual -objects can be saved to a specific database by providing a ``using`` argument -when you call ``save()``. - -Model validation ----------------- - -Model instances now have support for :ref:`validating their own data -<validating-objects>`, and both model and form fields now accept configurable -lists of :doc:`validators </ref/validators>` specifying reusable, encapsulated -validation behavior. Note, however, that validation must still be performed -explicitly. Simply invoking a model instance's ``save()`` method will not -perform any validation of the instance's data. - -Improved CSRF protection ------------------------- - -Django now has much improved protection against :doc:`Cross-Site Request Forgery -(CSRF) attacks</ref/contrib/csrf>`. This type of attack occurs when a malicious -Web site contains a link, a form button or some JavaScript that is intended to -perform some action on your Web site, using the credentials of a logged-in user -who visits the malicious site in their browser. A related type of attack, "login -CSRF," where an attacking site tricks a user's browser into logging into a site -with someone else's credentials, is also covered. - -Messages framework ------------------- - -Django now includes a robust and configurable :doc:`messages framework -</ref/contrib/messages>` with built-in support for cookie- and session-based -messaging, for both anonymous and authenticated clients. The messages framework -replaces the deprecated user message API and allows you to temporarily store -messages in one request and retrieve them for display in a subsequent request -(usually the next one). - -Object-level permissions ------------------------- - -A foundation for specifying permissions at the per-object level has been added. -Although there is no implementation of this in core, a custom authentication -backend can provide this implementation and it will be used by -:class:`django.contrib.auth.models.User`. See the :doc:`authentication docs -</topics/auth>` for more information. - -Permissions for anonymous users -------------------------------- - -If you provide a custom auth backend with ``supports_anonymous_user`` set to -``True``, AnonymousUser will check the backend for permissions, just like -User already did. This is useful for centralizing permission handling - apps -can always delegate the question of whether something is allowed or not to -the authorization/authentication backend. See the :doc:`authentication -docs </topics/auth>` for more details. - -Relaxed requirements for usernames ----------------------------------- - -The built-in :class:`~django.contrib.auth.models.User` model's -:attr:`~django.contrib.auth.models.User.username` field now allows a wider range -of characters, including ``@``, ``+``, ``.`` and ``-`` characters. - -E-mail backends ---------------- - -You can now :ref:`configure the way that Django sends e-mail -<topic-email-backends>`. Instead of using SMTP to send all e-mail, you -can now choose a configurable e-mail backend to send messages. If your -hosting provider uses a sandbox or some other non-SMTP technique for -sending mail, you can now construct an e-mail backend that will allow -Django's standard :doc:`mail sending methods</topics/email>` to use -those facilities. - -This also makes it easier to debug mail sending. Django ships with -backend implementations that allow you to send e-mail to a -:ref:`file<topic-email-file-backend>`, to the -:ref:`console<topic-email-console-backend>`, or to -:ref:`memory<topic-email-memory-backend>`. You can even configure all -e-mail to be :ref:`thrown away<topic-email-dummy-backend>`. - -.. _new-in-1.2-smart-if: - -"Smart" :ttag:`if` tag ----------------------- - -The :ttag:`if` tag has been upgraded to be much more powerful. First, we've -added support for comparison operators. No longer will you have to type: - -.. code-block:: html+django - - {% ifnotequal a b %} - ... - {% endifnotequal %} - -You can now do this: - -.. code-block:: html+django - - {% if a != b %} - ... - {% endif %} - -There's really no reason to use ``{% ifequal %}`` or ``{% ifnotequal %}`` -anymore, unless you're the nostalgic type. - -The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=``, -``in`` and ``not in``, all of which work like the Python operators, in addition -to ``and``, ``or`` and ``not``, which were already supported. - -Also, filters may now be used in the ``if`` expression. For example: - -.. code-block:: html+django - - <div - {% if user.email|lower == message.recipient|lower %} - class="highlight" - {% endif %} - >{{ message }}</div> - -Template caching ----------------- - -In previous versions of Django, every time you rendered a template, it -would be reloaded from disk. In Django 1.2, you can use a :ref:`cached -template loader <template-loaders>` to load templates once, then -cache the result for every subsequent render. This can lead to a -significant performance improvement if your templates are broken into -lots of smaller subtemplates (using the ``{% extends %}`` or ``{% -include %}`` tags). - -As a side effect, it is now much easier to support non-Django template -languages. For more details, see the :ref:`notes on supporting -non-Django template languages<topic-template-alternate-language>`. - -Natural keys in fixtures ------------------------- - -Fixtures can now refer to remote objects using -:ref:`topics-serialization-natural-keys`. This lookup scheme is an -alternative to the normal primary-key based object references in a -fixture, improving readability and resolving problems referring to -objects whose primary key value may not be predictable or known. - -Fast failure for tests ----------------------- - -Both the :djadmin:`test` subcommand of ``django-admin.py`` and the -``runtests.py`` script used to run Django's own test suite now support a -``--failfast`` option. When specified, this option causes the test runner to -exit after encountering a failure instead of continuing with the test run. In -addition, the handling of ``Ctrl-C`` during a test run has been improved to -trigger a graceful exit from the test run that reports details of the tests that -were run before the interruption. - -``BigIntegerField`` -------------------- - -Models can now use a 64-bit :class:`~django.db.models.BigIntegerField` type. - -Improved localization ---------------------- - -Django's :doc:`internationalization framework </topics/i18n/index>` has been expanded -with locale-aware formatting and form processing. That means, if enabled, dates -and numbers on templates will be displayed using the format specified for the -current locale. Django will also use localized formats when parsing data in -forms. See :ref:`Format localization <format-localization>` for more details. - -``readonly_fields`` in ``ModelAdmin`` -------------------------------------- - -:attr:`django.contrib.admin.ModelAdmin.readonly_fields` has been added to -enable non-editable fields in add/change pages for models and inlines. Field -and calculated values can be displayed alongside editable fields. - -Customizable syntax highlighting --------------------------------- - -You can now use a ``DJANGO_COLORS`` environment variable to modify or disable -the colors used by ``django-admin.py`` to provide :ref:`syntax highlighting -<syntax-coloring>`. - -Syndication feeds as views --------------------------- - -:doc:`Syndication feeds </ref/contrib/syndication>` can now be used directly as -views in your :doc:`URLconf </topics/http/urls>`. This means that you can -maintain complete control over the URL structure of your feeds. Like any other -view, feeds views are passed a ``request`` object, so you can do anything you -would normally do with a view, like user based access control, or making a feed -a named URL. - -GeoDjango ---------- - -The most significant new feature for :doc:`GeoDjango </ref/contrib/gis/index>` -in 1.2 is support for multiple spatial databases. As a result, -the following :ref:`spatial database backends <spatial-backends>` -are now included: - -* :mod:`django.contrib.gis.db.backends.postgis` -* :mod:`django.contrib.gis.db.backends.mysql` -* :mod:`django.contrib.gis.db.backends.oracle` -* :mod:`django.contrib.gis.db.backends.spatialite` - -GeoDjango now supports the rich capabilities added -in the `PostGIS 1.5 release <http://postgis.refractions.net/documentation/manual-1.5/>`_. -New features include suppport for the the :ref:`geography type <geography-type>` -and enabling of :ref:`distance queries <distance-queries>` -with non-point geometries on geographic coordinate systems. - -Support for 3D geometry fields was added, and may be enabled -by setting the :attr:`~django.contrib.gis.db.models.GeometryField.dim` -keyword to 3 in your :class:`~django.contrib.gis.db.models.GeometryField`. -The :class:`~django.contrib.gis.db.models.Extent3D` aggregate -and :meth:`~django.contrib.gis.db.models.GeoQuerySet.extent3d` ``GeoQuerySet`` -method were added as a part of this feature. - -The following :class:`~django.contrib.gis.db.models.GeoQuerySet` -methods are new in 1.2: - -* :meth:`~django.contrib.gis.db.models.GeoQuerySet.force_rhr` -* :meth:`~django.contrib.gis.db.models.GeoQuerySet.reverse_geom` -* :meth:`~django.contrib.gis.db.models.GeoQuerySet.geohash` - -The :ref:`GEOS interface <ref-geos>` was updated to use -thread-safe C library functions when available on the platform. - -The :ref:`GDAL interface <ref-gdal>` now allows the user to -set a :attr:`~django.contrib.gis.gdal.Layer.spatial_filter` on -the features returned when iterating over a -:class:`~django.contrib.gis.gdal.Layer`. - -Finally, :doc:`GeoDjango's documentation </ref/contrib/gis/index>` is now -included with Django's and is no longer -hosted separately at `geodjango.org <http://geodjango.org/>`_. - -.. _1.2-js-assisted-inlines: - -JavaScript-assisted handling of inline related objects in the admin -------------------------------------------------------------------- - -If a user has JavaScript enabled in their browser, the interface for -inline objects in the admin now allows inline objects to be -dynamically added and removed. Users without JavaScript-enabled -browsers will see no change in the behavior of inline objects. - -New ``now`` template tag format specifier characters: ``c`` and ``u`` ---------------------------------------------------------------------- - -The argument to the :ttag:`now` has gained two new format characters: -``c`` to specify that a datetime value should be formatted in ISO 8601 -format, and ``u`` that allows output of the microseconds part of a -datetime or time value. - -These are also available in others parts like the :tfilter:`date` and -:tfilter:`time` template filters, the ``humanize`` template tag library -and the new `format localization`_ framework. - -.. _format localization: `Improved localization`_ - -.. _backwards-incompatible-changes-1.2: - -Backwards-incompatible changes in 1.2 -===================================== - -Wherever possible the new features above have been introduced in a -backwards-compatible manner per :doc:`our API stability policy -</misc/api-stability>` policy. This means that practically all existing -code which worked with Django 1.1 will continue to work with Django -1.2; such code will, however, begin issuing warnings (see below for -details). - -However, a handful of features *have* changed in ways that, for some -users, will be immediately backwards-incompatible. Those changes are -detailed below. - -CSRF Protection ---------------- - -We've made large changes to the way CSRF protection works, detailed in -:doc:`the CSRF documentaton </ref/contrib/csrf>`. Here are the major changes you -should be aware of: - - * ``CsrfResponseMiddleware`` and ``CsrfMiddleware`` have been deprecated and - will be removed completely in Django 1.4, in favor of a template tag that - should be inserted into forms. - - * All contrib apps use a ``csrf_protect`` decorator to protect the view. This - requires the use of the ``csrf_token`` template tag in the template. If you - have used custom templates for contrib views, you MUST READ THE :ref:`UPGRADE - INSTRUCTIONS <ref-csrf-upgrading-notes>` to fix those templates. - - * ``CsrfViewMiddleware`` is included in :setting:`MIDDLEWARE_CLASSES` by - default. This turns on CSRF protection by default, so views that accept - POST requests need to be written to work with the middleware. Instructions - on how to do this are found in the CSRF docs. - - * All of the CSRF has moved from contrib to core (with backwards - compatible imports in the old locations, which are deprecated and - will cease to be supported in Django 1.4). - -``get_db_prep_*()`` methods on ``Field`` ----------------------------------------- - -Prior to Django 1.2, a custom ``Field`` had the option of defining -several functions to support conversion of Python values into -database-compatible values. A custom field might look something like:: - - class CustomModelField(models.Field): - # ... - def db_type(self): - # ... - - def get_db_prep_save(self, value): - # ... - - def get_db_prep_value(self, value): - # ... - - def get_db_prep_lookup(self, lookup_type, value): - # ... - -In 1.2, these three methods have undergone a change in prototype, and -two extra methods have been introduced:: - - class CustomModelField(models.Field): - # ... - - def db_type(self, connection): - # ... - - def get_prep_value(self, value): - # ... - - def get_prep_lookup(self, lookup_type, value): - # ... - - def get_db_prep_save(self, value, connection): - # ... - - def get_db_prep_value(self, value, connection, prepared=False): - # ... - - def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False): - # ... - -These changes are required to support multiple databases -- -``db_type`` and ``get_db_prep_*`` can no longer make any assumptions -regarding the database for which it is preparing. The ``connection`` -argument now provides the preparation methods with the specific -connection for which the value is being prepared. - -The two new methods exist to differentiate general data-preparation -requirements from requirements that are database-specific. The -``prepared`` argument is used to indicate to the database-preparation -methods whether generic value preparation has been performed. If -an unprepared (i.e., ``prepared=False``) value is provided to the -``get_db_prep_*()`` calls, they should invoke the corresponding -``get_prep_*()`` calls to perform generic data preparation. - -We've provided conversion functions that will transparently -convert functions adhering to the old prototype into functions -compatible with the new prototype. However, these conversion functions -will be removed in Django 1.4, so you should upgrade your ``Field`` -definitions to use the new prototype as soon as possible. - -If your ``get_db_prep_*()`` methods made no use of the database -connection, you should be able to upgrade by renaming -``get_db_prep_value()`` to ``get_prep_value()`` and -``get_db_prep_lookup()`` to ``get_prep_lookup()``. If you require -database specific conversions, then you will need to provide an -implementation ``get_db_prep_*`` that uses the ``connection`` -argument to resolve database-specific values. - -Stateful template tags ----------------------- - -Template tags that store rendering state on their ``Node`` subclass -have always been vulnerable to thread-safety and other issues; as of -Django 1.2, however, they may also cause problems when used with the -new :ref:`cached template loader<template-loaders>`. - -All of the built-in Django template tags are safe to use with the cached -loader, but if you're using custom template tags that come from third -party packages, or from your own code, you should ensure that the -``Node`` implementation for each tag is thread-safe. For more -information, see -:ref:`template tag thread safety considerations<template_tag_thread_safety>`. - -You may also need to update your templates if you were relying on the -implementation of Django's template tags *not* being thread safe. The -:ttag:`cycle` tag is the most likely to be affected in this way, -especially when used in conjunction with the :ttag:`include` tag. -Consider the following template fragment:: - - {% for object in object_list %} - {% include "subtemplate.html" %} - {% endfor %} - -with a ``subtemplate.html`` that reads:: - - {% cycle 'even' 'odd' %} - -Using the non-thread-safe, pre-Django 1.2 renderer, this would output:: - - even odd even odd ... - -Using the thread-safe Django 1.2 renderer, you will instead get:: - - even even even even ... - -This is because each rendering of the :ttag:`include` tag is an -independent rendering. When the :ttag:`cycle` tag was not thread safe, -the state of the :ttag:`cycle` tag would leak between multiple -renderings of the same :ttag:`include`. Now that the :ttag:`cycle` tag -is thread safe, this leakage no longer occurs. - -``user_passes_test``, ``login_required`` and ``permission_required`` --------------------------------------------------------------------- - -``django.contrib.auth.decorators`` provides the decorators -``login_required``, ``permission_required`` and -``user_passes_test``. Previously it was possible to use these -decorators both on functions (where the first argument is 'request') -and on methods (where the first argument is 'self', and the second -argument is 'request'). Unfortunately, flaws were discovered in the -code supporting this: it only works in limited circumstances, and -produces errors that are very difficult to debug when it does not -work. - -For this reason, the 'auto adapt' behavior has been removed, and if -you are using these decorators on methods, you will need to manually -apply :func:`django.utils.decorators.method_decorator` to convert the -decorator to one that works with methods. For example, you would -change code from this:: - - class MyClass(object): - - @login_required - def my_view(self, request): - pass - -to this:: - - from django.utils.decorators import method_decorator - - class MyClass(object): - - @method_decorator(login_required) - def my_view(self, request): - pass - -or:: - - from django.utils.decorators import method_decorator - - login_required_m = method_decorator(login_required) - - class MyClass(object): - - @login_required_m - def my_view(self, request): - pass - -For those of you who've been following the development trunk, this -change also applies to other decorators introduced since 1.1, -including ``csrf_protect``, ``cache_control`` and anything created -using ``decorator_from_middleware``. - -:ttag:`if` tag changes ----------------------- - -Due to new features in the :ttag:`if` template tag, it no longer -accepts 'and', 'or' and 'not' as valid **variable** names. Previously, -these strings could be used as variable names. Now, the keyword status -is always enforced, and template code such as ``{% if not %}`` or ``{% -if and %}`` will throw a ``TemplateSyntaxError``. Also, ``in`` is a -new keyword and so is not a valid variable name in this tag. - -``LazyObject`` --------------- - -``LazyObject`` is an undocumented-but-often-used utility class used for lazily -wrapping other objects of unknown type. - -In Django 1.1 and earlier, it handled introspection in a non-standard way, -depending on wrapped objects implementing a public method named -``get_all_members()``. Since this could easily lead to name clashes, it has been -changed to use the standard Python introspection method, involving -``__members__`` and ``__dir__()``. - -If you used ``LazyObject`` in your own code -and implemented the ``get_all_members()`` method for wrapped objects, you'll need -to make a couple of changes: - -First, if your class does not have special requirements for introspection (i.e., -you have not implemented ``__getattr__()`` or other methods that allow for -attributes not discoverable by normal mechanisms), you can simply remove the -``get_all_members()`` method. The default implementation on ``LazyObject`` will -do the right thing. - -If you have more complex requirements for introspection, first rename the -``get_all_members()`` method to ``__dir__()``. This is the standard -introspection method for Python 2.6 and above. If you require support for Python -versions earlier than 2.6, add the following code to the class:: - - __members__ = property(lambda self: self.__dir__()) - -``__dict__`` on model instances -------------------------------- - -Historically, the ``__dict__`` attribute of a model instance has only contained -attributes corresponding to the fields on a model. - -In order to support multiple database configurations, Django 1.2 has -added a ``_state`` attribute to object instances. This attribute will -appear in ``__dict__`` for a model instance. If your code relies on -iterating over ``__dict__`` to obtain a list of fields, you must now -be prepared to handle or filter out the ``_state`` attribute. - -Test runner exit status code ----------------------------- - -The exit status code of the test runners (``tests/runtests.py`` and ``python -manage.py test``) no longer represents the number of failed tests, because a -failure of 256 or more tests resulted in a wrong exit status code. The exit -status code for the test runner is now 0 for success (no failing tests) and 1 -for any number of test failures. If needed, the number of test failures can be -found at the end of the test runner's output. - -Cookie encoding ---------------- - -To fix bugs with cookies in Internet Explorer, Safari, and possibly -other browsers, our encoding of cookie values was changed so that the -comma and semicolon are treated as non-safe characters, and are -therefore encoded as ``\054`` and ``\073`` respectively. This could -produce backwards incompatibilities, especially if you are storing -comma or semi-colon in cookies and have javascript code that parses -and manipulates cookie values client-side. - -``ModelForm.is_valid()`` and ``ModelForm.errors`` -------------------------------------------------- - -Much of the validation work for ModelForms has been moved down to the model -level. As a result, the first time you call ``ModelForm.is_valid()``, access -``ModelForm.errors`` or otherwise trigger form validation, your model will be -cleaned in-place. This conversion used to happen when the model was saved. If -you need an unmodified instance of your model, you should pass a copy to the -``ModelForm`` constructor. - -``BooleanField`` on MySQL --------------------------- - -In previous versions of Django, a model's ``BooleanField`` under MySQL -would return its value as either ``1`` or ``0``, instead of ``True`` -or ``False``; for most people this wasn't a problem because ``bool`` -is a subclass of ``int`` in Python. In Django 1.2, however, -``BooleanField`` on MySQL correctly returns a real ``bool``. The only -time this should ever be an issue is if you were expecting the -``repr`` of a ``BooleanField`` to print ``1`` or ``0``. - -Changes to the interpretation of ``max_num`` in FormSets --------------------------------------------------------- - -As part of enhancements made to the handling of FormSets, the default -value and interpretation of the ``max_num`` parameter to the -:ref:`django.forms.formsets.formset_factory() <formsets-max-num>` and -:ref:`django.forms.models.modelformset_factory() -<model-formsets-max-num>` functions has changed slightly. This -change also affects the way the ``max_num`` argument is :ref:`used for -inline admin objects <ref-contrib-admin-inline-max-num>` - -Previously, the default value for ``max_num`` was ``0`` (zero). -FormSets then used the boolean value of ``max_num`` to determine if a -limit was to be imposed on the number of generated forms. The default -value of ``0`` meant that there was no default limit on the number of -forms in a FormSet. - -Starting with 1.2, the default value for ``max_num`` has been changed -to ``None``, and FormSets will differentiate between a value of -``None`` and a value of ``0``. A value of ``None`` indicates that no -limit on the number of forms is to be imposed; a value of ``0`` -indicates that a maximum of 0 forms should be imposed. This doesn't -necessarily mean that no forms will be displayed -- see the -:ref:`ModelFormSet documentation <model-formsets-max-num>` for more -details. - -If you were manually specifying a value of ``0`` for ``max_num``, you -will need to update your FormSet and/or admin definitions. - -.. seealso:: - - :ref:`1.2-js-assisted-inlines` - -``email_re`` ------------- - -An undocumented regular expression for validating email addresses has been moved -from ``django.form.fields`` to ``django.core.validators``. You will need to -update your imports if you are using it. - -.. _deprecated-features-1.2: - -Features deprecated in 1.2 -========================== - -Finally, Django 1.2 deprecates some features from earlier releases. -These features are still supported, but will be gradually phased out -over the next few release cycles. - -Code taking advantage of any of the features below will raise a -``PendingDeprecationWarning`` in Django 1.2. This warning will be -silent by default, but may be turned on using Python's `warnings -module`_, or by running Python with a ``-Wd`` or `-Wall` flag. - -.. _warnings module: http://docs.python.org/library/warnings.html - -In Django 1.3, these warnings will become a ``DeprecationWarning``, -which is *not* silent. In Django 1.4 support for these features will -be removed entirely. - -.. seealso:: - - For more details, see the documentation :doc:`Django's release process - </internals/release-process>` and our :doc:`deprecation timeline - </internals/deprecation>`.` - -.. _specifying-databases: - -Specifying databases --------------------- - -Prior to Django 1.2, Django used a number of settings to control -access to a single database. Django 1.2 introduces support for -multiple databases, and as a result the way you define database -settings has changed. - -Any existing Django settings file will continue to work as expected -until Django 1.4. Until then, old-style database settings will be -automatically translated to the new-style format. - -In the old-style (pre 1.2) format, you had a number of ``DATABASE_`` -settings in your settings file. For example:: - - DATABASE_NAME = 'test_db' - DATABASE_ENGINE = 'postgresql_psycopg2' - DATABASE_USER = 'myusername' - DATABASE_PASSWORD = 's3krit' - -These settings are now in a dictionary named -:setting:`DATABASES`. Each item in the dictionary corresponds to a -single database connection, with the name ``'default'`` describing the -default database connection. The setting names have also been -shortened. The previous sample settings would now look like this:: - - DATABASES = { - 'default': { - 'NAME': 'test_db', - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'USER': 'myusername', - 'PASSWORD': 's3krit', - } - } - -This affects the following settings: - - ========================================= ========================== - Old setting New Setting - ========================================= ========================== - :setting:`DATABASE_ENGINE` :setting:`ENGINE` - :setting:`DATABASE_HOST` :setting:`HOST` - :setting:`DATABASE_NAME` :setting:`NAME` - :setting:`DATABASE_OPTIONS` :setting:`OPTIONS` - :setting:`DATABASE_PASSWORD` :setting:`PASSWORD` - :setting:`DATABASE_PORT` :setting:`PORT` - :setting:`DATABASE_USER` :setting:`USER` - :setting:`TEST_DATABASE_CHARSET` :setting:`TEST_CHARSET` - :setting:`TEST_DATABASE_COLLATION` :setting:`TEST_COLLATION` - :setting:`TEST_DATABASE_NAME` :setting:`TEST_NAME` - ========================================= ========================== - -These changes are also required if you have manually created a database -connection using ``DatabaseWrapper()`` from your database backend of choice. - -In addition to the change in structure, Django 1.2 removes the special -handling for the built-in database backends. All database backends -must now be specified by a fully qualified module name (i.e., -``django.db.backends.postgresql_psycopg2``, rather than just -``postgresql_psycopg2``). - -``postgresql`` database backend -------------------------------- - -The ``psycopg1`` library has not been updated since October 2005. As a -result, the ``postgresql`` database backend, which uses this library, -has been deprecated. - -If you are currently using the ``postgresql`` backend, you should -migrate to using the ``postgresql_psycopg2`` backend. To update your -code, install the ``psycopg2`` library and change the -:setting:`DATABASE_ENGINE` setting to use -``django.db.backends.postgresql_psycopg2``. - -CSRF response-rewriting middleware ----------------------------------- - -``CsrfResponseMiddleware``, the middleware that automatically inserted -CSRF tokens into ``POST`` forms in outgoing pages, has been deprecated -in favor of a template tag method (see above), and will be removed -completely in Django 1.4. ``CsrfMiddleware``, which includes the -functionality of ``CsrfResponseMiddleware`` and -``CsrfViewMiddleware``, has likewise been deprecated. - -Also, the CSRF module has moved from contrib to core, and the old -imports are deprecated, as described in the :ref:`upgrading notes -<ref-csrf-upgrading-notes>`. - -``SMTPConnection`` ------------------- - -The ``SMTPConnection`` class has been deprecated in favor of a generic -e-mail backend API. Old code that explicitly instantiated an instance -of an SMTPConnection:: - - from django.core.mail import SMTPConnection - connection = SMTPConnection() - messages = get_notification_email() - connection.send_messages(messages) - -...should now call :meth:`~django.core.mail.get_connection()` to -instantiate a generic e-mail connection:: - - from django.core.mail import get_connection - connection = get_connection() - messages = get_notification_email() - connection.send_messages(messages) - -Depending on the value of the :setting:`EMAIL_BACKEND` setting, this -may not return an SMTP connection. If you explicitly require an SMTP -connection with which to send e-mail, you can explicitly request an -SMTP connection:: - - from django.core.mail import get_connection - connection = get_connection('django.core.mail.backends.smtp.EmailBackend') - messages = get_notification_email() - connection.send_messages(messages) - -If your call to construct an instance of ``SMTPConnection`` required -additional arguments, those arguments can be passed to the -:meth:`~django.core.mail.get_connection()` call:: - - connection = get_connection('django.core.mail.backends.smtp.EmailBackend', hostname='localhost', port=1234) - -User Messages API ------------------ - -The API for storing messages in the user ``Message`` model (via -``user.message_set.create``) is now deprecated and will be removed in Django -1.4 according to the standard :doc:`release process </internals/release-process>`. - -To upgrade your code, you need to replace any instances of this:: - - user.message_set.create('a message') - -...with the following:: - - from django.contrib import messages - messages.add_message(request, messages.INFO, 'a message') - -Additionally, if you make use of the method, you need to replace the -following:: - - for message in user.get_and_delete_messages(): - ... - -...with:: - - from django.contrib import messages - for message in messages.get_messages(request): - ... - -For more information, see the full -:doc:`messages documentation </ref/contrib/messages>`. You should begin to -update your code to use the new API immediately. - -Date format helper functions ----------------------------- - -``django.utils.translation.get_date_formats()`` and -``django.utils.translation.get_partial_date_formats()`` have been deprecated -in favor of the appropriate calls to ``django.utils.formats.get_format()``, -which is locale-aware when :setting:`USE_L10N` is set to ``True``, and falls -back to default settings if set to ``False``. - -To get the different date formats, instead of writing this:: - - from django.utils.translation import get_date_formats - date_format, datetime_format, time_format = get_date_formats() - -...use:: - - from django.utils import formats - date_format = formats.get_format('DATE_FORMAT') - datetime_format = formats.get_format('DATETIME_FORMAT') - time_format = formats.get_format('TIME_FORMAT') - -Or, when directly formatting a date value:: - - from django.utils import formats - value_formatted = formats.date_format(value, 'DATETIME_FORMAT') - -The same applies to the globals found in ``django.forms.fields``: - - * ``DEFAULT_DATE_INPUT_FORMATS`` - * ``DEFAULT_TIME_INPUT_FORMATS`` - * ``DEFAULT_DATETIME_INPUT_FORMATS`` - -Use ``django.utils.formats.get_format()`` to get the appropriate formats. - -Function-based test runners ---------------------------- - -Django 1.2 changes the test runner tools to use a class-based -approach. Old style function-based test runners will still work, but -should be updated to use the new :ref:`class-based runners -<topics-testing-test_runner>`. - -.. _1.2-updating-feeds: - -``Feed`` in ``django.contrib.syndication.feeds`` ------------------------------------------------- - -The :class:`django.contrib.syndication.feeds.Feed` class has been -replaced by the :class:`django.contrib.syndication.views.Feed` class. -The old ``feeds.Feed`` class is deprecated, and will be removed in -Django 1.4. - -The new class has an almost identical API, but allows instances to be -used as views. For example, consider the use of the old framework in -the following :doc:`URLconf </topics/http/urls>`:: - - from django.conf.urls.defaults import * - from myproject.feeds import LatestEntries, LatestEntriesByCategory - - feeds = { - 'latest': LatestEntries, - 'categories': LatestEntriesByCategory, - } - - urlpatterns = patterns('', - # ... - (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', - {'feed_dict': feeds}), - # ... - ) - -Using the new Feed class, these feeds can be deployed directly as views:: - - from django.conf.urls.defaults import * - from myproject.feeds import LatestEntries, LatestEntriesByCategory - - urlpatterns = patterns('', - # ... - (r'^feeds/latest/$', LatestEntries()), - (r'^feeds/categories/(?P<category_id>\d+)/$', LatestEntriesByCategory()), - # ... - ) - -If you currently use the ``feed()`` view, the ``LatestEntries`` class would -often not need to be modified apart from subclassing the new -:class:`~django.contrib.syndication.views.Feed` class. The exception is if -Django was automatically working out the name of the template to use to render -the feed's description and title elements (if you were not specifying the -``title_template`` and ``description_template`` attributes). You should ensure -that you always specify ``title_template`` and ``description_template`` -attributes, or provide ``item_title()`` and ``item_description()`` methods. - -However, ``LatestEntriesByCategory`` uses the ``get_object()`` method -with the ``bits`` argument to specify a specific category to show. In -the new :class:`~django.contrib.syndication.views.Feed` class, -``get_object()`` method takes a ``request`` and arguments from the -URL, so it would look like this:: - - from django.contrib.syndication.views import Feed - from django.shortcuts import get_object_or_404 - from myproject.models import Category - - class LatestEntriesByCategory(Feed): - def get_object(self, request, category_id): - return get_object_or_404(Category, id=category_id) - - # ... - -Additionally, the ``get_feed()`` method on ``Feed`` classes now take -different arguments, which may impact you if you use the ``Feed`` -classes directly. Instead of just taking an optional ``url`` argument, -it now takes two arguments: the object returned by its own -``get_object()`` method, and the current ``request`` object. - -To take into account ``Feed`` classes not being initialized for each -request, the ``__init__()`` method now takes no arguments by default. -Previously it would have taken the ``slug`` from the URL and the -``request`` object. - -In accordance with `RSS best practices`_, RSS feeds will now include -an ``atom:link`` element. You may need to update your tests to take -this into account. - -For more information, see the full :doc:`syndication framework -documentation </ref/contrib/syndication>`. - -.. _RSS best practices: http://www.rssboard.org/rss-profile - -Technical message IDs ---------------------- - -Up to version 1.1 Django used :ref:`technical message IDs<technical-messages>` -to provide localizers the possibility to translate date and time formats. They -were translatable :term:`translation strings <translation string>` that could -be recognized because they were all upper case (for example -``DATETIME_FORMAT``, ``DATE_FORMAT``, ``TIME_FORMAT``). They have been -deprecated in favor of the new :ref:`Format localization -<format-localization>` infrastructure that allows localizers to specify that -information in a ``formats.py`` file in the corresponding -``django/conf/locale/<locale name>/`` directory. - -GeoDjango ---------- - -To allow support for multiple databases, the GeoDjango database internals were -changed substantially. The largest backwards-incompatible change is that -the module ``django.contrib.gis.db.backend`` was renamed to -:mod:`django.contrib.gis.db.backends`, where the full-fledged -:ref:`spatial database backends <spatial-backends>` now exist. The -following sections provide information on the most-popular APIs that -were affected by these changes. - -``SpatialBackend`` -^^^^^^^^^^^^^^^^^^ - -Prior to the creation of the separate spatial backends, the -``django.contrib.gis.db.backend.SpatialBackend`` object was -provided as an abstraction to introspect on the capabilities of -the spatial database. All of the attributes and routines provided by -``SpatialBackend`` are now a part of the ``ops`` attribute of the -database backend. - -The old module ``django.contrib.gis.db.backend`` is still provided -for backwards-compatibility access to a ``SpatialBackend`` object, -which is just an alias to the ``ops`` module of the -*default* spatial database connection. - -Users that were relying on undocumented modules and objects -within ``django.contrib.gis.db.backend``, rather the abstractions -provided by ``SpatialBackend``, are required to modify their code. -For example, the following import which would work in 1.1 and -below:: - - from django.contrib.gis.db.backend.postgis import PostGISAdaptor - -Would need to be changed:: - - from django.db import connection - PostGISAdaptor = connection.ops.Adapter - -``SpatialRefSys`` and ``GeometryColumns`` models -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In previous versions of GeoDjango, :mod:`django.contrib.gis.db.models` -had ``SpatialRefSys`` and ``GeometryColumns`` models for querying -the OGC spatial metadata tables ``spatial_ref_sys`` and ``geometry_columns``, -respectively. - -While these aliases are still provided, they are only for the -*default* database connection and exist only if the default connection -is using a supported spatial database backend. - -.. note:: - - Because the table structure of the OGC spatial metadata tables - differs across spatial databases, the ``SpatialRefSys`` and - ``GeometryColumns`` models can no longer be associated with - the ``gis`` application name. Thus, no models will be returned - when using the ``get_models`` method in the following example:: - - >>> from django.db.models import get_app, get_models - >>> get_models(get_app('gis')) - [] - -To get the correct ``SpatialRefSys`` and ``GeometryColumns`` -for your spatial database use the methods provided by the spatial backend:: - - >>> from django.db import connections - >>> SpatialRefSys = connections['my_spatialite'].ops.spatial_ref_sys() - >>> GeometryColumns = connections['my_postgis'].ops.geometry_columns() - -.. note:: - - When using the models returned from the ``spatial_ref_sys()`` and - ``geometry_columns()`` method, you'll still need to use the - correct database alias when querying on the non-default connection. - In other words, to ensure that the models in the example above - use the correct database:: - - sr_qs = SpatialRefSys.objects.using('my_spatialite').filter(...) - gc_qs = GeometryColumns.objects.using('my_postgis').filter(...) - -Language code ``no`` --------------------- - -The currently used language code for Norwegian Bokmål ``no`` is being -replaced by the more common language code ``nb``. - diff --git a/parts/django/docs/releases/index.txt b/parts/django/docs/releases/index.txt deleted file mode 100644 index 7abaf78..0000000 --- a/parts/django/docs/releases/index.txt +++ /dev/null @@ -1,70 +0,0 @@ -============= -Release notes -============= - -Release notes for the official Django releases. Each release note will tell you -what's new in each version, and will also describe any backwards-incompatible -changes made in that version. - -For those upgrading to a new version of Django, you will need to check -all the backwards-incompatible changes and deprecated features for -each 'final' release from the one after your current Django version, -up to and including the new version. - -Final releases -============== - -1.2 release ------------ -.. toctree:: - :maxdepth: 1 - - 1.2.4 - 1.2.2 - 1.2 - -1.1 release ------------ -.. toctree:: - :maxdepth: 1 - - 1.1.2 - 1.1 - -1.0 release ------------ -.. toctree:: - :maxdepth: 1 - - 1.0.2 - 1.0.1 - 1.0 - -Pre-1.0 releases ----------------- -.. toctree:: - :maxdepth: 1 - - 0.96 - 0.95 - -Development releases -==================== - -These notes are retained for historical purposes. If you are upgrading -between formal Django releases, you don't need to worry about these -notes. - -.. toctree:: - :maxdepth: 1 - - 1.2-rc-1 - 1.2-beta-1 - 1.2-alpha-1 - 1.1-rc-1 - 1.1-beta-1 - 1.1-alpha-1 - 1.0-beta-2 - 1.0-beta - 1.0-alpha-2 - 1.0-alpha-1 diff --git a/parts/django/docs/topics/auth.txt b/parts/django/docs/topics/auth.txt deleted file mode 100644 index a58e523..0000000 --- a/parts/django/docs/topics/auth.txt +++ /dev/null @@ -1,1612 +0,0 @@ -============================= -User authentication in Django -============================= - -.. module:: django.contrib.auth - :synopsis: Django's authentication framework. - -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. - -.. deprecated:: 1.2 - The Messages component of the auth system will be removed in Django 1.4. - -Installation -============ - -Authentication support is bundled as a Django application in -``django.contrib.auth``. To install it, do the following: - - 1. Put ``'django.contrib.auth'`` and ``'django.contrib.contenttypes'`` in - your :setting:`INSTALLED_APPS` setting. - (The :class:`~django.contrib.auth.models.Permission` model in - :mod:`django.contrib.auth` depends on :mod:`django.contrib.contenttypes`.) - 2. Run the command ``manage.py syncdb``. - -Note that the default :file:`settings.py` file created by -:djadmin:`django-admin.py startproject <startproject>` includes -``'django.contrib.auth'`` and ``'django.contrib.contenttypes'`` in -:setting:`INSTALLED_APPS` for convenience. If your :setting:`INSTALLED_APPS` -already contains these apps, feel free to run :djadmin:`manage.py syncdb -<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 :djadmin:`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 -===== - -.. class:: models.User - -API reference -------------- - -Fields -~~~~~~ - -.. class:: models.User - - :class:`~django.contrib.auth.models.User` objects have the following - fields: - - .. attribute:: models.User.username - - Required. 30 characters or fewer. Alphanumeric characters only - (letters, digits and underscores). - - .. versionchanged:: 1.2 - Usernames may now contain ``@``, ``+``, ``.`` and ``-`` characters. - - .. attribute:: models.User.first_name - - Optional. 30 characters or fewer. - - .. attribute:: models.User.last_name - - Optional. 30 characters or fewer. - - .. attribute:: models.User.email - - Optional. E-mail address. - - .. attribute:: models.User.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. - - .. attribute:: models.User.is_staff - - Boolean. Designates whether this user can access the admin site. - - .. attribute:: models.User.is_active - - Boolean. Designates whether this user account should be considered - active. We recommend that you set this flag to ``False`` instead of - deleting accounts; that way, if your applications have any foreign keys - to users, the foreign keys won't break. - - This doesn't necessarily control whether or not the user can log in. - Authentication backends aren't required to check for the ``is_active`` - flag, so if you want to reject a login based on ``is_active`` being - ``False``, it's up to you to check that in your own login view. - However, the :class:`~django.contrib.auth.forms.AuthenticationForm` - used by the :func:`~django.contrib.auth.views.login` view *does* - perform this check, as do the permission-checking methods such as - :meth:`~models.User.has_perm` and the authentication in the Django - admin. All of those functions/methods will return ``False`` for - inactive users. - - .. attribute:: models.User.is_superuser - - Boolean. Designates that this user has all permissions without - explicitly assigning them. - - .. attribute:: models.User.last_login - - A datetime of the user's last login. Is set to the current date/time by - default. - - .. attribute:: models.User.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 -~~~~~~~ - -.. class:: models.User - - :class:`~django.contrib.auth.models.User` objects have two many-to-many - fields: models.User. ``groups`` and ``user_permissions``. - :class:`~django.contrib.auth.models.User` objects can access their related - objects in the same way as any other :doc:`Django model - </topics/db/models>`: - - .. code-block:: python - - 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, - :class:`~django.contrib.auth.models.User` objects have the following custom - methods: - - .. method:: models.User.is_anonymous() - - Always returns ``False``. This is a way of differentiating - :class:`~django.contrib.auth.models.User` and - :class:`~django.contrib.auth.models.AnonymousUser` objects. - Generally, you should prefer using - :meth:`~django.contrib.auth.models.User.is_authenticated()` to this - method. - - .. method:: models.User.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. - - .. method:: models.User.get_full_name() - - Returns the :attr:`~django.contrib.auth.models.User.first_name` plus - the :attr:`~django.contrib.auth.models.User.last_name`, with a space in - between. - - .. method:: models.User.set_password(raw_password) - - Sets the user's password to the given raw string, taking care of the - password hashing. Doesn't save the - :class:`~django.contrib.auth.models.User` object. - - .. method:: models.User.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.) - - .. method:: models.User.set_unusable_password() - - .. versionadded:: 1.0 - - Marks the user as having no password set. This isn't the same as - having a blank string for a password. - :meth:`~django.contrib.auth.models.User.check_password()` for this user - will never return ``True``. Doesn't save the - :class:`~django.contrib.auth.models.User` object. - - You may need this if authentication for your application takes place - against an existing external source such as an LDAP directory. - - .. method:: models.User.has_usable_password() - - .. versionadded:: 1.0 - - Returns ``False`` if - :meth:`~django.contrib.auth.models.User.set_unusable_password()` has - been called for this user. - - .. method:: models.User.get_group_permissions(obj=None) - - Returns a set of permission strings that the user has, through his/her - groups. - - .. versionadded:: 1.2 - - If ``obj`` is passed in, only returns the group permissions for - this specific object. - - .. method:: models.User.get_all_permissions(obj=None) - - Returns a set of permission strings that the user has, both through - group and user permissions. - - .. versionadded:: 1.2 - - If ``obj`` is passed in, only returns the permissions for this - specific object. - - .. method:: models.User.has_perm(perm, obj=None) - - Returns ``True`` if the user has the specified permission, where perm is - in the format ``"<app label>.<permission codename>"``. (see - `permissions`_ section below). If the user is inactive, this method will - always return ``False``. - - .. versionadded:: 1.2 - - If ``obj`` is passed in, this method won't check for a permission for - the model, but for this specific object. - - .. method:: models.User.has_perms(perm_list, obj=None) - - Returns ``True`` if the user has each of the specified permissions, - where each perm is in the format - ``"<app label>.<permission codename>"``. If the user is inactive, - this method will always return ``False``. - - .. versionadded:: 1.2 - - If ``obj`` is passed in, this method won't check for permissions for - the model, but for the specific object. - - .. method:: models.User.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``. - - .. method:: models.User.get_and_delete_messages() - - Returns a list of :class:`~django.contrib.auth.models.Message` objects - in the user's queue and deletes the messages from the queue. - - .. method:: models.User.email_user(subject, message, from_email=None) - - Sends an e-mail to the user. If - :attr:`~django.contrib.auth.models.User.from_email` is ``None``, Django - uses the :setting:`DEFAULT_FROM_EMAIL`. - - .. method:: models.User.get_profile() - - Returns a site-specific profile for this user. Raises - :exc:`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. - -.. _storing additional user information: #storing-additional-information-about-users - -Manager functions -~~~~~~~~~~~~~~~~~ - -.. class:: models.UserManager - - The :class:`~django.contrib.auth.models.User` model has a custom manager - that has the following helper functions: - - .. method:: models.UserManager.create_user(username, email, password=None) - - Creates, saves and returns a :class:`~django.contrib.auth.models.User`. - - The :attr:`~django.contrib.auth.models.User.username` and - :attr:`~django.contrib.auth.models.User.password` are set as given. The - domain portion of :attr:`~django.contrib.auth.models.User.email` is - automatically convered to lowercase, and the returned - :class:`~django.contrib.auth.models.User` object will have - :attr:`~models.User.is_active` set to ``True``. - - If no password is provided, - :meth:`~django.contrib.auth.models.User.set_unusable_password()` will - be called. - - See `Creating users`_ for example usage. - - .. method:: models.UserManager.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: - - * ``i``, ``l``, ``I``, and ``1`` (lowercase letter i, lowercase - letter L, uppercase letter i, and the number one) - * ``o``, ``O``, and ``0`` (uppercase letter o, lowercase letter o, - and zero) - -Basic usage ------------ - -.. _topics-auth-creating-users: - -Creating users -~~~~~~~~~~~~~~ - -The most basic way to create users is to use the -:meth:`~django.contrib.auth.models.UserManager.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() - -You can also create users using the Django admin site. Assuming you've enabled -the admin site and hooked it to the URL ``/admin/``, the "Add user" page is at -``/admin/auth/user/add/``. You should also see a link to "Users" in the "Auth" -section of the main admin index page. The "Add user" admin page is different -than standard admin pages in that it requires you to choose a username and -password before allowing you to edit the rest of the user's fields. - -Also note: if you want your own user account to be able to create users using -the Django admin site, you'll need to give yourself permission to add users -*and* change users (i.e., the "Add user" and "Change user" permissions). If -your account has permission to add users but not to change them, you won't be -able to add users. Why? Because if you have permission to add users, you have -the power to create superusers, which can then, in turn, change other users. So -Django requires add *and* change permissions as a slight security measure. - -Changing passwords -~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - The ``manage.py changepassword`` command was added. - -:djadmin:`manage.py changepassword *username* <changepassword>` offers a method -of changing a User's password from the command line. It prompts you to -change the password of a given user which you must enter twice. If -they both match, the new password will be changed immediately. If you -do not supply a user, the command will attempt to change the password -whose username matches the current user. - -You can also change a password programmatically, using -:meth:`~django.contrib.auth.models.User.set_password()`: - -.. code-block:: python - - >>> 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 :attr:`~django.contrib.auth.models.User.password` attribute -directly unless you know what you're doing. This is explained in the next -section. - -Passwords ---------- - -The :attr:`~django.contrib.auth.models.User.password` attribute of a -:class:`~django.contrib.auth.models.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. - -.. versionadded:: 1.0 - Support for the ``crypt`` module is new in Django 1.0. - -For example:: - - sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4 - -The :meth:`~django.contrib.auth.models.User.set_password` and -:meth:`~django.contrib.auth.models.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 -:meth:`~django.contrib.auth.models.User.check_password()` works correctly for -a given user. - -Anonymous users ---------------- - -.. class:: models.AnonymousUser - - :class:`django.contrib.auth.models.AnonymousUser` is a class that - implements the :class:`django.contrib.auth.models.User` interface, with - these differences: - - * :attr:`~django.contrib.auth.models.User.id` is always ``None``. - * :attr:`~django.contrib.auth.models.User.is_staff` and - :attr:`~django.contrib.auth.models.User.is_superuser` are always - ``False``. - * :attr:`~django.contrib.auth.models.User.is_active` is always ``False``. - * :attr:`~django.contrib.auth.models.User.groups` and - :attr:`~django.contrib.auth.models.User.user_permissions` are always - empty. - * :meth:`~django.contrib.auth.models.User.is_anonymous()` returns ``True`` - instead of ``False``. - * :meth:`~django.contrib.auth.models.User.is_authenticated()` returns - ``False`` instead of ``True``. - * :meth:`~django.contrib.auth.models.User.set_password()`, - :meth:`~django.contrib.auth.models.User.check_password()`, - :meth:`~django.contrib.auth.models.User.save()`, - :meth:`~django.contrib.auth.models.User.delete()`, - :meth:`~django.contrib.auth.models.User.set_groups()` and - :meth:`~django.contrib.auth.models.User.set_permissions()` raise - :exc:`NotImplementedError`. - -In practice, you probably won't need to use -:class:`~django.contrib.auth.models.AnonymousUser` objects on your own, but -they're used by Web requests, as explained in the next section. - -.. _topics-auth-creating-superusers: - -Creating superusers -------------------- - -.. versionadded:: 1.0 - The ``manage.py createsuperuser`` command is new. - -:djadmin:`manage.py syncdb <syncdb>` prompts you to create a superuser the -first time you run it after adding ``'django.contrib.auth'`` to your -:setting:`INSTALLED_APPS`. If you need to create a superuser at a later date, -you can use a command line utility:: - - 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 :djadminopt:`--username` or the -:djadminopt:`--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 :file:`/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. - -.. _auth-profiles: - -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 -:class:`~django.db.models.Field.OneToOneField` from your model to the -:class:`~django.contrib.auth.models.User` model. This will ensure only -one instance of your model can be created for each -:class:`~django.contrib.auth.models.User`. - -To indicate that this model is the user profile model for a given site, fill in -the setting :setting:`AUTH_PROFILE_MODULE` with a string consisting of the -following items, separated by a dot: - -1. The name of the application (case sensitive) in which the user - profile model is defined (in other words, the - name which was passed to :djadmin:`manage.py startapp <startapp>` to create - the application). - -2. The name of the model (not case sensitive) 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 -:class:`~django.contrib.auth.models.User` object will have a method -- -:class:`~django.contrib.auth.models.User.get_profile()` -- which returns the -instance of the user profile model associated with that -:class:`~django.contrib.auth.models.User`. - -The method :class:`~django.contrib.auth.models.User.get_profile()` -does not create the profile, if it does not exist. You need to -register a handler for the signal -:attr:`django.db.models.signals.post_save` on the User model, and, in -the handler, if created=True, create the associated user profile. - -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 -:class:`request objects <django.http.HttpRequest>`. - -First, install the -:class:`~django.contrib.sessions.middleware.SessionMiddleware` and -:class:`~django.contrib.auth.middleware.AuthenticationMiddleware` -middlewares by adding them to your :setting:`MIDDLEWARE_CLASSES` setting. See -the :doc:`session documentation </topics/http/sessions>` for more information. - -Once you have those middlewares installed, you'll be able to access -:attr:`request.user <django.http.HttpRequest.user>` in views. -:attr:`request.user <django.http.HttpRequest.user>` will give you a -:class:`~django.contrib.auth.models.User` object representing the currently -logged-in user. If a user isn't currently logged in, -:attr:`request.user <django.http.HttpRequest.user>` will be set to an instance -of :class:`~django.contrib.auth.models.AnonymousUser` (see the previous -section). You can tell them apart with -:meth:`~django.contrib.auth.models.User.is_authenticated()`, like so:: - - if request.user.is_authenticated(): - # Do something for authenticated users. - else: - # Do something for anonymous users. - -.. _how-to-log-a-user-in: - -How to log a user in --------------------- - -Django provides two functions in :mod:`django.contrib.auth`: -:func:`~django.contrib.auth.authenticate()` and -:func:`~django.contrib.auth.login()`. - -.. function:: authenticate() - - To authenticate a given username and password, use - :func:`~django.contrib.auth.authenticate()`. It takes two keyword - arguments, ``username`` and ``password``, and it returns a - :class:`~django.contrib.auth.models.User` object if the password is valid - for the given username. If the password is invalid, - :func:`~django.contrib.auth.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." - -.. function:: login() - - To log a user in, in a view, use :func:`~django.contrib.auth.login()`. It - takes an :class:`~django.http.HttpRequest` object and a - :class:`~django.contrib.auth.models.User` object. - :func:`~django.contrib.auth.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 - :func:`~django.contrib.auth.authenticate()` and - :func:`~django.contrib.auth.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 - :func:`~django.contrib.auth.authenticate()` before you call - :func:`~django.contrib.auth.login()`. - :func:`~django.contrib.auth.authenticate()` - sets an attribute on the :class:`~django.contrib.auth.models.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 ------------------------------------ - -.. function:: check_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 :func:`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 ---------------------- - -.. function:: logout() - - To log out a user who has been logged in via - :func:`django.contrib.auth.login()`, use - :func:`django.contrib.auth.logout()` within your view. It takes an - :class:`~django.http.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 :func:`~django.contrib.auth.logout()` doesn't throw any errors if - the user wasn't logged in. - - .. versionchanged:: 1.0 - Calling ``logout()`` now cleans session data. - - When you call :func:`~django.contrib.auth.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 - :func:`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 -:meth:`request.user.is_authenticated() -<django.contrib.auth.models.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 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. function:: decorators.login_required([redirect_field_name=REDIRECT_FIELD_NAME]) - - As a shortcut, you can use the convenient - :func:`~django.contrib.auth.decorators.login_required` decorator:: - - from django.contrib.auth.decorators import login_required - - @login_required - def my_view(request): - ... - - :func:`~django.contrib.auth.decorators.login_required` does the following: - - * If the user isn't logged in, redirect to - :setting:`settings.LOGIN_URL <LOGIN_URL>`, passing the current absolute - path in the query string. 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. - - By default, the path that the user should be redirected to upon - successful authentication is stored in a query string parameter called - ``"next"``. If you would prefer to use a different name for this parameter, - :func:`~django.contrib.auth.decorators.login_required` takes an - optional ``redirect_field_name`` parameter:: - - from django.contrib.auth.decorators import login_required - - @login_required(redirect_field_name='my_redirect_field') - def my_view(request): - ... - - If you provide a value to ``redirect_field_name``, you will most - likely need to customize your login template as well, since the template - context variable which stores the redirect path will use the value of - ``redirect_field_name`` as it's key rather than ``"next"`` (the default). - - Note that you'll need to map the appropriate Django view to - :setting:`settings.LOGIN_URL <LOGIN_URL>`. For example, using the defaults, - add the following line to your URLconf:: - - (r'^accounts/login/$', 'django.contrib.auth.views.login'), - -.. function:: views.login(request, [template_name, redirect_field_name, authentication_form]) - - 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 - :setting:`settings.LOGIN_REDIRECT_URL <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 four - template context variables: - - * ``form``: A :class:`~django.forms.Form` object representing the login - form. See the :doc:`forms documentation </topics/forms/index>` for - more on ``Form`` objects. - - * ``next``: The URL to redirect to after successful login. This may - contain a query string, too. - - * ``site``: The current :class:`~django.contrib.sites.models.Site`, - according to the :setting:`SITE_ID` setting. If you don't have the - site framework installed, this will be set to an instance of - :class:`~django.contrib.sites.models.RequestSite`, which derives the - site name and domain from the current - :class:`~django.http.HttpRequest`. - - * ``site_name``: An alias for ``site.name``. If you don't have the site - framework installed, this will be set to the value of - :attr:`request.META['SERVER_NAME'] <django.http.HttpRequest.META>`. - For more on sites, see :doc:`/ref/contrib/sites`. - - If you'd prefer not to call the template :file:`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 - :file:`myapp/login.html` instead:: - - (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}), - - You can also specify the name of the ``GET`` field which contains the URL - to redirect to after login by passing ``redirect_field_name`` to the view. - By default, the field is called ``next``. - - Here's a sample :file:`registration/login.html` template you can use as a - starting point. It assumes you have a :file:`base.html` template that - defines a ``content`` block: - - .. code-block:: html+django - - {% extends "base.html" %} - - {% block content %} - - {% if form.errors %} - <p>Your username and password didn't match. Please try again.</p> - {% endif %} - - <form method="post" action="{% url django.contrib.auth.views.login %}"> - {% csrf_token %} - <table> - <tr> - <td>{{ form.username.label_tag }}</td> - <td>{{ form.username }}</td> - </tr> - <tr> - <td>{{ form.password.label_tag }}</td> - <td>{{ form.password }}</td> - </tr> - </table> - - <input type="submit" value="login" /> - <input type="hidden" name="next" value="{{ next }}" /> - </form> - - {% endblock %} - - .. versionadded:: 1.2 - - If you are using alternate authentication (see - :ref:`authentication-backends`) you can pass a custom authentication form - to the login view via the ``authentication_form`` parameter. This form must - accept a ``request`` keyword argument in its ``__init__`` method, and - provide a ``get_user`` method which returns the authenticated user object - (this method is only ever called after successful form validation). - - .. _forms documentation: ../forms/ - .. _site framework docs: ../sites/ - -Other built-in views --------------------- - -In addition to the :func:`~views.login` view, the authentication system -includes a few other useful built-in views located in -:mod:`django.contrib.auth.views`: - -.. function:: views.logout(request, [next_page, template_name, redirect_field_name]) - - Logs a user out. - - **Optional arguments:** - - * ``next_page``: The URL to redirect to after logout. - - * ``template_name``: The full name of a template to display after - logging the user out. This will default to - :file:`registration/logged_out.html` if no argument is supplied. - - * ``redirect_field_name``: The name of a ``GET`` field containing the - URL to redirect to after log out. Overrides ``next_page`` if the given - ``GET`` parameter is passed. - - **Template context:** - - * ``title``: The string "Logged out", localized. - -.. function:: views.logout_then_login(request[, login_url]) - - 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 :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied. - -.. function:: views.password_change(request[, template_name, post_change_redirect, password_change_form]) - - 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 - :file:`registration/password_change_form.html` if not supplied. - - * ``post_change_redirect``: The URL to redirect to after a successful - password change. - - * .. versionadded:: 1.2 - - ``password_change_form``: A custom "change password" form which must - accept a ``user`` keyword argument. The form is responsible for - actually changing the user's password. - - - **Template context:** - - * ``form``: The password change form. - -.. function:: views.password_change_done(request[, template_name]) - - 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 :file:`registration/password_change_done.html` if not - supplied. - -.. function:: views.password_reset(request[, is_admin_site, template_name, email_template_name, password_reset_form, token_generator, post_reset_redirect]) - - Allows a user to reset their password by generating a one-time use link - that can be used to reset the password, and sending that link to the - user's registered e-mail address. - - **Optional arguments:** - - * ``template_name``: The full name of a template to use for - displaying the password reset form. This will default to - :file:`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 - :file:`registration/password_reset_email.html` if not supplied. - - * ``password_reset_form``: Form that will be used to set the password. - Defaults to :class:`~django.contrib.auth.forms.PasswordResetForm`. - - * ``token_generator``: Instance of the class to check the password. This - will default to ``default_token_generator``, it's an instance of - ``django.contrib.auth.tokens.PasswordResetTokenGenerator``. - - * ``post_reset_redirect``: The URL to redirect to after a successful - password change. - - **Template context:** - - * ``form``: The form for resetting the user's password. - -.. function:: views.password_reset_done(request[, template_name]) - - 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 :file:`registration/password_reset_done.html` if not - supplied. - -.. function:: views.redirect_to_login(next[, login_url, redirect_field_name]) - - 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 :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied. - - * ``redirect_field_name``: The name of a ``GET`` field containing the - URL to redirect to after log out. Overrides ``next`` if the given - ``GET`` parameter is passed. - -.. function:: password_reset_confirm(request[, uidb36, token, template_name, token_generator, set_password_form, post_reset_redirect]) - - Presents a form for entering a new password. - - **Optional arguments:** - - * ``uidb36``: The user's id encoded in base 36. This will default to - ``None``. - * ``token``: Token to check that the password is valid. This will default to ``None``. - * ``template_name``: The full name of a template to display the confirm - password view. Default value is :file:`registration/password_reset_confirm.html`. - * ``token_generator``: Instance of the class to check the password. This - will default to ``default_token_generator``, it's an instance of - ``django.contrib.auth.tokens.PasswordResetTokenGenerator``. - * ``set_password_form``: Form that will be used to set the password. - This will default to ``SetPasswordForm``. - * ``post_reset_redirect``: URL to redirect after the password reset - done. This will default to ``None``. - -.. function:: password_reset_complete(request[,template_name]) - - Presents a view which informs the user that the password has been - successfully changed. - - **Optional arguments:** - - * ``template_name``: The full name of a template to display the view. - This will default to :file:`registration/password_reset_complete.html`. - -Built-in forms --------------- - -.. module:: django.contrib.auth.forms - -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 located in :mod:`django.contrib.auth.forms`: - -.. class:: AdminPasswordChangeForm - - A form used in the admin interface to change a user's password. - -.. class:: AuthenticationForm - - A form for logging a user in. - -.. class:: PasswordChangeForm - - A form for allowing a user to change their password. - -.. class:: PasswordResetForm - - A form for generating and e-mailing a one-time use link to reset a - user's password. - -.. class:: SetPasswordForm - - A form that lets a user change his/her password without entering the old - password. - -.. class:: UserChangeForm - - A form used in the admin interface to change a user's information and - permissions. - -.. class:: UserCreationForm - - A form for creating a new user. - -Limiting access to logged-in users that pass a test ---------------------------------------------------- - -.. currentmodule:: django.contrib.auth - -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 :attr:`request.user -<django.http.HttpRequest.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.has_perm('polls.can_vote'): - return HttpResponse("You can't vote in this poll.") - # ... - -.. function:: decorators.user_passes_test() - - As a shortcut, you can use the convenient ``user_passes_test`` decorator:: - - from django.contrib.auth.decorators import user_passes_test - - @user_passes_test(lambda u: u.has_perm('polls.can_vote')) - def my_view(request): - ... - - 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 :func:`~django.contrib.auth.decorators.permission_required()` - decorator, described later in this document. - - :func:`~django.contrib.auth.decorators.user_passes_test` takes a required - argument: a callable that takes a - :class:`~django.contrib.auth.models.User` object and returns ``True`` if - the user is allowed to view the page. Note that - :func:`~django.contrib.auth.decorators.user_passes_test` does not - automatically check that the :class:`~django.contrib.auth.models.User` is - not anonymous. - - :func:`~django.contrib.auth.decorators.user_passes_test()` takes an - optional ``login_url`` argument, which lets you specify the URL for your - login page (:setting:`settings.LOGIN_URL <LOGIN_URL>` by default). - - For example:: - - 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 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. function:: decorators.permission_required() - - 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 - :func:`~django.contrib.auth.decorators.permission_required()` decorator. - Using this decorator, the earlier example can be written as:: - - from django.contrib.auth.decorators import permission_required - - @permission_required('polls.can_vote') - def my_view(request): - ... - - As for the :meth:`User.has_perm` method, permission names take the form - ``"<app label>.<permission codename>"`` (i.e. ``polls.can_vote`` for a - permission on a model in the ``polls`` application). - - Note that :func:`~django.contrib.auth.decorators.permission_required()` - also takes an optional ``login_url`` parameter. Example:: - - from django.contrib.auth.decorators import permission_required - - @permission_required('polls.can_vote', login_url='/loginpage/') - def my_view(request): - ... - - As in the :func:`~decorators.login_required` decorator, ``login_url`` - defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>`. - -Limiting access to generic views --------------------------------- - -To limit access to a :doc:`generic view </ref/generic-views>`, 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) - -.. _permissions: - -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 :setting:`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 :djadmin:`manage.py syncdb -<syncdb>`; the first time you run ``syncdb`` after adding -``django.contrib.auth`` to :setting:`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 :djadmin:`manage.py syncdb -<syncdb>`. - -Assuming you have an application with an -:attr:`~django.db.models.Options.app_label` ``foo`` and a model named ``Bar``, -to test for basic permissions you should use: - - * add: ``user.has_perm('foo.add_bar')`` - * change: ``user.has_perm('foo.change_bar')`` - * delete: ``user.has_perm('foo.delete_bar')`` - -.. _custom-permissions: - -Custom permissions ------------------- - -To create custom permissions for a given model object, use the ``permissions`` -:ref:`model Meta attribute <meta-options>`. - -This example Task model creates three custom permissions, i.e., actions users -can or cannot do with Task instances, specific to your appication:: - - class Task(models.Model): - ... - class Meta: - permissions = ( - ("can_view", "Can see available tasks"), - ("can_change_status", "Can change the status of tasks"), - ("can_close", "Can remove a task by setting its status as closed"), - ) - -The only thing this does is create those extra permissions when you run -:djadmin:`manage.py syncdb <syncdb>`. Your code is in charge of checking the -value of these permissions when an user is trying to access the functionality -provided by the application (viewing tasks, changing the status of tasks, -closing tasks.) - -API reference -------------- - -.. class:: models.Permission - - 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 -~~~~~~ - -:class:`~django.contrib.auth.models.Permission` objects have the following -fields: - -.. attribute:: models.Permission.name - - Required. 50 characters or fewer. Example: ``'Can vote'``. - -.. attribute:: models.Permission.content_type - - Required. A reference to the ``django_content_type`` database table, which - contains a record for each installed Django model. - -.. attribute:: models.Permission.codename - - Required. 100 characters or fewer. Example: ``'can_vote'``. - -Methods -~~~~~~~ - -:class:`~django.contrib.auth.models.Permission` objects have the standard -data-access methods like any other :doc:`Django model </ref/models/instances>`. - -Authentication data in templates -================================ - -The currently logged-in user and his/her permissions are made available in the -:doc:`template context </ref/templates/api>` when you use -:class:`~django.template.context.RequestContext`. - -.. admonition:: Technicality - - Technically, these variables are only made available in the template context - if you use :class:`~django.template.context.RequestContext` *and* your - :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting contains - ``"django.contrib.auth.context_processors.auth"``, which is default. For - more, see the :ref:`RequestContext docs <subclassing-context-requestcontext>`. - -Users ------ - -When rendering a template :class:`~django.template.context.RequestContext`, the -currently logged-in user, either a :class:`~django.contrib.auth.models.User` -instance or an :class:`~django.contrib.auth.models.AnonymousUser` instance, is -stored in the template variable ``{{ user }}``: - -.. code-block:: html+django - - {% if user.is_authenticated %} - <p>Welcome, {{ user.username }}. Thanks for logging in.</p> - {% else %} - <p>Welcome, new user. Please log in.</p> - {% endif %} - -This template context variable is not available if a ``RequestContext`` is not -being used. - -Permissions ------------ - -The currently logged-in user's permissions are stored in the template variable -``{{ perms }}``. This is an instance of -:class:`django.core.context_processors.PermWrapper`, which is a -template-friendly proxy of permissions. - -In the ``{{ perms }}`` object, single-attribute lookup is a proxy to -:meth:`User.has_module_perms <django.contrib.auth.models.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 -:meth:`User.has_perm <django.contrib.auth.models.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: - -.. code-block:: html+django - - {% if perms.foo %} - <p>You have permission to do something in the foo app.</p> - {% if perms.foo.can_vote %} - <p>You can vote!</p> - {% endif %} - {% if perms.foo.can_drive %} - <p>You can drive!</p> - {% endif %} - {% else %} - <p>You don't have permission to do anything in the foo app.</p> - {% endif %} - -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 -======== - -.. deprecated:: 1.2 - This functionality will be removed in Django 1.4. You should use the - :doc:`messages framework </ref/contrib/messages>` for all new projects and - begin to update your existing code immediately. - -The message system is a lightweight way to queue messages for given users. - -A message is associated with a :class:`~django.contrib.auth.models.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: - -.. method:: models.User.message_set.create(message) - - To create a new message, use - ``user_obj.message_set.create(message='message_text')``. - - To retrieve/delete messages, use - :meth:`user_obj.get_and_delete_messages() <django.contrib.auth.models.User.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 :class:`~django.template.context.RequestContext`, the currently -logged-in user and his/her messages are made available in the -:doc:`template context </ref/templates/api>` as the template variable -``{{ messages }}``. Here's an example of template code that displays messages: - -.. code-block:: html+django - - {% if messages %} - <ul> - {% for message in messages %} - <li>{{ message }}</li> - {% endfor %} - </ul> - {% endif %} - -.. versionchanged:: 1.2 - The ``messages`` template variable uses a backwards compatible method in the - :doc:`messages framework </ref/contrib/messages>` to retrieve messages from - both the user ``Message`` model and from the new framework. Unlike in - previous revisions, the messages will not be erased unless they are actually - displayed. - -Finally, note that this messages framework only works with users in the user -database. To send messages to anonymous users, use the -:doc:`messages framework </ref/contrib/messages>`. - -.. _authentication-backends: - -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 other authentication sources. You can override Django's default -database-based scheme, or you can use the default system in tandem with other -systems. - -See the :doc:`authentication backend reference </ref/authbackends>` -for information on the authentication backends included with Django. - -Specifying authentication backends ----------------------------------- - -Behind the scenes, Django maintains a list of "authentication backends" that it -checks for authentication. When somebody calls -:func:`django.contrib.auth.authenticate()` -- as described in :ref:`How to log -a user 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 -:setting:`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, :setting:`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 :setting:`AUTHENTICATION_BACKENDS` matters, so if the same -username and password is valid in multiple backends, Django will stop -processing at the first positive match. - -.. note:: - - Once a user has authenticated, Django stores which backend was used to - authenticate the user in the user's session, and re-uses the same backend - for subsequent authentication attempts for that user. This effectively means - that authentication sources are cached, so if you change - :setting:`AUTHENTICATION_BACKENDS`, you'll need to clear out session data if - you need to force users to re-authenticate using different methods. A simple - way to do that is simply to execute ``Session.objects.all().delete()``. - -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 -(:meth:`~django.contrib.auth.models.User.get_group_permissions()`, -:meth:`~django.contrib.auth.models.User.get_all_permissions()`, -:meth:`~django.contrib.auth.models.User.has_perm()`, and -:meth:`~django.contrib.auth.models.User.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 -:class:`django.contrib.auth.models.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 - -Authorization for anonymous users -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionchanged:: 1.2 - -An anonymous user is one that is not authenticated i.e. they have provided no -valid authentication details. However, that does not necessarily mean they are -not authorized to do anything. At the most basic level, most Web sites -authorize anonymous users to browse most of the site, and many allow anonymous -posting of comments etc. - -Django's permission framework does not have a place to store permissions for -anonymous users. However, it has a foundation that allows custom authentication -backends to specify authorization for anonymous users. This is especially useful -for the authors of re-usable apps, who can delegate all questions of authorization -to the auth backend, rather than needing settings, for example, to control -anonymous access. - -To enable this in your own backend, you must set the class attribute -``supports_anonymous_user`` to ``True``. (This precaution is to maintain -compatibility with backends that assume that all user objects are actual -instances of the :class:`django.contrib.auth.models.User` class). With this -in place, :class:`django.contrib.auth.models.AnonymousUser` will delegate all -the relevant permission methods to the authentication backends. - -A nonexistent ``supports_anonymous_user`` attribute will raise a hidden -``PendingDeprecationWarning`` if used in Django 1.2. In Django 1.3, this -warning will be upgraded to a ``DeprecationWarning``, which will be displayed -loudly. Additionally ``supports_anonymous_user`` will be set to ``False``. -Django 1.4 will assume that every backend supports anonymous users being -passed to the authorization methods. - -Handling object permissions ---------------------------- - -Django's permission framework has a foundation for object permissions, though -there is no implementation for it in the core. That means that checking for -object permissions will always return ``False`` or an empty list (depending on -the check performed). - -To enable object permissions in your own -:doc:`authentication backend </ref/authbackends>` you'll just have -to allow passing an ``obj`` parameter to the permission methods and set the -``supports_object_permissions`` class attribute to ``True``. - -A nonexistent ``supports_object_permissions`` will raise a hidden -``PendingDeprecationWarning`` if used in Django 1.2. In Django 1.3, this -warning will be upgraded to a ``DeprecationWarning``, which will be displayed -loudly. Additionally ``supports_object_permissions`` will be set to ``False``. -Django 1.4 will assume that every backend supports object permissions and -won't check for the existence of ``supports_object_permissions``, which -means not supporting ``obj`` as a parameter will raise a ``TypeError``. diff --git a/parts/django/docs/topics/cache.txt b/parts/django/docs/topics/cache.txt deleted file mode 100644 index c18b811..0000000 --- a/parts/django/docs/topics/cache.txt +++ /dev/null @@ -1,917 +0,0 @@ -======================== -Django's cache framework -======================== - -A fundamental trade-off in dynamic Web sites is, well, they're dynamic. Each -time a user requests a page, the Web server makes all sorts of calculations -- -from database queries to template rendering to business logic -- to create the -page that your site's visitor sees. This is a lot more expensive, from a -processing-overhead perspective, than your standard -read-a-file-off-the-filesystem server arrangement. - -For most Web applications, this overhead isn't a big deal. Most Web -applications aren't washingtonpost.com or slashdot.org; they're simply small- -to medium-sized sites with so-so traffic. But for medium- to high-traffic -sites, it's essential to cut as much overhead as possible. - -That's where caching comes in. - -To cache something is to save the result of an expensive calculation so that -you don't have to perform the calculation next time. Here's some pseudocode -explaining how this would work for a dynamically generated Web page:: - - given a URL, try finding that page in the cache - if the page is in the cache: - return the cached page - else: - generate the page - save the generated page in the cache (for next time) - return the generated page - -Django comes with a robust cache system that lets you save dynamic pages so -they don't have to be calculated for each request. For convenience, Django -offers different levels of cache granularity: You can cache the output of -specific views, you can cache only the pieces that are difficult to produce, or -you can cache your entire site. - -Django also works well with "upstream" caches, such as `Squid -<http://www.squid-cache.org>`_ and browser-based caches. These are the types of -caches that you don't directly control but to which you can provide hints (via -HTTP headers) about which parts of your site should be cached, and how. - -Setting up the cache -==================== - -The cache system requires a small amount of setup. Namely, you have to tell it -where your cached data should live -- whether in a database, on the filesystem -or directly in memory. This is an important decision that affects your cache's -performance; yes, some cache types are faster than others. - -Your cache preference goes in the ``CACHE_BACKEND`` setting in your settings -file. Here's an explanation of all available values for ``CACHE_BACKEND``. - -Memcached ---------- - -By far the fastest, most efficient type of cache available to Django, Memcached -is an entirely memory-based cache framework originally developed to handle high -loads at LiveJournal.com and subsequently open-sourced by Danga Interactive. -It's used by sites such as Facebook and Wikipedia to reduce database access and -dramatically increase site performance. - -Memcached is available for free at http://memcached.org/. It runs as a -daemon and is allotted a specified amount of RAM. All it does is provide a -fast interface for adding, retrieving and deleting arbitrary data in the cache. -All data is stored directly in memory, so there's no overhead of database or -filesystem usage. - -After installing Memcached itself, you'll need to install -``python-memcached``, which provides Python bindings to Memcached. -This is available at ftp://ftp.tummy.com/pub/python-memcached/ - -.. versionchanged:: 1.2 - In Django 1.0 and 1.1, you could also use ``cmemcache`` as a binding. - However, support for this library was deprecated in 1.2 due to - a lack of maintenance on the ``cmemcache`` library itself. Support for - ``cmemcache`` will be removed completely in Django 1.4. - -To use Memcached with Django, set ``CACHE_BACKEND`` to -``memcached://ip:port/``, where ``ip`` is the IP address of the Memcached -daemon and ``port`` is the port on which Memcached is running. - -In this example, Memcached is running on localhost (127.0.0.1) port 11211:: - - CACHE_BACKEND = 'memcached://127.0.0.1:11211/' - -One excellent feature of Memcached is its ability to share cache over multiple -servers. This means you can run Memcached daemons on multiple machines, and the -program will treat the group of machines as a *single* cache, without the need -to duplicate cache values on each machine. To take advantage of this feature, -include all server addresses in ``CACHE_BACKEND``, separated by semicolons. - -In this example, the cache is shared over Memcached instances running on IP -address 172.19.26.240 and 172.19.26.242, both on port 11211:: - - CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/' - -In the following example, the cache is shared over Memcached instances running -on the IP addresses 172.19.26.240 (port 11211), 172.19.26.242 (port 11212), and -172.19.26.244 (port 11213):: - - CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.244:11213/' - -A final point about Memcached is that memory-based caching has one -disadvantage: Because the cached data is stored in memory, the data will be -lost if your server crashes. Clearly, memory isn't intended for permanent data -storage, so don't rely on memory-based caching as your only data storage. -Without a doubt, *none* of the Django caching backends should be used for -permanent storage -- they're all intended to be solutions for caching, not -storage -- but we point this out here because memory-based caching is -particularly temporary. - -Database caching ----------------- - -To use a database table as your cache backend, first create a cache table in -your database by running this command:: - - python manage.py createcachetable [cache_table_name] - -...where ``[cache_table_name]`` is the name of the database table to create. -(This name can be whatever you want, as long as it's a valid table name that's -not already being used in your database.) This command creates a single table -in your database that is in the proper format that Django's database-cache -system expects. - -Once you've created that database table, set your ``CACHE_BACKEND`` setting to -``"db://tablename"``, where ``tablename`` is the name of the database table. -In this example, the cache table's name is ``my_cache_table``:: - - CACHE_BACKEND = 'db://my_cache_table' - -The database caching backend uses the same database as specified in your -settings file. You can't use a different database backend for your cache table. - -Database caching works best if you've got a fast, well-indexed database server. - -Database caching and multiple databases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you use database caching with multiple databases, you'll also need -to set up routing instructions for your database cache table. For the -purposes of routing, the database cache table appears as a model named -``CacheEntry``, in an application named ``django_cache``. This model -won't appear in the models cache, but the model details can be used -for routing purposes. - -For example, the following router would direct all cache read -operations to ``cache_slave``, and all write operations to -``cache_master``. The cache table will only be synchronized onto -``cache_master``:: - - class CacheRouter(object): - """A router to control all database cache operations""" - - def db_for_read(self, model, **hints): - "All cache read operations go to the slave" - if model._meta.app_label in ('django_cache',): - return 'cache_slave' - return None - - def db_for_write(self, model, **hints): - "All cache write operations go to master" - if model._meta.app_label in ('django_cache',): - return 'cache_master' - return None - - def allow_syncdb(self, db, model): - "Only synchronize the cache model on master" - if model._meta.app_label in ('django_cache',): - return db == 'cache_master' - return None - -If you don't specify routing directions for the database cache model, -the cache backend will use the ``default`` database. - -Of course, if you don't use the database cache backend, you don't need -to worry about providing routing instructions for the database cache -model. - -Filesystem caching ------------------- - -To store cached items on a filesystem, use the ``"file://"`` cache type for -``CACHE_BACKEND``. For example, to store cached data in ``/var/tmp/django_cache``, -use this setting:: - - CACHE_BACKEND = 'file:///var/tmp/django_cache' - -Note that there are three forward slashes toward the beginning of that example. -The first two are for ``file://``, and the third is the first character of the -directory path, ``/var/tmp/django_cache``. If you're on Windows, put the -drive letter after the ``file://``, like this:: - - file://c:/foo/bar - -The directory path should be absolute -- that is, it should start at the root -of your filesystem. It doesn't matter whether you put a slash at the end of the -setting. - -Make sure the directory pointed-to by this setting exists and is readable and -writable by the system user under which your Web server runs. Continuing the -above example, if your server runs as the user ``apache``, make sure the -directory ``/var/tmp/django_cache`` exists and is readable and writable by the -user ``apache``. - -Each cache value will be stored as a separate file whose contents are the -cache data saved in a serialized ("pickled") format, using Python's ``pickle`` -module. Each file's name is the cache key, escaped for safe filesystem use. - -Local-memory caching --------------------- - -If you want the speed advantages of in-memory caching but don't have the -capability of running Memcached, consider the local-memory cache backend. This -cache is multi-process and thread-safe. To use it, set ``CACHE_BACKEND`` to -``"locmem://"``. For example:: - - CACHE_BACKEND = 'locmem://' - -Note that each process will have its own private cache instance, which means no -cross-process caching is possible. This obviously also means the local memory -cache isn't particularly memory-efficient, so it's probably not a good choice -for production environments. It's nice for development. - -Dummy caching (for development) -------------------------------- - -Finally, Django comes with a "dummy" cache that doesn't actually cache -- it -just implements the cache interface without doing anything. - -This is useful if you have a production site that uses heavy-duty caching in -various places but a development/test environment where you don't want to cache -and don't want to have to change your code to special-case the latter. To -activate dummy caching, set ``CACHE_BACKEND`` like so:: - - CACHE_BACKEND = 'dummy://' - -Using a custom cache backend ----------------------------- - -.. versionadded:: 1.0 - -While Django includes support for a number of cache backends out-of-the-box, -sometimes you might want to use a customized cache backend. To use an external -cache backend with Django, use a Python import path as the scheme portion (the -part before the initial colon) of the ``CACHE_BACKEND`` URI, like so:: - - CACHE_BACKEND = 'path.to.backend://' - -If you're building your own backend, you can use the standard cache backends -as reference implementations. You'll find the code in the -``django/core/cache/backends/`` directory of the Django source. - -Note: Without a really compelling reason, such as a host that doesn't support -them, you should stick to the cache backends included with Django. They've -been well-tested and are easy to use. - -CACHE_BACKEND arguments ------------------------ - -Each cache backend may take arguments. They're given in query-string style on -the ``CACHE_BACKEND`` setting. Valid arguments are as follows: - - * ``timeout``: The default timeout, in seconds, to use for the cache. - This argument defaults to 300 seconds (5 minutes). - - * ``max_entries``: For the ``locmem``, ``filesystem`` and ``database`` - backends, the maximum number of entries allowed in the cache before old - values are deleted. This argument defaults to 300. - - * ``cull_frequency``: The fraction of entries that are culled when - ``max_entries`` is reached. The actual ratio is ``1/cull_frequency``, so - set ``cull_frequency=2`` to cull half of the entries when ``max_entries`` - is reached. - - A value of ``0`` for ``cull_frequency`` means that the entire cache will - be dumped when ``max_entries`` is reached. This makes culling *much* - faster at the expense of more cache misses. - -In this example, ``timeout`` is set to ``60``:: - - CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60" - -In this example, ``timeout`` is ``30`` and ``max_entries`` is ``400``:: - - CACHE_BACKEND = "locmem://?timeout=30&max_entries=400" - -Invalid arguments are silently ignored, as are invalid values of known -arguments. - -The per-site cache -================== - -.. versionchanged:: 1.0 - (previous versions of Django only provided a single ``CacheMiddleware`` instead - of the two pieces described below). - -Once the cache is set up, the simplest way to use caching is to cache your -entire site. You'll need to add -``'django.middleware.cache.UpdateCacheMiddleware'`` and -``'django.middleware.cache.FetchFromCacheMiddleware'`` to your -``MIDDLEWARE_CLASSES`` setting, as in this example:: - - MIDDLEWARE_CLASSES = ( - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', - ) - -.. note:: - - No, that's not a typo: the "update" middleware must be first in the list, - and the "fetch" middleware must be last. The details are a bit obscure, but - see `Order of MIDDLEWARE_CLASSES`_ below if you'd like the full story. - -Then, add the following required settings to your Django settings file: - -* ``CACHE_MIDDLEWARE_SECONDS`` -- The number of seconds each page should be - cached. -* ``CACHE_MIDDLEWARE_KEY_PREFIX`` -- If the cache is shared across multiple - sites using the same Django installation, set this to the name of the site, - or some other string that is unique to this Django instance, to prevent key - collisions. Use an empty string if you don't care. - -The cache middleware caches every page that doesn't have GET or POST -parameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is -``True``, only anonymous requests (i.e., not those made by a logged-in user) -will be cached. This is a simple and effective way of disabling caching for any -user-specific pages (include Django's admin interface). Note that if you use -``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated -``AuthenticationMiddleware``. - -Additionally, the cache middleware automatically sets a few headers in each -:class:`~django.http.HttpResponse`: - - * Sets the ``Last-Modified`` header to the current date/time when a fresh - (uncached) version of the page is requested. - - * Sets the ``Expires`` header to the current date/time plus the defined - ``CACHE_MIDDLEWARE_SECONDS``. - - * Sets the ``Cache-Control`` header to give a max age for the page -- - again, from the ``CACHE_MIDDLEWARE_SECONDS`` setting. - -See :doc:`/topics/http/middleware` for more on middleware. - -.. versionadded:: 1.0 - -If a view sets its own cache expiry time (i.e. it has a ``max-age`` section in -its ``Cache-Control`` header) then the page will be cached until the expiry -time, rather than ``CACHE_MIDDLEWARE_SECONDS``. Using the decorators in -``django.views.decorators.cache`` you can easily set a view's expiry time -(using the ``cache_control`` decorator) or disable caching for a view (using -the ``never_cache`` decorator). See the `using other headers`__ section for -more on these decorators. - -.. _i18n-cache-key: - -.. versionadded:: 1.2 - -If :setting:`USE_I18N` is set to ``True`` then the generated cache key will -include the name of the active :term:`language<language code>`. -This allows you to easily cache multilingual sites without having to create -the cache key yourself. - -See :doc:`/topics/i18n/deployment` for more on how Django discovers the active -language. - -__ `Controlling cache: Using other headers`_ - -The per-view cache -================== - -A more granular way to use the caching framework is by caching the output of -individual views. ``django.views.decorators.cache`` defines a ``cache_page`` -decorator that will automatically cache the view's response for you. It's easy -to use:: - - from django.views.decorators.cache import cache_page - - @cache_page(60 * 15) - def my_view(request): - ... - -``cache_page`` takes a single argument: the cache timeout, in seconds. In the -above example, the result of the ``my_view()`` view will be cached for 15 -minutes. (Note that we've written it as ``60 * 15`` for the purpose of -readability. ``60 * 15`` will be evaluated to ``900`` -- that is, 15 minutes -multiplied by 60 seconds per minute.) - -The per-view cache, like the per-site cache, is keyed off of the URL. If -multiple URLs point at the same view, each URL will be cached separately. -Continuing the ``my_view`` example, if your URLconf looks like this:: - - urlpatterns = ('', - (r'^foo/(\d{1,2})/$', my_view), - ) - -then requests to ``/foo/1/`` and ``/foo/23/`` will be cached separately, as -you may expect. But once a particular URL (e.g., ``/foo/23/``) has been -requested, subsequent requests to that URL will use the cache. - -``cache_page`` can also take an optional keyword argument, ``key_prefix``, which -works in the same way as the ``CACHE_MIDDLEWARE_KEY_PREFIX`` setting for the -middleware. It can be used like this:: - - @cache_page(60 * 15, key_prefix="site1") - def my_view(request): - ... - -Specifying per-view cache in the URLconf ----------------------------------------- - -The examples in the previous section have hard-coded the fact that the view is -cached, because ``cache_page`` alters the ``my_view`` function in place. This -approach couples your view to the cache system, which is not ideal for several -reasons. For instance, you might want to reuse the view functions on another, -cache-less site, or you might want to distribute the views to people who might -want to use them without being cached. The solution to these problems is to -specify the per-view cache in the URLconf rather than next to the view functions -themselves. - -Doing so is easy: simply wrap the view function with ``cache_page`` when you -refer to it in the URLconf. Here's the old URLconf from earlier:: - - urlpatterns = ('', - (r'^foo/(\d{1,2})/$', my_view), - ) - -Here's the same thing, with ``my_view`` wrapped in ``cache_page``:: - - from django.views.decorators.cache import cache_page - - urlpatterns = ('', - (r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)), - ) - -If you take this approach, don't forget to import ``cache_page`` within your -URLconf. - -Template fragment caching -========================= - -.. versionadded:: 1.0 - -If you're after even more control, you can also cache template fragments using -the ``cache`` template tag. To give your template access to this tag, put -``{% load cache %}`` near the top of your template. - -The ``{% cache %}`` template tag caches the contents of the block for a given -amount of time. It takes at least two arguments: the cache timeout, in seconds, -and the name to give the cache fragment. For example: - -.. code-block:: html+django - - {% load cache %} - {% cache 500 sidebar %} - .. sidebar .. - {% endcache %} - -Sometimes you might want to cache multiple copies of a fragment depending on -some dynamic data that appears inside the fragment. For example, you might want a -separate cached copy of the sidebar used in the previous example for every user -of your site. Do this by passing additional arguments to the ``{% cache %}`` -template tag to uniquely identify the cache fragment: - -.. code-block:: html+django - - {% load cache %} - {% cache 500 sidebar request.user.username %} - .. sidebar for logged in user .. - {% endcache %} - -It's perfectly fine to specify more than one argument to identify the fragment. -Simply pass as many arguments to ``{% cache %}`` as you need. - -If :setting:`USE_I18N` is set to ``True`` the per-site middleware cache will -:ref:`respect the active language<i18n-cache-key>`. For the ``cache`` template -tag you could use one of the -:ref:`translation-specific variables<template-translation-vars>` available in -templates to archieve the same result: - -.. code-block:: html+django - - {% load i18n %} - {% load cache %} - - {% get_current_language as LANGUAGE_CODE %} - - {% cache 600 welcome LANGUAGE_CODE %} - {% trans "Welcome to example.com" %} - {% endcache %} - -The cache timeout can be a template variable, as long as the template variable -resolves to an integer value. For example, if the template variable -``my_timeout`` is set to the value ``600``, then the following two examples are -equivalent: - -.. code-block:: html+django - - {% cache 600 sidebar %} ... {% endcache %} - {% cache my_timeout sidebar %} ... {% endcache %} - -This feature is useful in avoiding repetition in templates. You can set the -timeout in a variable, in one place, and just reuse that value. - -The low-level cache API -======================= - -.. highlight:: python - -Sometimes, caching an entire rendered page doesn't gain you very much and is, -in fact, inconvenient overkill. - -Perhaps, for instance, your site includes a view whose results depend on -several expensive queries, the results of which change at different intervals. -In this case, it would not be ideal to use the full-page caching that the -per-site or per-view cache strategies offer, because you wouldn't want to -cache the entire result (since some of the data changes often), but you'd still -want to cache the results that rarely change. - -For cases like this, Django exposes a simple, low-level cache API. You can use -this API to store objects in the cache with any level of granularity you like. -You can cache any Python object that can be pickled safely: strings, -dictionaries, lists of model objects, and so forth. (Most common Python objects -can be pickled; refer to the Python documentation for more information about -pickling.) - -The cache module, ``django.core.cache``, has a ``cache`` object that's -automatically created from the ``CACHE_BACKEND`` setting:: - - >>> from django.core.cache import cache - -The basic interface is ``set(key, value, timeout)`` and ``get(key)``:: - - >>> cache.set('my_key', 'hello, world!', 30) - >>> cache.get('my_key') - 'hello, world!' - -The ``timeout`` argument is optional and defaults to the ``timeout`` -argument in the ``CACHE_BACKEND`` setting (explained above). It's the number of -seconds the value should be stored in the cache. - -If the object doesn't exist in the cache, ``cache.get()`` returns ``None``:: - - # Wait 30 seconds for 'my_key' to expire... - - >>> cache.get('my_key') - None - -We advise against storing the literal value ``None`` in the cache, because you -won't be able to distinguish between your stored ``None`` value and a cache -miss signified by a return value of ``None``. - -``cache.get()`` can take a ``default`` argument. This specifies which value to -return if the object doesn't exist in the cache:: - - >>> cache.get('my_key', 'has expired') - 'has expired' - -.. versionadded:: 1.0 - -To add a key only if it doesn't already exist, use the ``add()`` method. -It takes the same parameters as ``set()``, but it will not attempt to -update the cache if the key specified is already present:: - - >>> cache.set('add_key', 'Initial value') - >>> cache.add('add_key', 'New value') - >>> cache.get('add_key') - 'Initial value' - -If you need to know whether ``add()`` stored a value in the cache, you can -check the return value. It will return ``True`` if the value was stored, -``False`` otherwise. - -There's also a ``get_many()`` interface that only hits the cache once. -``get_many()`` returns a dictionary with all the keys you asked for that -actually exist in the cache (and haven't expired):: - - >>> cache.set('a', 1) - >>> cache.set('b', 2) - >>> cache.set('c', 3) - >>> cache.get_many(['a', 'b', 'c']) - {'a': 1, 'b': 2, 'c': 3} - -.. versionadded:: 1.2 - -To set multiple values more efficiently, use ``set_many()`` to pass a dictionary -of key-value pairs:: - - >>> cache.set_many({'a': 1, 'b': 2, 'c': 3}) - >>> cache.get_many(['a', 'b', 'c']) - {'a': 1, 'b': 2, 'c': 3} - -Like ``cache.set()``, ``set_many()`` takes an optional ``timeout`` parameter. - -You can delete keys explicitly with ``delete()``. This is an easy way of -clearing the cache for a particular object:: - - >>> cache.delete('a') - -.. versionadded:: 1.2 - -If you want to clear a bunch of keys at once, ``delete_many()`` can take a list -of keys to be cleared:: - - >>> cache.delete_many(['a', 'b', 'c']) - -.. versionadded:: 1.2 - -Finally, if you want to delete all the keys in the cache, use -``cache.clear()``. Be careful with this; ``clear()`` will remove *everything* -from the cache, not just the keys set by your application. :: - - >>> cache.clear() - -.. versionadded:: 1.1 - -You can also increment or decrement a key that already exists using the -``incr()`` or ``decr()`` methods, respectively. By default, the existing cache -value will incremented or decremented by 1. Other increment/decrement values -can be specified by providing an argument to the increment/decrement call. A -ValueError will be raised if you attempt to increment or decrement a -nonexistent cache key.:: - - >>> cache.set('num', 1) - >>> cache.incr('num') - 2 - >>> cache.incr('num', 10) - 12 - >>> cache.decr('num') - 11 - >>> cache.decr('num', 5) - 6 - -.. note:: - - ``incr()``/``decr()`` methods are not guaranteed to be atomic. On those - backends that support atomic increment/decrement (most notably, the - memcached backend), increment and decrement operations will be atomic. - However, if the backend doesn't natively provide an increment/decrement - operation, it will be implemented using a two-step retrieve/update. - -Cache key warnings ------------------- - -.. versionadded:: 1.3 - -Memcached, the most commonly-used production cache backend, does not allow -cache keys longer than 250 characters or containing whitespace or control -characters, and using such keys will cause an exception. To encourage -cache-portable code and minimize unpleasant surprises, the other built-in cache -backends issue a warning (``django.core.cache.backends.base.CacheKeyWarning``) -if a key is used that would cause an error on memcached. - -If you are using a production backend that can accept a wider range of keys (a -custom backend, or one of the non-memcached built-in backends), and want to use -this wider range without warnings, you can silence ``CacheKeyWarning`` with -this code in the ``management`` module of one of your -:setting:`INSTALLED_APPS`:: - - import warnings - - from django.core.cache import CacheKeyWarning - - warnings.simplefilter("ignore", CacheKeyWarning) - -If you want to instead provide custom key validation logic for one of the -built-in backends, you can subclass it, override just the ``validate_key`` -method, and follow the instructions for `using a custom cache backend`_. For -instance, to do this for the ``locmem`` backend, put this code in a module:: - - from django.core.cache.backends.locmem import CacheClass as LocMemCacheClass - - class CacheClass(LocMemCacheClass): - def validate_key(self, key): - """Custom validation, raising exceptions or warnings as needed.""" - # ... - -...and use the dotted Python path to this module as the scheme portion of your -:setting:`CACHE_BACKEND`. - -Upstream caches -=============== - -So far, this document has focused on caching your *own* data. But another type -of caching is relevant to Web development, too: caching performed by "upstream" -caches. These are systems that cache pages for users even before the request -reaches your Web site. - -Here are a few examples of upstream caches: - - * Your ISP may cache certain pages, so if you requested a page from - http://example.com/, your ISP would send you the page without having to - access example.com directly. The maintainers of example.com have no - knowledge of this caching; the ISP sits between example.com and your Web - browser, handling all of the caching transparently. - - * Your Django Web site may sit behind a *proxy cache*, such as Squid Web - Proxy Cache (http://www.squid-cache.org/), that caches pages for - performance. In this case, each request first would be handled by the - proxy, and it would be passed to your application only if needed. - - * Your Web browser caches pages, too. If a Web page sends out the - appropriate headers, your browser will use the local cached copy for - subsequent requests to that page, without even contacting the Web page - again to see whether it has changed. - -Upstream caching is a nice efficiency boost, but there's a danger to it: -Many Web pages' contents differ based on authentication and a host of other -variables, and cache systems that blindly save pages based purely on URLs could -expose incorrect or sensitive data to subsequent visitors to those pages. - -For example, say you operate a Web e-mail system, and the contents of the -"inbox" page obviously depend on which user is logged in. If an ISP blindly -cached your site, then the first user who logged in through that ISP would have -his user-specific inbox page cached for subsequent visitors to the site. That's -not cool. - -Fortunately, HTTP provides a solution to this problem. A number of HTTP headers -exist to instruct upstream caches to differ their cache contents depending on -designated variables, and to tell caching mechanisms not to cache particular -pages. We'll look at some of these headers in the sections that follow. - -Using Vary headers -================== - -The ``Vary`` header defines which request headers a cache -mechanism should take into account when building its cache key. For example, if -the contents of a Web page depend on a user's language preference, the page is -said to "vary on language." - -By default, Django's cache system creates its cache keys using the requested -path (e.g., ``"/stories/2005/jun/23/bank_robbed/"``). This means every request -to that URL will use the same cached version, regardless of user-agent -differences such as cookies or language preferences. However, if this page -produces different content based on some difference in request headers -- such -as a cookie, or a language, or a user-agent -- you'll need to use the ``Vary`` -header to tell caching mechanisms that the page output depends on those things. - -To do this in Django, use the convenient ``vary_on_headers`` view decorator, -like so:: - - from django.views.decorators.vary import vary_on_headers - - @vary_on_headers('User-Agent') - def my_view(request): - # ... - -In this case, a caching mechanism (such as Django's own cache middleware) will -cache a separate version of the page for each unique user-agent. - -The advantage to using the ``vary_on_headers`` decorator rather than manually -setting the ``Vary`` header (using something like -``response['Vary'] = 'user-agent'``) is that the decorator *adds* to the -``Vary`` header (which may already exist), rather than setting it from scratch -and potentially overriding anything that was already in there. - -You can pass multiple headers to ``vary_on_headers()``:: - - @vary_on_headers('User-Agent', 'Cookie') - def my_view(request): - # ... - -This tells upstream caches to vary on *both*, which means each combination of -user-agent and cookie will get its own cache value. For example, a request with -the user-agent ``Mozilla`` and the cookie value ``foo=bar`` will be considered -different from a request with the user-agent ``Mozilla`` and the cookie value -``foo=ham``. - -Because varying on cookie is so common, there's a ``vary_on_cookie`` -decorator. These two views are equivalent:: - - @vary_on_cookie - def my_view(request): - # ... - - @vary_on_headers('Cookie') - def my_view(request): - # ... - -The headers you pass to ``vary_on_headers`` are not case sensitive; -``"User-Agent"`` is the same thing as ``"user-agent"``. - -You can also use a helper function, ``django.utils.cache.patch_vary_headers``, -directly. This function sets, or adds to, the ``Vary header``. For example:: - - from django.utils.cache import patch_vary_headers - - def my_view(request): - # ... - response = render_to_response('template_name', context) - patch_vary_headers(response, ['Cookie']) - return response - -``patch_vary_headers`` takes an :class:`~django.http.HttpResponse` instance as -its first argument and a list/tuple of case-insensitive header names as its -second argument. - -For more on Vary headers, see the `official Vary spec`_. - -.. _`official Vary spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44 - -Controlling cache: Using other headers -====================================== - -Other problems with caching are the privacy of data and the question of where -data should be stored in a cascade of caches. - -A user usually faces two kinds of caches: his or her own browser cache (a -private cache) and his or her provider's cache (a public cache). A public cache -is used by multiple users and controlled by someone else. This poses problems -with sensitive data--you don't want, say, your bank account number stored in a -public cache. So Web applications need a way to tell caches which data is -private and which is public. - -The solution is to indicate a page's cache should be "private." To do this in -Django, use the ``cache_control`` view decorator. Example:: - - from django.views.decorators.cache import cache_control - - @cache_control(private=True) - def my_view(request): - # ... - -This decorator takes care of sending out the appropriate HTTP header behind the -scenes. - -There are a few other ways to control cache parameters. For example, HTTP -allows applications to do the following: - - * Define the maximum time a page should be cached. - - * Specify whether a cache should always check for newer versions, only - delivering the cached content when there are no changes. (Some caches - might deliver cached content even if the server page changed, simply - because the cache copy isn't yet expired.) - -In Django, use the ``cache_control`` view decorator to specify these cache -parameters. In this example, ``cache_control`` tells caches to revalidate the -cache on every access and to store cached versions for, at most, 3,600 seconds:: - - from django.views.decorators.cache import cache_control - - @cache_control(must_revalidate=True, max_age=3600) - def my_view(request): - # ... - -Any valid ``Cache-Control`` HTTP directive is valid in ``cache_control()``. -Here's a full list: - - * ``public=True`` - * ``private=True`` - * ``no_cache=True`` - * ``no_transform=True`` - * ``must_revalidate=True`` - * ``proxy_revalidate=True`` - * ``max_age=num_seconds`` - * ``s_maxage=num_seconds`` - -For explanation of Cache-Control HTTP directives, see the `Cache-Control spec`_. - -(Note that the caching middleware already sets the cache header's max-age with -the value of the :setting:`CACHE_MIDDLEWARE_SECONDS` setting. If you use a custom -``max_age`` in a ``cache_control`` decorator, the decorator will take -precedence, and the header values will be merged correctly.) - -If you want to use headers to disable caching altogether, -``django.views.decorators.cache.never_cache`` is a view decorator that adds -headers to ensure the response won't be cached by browsers or other caches. -Example:: - - from django.views.decorators.cache import never_cache - - @never_cache - def myview(request): - # ... - -.. _`Cache-Control spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 - -Other optimizations -=================== - -Django comes with a few other pieces of middleware that can help optimize your -site's performance: - - * ``django.middleware.http.ConditionalGetMiddleware`` adds support for - modern browsers to conditionally GET responses based on the ``ETag`` - and ``Last-Modified`` headers. - - * ``django.middleware.gzip.GZipMiddleware`` compresses responses for all - moderns browsers, saving bandwidth and transfer time. - -Order of MIDDLEWARE_CLASSES -=========================== - -If you use caching middleware, it's important to put each half in the right -place within the ``MIDDLEWARE_CLASSES`` setting. That's because the cache -middleware needs to know which headers by which to vary the cache storage. -Middleware always adds something to the ``Vary`` response header when it can. - -``UpdateCacheMiddleware`` runs during the response phase, where middleware is -run in reverse order, so an item at the top of the list runs *last* during the -response phase. Thus, you need to make sure that ``UpdateCacheMiddleware`` -appears *before* any other middleware that might add something to the ``Vary`` -header. The following middleware modules do so: - - * ``SessionMiddleware`` adds ``Cookie`` - * ``GZipMiddleware`` adds ``Accept-Encoding`` - * ``LocaleMiddleware`` adds ``Accept-Language`` - -``FetchFromCacheMiddleware``, on the other hand, runs during the request phase, -where middleware is applied first-to-last, so an item at the top of the list -runs *first* during the request phase. The ``FetchFromCacheMiddleware`` also -needs to run after other middleware updates the ``Vary`` header, so -``FetchFromCacheMiddleware`` must be *after* any item that does so. - diff --git a/parts/django/docs/topics/conditional-view-processing.txt b/parts/django/docs/topics/conditional-view-processing.txt deleted file mode 100644 index c631a13..0000000 --- a/parts/django/docs/topics/conditional-view-processing.txt +++ /dev/null @@ -1,199 +0,0 @@ -=========================== -Conditional View Processing -=========================== - -.. versionadded:: 1.1 - -HTTP clients can send a number of headers to tell the server about copies of a -resource that they have already seen. This is commonly used when retrieving a -Web page (using an HTTP ``GET`` request) to avoid sending all the data for -something the client has already retrieved. However, the same headers can be -used for all HTTP methods (``POST``, ``PUT``, ``DELETE``, etc). - -For each page (response) that Django sends back from a view, it might provide -two HTTP headers: the ``ETag`` header and the ``Last-Modified`` header. These -headers are optional on HTTP responses. They can be set by your view function, -or you can rely on the :class:`~django.middleware.common.CommonMiddleware` -middleware to set the ``ETag`` header. - -When the client next requests the same resource, it might send along a header -such as `If-modified-since`_, containing the date of the last modification -time it was sent, or `If-none-match`_, containing the ``ETag`` it was sent. -If the current version of the page matches the ``ETag`` sent by the client, or -if the resource has not been modified, a 304 status code can be sent back, -instead of a full response, telling the client that nothing has changed. - -.. _If-none-match: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26 -.. _If-modified-since: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 - -When you need more fine-grained control you may use per-view conditional -processing functions. - -.. conditional-decorators: - -The ``condition`` decorator -=========================== - -Sometimes (in fact, quite often) you can create functions to rapidly compute the ETag_ -value or the last-modified time for a resource, **without** needing to do all -the computations needed to construct the full view. Django can then use these -functions to provide an "early bailout" option for the view processing. -Telling the client that the content has not been modified since the last -request, perhaps. - -.. _ETag: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11 - -These two functions are passed as parameters the -``django.views.decorators.http.condition`` decorator. This decorator uses -the two functions (you only need to supply one, if you can't compute both -quantities easily and quickly) to work out if the headers in the HTTP request -match those on the resource. If they don't match, a new copy of the resource -must be computed and your normal view is called. - -The ``condition`` decorator's signature looks like this:: - - condition(etag_func=None, last_modified_func=None) - -The two functions, to compute the ETag and the last modified time, will be -passed the incoming ``request`` object and the same parameters, in the same -order, as the view function they are helping to wrap. The function passed -``last_modified_func`` should return a standard datetime value specifying the -last time the resource was modified, or ``None`` if the resource doesn't -exist. The function passed to the ``etag`` decorator should return a string -representing the `Etag`_ for the resource, or ``None`` if it doesn't exist. - -Using this feature usefully is probably best explained with an example. -Suppose you have this pair of models, representing a simple blog system:: - - import datetime - from django.db import models - - class Blog(models.Model): - ... - - class Entry(models.Model): - blog = models.ForeignKey(Blog) - published = models.DateTimeField(default=datetime.datetime.now) - ... - -If the front page, displaying the latest blog entries, only changes when you -add a new blog entry, you can compute the last modified time very quickly. You -need the latest ``published`` date for every entry associated with that blog. -One way to do this would be:: - - def latest_entry(request, blog_id): - return Entry.objects.filter(blog=blog_id).latest("published").published - -You can then use this function to provide early detection of an unchanged page -for your front page view:: - - from django.views.decorators.http import condition - - @condition(last_modified_func=latest_entry) - def front_page(request, blog_id): - ... - -Shortcuts for only computing one value -====================================== - -As a general rule, if you can provide functions to compute *both* the ETag and -the last modified time, you should do so. You don't know which headers any -given HTTP client will send you, so be prepared to handle both. However, -sometimes only one value is easy to compute and Django provides decorators -that handle only ETag or only last-modified computations. - -The ``django.views.decorators.http.etag`` and -``django.views.decorators.http.last_modified`` decorators are passed the same -type of functions as the ``condition`` decorator. Their signatures are:: - - etag(etag_func) - last_modified(last_modified_func) - -We could write the earlier example, which only uses a last-modified function, -using one of these decorators:: - - @last_modified(latest_entry) - def front_page(request, blog_id): - ... - -...or:: - - def front_page(request, blog_id): - ... - front_page = last_modified(latest_entry)(front_page) - -Use ``condition`` when testing both conditions ------------------------------------------------- - -It might look nicer to some people to try and chain the ``etag`` and -``last_modified`` decorators if you want to test both preconditions. However, -this would lead to incorrect behavior. - -:: - - # Bad code. Don't do this! - @etag(etag_func) - @last_modified(last_modified_func) - def my_view(request): - # ... - - # End of bad code. - -The first decorator doesn't know anything about the second and might -answer that the response is not modified even if the second decorators would -determine otherwise. The ``condition`` decorator uses both callback functions -simultaneously to work out the right action to take. - -Using the decorators with other HTTP methods -============================================ - -The ``condition`` decorator is useful for more than only ``GET`` and -``HEAD`` requests (``HEAD`` requests are the same as ``GET`` in this -situation). It can be used also to be used to provide checking for ``POST``, -``PUT`` and ``DELETE`` requests. In these situations, the idea isn't to return -a "not modified" response, but to tell the client that the resource they are -trying to change has been altered in the meantime. - -For example, consider the following exchange between the client and server: - - 1. Client requests ``/foo/``. - 2. Server responds with some content with an ETag of ``"abcd1234"``. - 3. Client sends an HTTP ``PUT`` request to ``/foo/`` to update the - resource. It also sends an ``If-Match: "abcd1234"`` header to specify - the version it is trying to update. - 4. Server checks to see if the resource has changed, by computing the ETag - the same way it does for a ``GET`` request (using the same function). - If the resource *has* changed, it will return a 412 status code code, - meaning "precondition failed". - 5. Client sends a ``GET`` request to ``/foo/``, after receiving a 412 - response, to retrieve an updated version of the content before updating - it. - -The important thing this example shows is that the same functions can be used -to compute the ETag and last modification values in all situations. In fact, -you **should** use the same functions, so that the same values are returned -every time. - -Comparison with middleware conditional processing -================================================= - -You may notice that Django already provides simple and straightforward -conditional ``GET`` handling via the -:class:`django.middleware.http.ConditionalGetMiddleware` and -:class:`~django.middleware.common.CommonMiddleware`. Whilst certainly being -easy to use and suitable for many situations, those pieces of middleware -functionality have limitations for advanced usage: - - * They are applied globally to all views in your project - * They don't save you from generating the response itself, which may be - expensive - * They are only appropriate for HTTP ``GET`` requests. - -You should choose the most appropriate tool for your particular problem here. -If you have a way to compute ETags and modification times quickly and if some -view takes a while to generate the content, you should consider using the -``condition`` decorator described in this document. If everything already runs -fairly quickly, stick to using the middleware and the amount of network -traffic sent back to the clients will still be reduced if the view hasn't -changed. - diff --git a/parts/django/docs/topics/db/aggregation.txt b/parts/django/docs/topics/db/aggregation.txt deleted file mode 100644 index eb21021..0000000 --- a/parts/django/docs/topics/db/aggregation.txt +++ /dev/null @@ -1,378 +0,0 @@ -=========== -Aggregation -=========== - -.. versionadded:: 1.1 - -.. currentmodule:: django.db.models - -The topic guide on :doc:`Django's database-abstraction API </topics/db/queries>` -described the way that you can use Django queries that create, -retrieve, update and delete individual objects. However, sometimes you will -need to retrieve values that are derived by summarizing or *aggregating* a -collection of objects. This topic guide describes the ways that aggregate values -can be generated and returned using Django queries. - -Throughout this guide, we'll refer to the following models. These models are -used to track the inventory for a series of online bookstores: - -.. _queryset-model-example: - -.. code-block:: python - - class Author(models.Model): - name = models.CharField(max_length=100) - age = models.IntegerField() - friends = models.ManyToManyField('self', blank=True) - - class Publisher(models.Model): - name = models.CharField(max_length=300) - num_awards = models.IntegerField() - - class Book(models.Model): - isbn = models.CharField(max_length=9) - name = models.CharField(max_length=300) - pages = models.IntegerField() - price = models.DecimalField(max_digits=10, decimal_places=2) - rating = models.FloatField() - authors = models.ManyToManyField(Author) - publisher = models.ForeignKey(Publisher) - pubdate = models.DateField() - - class Store(models.Model): - name = models.CharField(max_length=300) - books = models.ManyToManyField(Book) - - -Generating aggregates over a QuerySet -===================================== - -Django provides two ways to generate aggregates. The first way is to generate -summary values over an entire ``QuerySet``. For example, say you wanted to -calculate the average price of all books available for sale. Django's query -syntax provides a means for describing the set of all books:: - - >>> Book.objects.all() - -What we need is a way to calculate summary values over the objects that -belong to this ``QuerySet``. This is done by appending an ``aggregate()`` -clause onto the ``QuerySet``:: - - >>> from django.db.models import Avg - >>> Book.objects.all().aggregate(Avg('price')) - {'price__avg': 34.35} - -The ``all()`` is redundant in this example, so this could be simplified to:: - - >>> Book.objects.aggregate(Avg('price')) - {'price__avg': 34.35} - -The argument to the ``aggregate()`` clause describes the aggregate value that -we want to compute - in this case, the average of the ``price`` field on the -``Book`` model. A list of the aggregate functions that are available can be -found in the :ref:`QuerySet reference <aggregation-functions>`. - -``aggregate()`` is a terminal clause for a ``QuerySet`` that, when invoked, -returns a dictionary of name-value pairs. The name is an identifier for the -aggregate value; the value is the computed aggregate. The name is -automatically generated from the name of the field and the aggregate function. -If you want to manually specify a name for the aggregate value, you can do so -by providing that name when you specify the aggregate clause:: - - >>> Book.objects.aggregate(average_price=Avg('price')) - {'average_price': 34.35} - -If you want to generate more than one aggregate, you just add another -argument to the ``aggregate()`` clause. So, if we also wanted to know -the maximum and minimum price of all books, we would issue the query:: - - >>> from django.db.models import Avg, Max, Min, Count - >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) - {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} - -Generating aggregates for each item in a QuerySet -================================================= - -The second way to generate summary values is to generate an independent -summary for each object in a ``QuerySet``. For example, if you are retrieving -a list of books, you may want to know how many authors contributed to -each book. Each Book has a many-to-many relationship with the Author; we -want to summarize this relationship for each book in the ``QuerySet``. - -Per-object summaries can be generated using the ``annotate()`` clause. -When an ``annotate()`` clause is specified, each object in the ``QuerySet`` -will be annotated with the specified values. - -The syntax for these annotations is identical to that used for the -``aggregate()`` clause. Each argument to ``annotate()`` describes an -aggregate that is to be calculated. For example, to annotate Books with -the number of authors:: - - # Build an annotated queryset - >>> q = Book.objects.annotate(Count('authors')) - # Interrogate the first object in the queryset - >>> q[0] - <Book: The Definitive Guide to Django> - >>> q[0].authors__count - 2 - # Interrogate the second object in the queryset - >>> q[1] - <Book: Practical Django Projects> - >>> q[1].authors__count - 1 - -As with ``aggregate()``, the name for the annotation is automatically derived -from the name of the aggregate function and the name of the field being -aggregated. You can override this default name by providing an alias when you -specify the annotation:: - - >>> q = Book.objects.annotate(num_authors=Count('authors')) - >>> q[0].num_authors - 2 - >>> q[1].num_authors - 1 - -Unlike ``aggregate()``, ``annotate()`` is *not* a terminal clause. The output -of the ``annotate()`` clause is a ``QuerySet``; this ``QuerySet`` can be -modified using any other ``QuerySet`` operation, including ``filter()``, -``order_by``, or even additional calls to ``annotate()``. - -Joins and aggregates -==================== - -So far, we have dealt with aggregates over fields that belong to the -model being queried. However, sometimes the value you want to aggregate -will belong to a model that is related to the model you are querying. - -When specifying the field to be aggregated in an aggregate function, Django -will allow you to use the same :ref:`double underscore notation -<field-lookups-intro>` that is used when referring to related fields in -filters. Django will then handle any table joins that are required to retrieve -and aggregate the related value. - -For example, to find the price range of books offered in each store, -you could use the annotation:: - - >>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price')) - -This tells Django to retrieve the Store model, join (through the -many-to-many relationship) with the Book model, and aggregate on the -price field of the book model to produce a minimum and maximum value. - -The same rules apply to the ``aggregate()`` clause. If you wanted to -know the lowest and highest price of any book that is available for sale -in a store, you could use the aggregate:: - - >>> Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price')) - -Join chains can be as deep as you require. For example, to extract the -age of the youngest author of any book available for sale, you could -issue the query:: - - >>> Store.objects.aggregate(youngest_age=Min('books__authors__age')) - -Aggregations and other QuerySet clauses -======================================= - -``filter()`` and ``exclude()`` ------------------------------- - -Aggregates can also participate in filters. Any ``filter()`` (or -``exclude()``) applied to normal model fields will have the effect of -constraining the objects that are considered for aggregation. - -When used with an ``annotate()`` clause, a filter has the effect of -constraining the objects for which an annotation is calculated. For example, -you can generate an annotated list of all books that have a title starting -with "Django" using the query:: - - >>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors')) - -When used with an ``aggregate()`` clause, a filter has the effect of -constraining the objects over which the aggregate is calculated. -For example, you can generate the average price of all books with a -title that starts with "Django" using the query:: - - >>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price')) - -Filtering on annotations -~~~~~~~~~~~~~~~~~~~~~~~~ - -Annotated values can also be filtered. The alias for the annotation can be -used in ``filter()`` and ``exclude()`` clauses in the same way as any other -model field. - -For example, to generate a list of books that have more than one author, -you can issue the query:: - - >>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1) - -This query generates an annotated result set, and then generates a filter -based upon that annotation. - -Order of ``annotate()`` and ``filter()`` clauses -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When developing a complex query that involves both ``annotate()`` and -``filter()`` clauses, particular attention should be paid to the order -in which the clauses are applied to the ``QuerySet``. - -When an ``annotate()`` clause is applied to a query, the annotation is -computed over the state of the query up to the point where the annotation -is requested. The practical implication of this is that ``filter()`` and -``annotate()`` are not commutative operations -- that is, there is a -difference between the query:: - - >>> Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0) - -and the query:: - - >>> Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book')) - -Both queries will return a list of Publishers that have at least one good -book (i.e., a book with a rating exceeding 3.0). However, the annotation in -the first query will provide the total number of all books published by the -publisher; the second query will only include good books in the annotated -count. In the first query, the annotation precedes the filter, so the -filter has no effect on the annotation. In the second query, the filter -preceeds the annotation, and as a result, the filter constrains the objects -considered when calculating the annotation. - -``order_by()`` --------------- - -Annotations can be used as a basis for ordering. When you -define an ``order_by()`` clause, the aggregates you provide can reference -any alias defined as part of an ``annotate()`` clause in the query. - -For example, to order a ``QuerySet`` of books by the number of authors -that have contributed to the book, you could use the following query:: - - >>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors') - -``values()`` ------------- - -Ordinarily, annotations are generated on a per-object basis - an annotated -``QuerySet`` will return one result for each object in the original -``QuerySet``. However, when a ``values()`` clause is used to constrain the -columns that are returned in the result set, the method for evaluating -annotations is slightly different. Instead of returning an annotated result -for each result in the original ``QuerySet``, the original results are -grouped according to the unique combinations of the fields specified in the -``values()`` clause. An annotation is then provided for each unique group; -the annotation is computed over all members of the group. - -For example, consider an author query that attempts to find out the average -rating of books written by each author: - - >>> Author.objects.annotate(average_rating=Avg('book__rating')) - -This will return one result for each author in the database, annotated with -their average book rating. - -However, the result will be slightly different if you use a ``values()`` clause:: - - >>> Author.objects.values('name').annotate(average_rating=Avg('book__rating')) - -In this example, the authors will be grouped by name, so you will only get -an annotated result for each *unique* author name. This means if you have -two authors with the same name, their results will be merged into a single -result in the output of the query; the average will be computed as the -average over the books written by both authors. - -Order of ``annotate()`` and ``values()`` clauses -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As with the ``filter()`` clause, the order in which ``annotate()`` and -``values()`` clauses are applied to a query is significant. If the -``values()`` clause precedes the ``annotate()``, the annotation will be -computed using the grouping described by the ``values()`` clause. - -However, if the ``annotate()`` clause precedes the ``values()`` clause, -the annotations will be generated over the entire query set. In this case, -the ``values()`` clause only constrains the fields that are generated on -output. - -For example, if we reverse the order of the ``values()`` and ``annotate()`` -clause from our previous example:: - - >>> Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rating') - -This will now yield one unique result for each author; however, only -the author's name and the ``average_rating`` annotation will be returned -in the output data. - -You should also note that ``average_rating`` has been explicitly included -in the list of values to be returned. This is required because of the -ordering of the ``values()`` and ``annotate()`` clause. - -If the ``values()`` clause precedes the ``annotate()`` clause, any annotations -will be automatically added to the result set. However, if the ``values()`` -clause is applied after the ``annotate()`` clause, you need to explicitly -include the aggregate column. - -Interaction with default ordering or ``order_by()`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Fields that are mentioned in the ``order_by()`` part of a queryset (or which -are used in the default ordering on a model) are used when selecting the -output data, even if they are not otherwise specified in the ``values()`` -call. These extra fields are used to group "like" results together and they -can make otherwise identical result rows appear to be separate. This shows up, -particularly, when counting things. - -By way of example, suppose you have a model like this:: - - class Item(models.Model): - name = models.CharField(max_length=10) - data = models.IntegerField() - - class Meta: - ordering = ["name"] - -The important part here is the default ordering on the ``name`` field. If you -want to count how many times each distinct ``data`` value appears, you might -try this:: - - # Warning: not quite correct! - Item.objects.values("data").annotate(Count("id")) - -...which will group the ``Item`` objects by their common ``data`` values and -then count the number of ``id`` values in each group. Except that it won't -quite work. The default ordering by ``name`` will also play a part in the -grouping, so this query will group by distinct ``(data, name)`` pairs, which -isn't what you want. Instead, you should construct this queryset:: - - Item.objects.values("data").annotate(Count("id")).order_by() - -...clearing any ordering in the query. You could also order by, say, ``data`` -without any harmful effects, since that is already playing a role in the -query. - -This behavior is the same as that noted in the queryset documentation for -:meth:`~django.db.models.QuerySet.distinct` and the general rule is the same: -normally you won't want extra columns playing a part in the result, so clear -out the ordering, or at least make sure it's restricted only to those fields -you also select in a ``values()`` call. - -.. note:: - You might reasonably ask why Django doesn't remove the extraneous columns - for you. The main reason is consistency with ``distinct()`` and other - places: Django **never** removes ordering constraints that you have - specified (and we can't change those other methods' behavior, as that - would violate our :doc:`/misc/api-stability` policy). - -Aggregating annotations ------------------------ - -You can also generate an aggregate on the result of an annotation. When you -define an ``aggregate()`` clause, the aggregates you provide can reference -any alias defined as part of an ``annotate()`` clause in the query. - -For example, if you wanted to calculate the average number of authors per -book you first annotate the set of books with the author count, then -aggregate that author count, referencing the annotation field:: - - >>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors')) - {'num_authors__avg': 1.66} diff --git a/parts/django/docs/topics/db/index.txt b/parts/django/docs/topics/db/index.txt deleted file mode 100644 index c49f158..0000000 --- a/parts/django/docs/topics/db/index.txt +++ /dev/null @@ -1,18 +0,0 @@ -Models and databases -==================== - -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. - -.. toctree:: - :maxdepth: 1 - - models - queries - aggregation - managers - sql - transactions - multi-db - optimization diff --git a/parts/django/docs/topics/db/managers.txt b/parts/django/docs/topics/db/managers.txt deleted file mode 100644 index 5ebe0b1..0000000 --- a/parts/django/docs/topics/db/managers.txt +++ /dev/null @@ -1,376 +0,0 @@ -======== -Managers -======== - -.. currentmodule:: django.db.models - -.. class:: Manager() - -A ``Manager`` is the interface through which database query operations are -provided to Django models. At least one ``Manager`` exists for every model in -a Django application. - -The way ``Manager`` classes work is documented in :doc:`/topics/db/queries`; -this document specifically touches on model options that customize ``Manager`` -behavior. - -.. _manager-names: - -Manager names -============= - -By default, Django adds a ``Manager`` with the name ``objects`` to every Django -model class. However, if you want to use ``objects`` as a field name, or if you -want to use a name other than ``objects`` for the ``Manager``, you can rename -it on a per-model basis. To rename the ``Manager`` for a given class, define a -class attribute of type ``models.Manager()`` on that model. For example:: - - from django.db import models - - class Person(models.Model): - #... - people = models.Manager() - -Using this example model, ``Person.objects`` will generate an -``AttributeError`` exception, but ``Person.people.all()`` will provide a list -of all ``Person`` objects. - -.. _custom-managers: - -Custom Managers -=============== - -You can use a custom ``Manager`` in a particular model by extending the base -``Manager`` class and instantiating your custom ``Manager`` in your model. - -There are two reasons you might want to customize a ``Manager``: to add extra -``Manager`` methods, and/or to modify the initial ``QuerySet`` the ``Manager`` -returns. - -Adding extra Manager methods ----------------------------- - -Adding extra ``Manager`` methods is the preferred way to add "table-level" -functionality to your models. (For "row-level" functionality -- i.e., functions -that act on a single instance of a model object -- use :ref:`Model methods -<model-methods>`, not custom ``Manager`` methods.) - -A custom ``Manager`` method can return anything you want. It doesn't have to -return a ``QuerySet``. - -For example, this custom ``Manager`` offers a method ``with_counts()``, which -returns a list of all ``OpinionPoll`` objects, each with an extra -``num_responses`` attribute that is the result of an aggregate query:: - - class PollManager(models.Manager): - def with_counts(self): - from django.db import connection - cursor = connection.cursor() - cursor.execute(""" - SELECT p.id, p.question, p.poll_date, COUNT(*) - FROM polls_opinionpoll p, polls_response r - WHERE p.id = r.poll_id - GROUP BY 1, 2, 3 - ORDER BY 3 DESC""") - result_list = [] - for row in cursor.fetchall(): - p = self.model(id=row[0], question=row[1], poll_date=row[2]) - p.num_responses = row[3] - result_list.append(p) - return result_list - - class OpinionPoll(models.Model): - question = models.CharField(max_length=200) - poll_date = models.DateField() - objects = PollManager() - - class Response(models.Model): - poll = models.ForeignKey(Poll) - person_name = models.CharField(max_length=50) - response = models.TextField() - -With this example, you'd use ``OpinionPoll.objects.with_counts()`` to return -that list of ``OpinionPoll`` objects with ``num_responses`` attributes. - -Another thing to note about this example is that ``Manager`` methods can -access ``self.model`` to get the model class to which they're attached. - -Modifying initial Manager QuerySets ------------------------------------ - -A ``Manager``'s base ``QuerySet`` returns all objects in the system. For -example, using this model:: - - class Book(models.Model): - title = models.CharField(max_length=100) - author = models.CharField(max_length=50) - -...the statement ``Book.objects.all()`` will return all books in the database. - -You can override a ``Manager``\'s base ``QuerySet`` by overriding the -``Manager.get_query_set()`` method. ``get_query_set()`` should return a -``QuerySet`` with the properties you require. - -For example, the following model has *two* ``Manager``\s -- one that returns -all objects, and one that returns only the books by Roald Dahl:: - - # First, define the Manager subclass. - class DahlBookManager(models.Manager): - def get_query_set(self): - return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl') - - # Then hook it into the Book model explicitly. - class Book(models.Model): - title = models.CharField(max_length=100) - author = models.CharField(max_length=50) - - objects = models.Manager() # The default manager. - dahl_objects = DahlBookManager() # The Dahl-specific manager. - -With this sample model, ``Book.objects.all()`` will return all books in the -database, but ``Book.dahl_objects.all()`` will only return the ones written by -Roald Dahl. - -Of course, because ``get_query_set()`` returns a ``QuerySet`` object, you can -use ``filter()``, ``exclude()`` and all the other ``QuerySet`` methods on it. -So these statements are all legal:: - - Book.dahl_objects.all() - Book.dahl_objects.filter(title='Matilda') - Book.dahl_objects.count() - -This example also pointed out another interesting technique: using multiple -managers on the same model. You can attach as many ``Manager()`` instances to -a model as you'd like. This is an easy way to define common "filters" for your -models. - -For example:: - - class MaleManager(models.Manager): - def get_query_set(self): - return super(MaleManager, self).get_query_set().filter(sex='M') - - class FemaleManager(models.Manager): - def get_query_set(self): - return super(FemaleManager, self).get_query_set().filter(sex='F') - - class Person(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female'))) - people = models.Manager() - men = MaleManager() - women = FemaleManager() - -This example allows you to request ``Person.men.all()``, ``Person.women.all()``, -and ``Person.people.all()``, yielding predictable results. - -If you use custom ``Manager`` objects, take note that the first ``Manager`` -Django encounters (in the order in which they're defined in the model) has a -special status. Django interprets the first ``Manager`` defined in a class as -the "default" ``Manager``, and several parts of Django -(including :djadmin:`dumpdata`) will use that ``Manager`` -exclusively for that model. As a result, it's a good idea to be careful in -your choice of default manager in order to avoid a situation where overriding -``get_query_set()`` results in an inability to retrieve objects you'd like to -work with. - -.. _managers-for-related-objects: - -Using managers for related object access -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default, Django uses an instance of a "plain" manager class when accessing -related objects (i.e. ``choice.poll``), not the default manager on the related -object. This is because Django needs to be able to retrieve the related -object, even if it would otherwise be filtered out (and hence be inaccessible) -by the default manager. - -If the normal plain manager class (:class:`django.db.models.Manager`) is not -appropriate for your circumstances, you can force Django to use the same class -as the default manager for your model by setting the `use_for_related_fields` -attribute on the manager class. This is documented fully below_. - -.. _below: manager-types_ - -.. _custom-managers-and-inheritance: - -Custom managers and model inheritance -------------------------------------- - -Class inheritance and model managers aren't quite a perfect match for each -other. Managers are often specific to the classes they are defined on and -inheriting them in subclasses isn't necessarily a good idea. Also, because the -first manager declared is the *default manager*, it is important to allow that -to be controlled. So here's how Django handles custom managers and -:ref:`model inheritance <model-inheritance>`: - - 1. Managers defined on non-abstract base classes are *not* inherited by - child classes. If you want to reuse a manager from a non-abstract base, - redeclare it explicitly on the child class. These sorts of managers are - likely to be fairly specific to the class they are defined on, so - inheriting them can often lead to unexpected results (particularly as - far as the default manager goes). Therefore, they aren't passed onto - child classes. - - 2. Managers from abstract base classes are always inherited by the child - class, using Python's normal name resolution order (names on the child - class override all others; then come names on the first parent class, - and so on). Abstract base classes are designed to capture information - and behavior that is common to their child classes. Defining common - managers is an appropriate part of this common information. - - 3. The default manager on a class is either the first manager declared on - the class, if that exists, or the default manager of the first abstract - base class in the parent hierarchy, if that exists. If no default - manager is explicitly declared, Django's normal default manager is - used. - -These rules provide the necessary flexibility if you want to install a -collection of custom managers on a group of models, via an abstract base -class, but still customize the default manager. For example, suppose you have -this base class:: - - class AbstractBase(models.Model): - ... - objects = CustomManager() - - class Meta: - abstract = True - -If you use this directly in a subclass, ``objects`` will be the default -manager if you declare no managers in the base class:: - - class ChildA(AbstractBase): - ... - # This class has CustomManager as the default manager. - -If you want to inherit from ``AbstractBase``, but provide a different default -manager, you can provide the default manager on the child class:: - - class ChildB(AbstractBase): - ... - # An explicit default manager. - default_manager = OtherManager() - -Here, ``default_manager`` is the default. The ``objects`` manager is -still available, since it's inherited. It just isn't used as the default. - -Finally for this example, suppose you want to add extra managers to the child -class, but still use the default from ``AbstractBase``. You can't add the new -manager directly in the child class, as that would override the default and you would -have to also explicitly include all the managers from the abstract base class. -The solution is to put the extra managers in another base class and introduce -it into the inheritance hierarchy *after* the defaults:: - - class ExtraManager(models.Model): - extra_manager = OtherManager() - - class Meta: - abstract = True - - class ChildC(AbstractBase, ExtraManager): - ... - # Default manager is CustomManager, but OtherManager is - # also available via the "extra_manager" attribute. - -.. _manager-types: - -Controlling Automatic Manager Types -=================================== - -This document has already mentioned a couple of places where Django creates a -manager class for you: `default managers`_ and the "plain" manager used to -`access related objects`_. There are other places in the implementation of -Django where temporary plain managers are needed. Those automatically created -managers will normally be instances of the :class:`django.db.models.Manager` -class. - -.. _default managers: manager-names_ -.. _access related objects: managers-for-related-objects_ - -Throughout this section, we will use the term "automatic manager" to mean a -manager that Django creates for you -- either as a default manager on a model -with no managers, or to use temporarily when accessing related objects. - -Sometimes this default class won't be the right choice. One example is in the -:mod:`django.contrib.gis` application that ships with Django itself. All ``gis`` -models must use a special manager class (:class:`~django.contrib.gis.db.models.GeoManager`) -because they need a special queryset (:class:`~django.contrib.gis.db.models.GeoQuerySet`) -to be used for interacting with the database. It turns out that models which require -a special manager like this need to use the same manager class wherever an automatic -manager is created. - -Django provides a way for custom manager developers to say that their manager -class should be used for automatic managers whenever it is the default manager -on a model. This is done by setting the ``use_for_related_fields`` attribute on -the manager class:: - - class MyManager(models.Manager): - use_for_related_fields = True - - ... - -If this attribute is set on the *default* manager for a model (only the -default manager is considered in these situations), Django will use that class -whenever it needs to automatically create a manager for the class. Otherwise, -it will use :class:`django.db.models.Manager`. - -.. admonition:: Historical Note - - Given the purpose for which it's used, the name of this attribute - (``use_for_related_fields``) might seem a little odd. Originally, the - attribute only controlled the type of manager used for related field - access, which is where the name came from. As it became clear the concept - was more broadly useful, the name hasn't been changed. This is primarily - so that existing code will :doc:`continue to work </misc/api-stability>` in - future Django versions. - -Writing Correct Managers For Use In Automatic Manager Instances ---------------------------------------------------------------- - -As already suggested by the `django.contrib.gis` example, above, the -``use_for_related_fields`` feature is primarily for managers that need to -return a custom ``QuerySet`` subclass. In providing this functionality in your -manager, there are a couple of things to remember. - -Do not filter away any results in this type of manager subclass -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -One reason an automatic manager is used is to access objects that are related -to from some other model. In those situations, Django has to be able to see -all the objects for the model it is fetching, so that *anything* which is -referred to can be retrieved. - -If you override the ``get_query_set()`` method and filter out any rows, Django -will return incorrect results. Don't do that. A manager that filters results -in ``get_query_set()`` is not appropriate for use as an automatic manager. - -Set ``use_for_related_fields`` when you define the class -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``use_for_related_fields`` attribute must be set on the manager *class*, -object not on an *instance* of the class. The earlier example shows the -correct way to set it, whereas the following will not work:: - - # BAD: Incorrect code - class MyManager(models.Manager): - ... - - # Sets the attribute on an instance of MyManager. Django will - # ignore this setting. - mgr = MyManager() - mgr.use_for_related_fields = True - - class MyModel(models.Model): - ... - objects = mgr - - # End of incorrect code. - -You also shouldn't change the attribute on the class object after it has been -used in a model, since the attribute's value is processed when the model class -is created and not subsequently reread. Set the attribute on the manager class -when it is first defined, as in the initial example of this section and -everything will work smoothly. - diff --git a/parts/django/docs/topics/db/models.txt b/parts/django/docs/topics/db/models.txt deleted file mode 100644 index 2a19cbd..0000000 --- a/parts/django/docs/topics/db/models.txt +++ /dev/null @@ -1,1234 +0,0 @@ -====== -Models -====== - -.. module:: django.db.models - -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 - :class:`django.db.models.Model`. - - * Each attribute of the model represents a database field. - - * With all of this, Django gives you an automatically-generated - database-access API; see :doc:`/topics/db/queries`. - -.. seealso:: - - 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.) - - .. _official repository of model examples: http://www.djangoproject.com/documentation/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: - -.. code-block:: sql - - 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 :ref:`table-names` for more - details.. - - * An ``id`` field is added automatically, but this behavior can be - overridden. See :ref:`automatic-primary-key-fields`. - - * 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 :doc:`settings file </topics/settings>`. - -Using models -============ - -Once you have defined your models, you need to tell Django you're going to *use* -those models. Do this by editing your settings file and changing the -:setting:`INSTALLED_APPS` setting to add the name of the module that contains -your ``models.py``. - -For example, if the models for your application live in the module -``mysite.myapp.models`` (the package structure that is created for an -application by the :djadmin:`manage.py startapp <startapp>` script), -:setting:`INSTALLED_APPS` should read, in part:: - - INSTALLED_APPS = ( - #... - 'mysite.myapp', - #... - ) - -When you add new apps to :setting:`INSTALLED_APPS`, be sure to run -:djadmin:`manage.py syncdb <syncdb>`. - -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 types ------------ - -Each field in your model should be an instance of the appropriate -:class:`~django.db.models.Field` class. Django uses the field class types to -determine a few things: - - * The database column type (e.g. ``INTEGER``, ``VARCHAR``). - - * The :doc:`widget </ref/forms/widgets>` to use in Django's admin interface, - if you care to use it (e.g. ``<input type="text">``, ``<select>``). - - * The minimal validation requirements, used in Django's admin and in - automatically-generated forms. - -Django ships with dozens of built-in field types; you can find the complete list -in the :ref:`model field reference <model-field-types>`. You can easily write -your own fields if Django's built-in ones don't do the trick; see -:doc:`/howto/custom-model-fields`. - -Field options -------------- - -Each field takes a certain set of field-specific arguments (documented in the -:ref:`model field reference <model-field-types>`). For example, -:class:`~django.db.models.CharField` (and its subclasses) require a -:attr:`~django.db.models.CharField.max_length` argument which specifies the size -of the ``VARCHAR`` database field used to store the data. - -There's also a set of common arguments available to all field types. All are -optional. They're fully explained in the :ref:`reference -<common-model-field-options>`, but here's a quick summary of the most often-used -ones: - - :attr:`~Field.null` - If ``True``, Django will store empty values as ``NULL`` in the database. - Default is ``False``. - - :attr:`~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 - :attr:`blank=True <Field.blank>`, validation on Django's admin site will - allow entry of an empty value. If a field has :attr:`blank=False - <Field.blank>`, the field will be required. - - :attr:`~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 = ( - (u'FR', u'Freshman'), - (u'SO', u'Sophomore'), - (u'JR', u'Junior'), - (u'SR', u'Senior'), - (u'GR', u'Graduate'), - ) - - The first element in each tuple is the value that will be stored in the - database, the second element will be displayed by the admin interface, - or in a ModelChoiceField. Given an instance of a model object, the - display value for a choices field can be accessed using the - ``get_FOO_display`` method. For example:: - - from django.db import models - - class Person(models.Model): - GENDER_CHOICES = ( - (u'M', u'Male'), - (u'F', u'Female'), - ) - name = models.CharField(max_length=60) - gender = models.CharField(max_length=2, choices=GENDER_CHOICES) - - :: - - >>> p = Person(name="Fred Flinstone", gender="M") - >>> p.save() - >>> p.gender - u'M' - >>> p.get_gender_display() - u'Male' - - :attr:`~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. - - :attr:`~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. - - :attr:`~Field.primary_key` - If ``True``, this field is the primary key for the model. - - If you don't specify :attr:`primary_key=True <Field.primary_key>` 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 - :attr:`primary_key=True <Field.primary_key>` on any of your fields - unless you want to override the default primary-key behavior. For more, - see :ref:`automatic-primary-key-fields`. - - :attr:`~Field.unique` - If ``True``, this field must be unique throughout the table. - -Again, these are just short descriptions of the most common field options. Full -details can be found in the :ref:`common model field option reference -<common-model-field-options>`. - -.. _automatic-primary-key-fields: - -Automatic primary key fields ----------------------------- - -By default, Django gives each model the following field:: - - id = models.AutoField(primary_key=True) - -This is an auto-incrementing primary key. - -If you'd like to specify a custom primary key, just specify -:attr:`primary_key=True <Field.primary_key>` on one of your fields. If Django -sees you've explicitly set :attr:`Field.primary_key`, it won't add the automatic -``id`` column. - -Each model requires exactly one field to have :attr:`primary_key=True -<Field.primary_key>`. - -.. _verbose-field-names: - -Verbose field names -------------------- - -Each field type, except for :class:`~django.db.models.ForeignKey`, -:class:`~django.db.models.ManyToManyField` and -:class:`~django.db.models.OneToOneField`, takes an optional first positional -argument -- a verbose name. If the verbose name isn't given, Django will -automatically create it using the field's attribute name, converting underscores -to spaces. - -In this example, the verbose name is ``"person's first name"``:: - - first_name = models.CharField("person's first name", max_length=30) - -In this example, the verbose name is ``"first name"``:: - - first_name = models.CharField(max_length=30) - -:class:`~django.db.models.ForeignKey`, -:class:`~django.db.models.ManyToManyField` and -:class:`~django.db.models.OneToOneField` require the first argument to be a -model class, so use the :attr:`~Field.verbose_name` keyword argument:: - - poll = models.ForeignKey(Poll, verbose_name="the related poll") - sites = models.ManyToManyField(Site, verbose_name="list of sites") - place = models.OneToOneField(Place, verbose_name="related place") - -The convention is not to capitalize the first letter of the -:attr:`~Field.verbose_name`. Django will automatically capitalize the first -letter where it needs to. - -Relationships -------------- - -Clearly, the power of relational databases lies in relating tables to each -other. Django offers ways to define the three most common types of database -relationships: many-to-one, many-to-many and one-to-one. - -Many-to-one relationships -~~~~~~~~~~~~~~~~~~~~~~~~~ - -To define a many-to-one relationship, use :class:`~django.db.models.ForeignKey`. -You use it just like any other :class:`~django.db.models.Field` type: by -including it as a class attribute of your model. - -:class:`~django.db.models.ForeignKey` requires a positional argument: the class -to which the model is related. - -For example, if a ``Car`` model has a ``Manufacturer`` -- that is, a -``Manufacturer`` makes multiple cars but each ``Car`` only has one -``Manufacturer`` -- use the following definitions:: - - class Manufacturer(models.Model): - # ... - - class Car(models.Model): - manufacturer = models.ForeignKey(Manufacturer) - # ... - -You can also create :ref:`recursive relationships <recursive-relationships>` (an -object with a many-to-one relationship to itself) and :ref:`relationships to -models not yet defined <lazy-relationships>`; see :ref:`the model field -reference <ref-foreignkey>` for details. - -It's suggested, but not required, that the name of a -:class:`~django.db.models.ForeignKey` field (``manufacturer`` in the example -above) be the name of the model, lowercase. You can, of course, call the field -whatever you want. For example:: - - class Car(models.Model): - company_that_makes_it = models.ForeignKey(Manufacturer) - # ... - -.. seealso:: - - See the `Many-to-one relationship model example`_ for a full example. - -.. _Many-to-one relationship model example: http://www.djangoproject.com/documentation/models/many_to_one/ - -:class:`~django.db.models.ForeignKey` fields also accept a number of extra -arguments which are explained in :ref:`the model field reference -<foreign-key-arguments>`. These options help define how the relationship should -work; all are optional. - -Many-to-many relationships -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To define a many-to-many relationship, use -:class:`~django.db.models.ManyToManyField`. You use it just like any other -:class:`~django.db.models.Field` type: by including it as a class attribute of -your model. - -:class:`~django.db.models.ManyToManyField` requires a positional argument: the -class to which the model is related. - -For example, if a ``Pizza`` has multiple ``Topping`` objects -- that is, a -``Topping`` can be on multiple pizzas and each ``Pizza`` has multiple toppings --- here's how you'd represent that:: - - class Topping(models.Model): - # ... - - class Pizza(models.Model): - # ... - toppings = models.ManyToManyField(Topping) - -As with :class:`~django.db.models.ForeignKey`, you can also create -:ref:`recursive relationships <recursive-relationships>` (an object with a -many-to-many relationship to itself) and :ref:`relationships to models not yet -defined <lazy-relationships>`; see :ref:`the model field reference -<ref-manytomany>` for details. - -It's suggested, but not required, that the name of a -:class:`~django.db.models.ManyToManyField` (``toppings`` in the example above) -be a plural describing the set of related model objects. - -It doesn't matter which model gets the -:class:`~django.db.models.ManyToManyField`, but you only need it in one of the -models -- not in both. - -Generally, :class:`~django.db.models.ManyToManyField` instances should go in the -object that's going to be edited in the admin interface, if you're using -Django's admin. In the above example, ``toppings`` is in ``Pizza`` (rather than -``Topping`` having a ``pizzas`` :class:`~django.db.models.ManyToManyField` ) -because it's more natural to think about a pizza having toppings than a -topping being on multiple pizzas. The way it's set up above, the ``Pizza`` admin -form would let users select the toppings. - -.. seealso:: - - See the `Many-to-many relationship model example`_ for a full example. - -.. _Many-to-many relationship model example: http://www.djangoproject.com/documentation/models/many_to_many/ - -:class:`~django.db.models.ManyToManyField` fields also accept a number of extra -arguments which are explained in :ref:`the model field reference -<manytomany-arguments>`. These options help define how the relationship should -work; all are optional. - -.. _intermediary-manytomany: - -Extra fields on many-to-many relationships -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -When you're only dealing with simple many-to-many relationships such as -mixing and matching pizzas and toppings, a standard :class:`~django.db.models.ManyToManyField` is all you need. However, sometimes -you may need to associate data with the relationship between two models. - -For example, consider the case of an application tracking the musical groups -which musicians belong to. There is a many-to-many relationship between a person -and the groups of which they are a member, so you could use a -:class:`~django.db.models.ManyToManyField` to represent this relationship. -However, there is a lot of detail about the membership that you might want to -collect, such as the date at which the person joined the group. - -For these situations, Django allows you to specify the model that will be used -to govern the many-to-many relationship. You can then put extra fields on the -intermediate model. The intermediate model is associated with the -:class:`~django.db.models.ManyToManyField` using the -:attr:`through <ManyToManyField.through>` argument to point to the model -that will act as an intermediary. For our musician example, the code would look -something like this:: - - class Person(models.Model): - name = models.CharField(max_length=128) - - def __unicode__(self): - return self.name - - class Group(models.Model): - name = models.CharField(max_length=128) - members = models.ManyToManyField(Person, through='Membership') - - def __unicode__(self): - return self.name - - class Membership(models.Model): - person = models.ForeignKey(Person) - group = models.ForeignKey(Group) - date_joined = models.DateField() - invite_reason = models.CharField(max_length=64) - -When you set up the intermediary model, you explicitly specify foreign -keys to the models that are involved in the ManyToMany relation. This -explicit declaration defines how the two models are related. - -There are a few restrictions on the intermediate model: - - * Your intermediate model must contain one - and *only* one - foreign key - to the target model (this would be ``Person`` in our example). If you - have more than one foreign key, a validation error will be raised. - - * Your intermediate model must contain one - and *only* one - foreign key - to the source model (this would be ``Group`` in our example). If you - have more than one foreign key, a validation error will be raised. - - * The only exception to this is a model which has a many-to-many - relationship to itself, through an intermediary model. In this - case, two foreign keys to the same model are permitted, but they - will be treated as the two (different) sides of the many-to-many - relation. - - * When defining a many-to-many relationship from a model to - itself, using an intermediary model, you *must* use - :attr:`symmetrical=False <ManyToManyField.symmetrical>` (see - :ref:`the model field reference <manytomany-arguments>`). - -Now that you have set up your :class:`~django.db.models.ManyToManyField` to use -your intermediary model (``Membership``, in this case), you're ready to start -creating some many-to-many relationships. You do this by creating instances of -the intermediate model:: - - >>> ringo = Person.objects.create(name="Ringo Starr") - >>> paul = Person.objects.create(name="Paul McCartney") - >>> beatles = Group.objects.create(name="The Beatles") - >>> m1 = Membership(person=ringo, group=beatles, - ... date_joined=date(1962, 8, 16), - ... invite_reason= "Needed a new drummer.") - >>> m1.save() - >>> beatles.members.all() - [<Person: Ringo Starr>] - >>> ringo.group_set.all() - [<Group: The Beatles>] - >>> m2 = Membership.objects.create(person=paul, group=beatles, - ... date_joined=date(1960, 8, 1), - ... invite_reason= "Wanted to form a band.") - >>> beatles.members.all() - [<Person: Ringo Starr>, <Person: Paul McCartney>] - -Unlike normal many-to-many fields, you *can't* use ``add``, ``create``, -or assignment (i.e., ``beatles.members = [...]``) to create relationships:: - - # THIS WILL NOT WORK - >>> beatles.members.add(john) - # NEITHER WILL THIS - >>> beatles.members.create(name="George Harrison") - # AND NEITHER WILL THIS - >>> beatles.members = [john, paul, ringo, george] - -Why? You can't just create a relationship between a ``Person`` and a ``Group`` -- you need to specify all the detail for the relationship required by the -``Membership`` model. The simple ``add``, ``create`` and assignment calls -don't provide a way to specify this extra detail. As a result, they are -disabled for many-to-many relationships that use an intermediate model. -The only way to create this type of relationship is to create instances of the -intermediate model. - -The :meth:`~django.db.models.fields.related.RelatedManager.remove` method is -disabled for similar reasons. However, the -:meth:`~django.db.models.fields.related.RelatedManager.clear` method can be -used to remove all many-to-many relationships for an instance:: - - # Beatles have broken up - >>> beatles.members.clear() - -Once you have established the many-to-many relationships by creating instances -of your intermediate model, you can issue queries. Just as with normal -many-to-many relationships, you can query using the attributes of the -many-to-many-related model:: - - # Find all the groups with a member whose name starts with 'Paul' - >>> Group.objects.filter(members__name__startswith='Paul') - [<Group: The Beatles>] - -As you are using an intermediate model, you can also query on its attributes:: - - # Find all the members of the Beatles that joined after 1 Jan 1961 - >>> Person.objects.filter( - ... group__name='The Beatles', - ... membership__date_joined__gt=date(1961,1,1)) - [<Person: Ringo Starr] - - -One-to-one relationships -~~~~~~~~~~~~~~~~~~~~~~~~ - -To define a one-to-one relationship, use -:class:`~django.db.models.OneToOneField`. You use it just like any other -``Field`` type: by including it as a class attribute of your model. - -This is most useful on the primary key of an object when that object "extends" -another object in some way. - -:class:`~django.db.models.OneToOneField` requires a positional argument: the -class to which the model is related. - -For example, if you were building a database of "places", you would -build pretty standard stuff such as address, phone number, etc. in the -database. Then, if you wanted to build a database of restaurants on -top of the places, instead of repeating yourself and replicating those -fields in the ``Restaurant`` model, you could make ``Restaurant`` have -a :class:`~django.db.models.OneToOneField` to ``Place`` (because a -restaurant "is a" place; in fact, to handle this you'd typically use -:ref:`inheritance <model-inheritance>`, which involves an implicit -one-to-one relation). - -As with :class:`~django.db.models.ForeignKey`, a -:ref:`recursive relationship <recursive-relationships>` -can be defined and -:ref:`references to as-yet undefined models <lazy-relationships>` -can be made; see :ref:`the model field reference <ref-onetoone>` for details. - -.. seealso:: - - See the `One-to-one relationship model example`_ for a full example. - -.. _One-to-one relationship model example: http://www.djangoproject.com/documentation/models/one_to_one/ - -.. versionadded:: 1.0 - -:class:`~django.db.models.OneToOneField` fields also accept one optional argument -described in the :ref:`model field reference <ref-onetoone>`. - -:class:`~django.db.models.OneToOneField` classes used to automatically become -the primary key on a model. This is no longer true (although you can manually -pass in the :attr:`~django.db.models.Field.primary_key` argument if you like). -Thus, it's now possible to have multiple fields of type -:class:`~django.db.models.OneToOneField` on a single model. - -Models across files -------------------- - -It's perfectly OK to relate a model to one from another app. To do this, -import the related model at the top of the model that holds your model. Then, -just refer to the other model class wherever needed. For example:: - - from geography.models import ZipCode - - class Restaurant(models.Model): - # ... - zip_code = models.ForeignKey(ZipCode) - -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 the -:attr:`~Field.db_column` option. - -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. - -Custom field types ------------------- - -.. versionadded:: 1.0 - -If one of the existing model fields cannot be used to fit your purposes, or if -you wish to take advantage of some less common database column types, you can -create your own field class. Full coverage of creating your own fields is -provided in :doc:`/howto/custom-model-fields`. - -.. _meta-options: - -Meta options -============ - -Give your model metadata by using an inner ``class Meta``, like so:: - - class Ox(models.Model): - horn_length = models.IntegerField() - - class Meta: - ordering = ["horn_length"] - verbose_name_plural = "oxen" - -Model metadata is "anything that's not a field", such as ordering options -(:attr:`~Options.ordering`), database table name (:attr:`~Options.db_table`), or -human-readable singular and plural names (:attr:`~Options.verbose_name` and -:attr:`~Options.verbose_name_plural`). None are required, and adding ``class -Meta`` to a model is completely optional. - -A complete list of all possible ``Meta`` options can be found in the :doc:`model -option reference </ref/models/options>`. - -.. _model-methods: - -Model methods -============= - -Define custom methods on a model to add custom "row-level" functionality to your -objects. Whereas :class:`~django.db.models.Manager` methods are intended to do -"table-wide" things, model methods should act on a particular model instance. - -This is a valuable technique for keeping business logic in one place -- the -model. - -For example, this model has a few custom methods:: - - from django.contrib.localflavor.us.models import USStateField - - class Person(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - birth_date = models.DateField() - address = models.CharField(max_length=100) - city = models.CharField(max_length=50) - state = USStateField() # Yes, this is America-centric... - - def baby_boomer_status(self): - "Returns the person's baby-boomer status." - import datetime - if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31): - return "Baby boomer" - if self.birth_date < datetime.date(1945, 8, 1): - return "Pre-boomer" - return "Post-boomer" - - def is_midwestern(self): - "Returns True if this person is from the Midwest." - return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO') - - def _get_full_name(self): - "Returns the person's full name." - return '%s %s' % (self.first_name, self.last_name) - full_name = property(_get_full_name) - -The last method in this example is a :term:`property`. `Read more about -properties`_. - -.. _Read more about properties: http://www.python.org/download/releases/2.2/descrintro/#property - -The :doc:`model instance reference </ref/models/instances>` has a complete list -of :ref:`methods automatically given to each model <model-instance-methods>`. -You can override most of these -- see `overriding predefined model methods`_, -below -- but there are a couple that you'll almost always want to define: - - :meth:`~Model.__unicode__` - A Python "magic method" that returns a unicode "representation" of any - object. This is what Python and Django will use whenever a model - instance needs to be coerced and displayed as a plain string. Most - notably, this happens when you display an object in an interactive - console or in the admin. - - You'll always want to define this method; the default isn't very helpful - at all. - - :meth:`~Model.get_absolute_url` - This tells Django how to calculate the URL for an object. Django uses - this in its admin interface, and any time it needs to figure out a URL - for an object. - - Any object that has a URL that uniquely identifies it should define this - method. - -.. _overriding-model-methods: - -Overriding predefined model methods ------------------------------------ - -There's another set of :ref:`model methods <model-instance-methods>` that -encapsulate a bunch of database behavior that you'll want to customize. In -particular you'll often want to change the way :meth:`~Model.save` and -:meth:`~Model.delete` work. - -You're free to override these methods (and any other model method) to alter -behavior. - -A classic use-case for overriding the built-in methods is if you want something -to happen whenever you save an object. For example (see -:meth:`~Model.save` for documentation of the parameters it accepts):: - - class Blog(models.Model): - name = models.CharField(max_length=100) - tagline = models.TextField() - - def save(self, *args, **kwargs): - do_something() - super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. - do_something_else() - -You can also prevent saving:: - - class Blog(models.Model): - name = models.CharField(max_length=100) - tagline = models.TextField() - - def save(self, *args, **kwargs): - if self.name == "Yoko Ono's blog": - return # Yoko shall never have her own blog! - else: - super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. - -It's important to remember to call the superclass method -- that's -that ``super(Blog, self).save(*args, **kwargs)`` business -- to ensure -that the object still gets saved into the database. If you forget to -call the superclass method, the default behavior won't happen and the -database won't get touched. - -It's also important that you pass through the arguments that can be -passed to the model method -- that's what the ``*args, **kwargs`` bit -does. Django will, from time to time, extend the capabilities of -built-in model methods, adding new arguments. If you use ``*args, -**kwargs`` in your method definitions, you are guaranteed that your -code will automatically support those arguments when they are added. - -Executing custom SQL --------------------- - -Another common pattern is writing custom SQL statements in model methods and -module-level methods. For more details on using raw SQL, see the documentation -on :doc:`using raw SQL</topics/db/sql>`. - -.. _model-inheritance: - -Model inheritance -================= - -.. versionadded:: 1.0 - -Model inheritance in Django works almost identically to the way normal -class inheritance works in Python. The only decision you have to make -is whether you want the parent models to be models in their own right -(with their own database tables), or if the parents are just holders -of common information that will only be visible through the child -models. - -There are three styles of inheritance that are possible in Django. - - 1. Often, you will just want to use the parent class to hold information that - you don't want to have to type out for each child model. This class isn't - going to ever be used in isolation, so :ref:`abstract-base-classes` are - what you're after. - 2. If you're subclassing an existing model (perhaps something from another - application entirely) and want each model to have its own database table, - :ref:`multi-table-inheritance` is the way to go. - 3. Finally, if you only want to modify the Python-level behaviour of a model, - without changing the models fields in any way, you can use - :ref:`proxy-models`. - -.. _abstract-base-classes: - -Abstract base classes ---------------------- - -Abstract base classes are useful when you want to put some common -information into a number of other models. You write your base class -and put ``abstract=True`` in the :ref:`Meta <meta-options>` -class. This model will then not be used to create any database -table. Instead, when it is used as a base class for other models, its -fields will be added to those of the child class. It is an error to -have fields in the abstract base class with the same name as those in -the child (and Django will raise an exception). - -An example:: - - class CommonInfo(models.Model): - name = models.CharField(max_length=100) - age = models.PositiveIntegerField() - - class Meta: - abstract = True - - class Student(CommonInfo): - home_group = models.CharField(max_length=5) - -The ``Student`` model will have three fields: ``name``, ``age`` and -``home_group``. The ``CommonInfo`` model cannot be used as a normal Django -model, since it is an abstract base class. It does not generate a database -table or have a manager, and cannot be instantiated or saved directly. - -For many uses, this type of model inheritance will be exactly what you want. -It provides a way to factor out common information at the Python level, whilst -still only creating one database table per child model at the database level. - -``Meta`` inheritance -~~~~~~~~~~~~~~~~~~~~ - -When an abstract base class is created, Django makes any :ref:`Meta <meta-options>` -inner class you declared in the base class available as an -attribute. If a child class does not declare its own :ref:`Meta <meta-options>` -class, it will inherit the parent's :ref:`Meta <meta-options>`. If the child wants to -extend the parent's :ref:`Meta <meta-options>` class, it can subclass it. For example:: - - class CommonInfo(models.Model): - ... - class Meta: - abstract = True - ordering = ['name'] - - class Student(CommonInfo): - ... - class Meta(CommonInfo.Meta): - db_table = 'student_info' - -Django does make one adjustment to the :ref:`Meta <meta-options>` class of an abstract base -class: before installing the :ref:`Meta <meta-options>` attribute, it sets ``abstract=False``. -This means that children of abstract base classes don't automatically become -abstract classes themselves. Of course, you can make an abstract base class -that inherits from another abstract base class. You just need to remember to -explicitly set ``abstract=True`` each time. - -Some attributes won't make sense to include in the :ref:`Meta <meta-options>` class of an -abstract base class. For example, including ``db_table`` would mean that all -the child classes (the ones that don't specify their own :ref:`Meta <meta-options>`) would use -the same database table, which is almost certainly not what you want. - -.. _abstract-related-name: - -Be careful with ``related_name`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you are using the :attr:`~django.db.models.ForeignKey.related_name` attribute on a ``ForeignKey`` or -``ManyToManyField``, you must always specify a *unique* reverse name for the -field. This would normally cause a problem in abstract base classes, since the -fields on this class are included into each of the child classes, with exactly -the same values for the attributes (including :attr:`~django.db.models.ForeignKey.related_name`) each time. - -.. versionchanged:: 1.2 - -To work around this problem, when you are using :attr:`~django.db.models.ForeignKey.related_name` in an -abstract base class (only), part of the name should contain -``'%(app_label)s'`` and ``'%(class)s'``. - -- ``'%(class)s'`` is replaced by the lower-cased name of the child class - that the field is used in. -- ``'%(app_label)s'`` is replaced by the lower-cased name of the app the child - class is contained within. Each installed application name must be unique - and the model class names within each app must also be unique, therefore the - resulting name will end up being different. - -For example, given an app ``common/models.py``:: - - class Base(models.Model): - m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related") - - class Meta: - abstract = True - - class ChildA(Base): - pass - - class ChildB(Base): - pass - -Along with another app ``rare/models.py``:: - - from common.models import Base - - class ChildB(Base): - pass - -The reverse name of the ``commmon.ChildA.m2m`` field will be -``common_childa_related``, whilst the reverse name of the -``common.ChildB.m2m`` field will be ``common_childb_related``, and finally the -reverse name of the ``rare.ChildB.m2m`` field will be ``rare_childb_related``. -It is up to you how you use the ``'%(class)s'`` and ``'%(app_label)s`` portion -to construct your related name, but if you forget to use it, Django will raise -errors when you validate your models (or run :djadmin:`syncdb`). - -If you don't specify a :attr:`~django.db.models.ForeignKey.related_name` -attribute for a field in an abstract base class, the default reverse name will -be the name of the child class followed by ``'_set'``, just as it normally -would be if you'd declared the field directly on the child class. For example, -in the above code, if the :attr:`~django.db.models.ForeignKey.related_name` -attribute was omitted, the reverse name for the ``m2m`` field would be -``childa_set`` in the ``ChildA`` case and ``childb_set`` for the ``ChildB`` -field. - -.. _multi-table-inheritance: - -Multi-table inheritance ------------------------ - -The second type of model inheritance supported by Django is when each model in -the hierarchy is a model all by itself. Each model corresponds to its own -database table and can be queried and created individually. The inheritance -relationship introduces links between the child model and each of its parents -(via an automatically-created :class:`~django.db.models.fields.OneToOneField`). -For example:: - - class Place(models.Model): - name = models.CharField(max_length=50) - address = models.CharField(max_length=80) - - class Restaurant(Place): - serves_hot_dogs = models.BooleanField() - serves_pizza = models.BooleanField() - -All of the fields of ``Place`` will also be available in ``Restaurant``, -although the data will reside in a different database table. So these are both -possible:: - - >>> Place.objects.filter(name="Bob's Cafe") - >>> Restaurant.objects.filter(name="Bob's Cafe") - -If you have a ``Place`` that is also a ``Restaurant``, you can get from the -``Place`` object to the ``Restaurant`` object by using the lower-case version -of the model name:: - - >>> p = Place.objects.get(id=12) - # If p is a Restaurant object, this will give the child class: - >>> p.restaurant - <Restaurant: ...> - -However, if ``p`` in the above example was *not* a ``Restaurant`` (it had been -created directly as a ``Place`` object or was the parent of some other class), -referring to ``p.restaurant`` would raise a Restaurant.DoesNotExist exception. - -``Meta`` and multi-table inheritance -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the multi-table inheritance situation, it doesn't make sense for a child -class to inherit from its parent's :ref:`Meta <meta-options>` class. All the :ref:`Meta <meta-options>` options -have already been applied to the parent class and applying them again would -normally only lead to contradictory behavior (this is in contrast with the -abstract base class case, where the base class doesn't exist in its own -right). - -So a child model does not have access to its parent's :ref:`Meta -<meta-options>` class. However, there are a few limited cases where the child -inherits behavior from the parent: if the child does not specify an -:attr:`~django.db.models.Options.ordering` attribute or a -:attr:`~django.db.models.Options.get_latest_by` attribute, it will inherit -these from its parent. - -If the parent has an ordering and you don't want the child to have any natural -ordering, you can explicitly disable it:: - - class ChildModel(ParentModel): - ... - class Meta: - # Remove parent's ordering effect - ordering = [] - -Inheritance and reverse relations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Because multi-table inheritance uses an implicit -:class:`~django.db.models.OneToOneField` to link the child and -the parent, it's possible to move from the parent down to the child, -as in the above example. However, this uses up the name that is the -default :attr:`~django.db.models.ForeignKey.related_name` value for -:class:`~django.db.models.ForeignKey` and -:class:`~django.db.models.ManyToManyField` relations. If you -are putting those types of relations on a subclass of another model, -you **must** specify the -:attr:`~django.db.models.ForeignKey.related_name` attribute on each -such field. If you forget, Django will raise an error when you run -:djadmin:`validate` or :djadmin:`syncdb`. - -For example, using the above ``Place`` class again, let's create another -subclass with a :class:`~django.db.models.ManyToManyField`:: - - class Supplier(Place): - # Must specify related_name on all relations. - customers = models.ManyToManyField(Restaurant, related_name='provider') - - -Specifying the parent link field -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As mentioned, Django will automatically create a -:class:`~django.db.models.OneToOneField` linking your child -class back any non-abstract parent models. If you want to control the -name of the attribute linking back to the parent, you can create your -own :class:`~django.db.models.OneToOneField` and set -:attr:`parent_link=True <django.db.models.OneToOneField.parent_link>` -to indicate that your field is the link back to the parent class. - -.. _proxy-models: - -Proxy models ------------- - -.. versionadded:: 1.1 - -When using :ref:`multi-table inheritance <multi-table-inheritance>`, a new -database table is created for each subclass of a model. This is usually the -desired behavior, since the subclass needs a place to store any additional -data fields that are not present on the base class. Sometimes, however, you -only want to change the Python behavior of a model -- perhaps to change the -default manager, or add a new method. - -This is what proxy model inheritance is for: creating a *proxy* for the -original model. You can create, delete and update instances of the proxy model -and all the data will be saved as if you were using the original (non-proxied) -model. The difference is that you can change things like the default model -ordering or the default manager in the proxy, without having to alter the -original. - -Proxy models are declared like normal models. You tell Django that it's a -proxy model by setting the :attr:`~django.db.models.Options.proxy` attribute of -the ``Meta`` class to ``True``. - -For example, suppose you want to add a method to the standard -:class:`~django.contrib.auth.models.User` model that will be used in your -templates. You can do it like this:: - - from django.contrib.auth.models import User - - class MyUser(User): - class Meta: - proxy = True - - def do_something(self): - ... - -The ``MyUser`` class operates on the same database table as its parent -:class:`~django.contrib.auth.models.User` class. In particular, any new -instances of :class:`~django.contrib.auth.models.User` will also be accessible -through ``MyUser``, and vice-versa:: - - >>> u = User.objects.create(username="foobar") - >>> MyUser.objects.get(username="foobar") - <MyUser: foobar> - -You could also use a proxy model to define a different default ordering on a -model. The standard :class:`~django.contrib.auth.models.User` model has no -ordering defined on it (intentionally; sorting is expensive and we don't want -to do it all the time when we fetch users). You might want to regularly order -by the ``username`` attribute when you use the proxy. This is easy:: - - class OrderedUser(User): - class Meta: - ordering = ["username"] - proxy = True - -Now normal :class:`~django.contrib.auth.models.User` queries will be unordered -and ``OrderedUser`` queries will be ordered by ``username``. - -QuerySets still return the model that was requested -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There is no way to have Django return, say, a ``MyUser`` object whenever you -query for :class:`~django.contrib.auth.models.User` objects. A queryset for -``User`` objects will return those types of objects. The whole point of proxy -objects is that code relying on the original ``User`` will use those and your -own code can use the extensions you included (that no other code is relying on -anyway). It is not a way to replace the ``User`` (or any other) model -everywhere with something of your own creation. - -Base class restrictions -~~~~~~~~~~~~~~~~~~~~~~~ - -A proxy model must inherit from exactly one non-abstract model class. You -can't inherit from multiple non-abstract models as the proxy model doesn't -provide any connection between the rows in the different database tables. A -proxy model can inherit from any number of abstract model classes, providing -they do *not* define any model fields. - -Proxy models inherit any ``Meta`` options that they don't define from their -non-abstract model parent (the model they are proxying for). - -Proxy model managers -~~~~~~~~~~~~~~~~~~~~ - -If you don't specify any model managers on a proxy model, it inherits the -managers from its model parents. If you define a manager on the proxy model, -it will become the default, although any managers defined on the parent -classes will still be available. - -Continuing our example from above, you could change the default manager used -when you query the ``User`` model like this:: - - class NewManager(models.Manager): - ... - - class MyUser(User): - objects = NewManager() - - class Meta: - proxy = True - -If you wanted to add a new manager to the Proxy, without replacing the -existing default, you can use the techniques described in the :ref:`custom -manager <custom-managers-and-inheritance>` documentation: create a base class -containing the new managers and inherit that after the primary base class:: - - # Create an abstract class for the new manager. - class ExtraManagers(models.Model): - secondary = NewManager() - - class Meta: - abstract = True - - class MyUser(User, ExtraManagers): - class Meta: - proxy = True - -You probably won't need to do this very often, but, when you do, it's -possible. - -.. _proxy-vs-unmanaged-models: - -Differences between proxy inheritance and unmanaged models -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Proxy model inheritance might look fairly similar to creating an unmanaged -model, using the :attr:`~django.db.models.Options.managed` attribute on a -model's ``Meta`` class. The two alternatives are not quite the same and it's -worth considering which one you should use. - -One difference is that you can (and, in fact, must unless you want an empty -model) specify model fields on models with ``Meta.managed=False``. You could, -with careful setting of :attr:`Meta.db_table -<django.db.models.Options.db_table>` create an unmanaged model that shadowed -an existing model and add Python methods to it. However, that would be very -repetitive and fragile as you need to keep both copies synchronized if you -make any changes. - -The other difference that is more important for proxy models, is how model -managers are handled. Proxy models are intended to behave exactly like the -model they are proxying for. So they inherit the parent model's managers, -including the default manager. In the normal multi-table model inheritance -case, children do not inherit managers from their parents as the custom -managers aren't always appropriate when extra fields are involved. The -:ref:`manager documentation <custom-managers-and-inheritance>` has more -details about this latter case. - -When these two features were implemented, attempts were made to squash them -into a single option. It turned out that interactions with inheritance, in -general, and managers, in particular, made the API very complicated and -potentially difficult to understand and use. It turned out that two options -were needed in any case, so the current separation arose. - -So, the general rules are: - - 1. If you are mirroring an existing model or database table and don't want - all the original database table columns, use ``Meta.managed=False``. - That option is normally useful for modeling database views and tables - not under the control of Django. - 2. If you are wanting to change the Python-only behavior of a model, but - keep all the same fields as in the original, use ``Meta.proxy=True``. - This sets things up so that the proxy model is an exact copy of the - storage structure of the original model when data is saved. - -Multiple inheritance --------------------- - -Just as with Python's subclassing, it's possible for a Django model to inherit -from multiple parent models. Keep in mind that normal Python name resolution -rules apply. The first base class that a particular name (e.g. :ref:`Meta -<meta-options>`) appears in will be the one that is used; for example, this -means that if multiple parents contain a :ref:`Meta <meta-options>` class, -only the first one is going to be used, and all others will be ignored. - -Generally, you won't need to inherit from multiple parents. The main use-case -where this is useful is for "mix-in" classes: adding a particular extra -field or method to every class that inherits the mix-in. Try to keep your -inheritance hierarchies as simple and straightforward as possible so that you -won't have to struggle to work out where a particular piece of information is -coming from. - -Field name "hiding" is not permitted -------------------------------------- - -In normal Python class inheritance, it is permissible for a child class to -override any attribute from the parent class. In Django, this is not permitted -for attributes that are :class:`~django.db.models.fields.Field` instances (at -least, not at the moment). If a base class has a field called ``author``, you -cannot create another model field called ``author`` in any class that inherits -from that base class. - -Overriding fields in a parent model leads to difficulties in areas such as -initialising new instances (specifying which field is being initialized in -``Model.__init__``) and serialization. These are features which normal Python -class inheritance doesn't have to deal with in quite the same way, so the -difference between Django model inheritance and Python class inheritance isn't -arbitrary. - -This restriction only applies to attributes which are -:class:`~django.db.models.fields.Field` instances. Normal Python attributes -can be overridden if you wish. It also only applies to the name of the -attribute as Python sees it: if you are manually specifying the database -column name, you can have the same column name appearing in both a child and -an ancestor model for multi-table inheritance (they are columns in two -different database tables). - -Django will raise a :exc:`~django.core.exceptions.FieldError` if you override -any model field in any ancestor model. diff --git a/parts/django/docs/topics/db/multi-db.txt b/parts/django/docs/topics/db/multi-db.txt deleted file mode 100644 index 1a939b0..0000000 --- a/parts/django/docs/topics/db/multi-db.txt +++ /dev/null @@ -1,574 +0,0 @@ -================== -Multiple databases -================== - -.. versionadded:: 1.2 - -This topic guide describes Django's support for interacting with -multiple databases. Most of the rest of Django's documentation assumes -you are interacting with a single database. If you want to interact -with multiple databases, you'll need to take some additional steps. - -Defining your databases -======================= - -The first step to using more than one database with Django is to tell -Django about the database servers you'll be using. This is done using -the :setting:`DATABASES` setting. This setting maps database aliases, -which are a way to refer to a specific database throughout Django, to -a dictionary of settings for that specific connection. The settings in -the inner dictionaries are described fully in the :setting:`DATABASES` -documentation. - -Databases can have any alias you choose. However, the alias -``default`` has special significance. Django uses the database with -the alias of ``default`` when no other database has been selected. If -you don't have a ``default`` database, you need to be careful to -always specify the database that you want to use. - -The following is an example ``settings.py`` snippet defining two -databases -- a default PostgreSQL database and a MySQL database called -``users``: - -.. code-block:: python - - DATABASES = { - 'default': { - 'NAME': 'app_data', - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'USER': 'postgres_user', - 'PASSWORD': 's3krit' - }, - 'users': { - 'NAME': 'user_data', - 'ENGINE': 'django.db.backends.mysql', - 'USER': 'mysql_user', - 'PASSWORD': 'priv4te' - } - } - -If you attempt to access a database that you haven't defined in your -:setting:`DATABASES` setting, Django will raise a -``django.db.utils.ConnectionDoesNotExist`` exception. - -Synchronizing your databases -============================ - -The :djadmin:`syncdb` management command operates on one database at a -time. By default, it operates on the ``default`` database, but by -providing a :djadminopt:`--database` argument, you can tell syncdb to -synchronize a different database. So, to synchronize all models onto -all databases in our example, you would need to call:: - - $ ./manage.py syncdb - $ ./manage.py syncdb --database=users - -If you don't want every application to be synchronized onto a -particular database, you can define a :ref:`database -router<topics-db-multi-db-routing>` that implements a policy -constraining the availability of particular models. - -Alternatively, if you want fine-grained control of synchronization, -you can pipe all or part of the output of :djadmin:`sqlall` for a -particular application directly into your database prompt, like this:: - - $ ./manage.py sqlall sales | ./manage.py dbshell - -Using other management commands -------------------------------- - -The other ``django-admin.py`` commands that interact with the database -operate in the same way as :djadmin:`syncdb` -- they only ever operate -on one database at a time, using :djadminopt:`--database` to control -the database used. - -.. _topics-db-multi-db-routing: - -Automatic database routing -========================== - -The easiest way to use multiple databases is to set up a database -routing scheme. The default routing scheme ensures that objects remain -'sticky' to their original database (i.e., an object retrieved from -the ``foo`` database will be saved on the same database). The default -routing scheme ensures that if a database isn't specified, all queries -fall back to the ``default`` database. - -You don't have to do anything to activate the default routing scheme --- it is provided 'out of the box' on every Django project. However, -if you want to implement more interesting database allocation -behaviors, you can define and install your own database routers. - -Database routers ----------------- - -A database Router is a class that provides up to four methods: - -.. method:: db_for_read(model, **hints) - - Suggest the database that should be used for read operations for - objects of type ``model``. - - If a database operation is able to provide any additional - information that might assist in selecting a database, it will be - provided in the ``hints`` dictionary. Details on valid hints are - provided :ref:`below <topics-db-multi-db-hints>`. - - Returns None if there is no suggestion. - -.. method:: db_for_write(model, **hints) - - Suggest the database that should be used for writes of objects of - type Model. - - If a database operation is able to provide any additional - information that might assist in selecting a database, it will be - provided in the ``hints`` dictionary. Details on valid hints are - provided :ref:`below <topics-db-multi-db-hints>`. - - Returns None if there is no suggestion. - -.. method:: allow_relation(obj1, obj2, **hints) - - Return True if a relation between obj1 and obj2 should be - allowed, False if the relation should be prevented, or None if - the router has no opinion. This is purely a validation operation, - used by foreign key and many to many operations to determine if a - relation should be allowed between two objects. - -.. method:: allow_syncdb(db, model) - - Determine if the ``model`` should be synchronized onto the - database with alias ``db``. Return True if the model should be - synchronized, False if it should not be synchronized, or None if - the router has no opinion. This method can be used to determine - the availability of a model on a given database. - -A router doesn't have to provide *all* these methods - it omit one or -more of them. If one of the methods is omitted, Django will skip that -router when performing the relevant check. - -.. _topics-db-multi-db-hints: - -Hints -~~~~~ - -The hints received by the database router can be used to decide which -database should receive a given request. - -At present, the only hint that will be provided is ``instance``, an -object instance that is related to the read or write operation that is -underway. This might be the instance that is being saved, or it might -be an instance that is being added in a many-to-many relation. In some -cases, no instance hint will be provided at all. The router checks for -the existence of an instance hint, and determine if that hint should be -used to alter routing behavior. - -Using routers -------------- - -Database routers are installed using the :setting:`DATABASE_ROUTERS` -setting. This setting defines a list of class names, each specifying a -router that should be used by the master router -(``django.db.router``). - -The master router is used by Django's database operations to allocate -database usage. Whenever a query needs to know which database to use, -it calls the master router, providing a model and a hint (if -available). Django then tries each router in turn until a database -suggestion can be found. If no suggestion can be found, it tries the -current ``_state.db`` of the hint instance. If a hint instance wasn't -provided, or the instance doesn't currently have database state, the -master router will allocate the ``default`` database. - -An example ----------- - -.. admonition:: Example purposes only! - - This example is intended as a demonstration of how the router - infrastructure can be used to alter database usage. It - intentionally ignores some complex issues in order to - demonstrate how routers are used. - - This example won't work if any of the models in ``myapp`` contain - relationships to models outside of the ``other`` database. - :ref:`Cross-database relationships <no_cross_database_relations>` - introduce referential integrity problems that Django can't - currently handle. - - The master/slave configuration described is also flawed -- it - doesn't provide any solution for handling replication lag (i.e., - query inconsistencies introduced because of the time taken for a - write to propagate to the slaves). It also doesn't consider the - interaction of transactions with the database utilization strategy. - -So - what does this mean in practice? Say you want ``myapp`` to -exist on the ``other`` database, and you want all other models in a -master/slave relationship between the databases ``master``, ``slave1`` and -``slave2``. To implement this, you would need 2 routers:: - - class MyAppRouter(object): - """A router to control all database operations on models in - the myapp application""" - - def db_for_read(self, model, **hints): - "Point all operations on myapp models to 'other'" - if model._meta.app_label == 'myapp': - return 'other' - return None - - def db_for_write(self, model, **hints): - "Point all operations on myapp models to 'other'" - if model._meta.app_label == 'myapp': - return 'other' - return None - - def allow_relation(self, obj1, obj2, **hints): - "Allow any relation if a model in myapp is involved" - if obj1._meta.app_label == 'myapp' or obj2._meta.app_label == 'myapp': - return True - return None - - def allow_syncdb(self, db, model): - "Make sure the myapp app only appears on the 'other' db" - if db == 'other': - return model._meta.app_label == 'myapp' - elif model._meta.app_label == 'myapp': - return False - return None - - class MasterSlaveRouter(object): - """A router that sets up a simple master/slave configuration""" - - def db_for_read(self, model, **hints): - "Point all read operations to a random slave" - return random.choice(['slave1','slave2']) - - def db_for_write(self, model, **hints): - "Point all write operations to the master" - return 'master' - - def allow_relation(self, obj1, obj2, **hints): - "Allow any relation between two objects in the db pool" - db_list = ('master','slave1','slave2') - if obj1._state.db in db_list and obj2._state.db in db_list: - return True - return None - - def allow_syncdb(self, db, model): - "Explicitly put all models on all databases." - return True - -Then, in your settings file, add the following (substituting ``path.to.`` with -the actual python path to the module where you define the routers):: - - DATABASE_ROUTERS = ['path.to.MyAppRouter', 'path.to.MasterSlaveRouter'] - -The order in which routers are processed is significant. Routers will -be queried in the order the are listed in the -:setting:`DATABASE_ROUTERS` setting . In this example, the -``MyAppRouter`` is processed before the ``MasterSlaveRouter``, and as a -result, decisions concerning the models in ``myapp`` are processed -before any other decision is made. If the :setting:`DATABASE_ROUTERS` -setting listed the two routers in the other order, -``MasterSlaveRouter.allow_syncdb()`` would be processed first. The -catch-all nature of the MasterSlaveRouter implementation would mean -that all models would be available on all databases. - -With this setup installed, lets run some Django code:: - - >>> # This retrieval will be performed on the 'credentials' database - >>> fred = User.objects.get(username='fred') - >>> fred.first_name = 'Frederick' - - >>> # This save will also be directed to 'credentials' - >>> fred.save() - - >>> # These retrieval will be randomly allocated to a slave database - >>> dna = Person.objects.get(name='Douglas Adams') - - >>> # A new object has no database allocation when created - >>> mh = Book(title='Mostly Harmless') - - >>> # This assignment will consult the router, and set mh onto - >>> # the same database as the author object - >>> mh.author = dna - - >>> # This save will force the 'mh' instance onto the master database... - >>> mh.save() - - >>> # ... but if we re-retrieve the object, it will come back on a slave - >>> mh = Book.objects.get(title='Mostly Harmless') - - -Manually selecting a database -============================= - -Django also provides an API that allows you to maintain complete control -over database usage in your code. A manually specified database allocation -will take priority over a database allocated by a router. - -Manually selecting a database for a ``QuerySet`` ------------------------------------------------- - -You can select the database for a ``QuerySet`` at any point in the -``QuerySet`` "chain." Just call ``using()`` on the ``QuerySet`` to get -another ``QuerySet`` that uses the specified database. - -``using()`` takes a single argument: the alias of the database on -which you want to run the query. For example:: - - >>> # This will run on the 'default' database. - >>> Author.objects.all() - - >>> # So will this. - >>> Author.objects.using('default').all() - - >>> # This will run on the 'other' database. - >>> Author.objects.using('other').all() - -Selecting a database for ``save()`` ------------------------------------ - -Use the ``using`` keyword to ``Model.save()`` to specify to which -database the data should be saved. - -For example, to save an object to the ``legacy_users`` database, you'd -use this:: - - >>> my_object.save(using='legacy_users') - -If you don't specify ``using``, the ``save()`` method will save into -the default database allocated by the routers. - -Moving an object from one database to another -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you've saved an instance to one database, it might be tempting to -use ``save(using=...)`` as a way to migrate the instance to a new -database. However, if you don't take appropriate steps, this could -have some unexpected consequences. - -Consider the following example:: - - >>> p = Person(name='Fred') - >>> p.save(using='first') # (statement 1) - >>> p.save(using='second') # (statement 2) - -In statement 1, a new ``Person`` object is saved to the ``first`` -database. At this time, ``p`` doesn't have a primary key, so Django -issues a SQL ``INSERT`` statement. This creates a primary key, and -Django assigns that primary key to ``p``. - -When the save occurs in statement 2, ``p`` already has a primary key -value, and Django will attempt to use that primary key on the new -database. If the primary key value isn't in use in the ``second`` -database, then you won't have any problems -- the object will be -copied to the new database. - -However, if the primary key of ``p`` is already in use on the -``second`` database, the existing object in the ``second`` database -will be overridden when ``p`` is saved. - -You can avoid this in two ways. First, you can clear the primary key -of the instance. If an object has no primary key, Django will treat it -as a new object, avoiding any loss of data on the ``second`` -database:: - - >>> p = Person(name='Fred') - >>> p.save(using='first') - >>> p.pk = None # Clear the primary key. - >>> p.save(using='second') # Write a completely new object. - -The second option is to use the ``force_insert`` option to ``save()`` -to ensure that Django does a SQL ``INSERT``:: - - >>> p = Person(name='Fred') - >>> p.save(using='first') - >>> p.save(using='second', force_insert=True) - -This will ensure that the person named ``Fred`` will have the same -primary key on both databases. If that primary key is already in use -when you try to save onto the ``second`` database, an error will be -raised. - -Selecting a database to delete from ------------------------------------ - -By default, a call to delete an existing object will be executed on -the same database that was used to retrieve the object in the first -place:: - - >>> u = User.objects.using('legacy_users').get(username='fred') - >>> u.delete() # will delete from the `legacy_users` database - -To specify the database from which a model will be deleted, pass a -``using`` keyword argument to the ``Model.delete()`` method. This -argument works just like the ``using`` keyword argument to ``save()``. - -For example, if you're migrating a user from the ``legacy_users`` -database to the ``new_users`` database, you might use these commands:: - - >>> user_obj.save(using='new_users') - >>> user_obj.delete(using='legacy_users') - -Using managers with multiple databases --------------------------------------- - -Use the ``db_manager()`` method on managers to give managers access to -a non-default database. - -For example, say you have a custom manager method that touches the -database -- ``User.objects.create_user()``. Because ``create_user()`` -is a manager method, not a ``QuerySet`` method, you can't do -``User.objects.using('new_users').create_user()``. (The -``create_user()`` method is only available on ``User.objects``, the -manager, not on ``QuerySet`` objects derived from the manager.) The -solution is to use ``db_manager()``, like this:: - - User.objects.db_manager('new_users').create_user(...) - -``db_manager()`` returns a copy of the manager bound to the database you specify. - -Using ``get_query_set()`` with multiple databases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you're overriding ``get_query_set()`` on your manager, be sure to -either call the method on the parent (using ``super()``) or do the -appropriate handling of the ``_db`` attribute on the manager (a string -containing the name of the database to use). - -For example, if you want to return a custom ``QuerySet`` class from -the ``get_query_set`` method, you could do this:: - - class MyManager(models.Manager): - def get_query_set(self): - qs = CustomQuerySet(self.model) - if self._db is not None: - qs = qs.using(self._db) - return qs - -Exposing multiple databases in Django's admin interface -======================================================= - -Django's admin doesn't have any explicit support for multiple -databases. If you want to provide an admin interface for a model on a -database other than that that specified by your router chain, you'll -need to write custom :class:`~django.contrib.admin.ModelAdmin` classes -that will direct the admin to use a specific database for content. - -``ModelAdmin`` objects have four methods that require customization for -multiple-database support:: - - class MultiDBModelAdmin(admin.ModelAdmin): - # A handy constant for the name of the alternate database. - using = 'other' - - def save_model(self, request, obj, form, change): - # Tell Django to save objects to the 'other' database. - obj.save(using=self.using) - - def queryset(self, request): - # Tell Django to look for objects on the 'other' database. - return super(MultiDBModelAdmin, self).queryset(request).using(self.using) - - def formfield_for_foreignkey(self, db_field, request=None, **kwargs): - # Tell Django to populate ForeignKey widgets using a query - # on the 'other' database. - return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs) - - def formfield_for_manytomany(self, db_field, request=None, **kwargs): - # Tell Django to populate ManyToMany widgets using a query - # on the 'other' database. - return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs) - -The implementation provided here implements a multi-database strategy -where all objects of a given type are stored on a specific database -(e.g., all ``User`` objects are in the ``other`` database). If your -usage of multiple databases is more complex, your ``ModelAdmin`` will -need to reflect that strategy. - -Inlines can be handled in a similar fashion. They require three customized methods:: - - class MultiDBTabularInline(admin.TabularInline): - using = 'other' - - def queryset(self, request): - # Tell Django to look for inline objects on the 'other' database. - return super(MultiDBTabularInline, self).queryset(request).using(self.using) - - def formfield_for_foreignkey(self, db_field, request=None, **kwargs): - # Tell Django to populate ForeignKey widgets using a query - # on the 'other' database. - return super(MultiDBTabularInline, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs) - - def formfield_for_manytomany(self, db_field, request=None, **kwargs): - # Tell Django to populate ManyToMany widgets using a query - # on the 'other' database. - return super(MultiDBTabularInline, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs) - -Once you've written your model admin definitions, they can be -registered with any ``Admin`` instance:: - - from django.contrib import admin - - # Specialize the multi-db admin objects for use with specific models. - class BookInline(MultiDBTabularInline): - model = Book - - class PublisherAdmin(MultiDBModelAdmin): - inlines = [BookInline] - - admin.site.register(Author, MultiDBModelAdmin) - admin.site.register(Publisher, PublisherAdmin) - - othersite = admin.Site('othersite') - othersite.register(Publisher, MultiDBModelAdmin) - -This example sets up two admin sites. On the first site, the -``Author`` and ``Publisher`` objects are exposed; ``Publisher`` -objects have an tabular inline showing books published by that -publisher. The second site exposes just publishers, without the -inlines. - -Using raw cursors with multiple databases -========================================= - -If you are using more than one database you can use -``django.db.connections`` to obtain the connection (and cursor) for a -specific database. ``django.db.connections`` is a dictionary-like -object that allows you to retrieve a specific connection using it's -alias:: - - from django.db import connections - cursor = connections['my_db_alias'].cursor() - -Limitations of multiple databases -================================= - -.. _no_cross_database_relations: - -Cross-database relations ------------------------- - -Django doesn't currently provide any support for foreign key or -many-to-many relationships spanning multiple databases. If you -have used a router to partition models to different databases, -any foreign key and many-to-many relationships defined by those -models must be internal to a single database. - -This is because of referential integrity. In order to maintain a -relationship between two objects, Django needs to know that the -primary key of the related object is valid. If the primary key is -stored on a separate database, it's not possible to easily evaluate -the validity of a primary key. - -If you're using Postgres, Oracle, or MySQL with InnoDB, this is -enforced at the database integrity level -- database level key -constraints prevent the creation of relations that can't be validated. - -However, if you're using SQLite or MySQL with MyISAM tables, there is -no enforced referential integrity; as a result, you may be able to -'fake' cross database foreign keys. However, this configuration is not -officially supported by Django. diff --git a/parts/django/docs/topics/db/optimization.txt b/parts/django/docs/topics/db/optimization.txt deleted file mode 100644 index 7d51052..0000000 --- a/parts/django/docs/topics/db/optimization.txt +++ /dev/null @@ -1,260 +0,0 @@ -============================ -Database access optimization -============================ - -Django's database layer provides various ways to help developers get the most -out of their databases. This document gathers together links to the relevant -documentation, and adds various tips, organized under a number of headings that -outline the steps to take when attempting to optimize your database usage. - -Profile first -============= - -As general programming practice, this goes without saying. Find out :ref:`what -queries you are doing and what they are costing you -<faq-see-raw-sql-queries>`. You may also want to use an external project like -django-debug-toolbar_, or a tool that monitors your database directly. - -Remember that you may be optimizing for speed or memory or both, depending on -your requirements. Sometimes optimizing for one will be detrimental to the -other, but sometimes they will help each other. Also, work that is done by the -database process might not have the same cost (to you) as the same amount of -work done in your Python process. It is up to you to decide what your -priorities are, where the balance must lie, and profile all of these as required -since this will depend on your application and server. - -With everything that follows, remember to profile after every change to ensure -that the change is a benefit, and a big enough benefit given the decrease in -readability of your code. **All** of the suggestions below come with the caveat -that in your circumstances the general principle might not apply, or might even -be reversed. - -.. _django-debug-toolbar: http://robhudson.github.com/django-debug-toolbar/ - -Use standard DB optimization techniques -======================================= - -...including: - -* Indexes. This is a number one priority, *after* you have determined from - profiling what indexes should be added. Use - :attr:`django.db.models.Field.db_index` to add these from Django. - -* Appropriate use of field types. - -We will assume you have done the obvious things above. The rest of this document -focuses on how to use Django in such a way that you are not doing unnecessary -work. This document also does not address other optimization techniques that -apply to all expensive operations, such as :doc:`general purpose caching -</topics/cache>`. - -Understand QuerySets -==================== - -Understanding :doc:`QuerySets </ref/models/querysets>` is vital to getting good -performance with simple code. In particular: - -Understand QuerySet evaluation ------------------------------- - -To avoid performance problems, it is important to understand: - -* that :ref:`QuerySets are lazy <querysets-are-lazy>`. - -* when :ref:`they are evaluated <when-querysets-are-evaluated>`. - -* how :ref:`the data is held in memory <caching-and-querysets>`. - -Understand cached attributes ----------------------------- - -As well as caching of the whole ``QuerySet``, there is caching of the result of -attributes on ORM objects. In general, attributes that are not callable will be -cached. For example, assuming the :ref:`example Weblog models -<queryset-model-example>`:: - - >>> entry = Entry.objects.get(id=1) - >>> entry.blog # Blog object is retrieved at this point - >>> entry.blog # cached version, no DB access - -But in general, callable attributes cause DB lookups every time:: - - >>> entry = Entry.objects.get(id=1) - >>> entry.authors.all() # query performed - >>> entry.authors.all() # query performed again - -Be careful when reading template code - the template system does not allow use -of parentheses, but will call callables automatically, hiding the above -distinction. - -Be careful with your own custom properties - it is up to you to implement -caching. - -Use the ``with`` template tag ------------------------------ - -To make use of the caching behaviour of ``QuerySet``, you may need to use the -:ttag:`with` template tag. - -Use ``iterator()`` ------------------- - -When you have a lot of objects, the caching behaviour of the ``QuerySet`` can -cause a large amount of memory to be used. In this case, -:meth:`~django.db.models.QuerySet.iterator()` may help. - -Do database work in the database rather than in Python -====================================================== - -For instance: - -* At the most basic level, use :ref:`filter and exclude <queryset-api>` to do - filtering in the database. - -* Use :ref:`F() object query expressions <query-expressions>` to do filtering - against other fields within the same model. - -* Use :doc:`annotate to do aggregation in the database </topics/db/aggregation>`. - -If these aren't enough to generate the SQL you need: - -Use ``QuerySet.extra()`` ------------------------- - -A less portable but more powerful method is -:meth:`~django.db.models.QuerySet.extra()`, which allows some SQL to be -explicitly added to the query. If that still isn't powerful enough: - -Use raw SQL ------------ - -Write your own :doc:`custom SQL to retrieve data or populate models -</topics/db/sql>`. Use ``django.db.connection.queries`` to find out what Django -is writing for you and start from there. - -Retrieve everything at once if you know you will need it -======================================================== - -Hitting the database multiple times for different parts of a single 'set' of -data that you will need all parts of is, in general, less efficient than -retrieving it all in one query. This is particularly important if you have a -query that is executed in a loop, and could therefore end up doing many database -queries, when only one was needed. So: - -Use ``QuerySet.select_related()`` ---------------------------------- - -Understand :ref:`QuerySet.select_related() <select-related>` thoroughly, and use it: - -* in view code, - -* and in :doc:`managers and default managers </topics/db/managers>` where - appropriate. Be aware when your manager is and is not used; sometimes this is - tricky so don't make assumptions. - -Don't retrieve things you don't need -==================================== - -Use ``QuerySet.values()`` and ``values_list()`` ------------------------------------------------ - -When you just want a ``dict`` or ``list`` of values, and don't need ORM model -objects, make appropriate usage of :meth:`~django.db.models.QuerySet.values()`. -These can be useful for replacing model objects in template code - as long as -the dicts you supply have the same attributes as those used in the template, -you are fine. - -Use ``QuerySet.defer()`` and ``only()`` ---------------------------------------- - -Use :meth:`~django.db.models.QuerySet.defer()` and -:meth:`~django.db.models.QuerySet.only()` if there are database columns you -know that you won't need (or won't need in most cases) to avoid loading -them. Note that if you *do* use them, the ORM will have to go and get them in a -separate query, making this a pessimization if you use it inappropriately. - -Use QuerySet.count() --------------------- - -...if you only want the count, rather than doing ``len(queryset)``. - -Use QuerySet.exists() ---------------------- - -...if you only want to find out if at least one result exists, rather than ``if -queryset``. - -But: - -Don't overuse ``count()`` and ``exists()`` ------------------------------------------- - -If you are going to need other data from the QuerySet, just evaluate it. - -For example, assuming an Email class that has a ``body`` attribute and a -many-to-many relation to User, the following template code is optimal: - -.. code-block:: html+django - - {% if display_inbox %} - {% with user.emails.all as emails %} - {% if emails %} - <p>You have {{ emails|length }} email(s)</p> - {% for email in emails %} - <p>{{ email.body }}</p> - {% endfor %} - {% else %} - <p>No messages today.</p> - {% endif %} - {% endwith %} - {% endif %} - - -It is optimal because: - - 1. Since QuerySets are lazy, this does no database if 'display_inbox' is False. - - #. Use of ``with`` means that we store ``user.emails.all`` in a variable for - later use, allowing its cache to be re-used. - - #. The line ``{% if emails %}`` causes ``QuerySet.__nonzero__()`` to be called, - which causes the ``user.emails.all()`` query to be run on the database, and - at the least the first line to be turned into an ORM object. If there aren't - any results, it will return False, otherwise True. - - #. The use of ``{{ emails|length }}`` calls ``QuerySet.__len__()``, filling - out the rest of the cache without doing another query. - - #. The ``for`` loop iterates over the already filled cache. - -In total, this code does either one or zero database queries. The only -deliberate optimization performed is the use of the ``with`` tag. Using -``QuerySet.exists()`` or ``QuerySet.count()`` at any point would cause -additional queries. - -Use ``QuerySet.update()`` and ``delete()`` ------------------------------------------- - -Rather than retrieve a load of objects, set some values, and save them -individual, use a bulk SQL UPDATE statement, via :ref:`QuerySet.update() -<topics-db-queries-update>`. Similarly, do :ref:`bulk deletes -<topics-db-queries-delete>` where possible. - -Note, however, that these bulk update methods cannot call the ``save()`` or -``delete()`` methods of individual instances, which means that any custom -behaviour you have added for these methods will not be executed, including -anything driven from the normal database object :doc:`signals </ref/signals>`. - -Use foreign key values directly -------------------------------- - -If you only need a foreign key value, use the foreign key value that is already on -the object you've got, rather than getting the whole related object and taking -its primary key. i.e. do:: - - entry.blog_id - -instead of:: - - entry.blog.id - diff --git a/parts/django/docs/topics/db/queries.txt b/parts/django/docs/topics/db/queries.txt deleted file mode 100644 index 923b1e4..0000000 --- a/parts/django/docs/topics/db/queries.txt +++ /dev/null @@ -1,1110 +0,0 @@ -============== -Making queries -============== - -.. currentmodule:: django.db.models - -Once you've created your :doc:`data models </topics/db/models>`, Django -automatically gives you a database-abstraction API that lets you create, -retrieve, update and delete objects. This document explains how to use this -API. Refer to the :doc:`data model reference </ref/models/index>` for full -details of all the various model lookup options. - -Throughout this guide (and in the reference), we'll refer to the following -models, which comprise a Weblog application: - -.. _queryset-model-example: - -.. code-block:: python - - 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) - n_comments = models.IntegerField() - n_pingbacks = models.IntegerField() - rating = models.IntegerField() - - 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 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. - -.. seealso:: - - ``save()`` takes a number of advanced options not described here. - See the documentation for ``save()`` for complete details. - - To create an object and save it all in one step see the ```create()``` - method. - -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()``. - -Saving ``ForeignKey`` and ``ManyToManyField`` fields ----------------------------------------------------- - -Updating a ``ForeignKey`` field works exactly the same way as saving a normal -field; simply assign an object of the right type to the field in question. -This example updates the ``blog`` attribute of an ``Entry`` instance ``entry``:: - - >>> from blog.models import Entry - >>> entry = Entry.objects.get(pk=1) - >>> 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. This example adds the -``Author`` instance ``joe`` to the ``entry`` object:: - - >>> from blog.models import Author - >>> 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. - -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 - <django.db.models.manager.Manager object at ...> - >>> b = Blog(name='Foo', tagline='Bar') - >>> b.objects - Traceback: - ... - AttributeError: "Manager isn't accessible via Blog instances." - -.. note:: - - ``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``:: - - >>> 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.) - - -Retrieving specific objects with filters ----------------------------------------- - -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) - -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: - -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) - ... ) - -This 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: - -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 -~~~~~~~~~~~~~~~~~~ - -``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*. Take a look at -this example:: - - >>> q = Entry.objects.filter(headline__startswith="What") - >>> q = q.filter(pub_date__lte=datetime.now()) - >>> q = q.exclude(body_text__icontains="food") - >>> print q - -Though this looks like three database hits, in fact it hits the database only -once, at the last line (``print q``). In general, the results of a ``QuerySet`` -aren't fetched from the database until you "ask" for them. When you do, the -``QuerySet`` is *evaluated* by accessing the database. For more details on -exactly when evaluation takes place, see :ref:`when-querysets-are-evaluated`. - - -.. _retrieving-single-object-with-get: - -Retrieving a single object with get ------------------------------------ - -``.filter()`` will always give you a ``QuerySet``, even if only a single -object matches the query - in this case, it will be a ``QuerySet`` containing -a single element. - -If you know there is only one object that matches your query, you can use -the ``get()`` method on a `Manager` which returns the object directly:: - - >>> one_entry = Entry.objects.get(pk=1) - -You can use any query expression with ``get()``, just like with ``filter()`` - -again, see `Field lookups`_ below. - -Note that there is a difference between using ``.get()``, and using -``.filter()`` with a slice of ``[0]``. If there are no results that match the -query, ``.get()`` will raise a ``DoesNotExist`` exception. This exception is an -attribute of the model class that the query is being performed on - so in the -code above, if there is no ``Entry`` object with a primary key of 1, Django will -raise ``Entry.DoesNotExist``. - -Similarly, Django will complain if more than one item matches the ``get()`` -query. In this case, it will raise ``MultipleObjectsReturned``, which again is -an attribute of the model class itself. - - -Other QuerySet methods ----------------------- - -Most of the time you'll use ``all()``, ``get()``, ``filter()`` and ``exclude()`` -when you need to look up objects from the database. However, that's far from all -there is; see the :ref:`QuerySet API Reference <queryset-api>` for a complete -list of all the various ``QuerySet`` methods. - -.. _limiting-querysets: - -Limiting QuerySets ------------------- - -Use a subset of 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] - -Negative indexing (i.e. ``Entry.objects.all()[-1]``) is not supported. - -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. See -:meth:`~django.db.models.QuerySet.get` for more details. - -.. _field-lookups-intro: - -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/tutorial/controlflow.html#keyword-arguments - -If you pass an invalid keyword argument, a lookup function will raise -``TypeError``. - -The database API supports about two dozen lookup types; a complete reference -can be found in the :ref:`field lookup reference <field-lookups>`. To give you a taste of what's available, here's some of the more common lookups -you'll probably use: - - :lookup:`exact` - An "exact" match. For example:: - - >>> Entry.objects.get(headline__exact="Man bites dog") - - Would generate SQL along these lines: - - .. code-block:: sql - - SELECT ... WHERE headline = 'Man bites dog'; - - 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. - - :lookup:`iexact` - A case-insensitive match. So, the query:: - - >>> Blog.objects.get(name__iexact="beatles blog") - - Would match a ``Blog`` titled "Beatles Blog", "beatles blog", or even - "BeAtlES blOG". - - :lookup:`contains` - Case-sensitive containment test. For example:: - - Entry.objects.get(headline__contains='Lennon') - - Roughly translates to this SQL: - - .. code-block:: sql - - SELECT ... WHERE headline LIKE '%Lennon%'; - - Note this will match the headline ``'Today Lennon honored'`` but not - ``'today lennon honored'``. - - There's also a case-insensitive version, :lookup:`icontains`. - - :lookup:`startswith`, :lookup:`endswith` - Starts-with and ends-with search, respectively. There are also - case-insensitive versions called :lookup:`istartswith` and - :lookup:`iendswith`. - -Again, this only scratches the surface. A complete reference can be found in the -:ref:`field lookup reference <field-lookups>`. - -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__authors__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__authors__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.objects.filter(entry__authors__isnull=False, - entry__authors__name__isnull=True) - -Spanning multi-valued relationships -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -When you are filtering an object based on a ``ManyToManyField`` or a reverse -``ForeignKey``, 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 contain entries with both *"Lennon"* in the headline -and that were published in 2008 (the same entry satisfying both conditions), -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. - -.. _query-expressions: - -Filters can reference fields on the model ------------------------------------------ - -.. versionadded:: 1.1 - -In the examples given so far, we have constructed filters that compare -the value of a model field with a constant. But what if you want to compare -the value of a model field with another field on the same model? - -Django provides the ``F()`` object to allow such comparisons. Instances -of ``F()`` act as a reference to a model field within a query. These -references can then be used in query filters to compare the values of two -different fields on the same model instance. - -For example, to find a list of all blog entries that have had more comments -than pingbacks, we construct an ``F()`` object to reference the comment count, -and use that ``F()`` object in the query:: - - >>> from django.db.models import F - >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks')) - -Django supports the use of addition, subtraction, multiplication, -division and modulo arithmetic with ``F()`` objects, both with constants -and with other ``F()`` objects. To find all the blog entries with more than -*twice* as many comments as pingbacks, we modify the query:: - - >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2) - -To find all the entries where the rating of the entry is less than the -sum of the pingback count and comment count, we would issue the -query:: - - >>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks')) - -You can also use the double underscore notation to span relationships in -an ``F()`` object. An ``F()`` object with a double underscore will introduce -any joins needed to access the related object. For example, to retrieve all -the entries where the author's name is the same as the blog name, we could -issue the query: - - >>> Entry.objects.filter(authors__name=F('blog__name')) - -The pk lookup shortcut ----------------------- - -For convenience, Django provides a ``pk`` lookup shortcut, 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 - -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: - -.. code-block:: sql - - SELECT ... WHERE headline LIKE '%\%%'; - -Same goes for underscores. Both percentage signs and underscores are handled -for you transparently. - -.. _caching-and-querysets: - -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 = Entry.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. - -.. _complex-lookups-with-q: - -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 and use parenthetical grouping. Also, ``Q`` -objects can 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. - -.. seealso:: - - The `OR lookups examples`_ in the Django unit tests show some possible uses - of ``Q``. - - .. _OR lookups examples: http://code.djangoproject.com/browser/django/trunk/tests/modeltests/or_lookups/tests.py - -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 - -.. _topics-db-queries-delete: - -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() - -.. _topics-db-queries-update: - -Updating multiple objects at once -================================= - -.. versionadded:: 1.0 - -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. To update a non-relation field, provide the new value as a constant. -To update ``ForeignKey`` fields, set the new value to be the new model -instance you want to point to. For 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 returns the number of rows -affected by the query. The only restriction on the ``QuerySet`` that is -updated is that it can only access one database table, the model's main -table. You can filter based on related fields, but you can only update columns -in the model's main table. Example:: - - >>> b = Blog.objects.get(pk=1) - - # Update all the headlines belonging to this Blog. - >>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same') - -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() - -.. versionadded:: 1.1 - -Calls to update can also use :ref:`F() objects <query-expressions>` to update -one field based on the value of another field in the model. This is especially -useful for incrementing counters based upon their current value. For example, to -increment the pingback count for every entry in the blog:: - - >>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1) - -However, unlike ``F()`` objects in filter and exclude clauses, you can't -introduce joins when you use ``F()`` objects in an update -- you can only -reference fields local to the model being updated. If you attempt to introduce -a join with an ``F()`` object, a ``FieldError`` will be raised:: - - # THIS WILL RAISE A FieldError - >>> Entry.objects.update(headline=F('blog__name')) - -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. - -.. _backwards-related-objects: - -Following relationships "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:: - - >>> Blog.entry_set - Traceback: - ... - AttributeError: "Manager must be accessed via instance". - -In addition to the ``QuerySet`` methods defined in "Retrieving objects" above, -the ``ForeignKey`` ``Manager`` has additional methods used to handle the set of -related objects. A synopsis of each is below, and complete details can be found -in the :doc:`related objects reference </ref/models/relations>`. - -``add(obj1, obj2, ...)`` - Adds the specified model objects to the related object set. - -``create(**kwargs)`` - Creates a new object, saves it and puts it in the related object set. - Returns the newly created object. - -``remove(obj1, obj2, ...)`` - Removes the specified model objects from the related object set. - -``clear()`` - Removes all objects from the related object set. - -To assign the members of a related set in one fell swoop, just assign to it -from any iterable object. The iterable can contain object instances, or just -a list of primary key values. For example:: - - b = Blog.objects.get(id=1) - b.entry_set = [e1, e2] - -In this example, ``e1`` and ``e2`` can be full Entry instances, or integer -primary key values. - -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. - -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, 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``. - -One-to-one relationships ------------------------- - -One-to-one relationships are very similar to many-to-one relationships. If you -define a :class:`~django.db.models.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 :class:`~django.db.models.Manager` object, but -that :class:`~django.db.models.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 - -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 :setting:`INSTALLED_APPS` setting. The first time any model is -loaded, Django iterates over every model in :setting:`INSTALLED_APPS` and creates the -backward relationships in memory as needed. Essentially, one of the functions -of :setting:`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 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 - -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 on writing SQL by hand. -Django has a couple of options for writing raw SQL queries; see -:doc:`/topics/db/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. diff --git a/parts/django/docs/topics/db/sql.txt b/parts/django/docs/topics/db/sql.txt deleted file mode 100644 index cac9a72..0000000 --- a/parts/django/docs/topics/db/sql.txt +++ /dev/null @@ -1,279 +0,0 @@ -========================== -Performing raw SQL queries -========================== - -.. currentmodule:: django.db.models - -When the :doc:`model query APIs </topics/db/queries>` don't go far enough, you -can fall back to writing raw SQL. Django gives you two ways of performing raw -SQL queries: you can use :meth:`Manager.raw()` to `perform raw queries and -return model instances`__, or you can avoid the model layer entirely and -`execute custom SQL directly`__. - -__ `performing raw queries`_ -__ `executing custom SQL directly`_ - -Performing raw queries -====================== - -.. versionadded:: 1.2 - -The ``raw()`` manager method can be used to perform raw SQL queries that -return model instances: - -.. method:: Manager.raw(raw_query, params=None, translations=None) - -This method method takes a raw SQL query, executes it, and returns a -:class:`~django.db.models.query.RawQuerySet` instance. This -:class:`~django.db.models.query.RawQuerySet` instance can be iterated -over just like an normal QuerySet to provide object instances. - -This is best illustrated with an example. Suppose you've got the following model:: - - class Person(models.Model): - first_name = models.CharField(...) - last_name = models.CharField(...) - birth_date = models.DateField(...) - -You could then execute custom SQL like so:: - - >>> for p in Person.objects.raw('SELECT * FROM myapp_person'): - ... print p - John Smith - Jane Jones - -.. admonition:: Model table names - - Where'd the name of the ``Person`` table come from in that example? - - By default, Django figures out a database table name by joining the - model's "app label" -- the name you used in ``manage.py startapp`` -- to - the model's class name, with an underscore between them. In the example - we've assumed that the ``Person`` model lives in an app named ``myapp``, - so its table would be ``myapp_person``. - - For more details check out the documentation for the - :attr:`~Options.db_table` option, which also lets you manually set the - database table name. - -Of course, this example isn't very exciting -- it's exactly the same as -running ``Person.objects.all()``. However, ``raw()`` has a bunch of other -options that make it very powerful. - -Mapping query fields to model fields ------------------------------------- - -``raw()`` automatically maps fields in the query to fields on the model. - -The order of fields in your query doesn't matter. In other words, both -of the following queries work identically:: - - >>> Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person') - ... - >>> Person.objects.raw('SELECT last_name, birth_date, first_name, id FROM myapp_person') - ... - -Matching is done by name. This means that you can use SQL's ``AS`` clauses to -map fields in the query to model fields. So if you had some other table that -had ``Person`` data in it, you could easily map it into ``Person`` instances:: - - >>> Person.objects.raw('''SELECT first AS first_name, - ... last AS last_name, - ... bd AS birth_date, - ... pk as id, - ... FROM some_other_table''') - -As long as the names match, the model instances will be created correctly. - -Alternatively, you can map fields in the query to model fields using the -``translations`` argument to ``raw()``. This is a dictionary mapping names of -fields in the query to names of fields on the model. For example, the above -query could also be written:: - - >>> name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'} - >>> Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) - -Index lookups -------------- - -``raw()`` supports indexing, so if you need only the first result you can -write:: - - >>> first_person = Person.objects.raw('SELECT * from myapp_person')[0] - -However, the indexing and slicing are not performed at the database level. If -you have a big amount of ``Person`` objects in your database, it is more -efficient to limit the query at the SQL level:: - - >>> first_person = Person.objects.raw('SELECT * from myapp_person LIMIT 1')[0] - -Deferring model fields ----------------------- - -Fields may also be left out:: - - >>> people = Person.objects.raw('SELECT id, first_name FROM myapp_person') - -The ``Person`` objects returned by this query will be deferred model instances -(see :meth:`~django.db.models.QuerySet.defer()`). This means that the fields -that are omitted from the query will be loaded on demand. For example:: - - >>> for p in Person.objects.raw('SELECT id, first_name FROM myapp_person'): - ... print p.first_name, # This will be retrieved by the original query - ... print p.last_name # This will be retrieved on demand - ... - John Smith - Jane Jones - -From outward appearances, this looks like the query has retrieved both -the first name and last name. However, this example actually issued 3 -queries. Only the first names were retrieved by the raw() query -- the -last names were both retrieved on demand when they were printed. - -There is only one field that you can't leave out - the primary key -field. Django uses the primary key to identify model instances, so it -must always be included in a raw query. An ``InvalidQuery`` exception -will be raised if you forget to include the primary key. - -Adding annotations ------------------- - -You can also execute queries containing fields that aren't defined on the -model. For example, we could use `PostgreSQL's age() function`__ to get a list -of people with their ages calculated by the database:: - - >>> people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person') - >>> for p in people: - ... print "%s is %s." % (p.first_name, p.age) - John is 37. - Jane is 42. - ... - -__ http://www.postgresql.org/docs/8.4/static/functions-datetime.html - -Passing parameters into ``raw()`` ---------------------------------- - -If you need to perform parameterized queries, you can use the ``params`` -argument to ``raw()``:: - - >>> lname = 'Doe' - >>> Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname]) - -``params`` is a list of parameters. You'll use ``%s`` placeholders in the -query string (regardless of your database engine); they'll be replaced with -parameters from the ``params`` list. - -.. warning:: - - **Do not use string formatting on raw queries!** - - It's tempting to write the above query as:: - - >>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname - >>> Person.objects.raw(query) - - **Don't.** - - Using the ``params`` list completely protects you from `SQL injection - attacks`__, a common exploit where attackers inject arbitrary SQL into - your database. If you use string interpolation, sooner or later you'll - fall victim to SQL injection. As long as you remember to always use the - ``params`` list you'll be protected. - -__ http://en.wikipedia.org/wiki/SQL_injection - -Executing custom SQL directly -============================= - -Sometimes even :meth:`Manager.raw` isn't quite enough: you might need to -perform queries that don't map cleanly to models, or directly execute -``UPDATE``, ``INSERT``, or ``DELETE`` queries. - -In these cases, you can always access the database directly, routing around -the model layer entirely. - -The object ``django.db.connection`` represents the -default database connection, and ``django.db.transaction`` represents the -default database transaction. To use the database connection, call -``connection.cursor()`` to get a cursor object. Then, call -``cursor.execute(sql, [params])`` to execute the SQL and ``cursor.fetchone()`` -or ``cursor.fetchall()`` to return the resulting rows. After performing a data -changing operation, you should then call -``transaction.commit_unless_managed()`` to ensure your changes are committed -to the database. If your query is purely a data retrieval operation, no commit -is required. For example:: - - def my_custom_sql(): - from django.db import connection, transaction - cursor = connection.cursor() - - # Data modifying operation - commit required - cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz]) - transaction.commit_unless_managed() - - # Data retrieval operation - no commit required - cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz]) - row = cursor.fetchone() - - return row - -If you are using more than one database you can use -``django.db.connections`` to obtain the connection (and cursor) for a -specific database. ``django.db.connections`` is a dictionary-like -object that allows you to retrieve a specific connection using it's -alias:: - - from django.db import connections - cursor = connections['my_db_alias'].cursor() - -.. _transactions-and-raw-sql: - -Transactions and raw SQL ------------------------- -If you are using transaction decorators (such as ``commit_on_success``) to -wrap your views and provide transaction control, you don't have to make a -manual call to ``transaction.commit_unless_managed()`` -- you can manually -commit if you want to, but you aren't required to, since the decorator will -commit for you. However, if you don't manually commit your changes, you will -need to manually mark the transaction as dirty, using -``transaction.set_dirty()``:: - - @commit_on_success - def my_custom_sql_view(request, value): - from django.db import connection, transaction - cursor = connection.cursor() - - # Data modifying operation - cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [value]) - - # Since we modified data, mark the transaction as dirty - transaction.set_dirty() - - # Data retrieval operation. This doesn't dirty the transaction, - # so no call to set_dirty() is required. - cursor.execute("SELECT foo FROM bar WHERE baz = %s", [value]) - row = cursor.fetchone() - - return render_to_response('template.html', {'row': row}) - -The call to ``set_dirty()`` is made automatically when you use the Django ORM -to make data modifying database calls. However, when you use raw SQL, Django -has no way of knowing if your SQL modifies data or not. The manual call to -``set_dirty()`` ensures that Django knows that there are modifications that -must be committed. - -Connections and cursors ------------------------ - -``connection`` and ``cursor`` mostly implement the standard `Python DB-API`_ -(except when it comes to :doc:`transaction handling </topics/db/transactions>`). -If you're not familiar with the Python DB-API, note that the SQL statement in -``cursor.execute()`` uses placeholders, ``"%s"``, rather than adding parameters -directly within the SQL. If you use this technique, the underlying database -library will automatically add quotes and escaping to your parameter(s) as -necessary. (Also note that Django expects the ``"%s"`` placeholder, *not* the -``"?"`` placeholder, which is used by the SQLite Python bindings. This is for -the sake of consistency and sanity.) - -.. _Python DB-API: http://www.python.org/dev/peps/pep-0249/ diff --git a/parts/django/docs/topics/db/transactions.txt b/parts/django/docs/topics/db/transactions.txt deleted file mode 100644 index be9d9a8..0000000 --- a/parts/django/docs/topics/db/transactions.txt +++ /dev/null @@ -1,328 +0,0 @@ -============================== -Managing database transactions -============================== - -.. currentmodule:: django.db - -Django gives you a few ways to control how database transactions are managed, -if you're using a database that supports transactions. - -Django's default transaction behavior -===================================== - -Django's default behavior is to run with an open transaction which it -commits automatically when any built-in, data-altering model function is -called. For example, if you call ``model.save()`` or ``model.delete()``, the -change will be committed immediately. - -This is much like the auto-commit setting for most databases. As soon as you -perform an action that needs to write to the database, Django produces the -``INSERT``/``UPDATE``/``DELETE`` statements and then does the ``COMMIT``. -There's no implicit ``ROLLBACK``. - -Tying transactions to HTTP requests -=================================== - -The recommended way to handle transactions in Web requests is to tie them to -the request and response phases via Django's ``TransactionMiddleware``. - -It works like this: When a request starts, Django starts a transaction. If the -response is produced without problems, Django commits any pending transactions. -If the view function produces an exception, Django rolls back any pending -transactions. - -To activate this feature, just add the ``TransactionMiddleware`` middleware to -your :setting:`MIDDLEWARE_CLASSES` setting:: - - MIDDLEWARE_CLASSES = ( - 'django.middleware.cache.UpdateCacheMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.transaction.TransactionMiddleware', - 'django.middleware.cache.FetchFromCacheMiddleware', - ) - -The order is quite important. The transaction middleware applies not only to -view functions, but also for all middleware modules that come after it. So if -you use the session middleware after the transaction middleware, session -creation will be part of the transaction. - -The various cache middlewares are an exception: -:class:`~django.middleware.cache.CacheMiddleware`, -:class:`~django.middleware.cache.UpdateCacheMiddleware`, and -:class:`~django.middleware.cache.FetchFromCacheMiddleware` are never affected. -Even when using database caching, Django's cache backend uses its own -database cursor (which is mapped to its own database connection internally). - -Controlling transaction management in views -=========================================== - -For most people, implicit request-based transactions work wonderfully. However, -if you need more fine-grained control over how transactions are managed, you -can use Python decorators to change the way transactions are handled by a -particular view function. All of the decorators take an option ``using`` -parameter which should be the alias for a database connection for which the -behavior applies to. If no alias is specified then the ``"default"`` database -is used. - -.. note:: - - Although the examples below use view functions as examples, these - decorators can be applied to non-view functions as well. - -.. _topics-db-transactions-autocommit: - -``django.db.transaction.autocommit`` ------------------------------------- - -Use the ``autocommit`` decorator to switch a view function to Django's default -commit behavior, regardless of the global transaction setting. - -Example:: - - from django.db import transaction - - @transaction.autocommit - def viewfunc(request): - .... - - @transaction.autocommit(using="my_other_database") - def viewfunc2(request): - .... - -Within ``viewfunc()``, transactions will be committed as soon as you call -``model.save()``, ``model.delete()``, or any other function that writes to the -database. ``viewfunc2()`` will have this same behavior, but for the -``"my_other_database"`` connection. - -``django.db.transaction.commit_on_success`` -------------------------------------------- - -Use the ``commit_on_success`` decorator to use a single transaction for -all the work done in a function:: - - from django.db import transaction - - @transaction.commit_on_success - def viewfunc(request): - .... - - @transaction.commit_on_success(using="my_other_database") - def viewfunc2(request): - .... - -If the function returns successfully, then Django will commit all work done -within the function at that point. If the function raises an exception, though, -Django will roll back the transaction. - -``django.db.transaction.commit_manually`` ------------------------------------------ - -Use the ``commit_manually`` decorator if you need full control over -transactions. It tells Django you'll be managing the transaction on your own. - -If your view changes data and doesn't ``commit()`` or ``rollback()``, Django -will raise a ``TransactionManagementError`` exception. - -Manual transaction management looks like this:: - - from django.db import transaction - - @transaction.commit_manually - def viewfunc(request): - ... - # You can commit/rollback however and whenever you want - transaction.commit() - ... - - # But you've got to remember to do it yourself! - try: - ... - except: - transaction.rollback() - else: - transaction.commit() - - @transaction.commit_manually(using="my_other_database") - def viewfunc2(request): - .... - -.. admonition:: An important note to users of earlier Django releases: - - The database ``connection.commit()`` and ``connection.rollback()`` methods - (called ``db.commit()`` and ``db.rollback()`` in 0.91 and earlier) no - longer exist. They've been replaced by ``transaction.commit()`` and - ``transaction.rollback()``. - -How to globally deactivate transaction management -================================================= - -Control freaks can totally disable all transaction management by setting -``DISABLE_TRANSACTION_MANAGEMENT`` to ``True`` in the Django settings file. - -If you do this, Django won't provide any automatic transaction management -whatsoever. Middleware will no longer implicitly commit transactions, and -you'll need to roll management yourself. This even requires you to commit -changes done by middleware somewhere else. - -Thus, this is best used in situations where you want to run your own -transaction-controlling middleware or do something really strange. In almost -all situations, you'll be better off using the default behavior, or the -transaction middleware, and only modify selected functions as needed. - -.. _topics-db-transactions-savepoints: - -Savepoints -========== - -A savepoint is a marker within a transaction that enables you to roll back -part of a transaction, rather than the full transaction. Savepoints are -available to the PostgreSQL 8 and Oracle backends. Other backends will -provide the savepoint functions, but they are empty operations - they won't -actually do anything. - -Savepoints aren't especially useful if you are using the default -``autocommit`` behaviour of Django. However, if you are using -``commit_on_success`` or ``commit_manually``, each open transaction will build -up a series of database operations, awaiting a commit or rollback. If you -issue a rollback, the entire transaction is rolled back. Savepoints provide -the ability to perform a fine-grained rollback, rather than the full rollback -that would be performed by ``transaction.rollback()``. - -Each of these functions takes a ``using`` argument which should be the name of -a database for which the behavior applies. If no ``using`` argument is -provided then the ``"default"`` database is used. - -Savepoints are controlled by three methods on the transaction object: - -.. method:: transaction.savepoint(using=None) - - Creates a new savepoint. This marks a point in the transaction that - is known to be in a "good" state. - - Returns the savepoint ID (sid). - -.. method:: transaction.savepoint_commit(sid, using=None) - - Updates the savepoint to include any operations that have been performed - since the savepoint was created, or since the last commit. - -.. method:: transaction.savepoint_rollback(sid, using=None) - - Rolls the transaction back to the last point at which the savepoint was - committed. - -The following example demonstrates the use of savepoints:: - - from django.db import transaction - - @transaction.commit_manually - def viewfunc(request): - - a.save() - # open transaction now contains a.save() - sid = transaction.savepoint() - - b.save() - # open transaction now contains a.save() and b.save() - - if want_to_keep_b: - transaction.savepoint_commit(sid) - # open transaction still contains a.save() and b.save() - else: - transaction.savepoint_rollback(sid) - # open transaction now contains only a.save() - - transaction.commit() - -Transactions in MySQL -===================== - -If you're using MySQL, your tables may or may not support transactions; it -depends on your MySQL version and the table types you're using. (By -"table types," we mean something like "InnoDB" or "MyISAM".) MySQL transaction -peculiarities are outside the scope of this article, but the MySQL site has -`information on MySQL transactions`_. - -If your MySQL setup does *not* support transactions, then Django will function -in auto-commit mode: Statements will be executed and committed as soon as -they're called. If your MySQL setup *does* support transactions, Django will -handle transactions as explained in this document. - -.. _information on MySQL transactions: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html - -Handling exceptions within PostgreSQL transactions -================================================== - -When a call to a PostgreSQL cursor raises an exception (typically -``IntegrityError``), all subsequent SQL in the same transaction will fail with -the error "current transaction is aborted, queries ignored until end of -transaction block". Whilst simple use of ``save()`` is unlikely to raise an -exception in PostgreSQL, there are more advanced usage patterns which -might, such as saving objects with unique fields, saving using the -force_insert/force_update flag, or invoking custom SQL. - -There are several ways to recover from this sort of error. - -Transaction rollback --------------------- - -The first option is to roll back the entire transaction. For example:: - - a.save() # Succeeds, but may be undone by transaction rollback - try: - b.save() # Could throw exception - except IntegrityError: - transaction.rollback() - c.save() # Succeeds, but a.save() may have been undone - -Calling ``transaction.rollback()`` rolls back the entire transaction. Any -uncommitted database operations will be lost. In this example, the changes -made by ``a.save()`` would be lost, even though that operation raised no error -itself. - -Savepoint rollback ------------------- - -If you are using PostgreSQL 8 or later, you can use :ref:`savepoints -<topics-db-transactions-savepoints>` to control the extent of a rollback. -Before performing a database operation that could fail, you can set or update -the savepoint; that way, if the operation fails, you can roll back the single -offending operation, rather than the entire transaction. For example:: - - a.save() # Succeeds, and never undone by savepoint rollback - try: - sid = transaction.savepoint() - b.save() # Could throw exception - transaction.savepoint_commit(sid) - except IntegrityError: - transaction.savepoint_rollback(sid) - c.save() # Succeeds, and a.save() is never undone - -In this example, ``a.save()`` will not be undone in the case where -``b.save()`` raises an exception. - -Database-level autocommit -------------------------- - -.. versionadded:: 1.1 - -With PostgreSQL 8.2 or later, there is an advanced option to run PostgreSQL -with :doc:`database-level autocommit </ref/databases>`. If you use this option, -there is no constantly open transaction, so it is always possible to continue -after catching an exception. For example:: - - a.save() # succeeds - try: - b.save() # Could throw exception - except IntegrityError: - pass - c.save() # succeeds - -.. note:: - - This is not the same as the :ref:`autocommit decorator - <topics-db-transactions-autocommit>`. When using database level autocommit - there is no database transaction at all. The ``autocommit`` decorator - still uses transactions, automatically committing each transaction when - a database modifying operation occurs. diff --git a/parts/django/docs/topics/email.txt b/parts/django/docs/topics/email.txt deleted file mode 100644 index 36bebfb..0000000 --- a/parts/django/docs/topics/email.txt +++ /dev/null @@ -1,618 +0,0 @@ -============== -Sending e-mail -============== - -.. module:: django.core.mail - :synopsis: Helpers to easily send e-mail. - -Although Python makes sending e-mail relatively easy via the `smtplib -library`_, Django provides a couple of light wrappers over it. These wrappers -are provided to make sending e-mail extra quick, to make it easy to test -e-mail sending during development, and to provide support for platforms that -can't use SMTP. - -The code lives in the ``django.core.mail`` module. - -.. _smtplib library: http://docs.python.org/library/smtplib.html - -Quick example -============= - -In two lines:: - - from django.core.mail import send_mail - - send_mail('Subject here', 'Here is the message.', 'from@example.com', - ['to@example.com'], fail_silently=False) - -Mail is sent using the SMTP host and port specified in the -:setting:`EMAIL_HOST` and :setting:`EMAIL_PORT` settings. The -:setting:`EMAIL_HOST_USER` and :setting:`EMAIL_HOST_PASSWORD` settings, if -set, are used to authenticate to the SMTP server, and the -:setting:`EMAIL_USE_TLS` setting controls whether a secure connection is used. - -.. note:: - - The character set of e-mail sent with ``django.core.mail`` will be set to - the value of your :setting:`DEFAULT_CHARSET` setting. - -send_mail() -=========== - -.. function:: send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None) - -The simplest way to send e-mail is using -``django.core.mail.send_mail()``. - -The ``subject``, ``message``, ``from_email`` and ``recipient_list`` parameters -are required. - - * ``subject``: A string. - * ``message``: A string. - * ``from_email``: A string. - * ``recipient_list``: A list of strings, each an e-mail address. Each - member of ``recipient_list`` will see the other recipients in the "To:" - field of the e-mail message. - * ``fail_silently``: A boolean. If it's ``False``, ``send_mail`` will raise - an ``smtplib.SMTPException``. See the `smtplib docs`_ for a list of - possible exceptions, all of which are subclasses of ``SMTPException``. - * ``auth_user``: The optional username to use to authenticate to the SMTP - server. If this isn't provided, Django will use the value of the - :setting:`EMAIL_HOST_USER` setting. - * ``auth_password``: The optional password to use to authenticate to the - SMTP server. If this isn't provided, Django will use the value of the - :setting:`EMAIL_HOST_PASSWORD` setting. - * ``connection``: The optional e-mail backend to use to send the mail. - If unspecified, an instance of the default backend will be used. - See the documentation on :ref:`E-mail backends <topic-email-backends>` - for more details. - -.. _smtplib docs: http://docs.python.org/library/smtplib.html - -send_mass_mail() -================ - -.. function:: send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None) - -``django.core.mail.send_mass_mail()`` is intended to handle mass e-mailing. - -``datatuple`` is a tuple in which each element is in this format:: - - (subject, message, from_email, recipient_list) - -``fail_silently``, ``auth_user`` and ``auth_password`` have the same functions -as in :meth:`~django.core.mail.send_mail()`. - -Each separate element of ``datatuple`` results in a separate e-mail message. -As in :meth:`~django.core.mail.send_mail()`, recipients in the same -``recipient_list`` will all see the other addresses in the e-mail messages' -"To:" field. - -For example, the following code would send two different messages to -two different sets of recipients; however, only one connection to the -mail server would be opened:: - - message1 = ('Subject here', 'Here is the message', 'from@example.com, ['first@example.com', 'other@example.com']) - message2 = ('Another Subject', 'Here is another message', 'from@example.com', ['second@test.com']) - send_mass_mail((message1, message2), fail_silently=False) - -send_mass_mail() vs. send_mail() --------------------------------- - -The main difference between :meth:`~django.core.mail.send_mass_mail()` and -:meth:`~django.core.mail.send_mail()` is that -:meth:`~django.core.mail.send_mail()` opens a connection to the mail server -each time it's executed, while :meth:`~django.core.mail.send_mass_mail()` uses -a single connection for all of its messages. This makes -:meth:`~django.core.mail.send_mass_mail()` slightly more efficient. - -mail_admins() -============= - -.. function:: mail_admins(subject, message, fail_silently=False, connection=None) - -``django.core.mail.mail_admins()`` is a shortcut for sending an e-mail to the -site admins, as defined in the :setting:`ADMINS` setting. - -``mail_admins()`` prefixes the subject with the value of the -:setting:`EMAIL_SUBJECT_PREFIX` setting, which is ``"[Django] "`` by default. - -The "From:" header of the e-mail will be the value of the -:setting:`SERVER_EMAIL` setting. - -This method exists for convenience and readability. - -mail_managers() -=============== - -.. function:: mail_managers(subject, message, fail_silently=False, connection=None) - -``django.core.mail.mail_managers()`` is just like ``mail_admins()``, except it -sends an e-mail to the site managers, as defined in the :setting:`MANAGERS` -setting. - -Examples -======== - -This sends a single e-mail to john@example.com and jane@example.com, with them -both appearing in the "To:":: - - send_mail('Subject', 'Message.', 'from@example.com', - ['john@example.com', 'jane@example.com']) - -This sends a message to john@example.com and jane@example.com, with them both -receiving a separate e-mail:: - - datatuple = ( - ('Subject', 'Message.', 'from@example.com', ['john@example.com']), - ('Subject', 'Message.', 'from@example.com', ['jane@example.com']), - ) - send_mass_mail(datatuple) - -Preventing header injection -=========================== - -`Header injection`_ is a security exploit in which an attacker inserts extra -e-mail headers to control the "To:" and "From:" in e-mail messages that your -scripts generate. - -The Django e-mail functions outlined above all protect against header injection -by forbidding newlines in header values. If any ``subject``, ``from_email`` or -``recipient_list`` contains a newline (in either Unix, Windows or Mac style), -the e-mail function (e.g. :meth:`~django.core.mail.send_mail()`) will raise -``django.core.mail.BadHeaderError`` (a subclass of ``ValueError``) and, hence, -will not send the e-mail. It's your responsibility to validate all data before -passing it to the e-mail functions. - -If a ``message`` contains headers at the start of the string, the headers will -simply be printed as the first bit of the e-mail message. - -Here's an example view that takes a ``subject``, ``message`` and ``from_email`` -from the request's POST data, sends that to admin@example.com and redirects to -"/contact/thanks/" when it's done:: - - from django.core.mail import send_mail, BadHeaderError - - def send_email(request): - subject = request.POST.get('subject', '') - message = request.POST.get('message', '') - from_email = request.POST.get('from_email', '') - if subject and message and from_email: - try: - send_mail(subject, message, from_email, ['admin@example.com']) - except BadHeaderError: - return HttpResponse('Invalid header found.') - return HttpResponseRedirect('/contact/thanks/') - else: - # In reality we'd use a form class - # to get proper validation errors. - return HttpResponse('Make sure all fields are entered and valid.') - -.. _Header injection: http://www.nyphp.org/phundamentals/email_header_injection.php - -.. _emailmessage-and-smtpconnection: - -The EmailMessage class -====================== - -.. versionadded:: 1.0 - -Django's :meth:`~django.core.mail.send_mail()` and -:meth:`~django.core.mail.send_mass_mail()` functions are actually thin -wrappers that make use of the :class:`~django.core.mail.EmailMessage` class. - -Not all features of the :class:`~django.core.mail.EmailMessage` class are -available through the :meth:`~django.core.mail.send_mail()` and related -wrapper functions. If you wish to use advanced features, such as BCC'ed -recipients, file attachments, or multi-part e-mail, you'll need to create -:class:`~django.core.mail.EmailMessage` instances directly. - -.. note:: - This is a design feature. :meth:`~django.core.mail.send_mail()` and - related functions were originally the only interface Django provided. - However, the list of parameters they accepted was slowly growing over - time. It made sense to move to a more object-oriented design for e-mail - messages and retain the original functions only for backwards - compatibility. - -:class:`~django.core.mail.EmailMessage` is responsible for creating the e-mail -message itself. The :ref:`e-mail backend <topic-email-backends>` is then -responsible for sending the e-mail. - -For convenience, :class:`~django.core.mail.EmailMessage` provides a simple -``send()`` method for sending a single e-mail. If you need to send multiple -messages, the e-mail backend API :ref:`provides an alternative -<topics-sending-multiple-emails>`. - -EmailMessage Objects --------------------- - -.. class:: EmailMessage - -The :class:`~django.core.mail.EmailMessage` class is initialized with the -following parameters (in the given order, if positional arguments are used). -All parameters are optional and can be set at any time prior to calling the -``send()`` method. - - * ``subject``: The subject line of the e-mail. - - * ``body``: The body text. This should be a plain text message. - - * ``from_email``: The sender's address. Both ``fred@example.com`` and - ``Fred <fred@example.com>`` forms are legal. If omitted, the - :setting:`DEFAULT_FROM_EMAIL` setting is used. - - * ``to``: A list or tuple of recipient addresses. - - * ``bcc``: A list or tuple of addresses used in the "Bcc" header when - sending the e-mail. - - * ``connection``: An e-mail backend instance. Use this parameter if - you want to use the same connection for multiple messages. If omitted, a - new connection is created when ``send()`` is called. - - * ``attachments``: A list of attachments to put on the message. These can - be either ``email.MIMEBase.MIMEBase`` instances, or ``(filename, - content, mimetype)`` triples. - - * ``headers``: A dictionary of extra headers to put on the message. The - keys are the header name, values are the header values. It's up to the - caller to ensure header names and values are in the correct format for - an e-mail message. - -For example:: - - email = EmailMessage('Hello', 'Body goes here', 'from@example.com', - ['to1@example.com', 'to2@example.com'], ['bcc@example.com'], - headers = {'Reply-To': 'another@example.com'}) - -The class has the following methods: - - * ``send(fail_silently=False)`` sends the message. If a connection was - specified when the e-mail was constructed, that connection will be used. - Otherwise, an instance of the default backend will be instantiated and - used. If the keyword argument ``fail_silently`` is ``True``, exceptions - raised while sending the message will be quashed. - - * ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a - subclass of Python's ``email.MIMEText.MIMEText`` class) or a - ``django.core.mail.SafeMIMEMultipart`` object holding the message to be - sent. If you ever need to extend the - :class:`~django.core.mail.EmailMessage` class, you'll probably want to - override this method to put the content you want into the MIME object. - - * ``recipients()`` returns a list of all the recipients of the message, - whether they're recorded in the ``to`` or ``bcc`` attributes. This is - another method you might need to override when subclassing, because the - SMTP server needs to be told the full list of recipients when the message - is sent. If you add another way to specify recipients in your class, they - need to be returned from this method as well. - - * ``attach()`` creates a new file attachment and adds it to the message. - There are two ways to call ``attach()``: - - * You can pass it a single argument that is an - ``email.MIMEBase.MIMEBase`` instance. This will be inserted directly - into the resulting message. - - * Alternatively, you can pass ``attach()`` three arguments: - ``filename``, ``content`` and ``mimetype``. ``filename`` is the name - of the file attachment as it will appear in the e-mail, ``content`` is - the data that will be contained inside the attachment and - ``mimetype`` is the optional MIME type for the attachment. If you - omit ``mimetype``, the MIME content type will be guessed from the - filename of the attachment. - - For example:: - - message.attach('design.png', img_data, 'image/png') - - * ``attach_file()`` creates a new attachment using a file from your - filesystem. Call it with the path of the file to attach and, optionally, - the MIME type to use for the attachment. If the MIME type is omitted, it - will be guessed from the filename. The simplest use would be:: - - message.attach_file('/images/weather_map.png') - -.. _DEFAULT_FROM_EMAIL: ../settings/#default-from-email - -Sending alternative content types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It can be useful to include multiple versions of the content in an e-mail; the -classic example is to send both text and HTML versions of a message. With -Django's e-mail library, you can do this using the ``EmailMultiAlternatives`` -class. This subclass of :class:`~django.core.mail.EmailMessage` has an -``attach_alternative()`` method for including extra versions of the message -body in the e-mail. All the other methods (including the class initialization) -are inherited directly from :class:`~django.core.mail.EmailMessage`. - -To send a text and HTML combination, you could write:: - - from django.core.mail import EmailMultiAlternatives - - subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' - text_content = 'This is an important message.' - html_content = '<p>This is an <strong>important</strong> message.</p>' - msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) - msg.attach_alternative(html_content, "text/html") - msg.send() - -By default, the MIME type of the ``body`` parameter in an -:class:`~django.core.mail.EmailMessage` is ``"text/plain"``. It is good -practice to leave this alone, because it guarantees that any recipient will be -able to read the e-mail, regardless of their mail client. However, if you are -confident that your recipients can handle an alternative content type, you can -use the ``content_subtype`` attribute on the -:class:`~django.core.mail.EmailMessage` class to change the main content type. -The major type will always be ``"text"``, but you can change the -subtype. For example:: - - msg = EmailMessage(subject, html_content, from_email, [to]) - msg.content_subtype = "html" # Main content is now text/html - msg.send() - -.. _topic-email-backends: - -E-Mail Backends -=============== - -.. versionadded:: 1.2 - -The actual sending of an e-mail is handled by the e-mail backend. - -The e-mail backend class has the following methods: - - * ``open()`` instantiates an long-lived e-mail-sending connection. - - * ``close()`` closes the current e-mail-sending connection. - - * ``send_messages(email_messages)`` sends a list of - :class:`~django.core.mail.EmailMessage` objects. If the connection is - not open, this call will implicitly open the connection, and close the - connection afterwards. If the connection is already open, it will be - left open after mail has been sent. - -Obtaining an instance of an e-mail backend ------------------------------------------- - -The :meth:`get_connection` function in ``django.core.mail`` returns an -instance of the e-mail backend that you can use. - -.. currentmodule:: django.core.mail - -.. function:: get_connection(backend=None, fail_silently=False, *args, **kwargs) - -By default, a call to ``get_connection()`` will return an instance of the -e-mail backend specified in :setting:`EMAIL_BACKEND`. If you specify the -``backend`` argument, an instance of that backend will be instantiated. - -The ``fail_silently`` argument controls how the backend should handle errors. -If ``fail_silently`` is True, exceptions during the e-mail sending process -will be silently ignored. - -All other arguments are passed directly to the constructor of the -e-mail backend. - -Django ships with several e-mail sending backends. With the exception of the -SMTP backend (which is the default), these backends are only useful during -testing and development. If you have special e-mail sending requirements, you -can :ref:`write your own e-mail backend <topic-custom-email-backend>`. - -.. _topic-email-smtp-backend: - -SMTP backend -~~~~~~~~~~~~ - -This is the default backend. E-mail will be sent through a SMTP server. -The server address and authentication credentials are set in the -:setting:`EMAIL_HOST`, :setting:`EMAIL_PORT`, :setting:`EMAIL_HOST_USER`, -:setting:`EMAIL_HOST_PASSWORD` and :setting:`EMAIL_USE_TLS` settings in your -settings file. - -The SMTP backend is the default configuration inherited by Django. If you -want to specify it explicitly, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' - -.. admonition:: SMTPConnection objects - - Prior to version 1.2, Django provided a - :class:`~django.core.mail.SMTPConnection` class. This class provided a way - to directly control the use of SMTP to send e-mail. This class has been - deprecated in favor of the generic e-mail backend API. - - For backwards compatibility :class:`~django.core.mail.SMTPConnection` is - still available in ``django.core.mail`` as an alias for the SMTP backend. - New code should use :meth:`~django.core.mail.get_connection` instead. - -.. _topic-email-console-backend: - -Console backend -~~~~~~~~~~~~~~~ - -Instead of sending out real e-mails the console backend just writes the -e-mails that would be send to the standard output. By default, the console -backend writes to ``stdout``. You can use a different stream-like object by -providing the ``stream`` keyword argument when constructing the connection. - -To specify this backend, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' - -This backend is not intended for use in production -- it is provided as a -convenience that can be used during development. - -.. _topic-email-file-backend: - -File backend -~~~~~~~~~~~~ - -The file backend writes e-mails to a file. A new file is created for each new -session that is opened on this backend. The directory to which the files are -written is either taken from the :setting:`EMAIL_FILE_PATH` setting or from -the ``file_path`` keyword when creating a connection with -:meth:`~django.core.mail.get_connection`. - -To specify this backend, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' - EMAIL_FILE_PATH = '/tmp/app-messages' # change this to a proper location - -This backend is not intended for use in production -- it is provided as a -convenience that can be used during development. - -.. _topic-email-memory-backend: - -In-memory backend -~~~~~~~~~~~~~~~~~ - -The ``'locmem'`` backend stores messages in a special attribute of the -``django.core.mail`` module. The ``outbox`` attribute is created when the -first message is sent. It's a list with an -:class:`~django.core.mail.EmailMessage` instance for each message that would -be send. - -To specify this backend, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend' - -This backend is not intended for use in production -- it is provided as a -convenience that can be used during development and testing. - -.. _topic-email-dummy-backend: - -Dummy backend -~~~~~~~~~~~~~ - -As the name suggests the dummy backend does nothing with your messages. To -specify this backend, put the following in your settings:: - - EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' - -This backend is not intended for use in production -- it is provided as a -convenience that can be used during development. - -.. _topic-custom-email-backend: - -Defining a custom e-mail backend --------------------------------- - -If you need to change how e-mails are sent you can write your own e-mail -backend. The ``EMAIL_BACKEND`` setting in your settings file is then the -Python import path for your backend class. - -Custom e-mail backends should subclass ``BaseEmailBackend`` that is located in -the ``django.core.mail.backends.base`` module. A custom e-mail backend must -implement the ``send_messages(email_messages)`` method. This method receives a -list of :class:`~django.core.mail.EmailMessage` instances and returns the -number of successfully delivered messages. If your backend has any concept of -a persistent session or connection, you should also implement the ``open()`` -and ``close()`` methods. Refer to ``smtp.EmailBackend`` for a reference -implementation. - -.. _topics-sending-multiple-emails: - -Sending multiple e-mails ------------------------- - -Establishing and closing an SMTP connection (or any other network connection, -for that matter) is an expensive process. If you have a lot of e-mails to send, -it makes sense to reuse an SMTP connection, rather than creating and -destroying a connection every time you want to send an e-mail. - -There are two ways you tell an e-mail backend to reuse a connection. - -Firstly, you can use the ``send_messages()`` method. ``send_messages()`` takes -a list of :class:`~django.core.mail.EmailMessage` instances (or subclasses), -and sends them all using a single connection. - -For example, if you have a function called ``get_notification_email()`` that -returns a list of :class:`~django.core.mail.EmailMessage` objects representing -some periodic e-mail you wish to send out, you could send these e-mails using -a single call to send_messages:: - - from django.core import mail - connection = mail.get_connection() # Use default e-mail connection - messages = get_notification_email() - connection.send_messages(messages) - -In this example, the call to ``send_messages()`` opens a connection on the -backend, sends the list of messages, and then closes the connection again. - -The second approach is to use the ``open()`` and ``close()`` methods on the -e-mail backend to manually control the connection. ``send_messages()`` will not -manually open or close the connection if it is already open, so if you -manually open the connection, you can control when it is closed. For example:: - - from django.core import mail - connection = mail.get_connection() - - # Manually open the connection - connection.open() - - # Construct an e-mail message that uses the connection - email1 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com', - ['to1@example.com'], connection=connection) - email1.send() # Send the e-mail - - # Construct two more messages - email2 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com', - ['to2@example.com']) - email3 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com', - ['to3@example.com']) - - # Send the two e-mails in a single call - - connection.send_messages([email2, email3]) - # The connection was already open so send_messages() doesn't close it. - # We need to manually close the connection. - connection.close() - - -Testing e-mail sending -====================== - -There are times when you do not want Django to send e-mails at -all. For example, while developing a Web site, you probably don't want -to send out thousands of e-mails -- but you may want to validate that -e-mails will be sent to the right people under the right conditions, -and that those e-mails will contain the correct content. - -The easiest way to test your project's use of e-mail is to use the ``console`` -e-mail backend. This backend redirects all e-mail to stdout, allowing you to -inspect the content of mail. - -The ``file`` e-mail backend can also be useful during development -- this backend -dumps the contents of every SMTP connection to a file that can be inspected -at your leisure. - -Another approach is to use a "dumb" SMTP server that receives the e-mails -locally and displays them to the terminal, but does not actually send -anything. Python has a built-in way to accomplish this with a single command:: - - python -m smtpd -n -c DebuggingServer localhost:1025 - -This command will start a simple SMTP server listening on port 1025 of -localhost. This server simply prints to standard output all e-mail headers and -the e-mail body. You then only need to set the :setting:`EMAIL_HOST` and -:setting:`EMAIL_PORT` accordingly, and you are set. - -For a more detailed discussion of testing and processing of e-mails locally, -see the Python documentation on the `SMTP Server`_. - -.. _SMTP Server: http://docs.python.org/library/smtpd.html - -SMTPConnection -============== - -.. class:: SMTPConnection - -.. deprecated:: 1.2 - -The ``SMTPConnection`` class has been deprecated in favor of the generic e-mail -backend API. - -For backwards compatibility ``SMTPConnection`` is still available in -``django.core.mail`` as an alias for the :ref:`SMTP backend -<topic-email-smtp-backend>`. New code should use -:meth:`~django.core.mail.get_connection` instead. diff --git a/parts/django/docs/topics/files.txt b/parts/django/docs/topics/files.txt deleted file mode 100644 index d1926c6..0000000 --- a/parts/django/docs/topics/files.txt +++ /dev/null @@ -1,147 +0,0 @@ -============== -Managing files -============== - -.. versionadded:: 1.0 - -This document describes Django's file access APIs. - -By default, Django stores files locally, using the :setting:`MEDIA_ROOT` and -:setting:`MEDIA_URL` settings. The examples below assume that you're using these -defaults. - -However, Django provides ways to write custom `file storage systems`_ that -allow you to completely customize where and how Django stores files. The -second half of this document describes how these storage systems work. - -.. _file storage systems: `File storage`_ - -Using files in models -===================== - -When you use a :class:`~django.db.models.FileField` or -:class:`~django.db.models.ImageField`, Django provides a set of APIs you can use -to deal with that file. - -Consider the following model, using an :class:`~django.db.models.ImageField` to -store a photo:: - - class Car(models.Model): - name = models.CharField(max_length=255) - price = models.DecimalField(max_digits=5, decimal_places=2) - photo = models.ImageField(upload_to='cars') - -Any ``Car`` instance will have a ``photo`` attribute that you can use to get at -the details of the attached photo:: - - >>> car = Car.objects.get(name="57 Chevy") - >>> car.photo - <ImageFieldFile: chevy.jpg> - >>> car.photo.name - u'cars/chevy.jpg' - >>> car.photo.path - u'/media/cars/chevy.jpg' - >>> car.photo.url - u'http://media.example.com/cars/chevy.jpg' - -This object -- ``car.photo`` in the example -- is a ``File`` object, which means -it has all the methods and attributes described below. - -The ``File`` object -=================== - -Internally, Django uses a :class:`django.core.files.File` instance any time it -needs to represent a file. This object is a thin wrapper around Python's -`built-in file object`_ with some Django-specific additions. - -.. _built-in file object: http://docs.python.org/library/stdtypes.html#bltin-file-objects - -Most of the time you'll simply use a ``File`` that Django's given you (i.e. a -file attached to a model as above, or perhaps an uploaded file). - -If you need to construct a ``File`` yourself, the easiest way is to create one -using a Python built-in ``file`` object:: - - >>> from django.core.files import File - - # Create a Python file object using open() - >>> f = open('/tmp/hello.world', 'w') - >>> myfile = File(f) - -Now you can use any of the documented attributes and methods -of the :class:`~django.core.files.File` class. - -File storage -============ - -Behind the scenes, Django delegates decisions about how and where to store files -to a file storage system. This is the object that actually understands things -like file systems, opening and reading files, etc. - -Django's default file storage is given by the :setting:`DEFAULT_FILE_STORAGE` -setting; if you don't explicitly provide a storage system, this is the one that -will be used. - -See below for details of the built-in default file storage system, and see -:doc:`/howto/custom-file-storage` for information on writing your own file -storage system. - -Storage objects ---------------- - -Though most of the time you'll want to use a ``File`` object (which delegates to -the proper storage for that file), you can use file storage systems directly. -You can create an instance of some custom file storage class, or -- often more -useful -- you can use the global default storage system:: - - >>> from django.core.files.storage import default_storage - >>> from django.core.files.base import ContentFile - - >>> path = default_storage.save('/path/to/file', ContentFile('new content')) - >>> path - u'/path/to/file' - - >>> default_storage.size(path) - 11 - >>> default_storage.open(path).read() - 'new content' - - >>> default_storage.delete(path) - >>> default_storage.exists(path) - False - -See :doc:`/ref/files/storage` for the file storage API. - -The built-in filesystem storage class -------------------------------------- - -Django ships with a built-in ``FileSystemStorage`` class (defined in -``django.core.files.storage``) which implements basic local filesystem file -storage. Its initializer takes two arguments: - -====================== =================================================== -Argument Description -====================== =================================================== -``location`` Optional. Absolute path to the directory that will - hold the files. If omitted, it will be set to the - value of your :setting:`MEDIA_ROOT` setting. -``base_url`` Optional. URL that serves the files stored at this - location. If omitted, it will default to the value - of your :setting:`MEDIA_URL` setting. -====================== =================================================== - -For example, the following code will store uploaded files under -``/media/photos`` regardless of what your :setting:`MEDIA_ROOT` setting is:: - - from django.db import models - from django.core.files.storage import FileSystemStorage - - fs = FileSystemStorage(location='/media/photos') - - class Car(models.Model): - ... - photo = models.ImageField(storage=fs) - -:doc:`Custom storage systems </howto/custom-file-storage>` work the same way: -you can pass them in as the ``storage`` argument to a -:class:`~django.db.models.FileField`. diff --git a/parts/django/docs/topics/forms/formsets.txt b/parts/django/docs/topics/forms/formsets.txt deleted file mode 100644 index 72296bc..0000000 --- a/parts/django/docs/topics/forms/formsets.txt +++ /dev/null @@ -1,440 +0,0 @@ -.. _formsets: - -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() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr> - -As you can see it only displayed one empty form. The number of empty forms -that is displayed is controlled by the ``extra`` parameter. By default, -``formset_factory`` defines one extra form; the following example will -display two blank forms:: - - >>> 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() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date" /></td></tr> - <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr> - <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr> - <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr> - <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr> - -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. - -.. seealso:: - - :ref:`Creating formsets from models with model formsets <model-formsets>`. - -.. _formsets-max-num: - -Limiting the maximum number of forms ------------------------------------- - -The ``max_num`` parameter to ``formset_factory`` gives you the ability to -limit the maximum number of empty 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() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr> - -.. versionchanged:: 1.2 - -If the value of ``max_num`` is greater than the number of existing -objects, up to ``extra`` additional blank forms will be added to the formset, -so long as the total number of forms does not exceed ``max_num``. - -A ``max_num`` value of ``None`` (the default) puts no limit on the number of -forms displayed. Please note that the default value of ``max_num`` was changed -from ``0`` to ``None`` in version 1.2 to allow ``0`` as a valid value. - -Formset validation ------------------- - -Validation with a formset is almost identical to a regular ``Form``. There is -an ``is_valid`` method on the formset to provide a convenient way to validate -all forms 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 -provide an invalid article:: - - >>> data = { - ... 'form-TOTAL_FORMS': u'2', - ... 'form-INITIAL_FORMS': u'0', - ... 'form-MAX_NUM_FORMS': u'', - ... 'form-0-title': u'Test', - ... 'form-0-pub_date': u'16 June 1904', - ... 'form-1-title': u'Test', - ... 'form-1-pub_date': u'', # <-- this date is missing but required - ... } - >>> formset = ArticleFormSet(data) - >>> formset.is_valid() - False - >>> formset.errors - [{}, {'pub_date': [u'This field is required.']}] - -As we can see, ``formset.errors`` is a list whose entries correspond to the -forms in the formset. Validation was performed for each of the two forms, and -the expected error message appears for the second item. - -.. _understanding-the-managementform: - -Understanding the ManagementForm -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You may have noticed the additional data (``form-TOTAL_FORMS``, -``form-INITIAL_FORMS`` and ``form-MAX_NUM_FORMS``) that was required -in the formset's data above. This data is required for the -``ManagementForm``. This form is used by the formset to manage the -collection of forms contained in the formset. If you don't provide -this management data, an exception will be raised:: - - >>> 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. - -The management form is available as an attribute of the formset -itself. When rendering a formset in a template, you can include all -the management data by rendering ``{{ my_formset.management_form }}`` -(substituting the name of your formset as appropriate). - -.. versionadded:: 1.1 - -``total_form_count`` and ``initial_form_count`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``BaseFormSet`` has a couple of methods that are closely related to the -``ManagementForm``, ``total_form_count`` and ``initial_form_count``. - -``total_form_count`` returns the total number of forms in this formset. -``initial_form_count`` returns the number of forms in the formset that were -pre-filled, and is also used to determine how many forms are required. You -will probably never need to override either of these methods, so please be -sure you understand what they do before doing so. - -.. versionadded:: 1.2 - -``empty_form`` -~~~~~~~~~~~~~~ - -``BaseFormSet`` provides an additional attribute ``empty_form`` which returns -a form instance with a prefix of ``__prefix__`` for easier use in dynamic -forms with JavaScript. - -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 works at the formset level:: - - >>> from django.forms.formsets import BaseFormSet - - >>> class BaseArticleFormSet(BaseFormSet): - ... def clean(self): - ... """Checks that no two articles have the same title.""" - ... if any(self.errors): - ... # Don't bother validating the formset unless each form is valid on its own - ... return - ... titles = [] - ... for i in range(0, self.total_form_count()): - ... form = self.forms[i] - ... title = form.cleaned_data['title'] - ... if title in titles: - ... raise forms.ValidationError, "Articles in a set must have distinct titles." - ... titles.append(title) - - >>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet) - >>> data = { - ... 'form-TOTAL_FORMS': u'2', - ... 'form-INITIAL_FORMS': u'0', - ... 'form-MAX_NUM_FORMS': u'', - ... 'form-0-title': u'Test', - ... 'form-0-pub_date': u'16 June 1904', - ... 'form-1-title': u'Test', - ... 'form-1-pub_date': u'23 June 1912', - ... } - >>> formset = ArticleFormSet(data) - >>> formset.is_valid() - False - >>> formset.errors - [{}, {}] - >>> formset.non_form_errors() - [u'Articles in a set must have distinct titles.'] - -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() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date" /></td></tr> - <tr><th><label for="id_form-0-ORDER">Order:</label></th><td><input type="text" name="form-0-ORDER" value="1" id="id_form-0-ORDER" /></td></tr> - <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr> - <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr> - <tr><th><label for="id_form-1-ORDER">Order:</label></th><td><input type="text" name="form-1-ORDER" value="2" id="id_form-1-ORDER" /></td></tr> - <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr> - <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr> - <tr><th><label for="id_form-2-ORDER">Order:</label></th><td><input type="text" name="form-2-ORDER" id="id_form-2-ORDER" /></td></tr> - -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-MAX_NUM_FORMS': u'', - ... '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() - <input type="hidden" name="form-TOTAL_FORMS" value="3" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="2" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" id="id_form-MAX_NUM_FORMS" /> - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-10" id="id_form-0-pub_date" /></td></tr> - <tr><th><label for="id_form-0-DELETE">Delete:</label></th><td><input type="checkbox" name="form-0-DELETE" id="id_form-0-DELETE" /></td></tr> - <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr> - <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr> - <tr><th><label for="id_form-1-DELETE">Delete:</label></th><td><input type="checkbox" name="form-1-DELETE" id="id_form-1-DELETE" /></td></tr> - <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr> - <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr> - <tr><th><label for="id_form-2-DELETE">Delete:</label></th><td><input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE" /></td></tr> - -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-MAX_NUM_FORMS': u'', - ... '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() - <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr> - <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr> - <tr><th><label for="id_form-0-my_field">My field:</label></th><td><input type="text" name="form-0-my_field" id="id_form-0-my_field" /></td></tr> - -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. Let's look at a sample view: - -.. code-block:: python - - 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 - pass - else: - formset = ArticleFormSet() - return render_to_response('manage_articles.html', {'formset': formset}) - -The ``manage_articles.html`` template might look like this: - -.. code-block:: html+django - - <form method="post" action=""> - {{ formset.management_form }} - <table> - {% for form in formset.forms %} - {{ form }} - {% endfor %} - </table> - </form> - -However the above can be slightly shortcutted and let the formset itself deal -with the management form: - -.. code-block:: html+django - - <form method="post" action=""> - <table> - {{ formset }} - </table> - </form> - -The above ends up calling the ``as_table`` method on the formset class. - -Using more than one formset in a view -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You are able to use more than one formset in a view if you like. Formsets -borrow much of its behavior from forms. With that said you are able to use -``prefix`` to prefix formset form field names with a given value to allow -more than one formset to be sent to a view without name clashing. Lets take -a look at how this might be accomplished: - -.. code-block:: python - - def manage_articles(request): - ArticleFormSet = formset_factory(ArticleForm) - BookFormSet = formset_factory(BookForm) - if request.method == 'POST': - article_formset = ArticleFormSet(request.POST, request.FILES, prefix='articles') - book_formset = BookFormSet(request.POST, request.FILES, prefix='books') - if article_formset.is_valid() and book_formset.is_valid(): - # do something with the cleaned_data on the formsets. - pass - else: - article_formset = ArticleFormSet(prefix='articles') - book_formset = BookFormSet(prefix='books') - return render_to_response('manage_articles.html', { - 'article_formset': article_formset, - 'book_formset': book_formset, - }) - -You would then render the formsets as normal. It is important to point out -that you need to pass ``prefix`` on both the POST and non-POST cases so that -it is rendered and processed correctly. diff --git a/parts/django/docs/topics/forms/index.txt b/parts/django/docs/topics/forms/index.txt deleted file mode 100644 index 30b09c0..0000000 --- a/parts/django/docs/topics/forms/index.txt +++ /dev/null @@ -1,402 +0,0 @@ -================== -Working with forms -================== - -.. admonition:: About this document - - This document provides an introduction to Django's form handling features. - For a more detailed look at specific areas of the forms API, see - :doc:`/ref/forms/api`, :doc:`/ref/forms/fields`, and - :doc:`/ref/forms/validation`. - -.. highlightlang:: html+django - -``django.forms`` is Django's form-handling library. - -While it is possible to process form submissions just using Django's -:class:`~django.http.HttpRequest` class, using the form library takes care of a -number of common form-related tasks. Using it, you can: - - 1. Display an HTML form with automatically generated form widgets. - 2. Check submitted data against a set of validation rules. - 3. Redisplay a form in the case of validation errors. - 4. Convert submitted form data to the relevant Python data types. - -Overview -======== - -The library deals with these concepts: - -.. glossary:: - - Widget - A class that corresponds to an HTML form widget, e.g. - ``<input type="text">`` or ``<textarea>``. This handles rendering of the - widget as HTML. - - Field - A class that is responsible for doing validation, e.g. - an ``EmailField`` that makes sure its data is a valid e-mail address. - - Form - A collection of fields that knows how to validate itself and - display itself as HTML. - - Form Media - The CSS and JavaScript resources that are required to render a form. - -The library is decoupled from the other Django components, such as the database -layer, views and templates. It relies only on Django settings, a couple of -``django.utils`` helper functions and Django's internationalization hooks (but -you're not required to be using internationalization features to use this -library). - -Form objects -============ - -A Form object encapsulates a sequence of form fields and a collection of -validation rules that must be fulfilled in order for the form to be accepted. -Form classes are created as subclasses of ``django.forms.Form`` and -make use of a declarative style that you'll be familiar with if you've used -Django's database models. - -For example, consider a form used to implement "contact me" functionality on a -personal Web site: - -.. code-block:: python - - from django import forms - - class ContactForm(forms.Form): - subject = forms.CharField(max_length=100) - message = forms.CharField() - sender = forms.EmailField() - cc_myself = forms.BooleanField(required=False) - -A form is composed of ``Field`` objects. In this case, our form has four -fields: ``subject``, ``message``, ``sender`` and ``cc_myself``. ``CharField``, -``EmailField`` and ``BooleanField`` are just three of the available field types; -a full list can be found in :doc:`/ref/forms/fields`. - -If your form is going to be used to directly add or edit a Django model, you can -use a :doc:`ModelForm </topics/forms/modelforms>` to avoid duplicating your model -description. - -Using a form in a view ----------------------- - -The standard pattern for processing a form in a view looks like this: - -.. code-block:: python - - def contact(request): - if request.method == 'POST': # If the form has been submitted... - form = ContactForm(request.POST) # A form bound to the POST data - if form.is_valid(): # All validation rules pass - # Process the data in form.cleaned_data - # ... - return HttpResponseRedirect('/thanks/') # Redirect after POST - else: - form = ContactForm() # An unbound form - - return render_to_response('contact.html', { - 'form': form, - }) - - -There are three code paths here: - - 1. If the form has not been submitted, an unbound instance of ContactForm is - created and passed to the template. - 2. If the form has been submitted, a bound instance of the form is created - using ``request.POST``. If the submitted data is valid, it is processed - and the user is re-directed to a "thanks" page. - 3. If the form has been submitted but is invalid, the bound form instance is - passed on to the template. - -.. versionchanged:: 1.0 - The ``cleaned_data`` attribute was called ``clean_data`` in earlier releases. - -The distinction between **bound** and **unbound** forms is important. An unbound -form does not have any data associated with it; when rendered to the user, it -will be empty or will contain default values. A bound form does have submitted -data, and hence can be used to tell if that data is valid. If an invalid bound -form is rendered it can include inline error messages telling the user where -they went wrong. - -See :ref:`ref-forms-api-bound-unbound` for further information on the -differences between bound and unbound forms. - -Handling file uploads with a form ---------------------------------- - -To see how to handle file uploads with your form see -:ref:`binding-uploaded-files` for more information. - -Processing the data from a form -------------------------------- - -Once ``is_valid()`` returns ``True``, you can process the form submission safe -in the knowledge that it conforms to the validation rules defined by your form. -While you could access ``request.POST`` directly at this point, it is better to -access ``form.cleaned_data``. This data has not only been validated but will -also be converted in to the relevant Python types for you. In the above example, -``cc_myself`` will be a boolean value. Likewise, fields such as ``IntegerField`` -and ``FloatField`` convert values to a Python int and float respectively. - -Extending the above example, here's how the form data could be processed: - -.. code-block:: python - - if form.is_valid(): - subject = form.cleaned_data['subject'] - message = form.cleaned_data['message'] - sender = form.cleaned_data['sender'] - cc_myself = form.cleaned_data['cc_myself'] - - recipients = ['info@example.com'] - if cc_myself: - recipients.append(sender) - - from django.core.mail import send_mail - send_mail(subject, message, sender, recipients) - return HttpResponseRedirect('/thanks/') # Redirect after POST - -For more on sending e-mail from Django, see :doc:`/topics/email`. - -Displaying a form using a template ----------------------------------- - -Forms are designed to work with the Django template language. In the above -example, we passed our ``ContactForm`` instance to the template using the -context variable ``form``. Here's a simple example template:: - - <form action="/contact/" method="post"> - {{ form.as_p }} - <input type="submit" value="Submit" /> - </form> - -The form only outputs its own fields; it is up to you to provide the surrounding -``<form>`` tags and the submit button. - -``form.as_p`` will output the form with each form field and accompanying label -wrapped in a paragraph. Here's the output for our example template:: - - <form action="/contact/" method="post"> - <p><label for="id_subject">Subject:</label> - <input id="id_subject" type="text" name="subject" maxlength="100" /></p> - <p><label for="id_message">Message:</label> - <input type="text" name="message" id="id_message" /></p> - <p><label for="id_sender">Sender:</label> - <input type="text" name="sender" id="id_sender" /></p> - <p><label for="id_cc_myself">Cc myself:</label> - <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p> - <input type="submit" value="Submit" /> - </form> - -Note that each form field has an ID attribute set to ``id_<field-name>``, which -is referenced by the accompanying label tag. This is important for ensuring -forms are accessible to assistive technology such as screen reader software. You -can also :ref:`customize the way in which labels and ids are generated -<ref-forms-api-configuring-label>`. - -You can also use ``form.as_table`` to output table rows (you'll need to provide -your own ``<table>`` tags) and ``form.as_ul`` to output list items. - -Customizing the form template ------------------------------ - -If the default generated HTML is not to your taste, you can completely customize -the way a form is presented using the Django template language. Extending the -above example:: - - <form action="/contact/" method="post"> - {{ form.non_field_errors }} - <div class="fieldWrapper"> - {{ form.subject.errors }} - <label for="id_subject">E-mail subject:</label> - {{ form.subject }} - </div> - <div class="fieldWrapper"> - {{ form.message.errors }} - <label for="id_message">Your message:</label> - {{ form.message }} - </div> - <div class="fieldWrapper"> - {{ form.sender.errors }} - <label for="id_sender">Your email address:</label> - {{ form.sender }} - </div> - <div class="fieldWrapper"> - {{ form.cc_myself.errors }} - <label for="id_cc_myself">CC yourself?</label> - {{ form.cc_myself }} - </div> - <p><input type="submit" value="Send message" /></p> - </form> - -Each named form-field can be output to the template using -``{{ form.name_of_field }}``, which will produce the HTML needed to display the -form widget. Using ``{{ form.name_of_field.errors }}`` displays a list of form -errors, rendered as an unordered list. This might look like:: - - <ul class="errorlist"> - <li>Sender is required.</li> - </ul> - -The list has a CSS class of ``errorlist`` to allow you to style its appearance. -If you wish to further customize the display of errors you can do so by looping -over them:: - - {% if form.subject.errors %} - <ol> - {% for error in form.subject.errors %} - <li><strong>{{ error|escape }}</strong></li> - {% endfor %} - </ol> - {% endif %} - -Looping over the form's fields ------------------------------- - -If you're using the same HTML for each of your form fields, you can reduce -duplicate code by looping through each field in turn using a ``{% for %}`` -loop:: - - <form action="/contact/" method="post"> - {% for field in form %} - <div class="fieldWrapper"> - {{ field.errors }} - {{ field.label_tag }}: {{ field }} - </div> - {% endfor %} - <p><input type="submit" value="Send message" /></p> - </form> - -Within this loop, ``{{ field }}`` is an instance of :class:`BoundField`. -``BoundField`` also has the following attributes, which can be useful in your -templates: - - ``{{ field.label }}`` - The label of the field, e.g. ``E-mail address``. - - ``{{ field.label_tag }}`` - The field's label wrapped in the appropriate HTML ``<label>`` tag, - e.g. ``<label for="id_email">E-mail address</label>`` - - ``{{ field.html_name }}`` - The name of the field that will be used in the input element's name - field. This takes the form prefix into account, if it has been set. - - ``{{ field.help_text }}`` - Any help text that has been associated with the field. - - ``{{ field.errors }}`` - Outputs a ``<ul class="errorlist">`` containing any validation errors - corresponding to this field. You can customize the presentation of - the errors with a ``{% for error in field.errors %}`` loop. In this - case, each object in the loop is a simple string containing the error - message. - - ``field.is_hidden`` - This attribute is ``True`` if the form field is a hidden field and - ``False`` otherwise. It's not particularly useful as a template - variable, but could be useful in conditional tests such as:: - - {% if field.is_hidden %} - {# Do something special #} - {% endif %} - -Looping over hidden and visible fields -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you're manually laying out a form in a template, as opposed to relying on -Django's default form layout, you might want to treat ``<input type="hidden">`` -fields differently than non-hidden fields. For example, because hidden fields -don't display anything, putting error messages "next to" the field could cause -confusion for your users -- so errors for those fields should be handled -differently. - -Django provides two methods on a form that allow you to loop over the hidden -and visible fields independently: ``hidden_fields()`` and -``visible_fields()``. Here's a modification of an earlier example that uses -these two methods:: - - <form action="/contact/" method="post"> - {% for field in form.visible_fields %} - <div class="fieldWrapper"> - - {# Include the hidden fields in the form #} - {% if forloop.first %} - {% for hidden in form.hidden_fields %} - {{ hidden }} - {% endfor %} - {% endif %} - - {{ field.errors }} - {{ field.label_tag }}: {{ field }} - </div> - {% endfor %} - <p><input type="submit" value="Send message" /></p> - </form> - -This example does not handle any errors in the hidden fields. Usually, an -error in a hidden field is a sign of form tampering, since normal form -interaction won't alter them. However, you could easily insert some error -displays for those form errors, as well. - -.. versionadded:: 1.1 - The ``hidden_fields`` and ``visible_fields`` methods are new in Django - 1.1. - -Reusable form templates ------------------------ - -If your site uses the same rendering logic for forms in multiple places, you -can reduce duplication by saving the form's loop in a standalone template and -using the :ttag:`include` tag to reuse it in other templates:: - - <form action="/contact/" method="post"> - {% include "form_snippet.html" %} - <p><input type="submit" value="Send message" /></p> - </form> - - # In form_snippet.html: - - {% for field in form %} - <div class="fieldWrapper"> - {{ field.errors }} - {{ field.label_tag }}: {{ field }} - </div> - {% endfor %} - -If the form object passed to a template has a different name within the -context, you can alias it using the :ttag:`with` tag:: - - <form action="/comments/add/" method="post"> - {% with comment_form as form %} - {% include "form_snippet.html" %} - {% endwith %} - <p><input type="submit" value="Submit comment" /></p> - </form> - -If you find yourself doing this often, you might consider creating a custom -:ref:`inclusion tag<howto-custom-template-tags-inclusion-tags>`. - -Further topics -============== - -This covers the basics, but forms can do a whole lot more: - -.. toctree:: - :maxdepth: 2 - - modelforms - formsets - media - -.. seealso:: - - :doc:`The Forms Reference </ref/forms/index>` - Covers the full API reference, including form fields, form widgets, - and form and field validation. diff --git a/parts/django/docs/topics/forms/media.txt b/parts/django/docs/topics/forms/media.txt deleted file mode 100644 index fe70894..0000000 --- a/parts/django/docs/topics/forms/media.txt +++ /dev/null @@ -1,309 +0,0 @@ -Form Media -========== - -Rendering an attractive and easy-to-use Web form requires more than just -HTML - it also requires CSS stylesheets, and if you want to use fancy -"Web2.0" widgets, you may also need to include some JavaScript on each -page. The exact combination of CSS and JavaScript that is required for -any given page will depend upon the widgets that are in use on that page. - -This is where Django media definitions come in. Django allows you to -associate different media files with the forms and widgets that require -that media. For example, if you want to use a calendar to render DateFields, -you can define a custom Calendar widget. This widget can then be associated -with the CSS and JavaScript that is required to render the calendar. When -the Calendar widget is used on a form, Django is able to identify the CSS and -JavaScript files that are required, and provide the list of file names -in a form suitable for easy inclusion on your Web page. - -.. admonition:: Media and Django Admin - - The Django Admin application defines a number of customized widgets - for calendars, filtered selections, and so on. These widgets define - media requirements, and the Django Admin uses the custom widgets - in place of the Django defaults. The Admin templates will only include - those media files that are required to render the widgets on any - given page. - - If you like the widgets that the Django Admin application uses, - feel free to use them in your own application! They're all stored - in ``django.contrib.admin.widgets``. - -.. admonition:: Which JavaScript toolkit? - - Many JavaScript toolkits exist, and many of them include widgets (such - as calendar widgets) that can be used to enhance your application. - Django has deliberately avoided blessing any one JavaScript toolkit. - Each toolkit has its own relative strengths and weaknesses - use - whichever toolkit suits your requirements. Django is able to integrate - with any JavaScript toolkit. - -Media as a static definition ----------------------------- - -The easiest way to define media is as a static definition. Using this method, -the media declaration is an inner class. The properties of the inner class -define the media requirements. - -Here's a simple example:: - - class CalendarWidget(forms.TextInput): - class Media: - css = { - 'all': ('pretty.css',) - } - js = ('animations.js', 'actions.js') - -This code defines a ``CalendarWidget``, which will be based on ``TextInput``. -Every time the CalendarWidget is used on a form, that form will be directed -to include the CSS file ``pretty.css``, and the JavaScript files -``animations.js`` and ``actions.js``. - -This static media definition is converted at runtime into a widget property -named ``media``. The media for a CalendarWidget instance can be retrieved -through this property:: - - >>> w = CalendarWidget() - >>> print w.media - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - -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:: - - <link href="http://media.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" /> - <link href="http://media.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" /> - <link href="http://media.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" /> - -``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 - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> - -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 FancyCalendarWidget(CalendarWidget): - ... class Media: - ... extend = False - ... css = { - ... 'all': ('fancy.css',) - ... } - ... js = ('whizbang.js',) - - >>> w = FancyCalendarWidget() - >>> print w.media - <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> - -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 widget 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 - <link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://othersite.com/actions.js"></script> - -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 ``<head>`` 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 - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - - >>> print w.media['css'] - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - -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 - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> - -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 - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> - -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 - <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" /> - <link href="http://media.example.com/layout.css" type="text/css" media="all" rel="stylesheet" /> - <script type="text/javascript" src="http://media.example.com/animations.js"></script> - <script type="text/javascript" src="http://media.example.com/actions.js"></script> - <script type="text/javascript" src="http://media.example.com/whizbang.js"></script> diff --git a/parts/django/docs/topics/forms/modelforms.txt b/parts/django/docs/topics/forms/modelforms.txt deleted file mode 100644 index 23ed9a7..0000000 --- a/parts/django/docs/topics/forms/modelforms.txt +++ /dev/null @@ -1,885 +0,0 @@ -========================== -Creating forms from models -========================== - -.. module:: django.forms.models - :synopsis: ModelForm and ModelFormset. - -.. currentmodule:: django.forms - -``ModelForm`` -============= -.. class:: ModelForm - -If you're building a database-driven app, chances are you'll have forms that -map closely to Django models. For instance, you might have a ``BlogComment`` -model, and you want to create a form that lets people submit comments. In this -case, it would be redundant to define the field types in your form, because -you've already defined the fields in your model. - -For this reason, Django provides a helper class that let you create a ``Form`` -class from a Django model. - -For example:: - - >>> from django.forms import ModelForm - - # Create the form class. - >>> class ArticleForm(ModelForm): - ... class Meta: - ... model = Article - - # Creating a form to add an article. - >>> form = ArticleForm() - - # Creating a form to change an existing article. - >>> article = Article.objects.get(pk=1) - >>> form = ArticleForm(instance=article) - -Field types ------------ - -The generated ``Form`` class will have a form field for every model field. Each -model field has a corresponding default form field. For example, a -``CharField`` on a model is represented as a ``CharField`` on a form. A -model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is -the full list of conversions: - - =============================== ======================================== - Model field Form field - =============================== ======================================== - ``AutoField`` Not represented in the form - - ``BigIntegerField`` ``IntegerField`` with ``min_value`` set - to -9223372036854775808 and ``max_value`` - set to 9223372036854775807. - - ``BooleanField`` ``BooleanField`` - - ``CharField`` ``CharField`` with ``max_length`` set to - the model field's ``max_length`` - - ``CommaSeparatedIntegerField`` ``CharField`` - - ``DateField`` ``DateField`` - - ``DateTimeField`` ``DateTimeField`` - - ``DecimalField`` ``DecimalField`` - - ``EmailField`` ``EmailField`` - - ``FileField`` ``FileField`` - - ``FilePathField`` ``CharField`` - - ``FloatField`` ``FloatField`` - - ``ForeignKey`` ``ModelChoiceField`` (see below) - - ``ImageField`` ``ImageField`` - - ``IntegerField`` ``IntegerField`` - - ``IPAddressField`` ``IPAddressField`` - - ``ManyToManyField`` ``ModelMultipleChoiceField`` (see - below) - - ``NullBooleanField`` ``CharField`` - - ``PhoneNumberField`` ``USPhoneNumberField`` - (from ``django.contrib.localflavor.us``) - - ``PositiveIntegerField`` ``IntegerField`` - - ``PositiveSmallIntegerField`` ``IntegerField`` - - ``SlugField`` ``SlugField`` - - ``SmallIntegerField`` ``IntegerField`` - - ``TextField`` ``CharField`` with - ``widget=forms.Textarea`` - - ``TimeField`` ``TimeField`` - - ``URLField`` ``URLField`` with ``verify_exists`` set - to the model field's ``verify_exists`` - - ``XMLField`` ``CharField`` with - ``widget=forms.Textarea`` - =============================== ======================================== - - -.. versionadded:: 1.0 - The ``FloatField`` form field and ``DecimalField`` model and form fields - are new in Django 1.0. - -.. versionadded:: 1.2 - The ``BigIntegerField`` is new in Django 1.2. - - -As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field -types are special cases: - - * ``ForeignKey`` is represented by ``django.forms.ModelChoiceField``, - which is a ``ChoiceField`` whose choices are a model ``QuerySet``. - - * ``ManyToManyField`` is represented by - ``django.forms.ModelMultipleChoiceField``, which is a - ``MultipleChoiceField`` whose choices are a model ``QuerySet``. - -In addition, each generated form field has attributes set as follows: - - * If the model field has ``blank=True``, then ``required`` is set to - ``False`` on the form field. Otherwise, ``required=True``. - - * The form field's ``label`` is set to the ``verbose_name`` of the model - field, with the first character capitalized. - - * The form field's ``help_text`` is set to the ``help_text`` of the model - field. - - * If the model field has ``choices`` set, then the form field's ``widget`` - will be set to ``Select``, with choices coming from the model field's - ``choices``. The choices will normally include the blank choice which is - selected by default. If the field is required, this forces the user to - make a selection. The blank choice will not be included if the model - field has ``blank=False`` and an explicit ``default`` value (the - ``default`` value will be initially selected instead). - -Finally, note that you can override the form field used for a given model -field. See `Overriding the default field types or widgets`_ below. - -A full example --------------- - -Consider this set of models:: - - from django.db import models - from django.forms import ModelForm - - TITLE_CHOICES = ( - ('MR', 'Mr.'), - ('MRS', 'Mrs.'), - ('MS', 'Ms.'), - ) - - class Author(models.Model): - name = models.CharField(max_length=100) - title = models.CharField(max_length=3, choices=TITLE_CHOICES) - birth_date = models.DateField(blank=True, null=True) - - def __unicode__(self): - return self.name - - class Book(models.Model): - name = models.CharField(max_length=100) - authors = models.ManyToManyField(Author) - - class AuthorForm(ModelForm): - class Meta: - model = Author - - class BookForm(ModelForm): - class Meta: - model = Book - -With these models, the ``ModelForm`` subclasses above would be roughly -equivalent to this (the only difference being the ``save()`` method, which -we'll discuss in a moment.):: - - class AuthorForm(forms.Form): - name = forms.CharField(max_length=100) - title = forms.CharField(max_length=3, - widget=forms.Select(choices=TITLE_CHOICES)) - birth_date = forms.DateField(required=False) - - class BookForm(forms.Form): - name = forms.CharField(max_length=100) - authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all()) - -The ``is_valid()`` method and ``errors`` ----------------------------------------- - -.. versionchanged:: 1.2 - -The first time you call ``is_valid()`` or access the ``errors`` attribute of a -``ModelForm`` has always triggered form validation, but as of Django 1.2, it -will also trigger :ref:`model validation <validating-objects>`. This has the -side-effect of cleaning the model you pass to the ``ModelForm`` constructor. -For instance, calling ``is_valid()`` on your form will convert any date fields -on your model to actual date objects. - - -The ``save()`` method ---------------------- - -Every form produced by ``ModelForm`` also has a ``save()`` -method. This method creates and saves a database object from the data -bound to the form. A subclass of ``ModelForm`` can accept an existing -model instance as the keyword argument ``instance``; if this is -supplied, ``save()`` will update that instance. If it's not supplied, -``save()`` will create a new instance of the specified model:: - - # Create a form instance from POST data. - >>> f = ArticleForm(request.POST) - - # Save a new Article object from the form's data. - >>> new_article = f.save() - - # Create a form to edit an existing Article. - >>> a = Article.objects.get(pk=1) - >>> f = ArticleForm(instance=a) - >>> f.save() - - # Create a form to edit an existing Article, but use - # POST data to populate the form. - >>> a = Article.objects.get(pk=1) - >>> f = ArticleForm(request.POST, instance=a) - >>> f.save() - -Note that ``save()`` will raise a ``ValueError`` if the data in the form -doesn't validate -- i.e., if form.errors evaluates to True. - -This ``save()`` method accepts an optional ``commit`` keyword argument, which -accepts either ``True`` or ``False``. If you call ``save()`` with -``commit=False``, then it will return an object that hasn't yet been saved to -the database. In this case, it's up to you to call ``save()`` on the resulting -model instance. This is useful if you want to do custom processing on the -object before saving it, or if you want to use one of the specialized -:ref:`model saving options <ref-models-force-insert>`. ``commit`` is ``True`` -by default. - -Another side effect of using ``commit=False`` is seen when your model has -a many-to-many relation with another model. If your model has a many-to-many -relation and you specify ``commit=False`` when you save a form, Django cannot -immediately save the form data for the many-to-many relation. This is because -it isn't possible to save many-to-many data for an instance until the instance -exists in the database. - -To work around this problem, every time you save a form using ``commit=False``, -Django adds a ``save_m2m()`` method to your ``ModelForm`` subclass. After -you've manually saved the instance produced by the form, you can invoke -``save_m2m()`` to save the many-to-many form data. For example:: - - # Create a form instance with POST data. - >>> f = AuthorForm(request.POST) - - # Create, but don't save the new author instance. - >>> new_author = f.save(commit=False) - - # Modify the author in some way. - >>> new_author.some_field = 'some_value' - - # Save the new instance. - >>> new_author.save() - - # Now, save the many-to-many data for the form. - >>> f.save_m2m() - -Calling ``save_m2m()`` is only required if you use ``save(commit=False)``. -When you use a simple ``save()`` on a form, all data -- including -many-to-many data -- is saved without the need for any additional method calls. -For example:: - - # Create a form instance with POST data. - >>> a = Author() - >>> f = AuthorForm(request.POST, instance=a) - - # Create and save the new author instance. There's no need to do anything else. - >>> new_author = f.save() - -Other than the ``save()`` and ``save_m2m()`` methods, a ``ModelForm`` works -exactly the same way as any other ``forms`` form. For example, the -``is_valid()`` method is used to check for validity, the ``is_multipart()`` -method is used to determine whether a form requires multipart file upload (and -hence whether ``request.FILES`` must be passed to the form), etc. See -:ref:`binding-uploaded-files` for more information. - -Using a subset of fields on the form ------------------------------------- - -In some cases, you may not want all the model fields to appear on the generated -form. There are three ways of telling ``ModelForm`` to use only a subset of the -model fields: - -1. Set ``editable=False`` on the model field. As a result, *any* form - created from the model via ``ModelForm`` will not include that - field. - -2. Use the ``fields`` attribute of the ``ModelForm``'s inner ``Meta`` - class. This attribute, if given, should be a list of field names - to include in the form. - - .. versionchanged:: 1.1 - - The form will render the fields in the same order they are specified in the - ``fields`` attribute. - -3. Use the ``exclude`` attribute of the ``ModelForm``'s inner ``Meta`` - class. This attribute, if given, should be a list of field names - to exclude from the form. - -For example, if you want a form for the ``Author`` model (defined -above) that includes only the ``name`` and ``title`` fields, you would -specify ``fields`` or ``exclude`` like this:: - - class PartialAuthorForm(ModelForm): - class Meta: - model = Author - fields = ('name', 'title') - - class PartialAuthorForm(ModelForm): - class Meta: - model = Author - exclude = ('birth_date',) - -Since the Author model has only 3 fields, 'name', 'title', and -'birth_date', the forms above will contain exactly the same fields. - -.. note:: - - If you specify ``fields`` or ``exclude`` when creating a form with - ``ModelForm``, then the fields that are not in the resulting form will not - be set by the form's ``save()`` method. Django will prevent any attempt to - save an incomplete model, so if the model does not allow the missing fields - to be empty, and does not provide a default value for the missing fields, - any attempt to ``save()`` a ``ModelForm`` with missing fields will fail. - To avoid this failure, you must instantiate your model with initial values - for the missing, but required fields:: - - author = Author(title='Mr') - form = PartialAuthorForm(request.POST, instance=author) - form.save() - - Alternatively, you can use ``save(commit=False)`` and manually set - any extra required fields:: - - form = PartialAuthorForm(request.POST) - author = form.save(commit=False) - author.title = 'Mr' - author.save() - - See the `section on saving forms`_ for more details on using - ``save(commit=False)``. - -.. _section on saving forms: `The save() method`_ - -Overriding the default field types or widgets ---------------------------------------------- - -.. versionadded:: 1.2 - The ``widgets`` attribute is new in Django 1.2. - -The default field types, as described in the `Field types`_ table above, are -sensible defaults. If you have a ``DateField`` in your model, chances are you'd -want that to be represented as a ``DateField`` in your form. But -``ModelForm`` gives you the flexibility of changing the form field type and -widget for a given model field. - -To specify a custom widget for a field, use the ``widgets`` attribute of the -inner ``Meta`` class. This should be a dictionary mapping field names to widget -classes or instances. - -For example, if you want the a ``CharField`` for the ``name`` -attribute of ``Author`` to be represented by a ``<textarea>`` instead -of its default ``<input type="text">``, you can override the field's -widget:: - - from django.forms import ModelForm, Textarea - - class AuthorForm(ModelForm): - class Meta: - model = Author - fields = ('name', 'title', 'birth_date') - widgets = { - 'name': Textarea(attrs={'cols': 80, 'rows': 20}), - } - -The ``widgets`` dictionary accepts either widget instances (e.g., -``Textarea(...)``) or classes (e.g., ``Textarea``). - -If you want to further customize a field -- including its type, label, etc. -- -you can do this by declaratively specifying fields like you would in a regular -``Form``. Declared fields will override the default ones generated by using the -``model`` attribute. - -For example, if you wanted to use ``MyDateFormField`` for the ``pub_date`` -field, you could do the following:: - - class ArticleForm(ModelForm): - pub_date = MyDateFormField() - - class Meta: - model = Article - -If you want to override a field's default label, then specify the ``label`` -parameter when declaring the form field:: - - >>> class ArticleForm(ModelForm): - ... pub_date = DateField(label='Publication date') - ... - ... class Meta: - ... model = Article - -.. note:: - - If you explicitly instantiate a form field like this, Django assumes that you - want to completely define its behavior; therefore, default attributes (such as - ``max_length`` or ``required``) are not drawn from the corresponding model. If - you want to maintain the behavior specified in the model, you must set the - relevant arguments explicitly when declaring the form field. - - For example, if the ``Article`` model looks like this:: - - class Article(models.Model): - headline = models.CharField(max_length=200, null=True, blank=True, - help_text="Use puns liberally") - content = models.TextField() - - and you want to do some custom validation for ``headline``, while keeping - the ``blank`` and ``help_text`` values as specified, you might define - ``ArticleForm`` like this:: - - class ArticleForm(ModelForm): - headline = MyFormField(max_length=200, required=False, - help_text="Use puns liberally") - - class Meta: - model = Article - - See the :doc:`form field documentation </ref/forms/fields>` for more information - on fields and their arguments. - -Changing the order of fields ----------------------------- - -.. versionadded:: 1.1 - -By default, a ``ModelForm`` will render fields in the same order that they are -defined on the model, with ``ManyToManyField`` instances appearing last. If -you want to change the order in which fields are rendered, you can use the -``fields`` attribute on the ``Meta`` class. - -The ``fields`` attribute defines the subset of model fields that will be -rendered, and the order in which they will be rendered. For example given this -model:: - - class Book(models.Model): - author = models.ForeignKey(Author) - title = models.CharField(max_length=100) - -the ``author`` field would be rendered first. If we wanted the title field -to be rendered first, we could specify the following ``ModelForm``:: - - >>> class BookForm(ModelForm): - ... class Meta: - ... model = Book - ... fields = ('title', 'author') - -.. _overriding-modelform-clean-method: - -Overriding the clean() method ------------------------------ - -You can override the ``clean()`` method on a model form to provide additional -validation in the same way you can on a normal form. - -In this regard, model forms have two specific characteristics when compared to -forms: - -By default the ``clean()`` method validates the uniqueness of fields that are -marked as ``unique``, ``unique_together`` or ``unique_for_date|month|year`` on -the model. Therefore, if you would like to override the ``clean()`` method and -maintain the default validation, you must call the parent class's ``clean()`` -method. - -Also, a model form instance bound to a model object will contain a -``self.instance`` attribute that gives model form methods access to that -specific model instance. - -Form inheritance ----------------- - -As with basic forms, you can extend and reuse ``ModelForms`` by inheriting -them. This is useful if you need to declare extra fields or extra methods on a -parent class for use in a number of forms derived from models. For example, -using the previous ``ArticleForm`` class:: - - >>> class EnhancedArticleForm(ArticleForm): - ... def clean_pub_date(self): - ... ... - -This creates a form that behaves identically to ``ArticleForm``, except there's -some extra validation and cleaning for the ``pub_date`` field. - -You can also subclass the parent's ``Meta`` inner class if you want to change -the ``Meta.fields`` or ``Meta.excludes`` lists:: - - >>> class RestrictedArticleForm(EnhancedArticleForm): - ... class Meta(ArticleForm.Meta): - ... exclude = ('body',) - -This adds the extra method from the ``EnhancedArticleForm`` and modifies -the original ``ArticleForm.Meta`` to remove one field. - -There are a couple of things to note, however. - - * Normal Python name resolution rules apply. If you have multiple base - classes that declare a ``Meta`` inner class, only the first one will be - used. This means the child's ``Meta``, if it exists, otherwise the - ``Meta`` of the first parent, etc. - - * For technical reasons, a subclass cannot inherit from both a ``ModelForm`` - and a ``Form`` simultaneously. - -Chances are these notes won't affect you unless you're trying to do something -tricky with subclassing. - -Interaction with model validation ---------------------------------- - -As part of its validation process, ``ModelForm`` will call the ``clean()`` -method of each field on your model that has a corresponding field on your form. -If you have excluded any model fields, validation will not be run on those -fields. See the :doc:`form validation </ref/forms/validation>` documentation -for more on how field cleaning and validation work. Also, your model's -``clean()`` method will be called before any uniqueness checks are made. See -:ref:`Validating objects <validating-objects>` for more information on the -model's ``clean()`` hook. - -.. _model-formsets: - -Model formsets -============== - -Like :doc:`regular formsets </topics/forms/formsets>`, Django provides a couple -of enhanced formset classes that make it easy to work with Django models. Let's -reuse the ``Author`` model from above:: - - >>> from django.forms.models import modelformset_factory - >>> AuthorFormSet = modelformset_factory(Author) - -This will create a formset that is capable of working with the data associated -with the ``Author`` model. It works just like a regular formset:: - - >>> formset = AuthorFormSet() - >>> print formset - <input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" id="id_form-MAX_NUM_FORMS" /> - <tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></td></tr> - <tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title"> - <option value="" selected="selected">---------</option> - <option value="MR">Mr.</option> - <option value="MRS">Mrs.</option> - <option value="MS">Ms.</option> - </select></td></tr> - <tr><th><label for="id_form-0-birth_date">Birth date:</label></th><td><input type="text" name="form-0-birth_date" id="id_form-0-birth_date" /><input type="hidden" name="form-0-id" id="id_form-0-id" /></td></tr> - -.. note:: - ``modelformset_factory`` uses ``formset_factory`` to generate formsets. - This means that a model formset is just an extension of a basic formset - that knows how to interact with a particular model. - -Changing the queryset ---------------------- - -By default, when you create a formset from a model, the formset will use a -queryset that includes all objects in the model (e.g., -``Author.objects.all()``). You can override this behavior by using the -``queryset`` argument:: - - >>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O')) - -Alternatively, you can create a subclass that sets ``self.queryset`` in -``__init__``:: - - from django.forms.models import BaseModelFormSet - - class BaseAuthorFormSet(BaseModelFormSet): - def __init__(self, *args, **kwargs): - super(BaseAuthorFormSet, self).__init__(*args, **kwargs) - self.queryset = Author.objects.filter(name__startswith='O') - -Then, pass your ``BaseAuthorFormSet`` class to the factory function:: - - >>> AuthorFormSet = modelformset_factory(Author, formset=BaseAuthorFormSet) - -If you want to return a formset that doesn't include *any* pre-existing -instances of the model, you can specify an empty QuerySet:: - - >>> AuthorFormSet(queryset=Author.objects.none()) - - -Controlling which fields are used with ``fields`` and ``exclude`` ------------------------------------------------------------------ - -By default, a model formset uses all fields in the model that are not marked -with ``editable=False``. However, this can be overridden at the formset level:: - - >>> AuthorFormSet = modelformset_factory(Author, fields=('name', 'title')) - -Using ``fields`` restricts the formset to use only the given fields. -Alternatively, you can take an "opt-out" approach, specifying which fields to -exclude:: - - >>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',)) - -.. _saving-objects-in-the-formset: - -Saving objects in the formset ------------------------------ - -As with a ``ModelForm``, you can save the data as a model object. This is done -with the formset's ``save()`` method:: - - # Create a formset instance with POST data. - >>> formset = AuthorFormSet(request.POST) - - # Assuming all is valid, save the data. - >>> instances = formset.save() - -The ``save()`` method returns the instances that have been saved to the -database. If a given instance's data didn't change in the bound data, the -instance won't be saved to the database and won't be included in the return -value (``instances``, in the above example). - -Pass ``commit=False`` to return the unsaved model instances:: - - # don't save to the database - >>> instances = formset.save(commit=False) - >>> for instance in instances: - ... # do something with instance - ... instance.save() - -This gives you the ability to attach data to the instances before saving them -to the database. If your formset contains a ``ManyToManyField``, you'll also -need to call ``formset.save_m2m()`` to ensure the many-to-many relationships -are saved properly. - -.. _model-formsets-max-num: - -Limiting the number of editable objects ---------------------------------------- - -.. versionchanged:: 1.2 - -As with regular formsets, you can use the ``max_num`` and ``extra`` parameters -to ``modelformset_factory`` to limit the number of extra forms displayed. - -``max_num`` does not prevent existing objects from being displayed:: - - >>> Author.objects.order_by('name') - [<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>] - - >>> AuthorFormSet = modelformset_factory(Author, max_num=1) - >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name')) - >>> [x.name for x in formset.get_queryset()] - [u'Charles Baudelaire', u'Paul Verlaine', u'Walt Whitman'] - -If the value of ``max_num`` is greater than the number of existing related -objects, up to ``extra`` additional blank forms will be added to the formset, -so long as the total number of forms does not exceed ``max_num``:: - - >>> AuthorFormSet = modelformset_factory(Author, max_num=4, extra=2) - >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name')) - >>> for form in formset.forms: - ... print form.as_table() - <tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100" /><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></td></tr> - <tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100" /><input type="hidden" name="form-1-id" value="3" id="id_form-1-id" /></td></tr> - <tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100" /><input type="hidden" name="form-2-id" value="2" id="id_form-2-id" /></td></tr> - <tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100" /><input type="hidden" name="form-3-id" id="id_form-3-id" /></td></tr> - -.. versionchanged:: 1.2 - -A ``max_num`` value of ``None`` (the default) puts no limit on the number of -forms displayed. - -Using a model formset in a view -------------------------------- - -Model formsets are very similar to formsets. Let's say we want to present a -formset to edit ``Author`` model instances:: - - def manage_authors(request): - AuthorFormSet = modelformset_factory(Author) - if request.method == 'POST': - formset = AuthorFormSet(request.POST, request.FILES) - if formset.is_valid(): - formset.save() - # do something. - else: - formset = AuthorFormSet() - return render_to_response("manage_authors.html", { - "formset": formset, - }) - -As you can see, the view logic of a model formset isn't drastically different -than that of a "normal" formset. The only difference is that we call -``formset.save()`` to save the data into the database. (This was described -above, in :ref:`saving-objects-in-the-formset`.) - -Overiding ``clean()`` on a ``model_formset`` --------------------------------------------- - -Just like with ``ModelForms``, by default the ``clean()`` method of a -``model_formset`` will validate that none of the items in the formset violate -the unique constraints on your model (either ``unique``, ``unique_together`` or -``unique_for_date|month|year``). If you want to overide the ``clean()`` method -on a ``model_formset`` and maintain this validation, you must call the parent -class's ``clean`` method:: - - class MyModelFormSet(BaseModelFormSet): - def clean(self): - super(MyModelFormSet, self).clean() - # example custom validation across forms in the formset: - for form in self.forms: - # your custom formset validation - -Using a custom queryset ------------------------ - -As stated earlier, you can override the default queryset used by the model -formset:: - - def manage_authors(request): - AuthorFormSet = modelformset_factory(Author) - if request.method == "POST": - formset = AuthorFormSet(request.POST, request.FILES, - queryset=Author.objects.filter(name__startswith='O')) - if formset.is_valid(): - formset.save() - # Do something. - else: - formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O')) - return render_to_response("manage_authors.html", { - "formset": formset, - }) - -Note that we pass the ``queryset`` argument in both the ``POST`` and ``GET`` -cases in this example. - -Using the formset in the template ---------------------------------- - -.. highlight:: html+django - -There are three ways to render a formset in a Django template. - -First, you can let the formset do most of the work:: - - <form method="post" action=""> - {{ formset }} - </form> - -Second, you can manually render the formset, but let the form deal with -itself:: - - <form method="post" action=""> - {{ formset.management_form }} - {% for form in formset.forms %} - {{ form }} - {% endfor %} - </form> - -When you manually render the forms yourself, be sure to render the management -form as shown above. See the :ref:`management form documentation -<understanding-the-managementform>`. - -Third, you can manually render each field:: - - <form method="post" action=""> - {{ formset.management_form }} - {% for form in formset.forms %} - {% for field in form %} - {{ field.label_tag }}: {{ field }} - {% endfor %} - {% endfor %} - </form> - -If you opt to use this third method and you don't iterate over the fields with -a ``{% for %}`` loop, you'll need to render the primary key field. For example, -if you were rendering the ``name`` and ``age`` fields of a model:: - - <form method="post" action=""> - {{ formset.management_form }} - {% for form in formset.forms %} - {{ form.id }} - <ul> - <li>{{ form.name }}</li> - <li>{{ form.age }}</li> - </ul> - {% endfor %} - </form> - -Notice how we need to explicitly render ``{{ form.id }}``. This ensures that -the model formset, in the ``POST`` case, will work correctly. (This example -assumes a primary key named ``id``. If you've explicitly defined your own -primary key that isn't called ``id``, make sure it gets rendered.) - -.. highlight:: python - -Inline formsets -=============== - -Inline formsets is a small abstraction layer on top of model formsets. These -simplify the case of working with related objects via a foreign key. Suppose -you have these two models:: - - class Author(models.Model): - name = models.CharField(max_length=100) - - class Book(models.Model): - author = models.ForeignKey(Author) - title = models.CharField(max_length=100) - -If you want to create a formset that allows you to edit books belonging to -a particular author, you could do this:: - - >>> from django.forms.models import inlineformset_factory - >>> BookFormSet = inlineformset_factory(Author, Book) - >>> author = Author.objects.get(name=u'Mike Royko') - >>> formset = BookFormSet(instance=author) - -.. note:: - ``inlineformset_factory`` uses ``modelformset_factory`` and marks - ``can_delete=True``. - -More than one foreign key to the same model -------------------------------------------- - -If your model contains more than one foreign key to the same model, you'll -need to resolve the ambiguity manually using ``fk_name``. For example, consider -the following model:: - - class Friendship(models.Model): - from_friend = models.ForeignKey(Friend) - to_friend = models.ForeignKey(Friend) - length_in_months = models.IntegerField() - -To resolve this, you can use ``fk_name`` to ``inlineformset_factory``:: - - >>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name="from_friend") - -Using an inline formset in a view ---------------------------------- - -You may want to provide a view that allows a user to edit the related objects -of a model. Here's how you can do that:: - - def manage_books(request, author_id): - author = Author.objects.get(pk=author_id) - BookInlineFormSet = inlineformset_factory(Author, Book) - if request.method == "POST": - formset = BookInlineFormSet(request.POST, request.FILES, instance=author) - if formset.is_valid(): - formset.save() - # Do something. - else: - formset = BookInlineFormSet(instance=author) - return render_to_response("manage_books.html", { - "formset": formset, - }) - -Notice how we pass ``instance`` in both the ``POST`` and ``GET`` cases. diff --git a/parts/django/docs/topics/generic-views.txt b/parts/django/docs/topics/generic-views.txt deleted file mode 100644 index 41e32c8..0000000 --- a/parts/django/docs/topics/generic-views.txt +++ /dev/null @@ -1,501 +0,0 @@ -============= -Generic views -============= - -Writing Web applications can be monotonous, because we repeat certain patterns -again and again. Django tries to take away some of that monotony at the model -and template layers, but Web developers also experience this boredom at the view -level. - -Django's *generic views* were developed to ease that pain. They take certain -common idioms and patterns found in view development and abstract them so that -you can quickly write common views of data without having to write too much -code. - -We can recognize certain common tasks, like displaying a list of objects, and -write code that displays a list of *any* object. Then the model in question can -be passed as an extra argument to the URLconf. - -Django ships with generic views to do the following: - - * Perform common "simple" tasks: redirect to a different page and - render a given template. - - * Display list and detail pages for a single object. If we were creating an - application to manage conferences then a ``talk_list`` view and a - ``registered_user_list`` view would be examples of list views. A single - talk page is an example of what we call a "detail" view. - - * Present date-based objects in year/month/day archive pages, - associated detail, and "latest" pages. The Django Weblog's - (http://www.djangoproject.com/weblog/) year, month, and - day archives are built with these, as would be a typical - newspaper's archives. - - * Allow users to create, update, and delete objects -- with or - without authorization. - -Taken together, these views provide easy interfaces to perform the most common -tasks developers encounter. - -Using generic views -=================== - -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 a simple URLconf you could use to present a static "about" -page:: - - from django.conf.urls.defaults import * - from django.views.generic.simple import direct_to_template - - urlpatterns = patterns('', - ('^about/$', direct_to_template, { - 'template': 'about.html' - }) - ) - -Though this might seem a bit "magical" at first glance -- look, a view with no -code! --, actually the ``direct_to_template`` view simply grabs information from -the extra-parameters dictionary and uses that information when rendering the -view. - -Because this generic view -- and all the others -- is a regular view function -like any other, we can reuse it inside our own views. As an example, let's -extend our "about" example to map URLs of the form ``/about/<whatever>/`` to -statically rendered ``about/<whatever>.html``. We'll do this by first modifying -the URLconf to point to a view function: - -.. parsed-literal:: - - from django.conf.urls.defaults import * - from django.views.generic.simple import direct_to_template - **from books.views import about_pages** - - urlpatterns = patterns('', - ('^about/$', direct_to_template, { - 'template': 'about.html' - }), - **('^about/(\\w+)/$', about_pages),** - ) - -Next, we'll write the ``about_pages`` view:: - - from django.http import Http404 - from django.template import TemplateDoesNotExist - from django.views.generic.simple import direct_to_template - - def about_pages(request, page): - try: - return direct_to_template(request, template="about/%s.html" % page) - except TemplateDoesNotExist: - raise Http404() - -Here we're treating ``direct_to_template`` like any other function. Since it -returns an ``HttpResponse``, we can simply return it as-is. The only slightly -tricky business here is dealing with missing templates. We don't want a -nonexistent template to cause a server error, so we catch -``TemplateDoesNotExist`` exceptions and return 404 errors instead. - -.. admonition:: Is there a security vulnerability here? - - Sharp-eyed readers may have noticed a possible security hole: we're - constructing the template name using interpolated content from the browser - (``template="about/%s.html" % page``). At first glance, this looks like a - classic *directory traversal* vulnerability. But is it really? - - Not exactly. Yes, a maliciously crafted value of ``page`` could cause - directory traversal, but although ``page`` *is* taken from the request URL, - not every value will be accepted. The key is in the URLconf: we're using - the regular expression ``\w+`` to match the ``page`` part of the URL, and - ``\w`` only accepts letters and numbers. Thus, any malicious characters - (dots and slashes, here) will be rejected by the URL resolver before they - reach the view itself. - -Generic views of objects -======================== - -The ``direct_to_template`` certainly is useful, but Django's generic views -really shine when it comes to presenting views on your database content. Because -it's such a common task, Django comes with a handful of built-in generic views -that make generating list and detail views of objects incredibly easy. - -Let's take a look at one of these generic views: the "object list" view. We'll -be using these models:: - - # models.py - from django.db import models - - class Publisher(models.Model): - name = models.CharField(max_length=30) - address = models.CharField(max_length=50) - city = models.CharField(max_length=60) - state_province = models.CharField(max_length=30) - country = models.CharField(max_length=50) - website = models.URLField() - - def __unicode__(self): - return self.name - - class Meta: - ordering = ["-name"] - - class Book(models.Model): - title = models.CharField(max_length=100) - authors = models.ManyToManyField('Author') - publisher = models.ForeignKey(Publisher) - publication_date = models.DateField() - -To build a list page of all publishers, we'd use a URLconf along these lines:: - - from django.conf.urls.defaults import * - from django.views.generic import list_detail - from books.models import Publisher - - publisher_info = { - "queryset" : Publisher.objects.all(), - } - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info) - ) - -That's all the Python code we need to write. We still need to write a template, -however. We could explicitly tell the ``object_list`` view which template to use -by including a ``template_name`` key in the extra arguments dictionary, but in -the absence of an explicit template Django will infer one from the object's -name. In this case, the inferred template will be -``"books/publisher_list.html"`` -- the "books" part comes from the name of the -app that defines the model, while the "publisher" bit is just the lowercased -version of the model's name. - -.. highlightlang:: html+django - -This template will be rendered against a context containing a variable called -``object_list`` that contains all the publisher objects. A very simple template -might look like the following:: - - {% extends "base.html" %} - - {% block content %} - <h2>Publishers</h2> - <ul> - {% for publisher in object_list %} - <li>{{ publisher.name }}</li> - {% endfor %} - </ul> - {% endblock %} - -That's really all there is to it. All the cool features of generic views come -from changing the "info" dictionary passed to the generic view. The -:doc:`generic views reference</ref/generic-views>` documents all the generic -views and all their options in detail; the rest of this document will consider -some of the common ways you might customize and extend generic views. - -Extending generic views -======================= - -.. highlightlang:: python - -There's no question that using generic views can speed up development -substantially. In most projects, however, there comes a moment when the -generic views no longer suffice. Indeed, the most common question asked by new -Django developers is how to make generic views handle a wider array of -situations. - -Luckily, in nearly every one of these cases, there are ways to simply extend -generic views to handle a larger array of use cases. These situations usually -fall into a handful of patterns dealt with in the sections that follow. - -Making "friendly" template contexts ------------------------------------ - -You might have noticed that our sample publisher list template stores all the -books in a variable named ``object_list``. While this works just fine, it isn't -all that "friendly" to template authors: they have to "just know" that they're -dealing with publishers here. A better name for that variable would be -``publisher_list``; that variable's content is pretty obvious. - -We can change the name of that variable easily with the ``template_object_name`` -argument: - -.. parsed-literal:: - - publisher_info = { - "queryset" : Publisher.objects.all(), - **"template_object_name" : "publisher",** - } - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info) - ) - -Providing a useful ``template_object_name`` is always a good idea. Your -coworkers who design templates will thank you. - -Adding extra context --------------------- - -Often you simply need to present some extra information beyond that provided by -the generic view. For example, think of showing a list of all the books on each -publisher detail page. The ``object_detail`` generic view provides the -publisher to the context, but it seems there's no way to get additional -information in that template. - -But there is: all generic views take an extra optional parameter, -``extra_context``. This is a dictionary of extra objects that will be added to -the template's context. So, to provide the list of all books on the detail -detail view, we'd use an info dict like this: - -.. parsed-literal:: - - from books.models import Publisher, **Book** - - publisher_info = { - "queryset" : Publisher.objects.all(), - "template_object_name" : "publisher", - **"extra_context" : {"book_list" : Book.objects.all()}** - } - -This would populate a ``{{ book_list }}`` variable in the template context. -This pattern can be used to pass any information down into the template for the -generic view. It's very handy. - -However, there's actually a subtle bug here -- can you spot it? - -The problem has to do with when the queries in ``extra_context`` are evaluated. -Because this example puts ``Book.objects.all()`` in the URLconf, it will -be evaluated only once (when the URLconf is first loaded). Once you add or -remove books, you'll notice that the generic view doesn't reflect those -changes until you reload the Web server (see :ref:`caching-and-querysets` -for more information about when QuerySets are cached and evaluated). - -.. note:: - - This problem doesn't apply to the ``queryset`` generic view argument. Since - Django knows that particular QuerySet should *never* be cached, the generic - view takes care of clearing the cache when each view is rendered. - -The solution is to use a callback in ``extra_context`` instead of a value. Any -callable (i.e., a function) that's passed to ``extra_context`` will be evaluated -when the view is rendered (instead of only once). You could do this with an -explicitly defined function: - -.. parsed-literal:: - - def get_books(): - return Book.objects.all() - - publisher_info = { - "queryset" : Publisher.objects.all(), - "template_object_name" : "publisher", - "extra_context" : **{"book_list" : get_books}** - } - -or you could use a less obvious but shorter version that relies on the fact that -``Book.objects.all`` is itself a callable: - -.. parsed-literal:: - - publisher_info = { - "queryset" : Publisher.objects.all(), - "template_object_name" : "publisher", - "extra_context" : **{"book_list" : Book.objects.all}** - } - -Notice the lack of parentheses after ``Book.objects.all``; this references -the function without actually calling it (which the generic view will do later). - -Viewing subsets of objects --------------------------- - -Now let's take a closer look at this ``queryset`` key we've been using all -along. Most generic views take one of these ``queryset`` arguments -- it's how -the view knows which set of objects to display (see :doc:`/topics/db/queries` for -more information about ``QuerySet`` objects, and see the -:doc:`generic views reference</ref/generic-views>` for the complete details). - -To pick a simple example, we might want to order a list of books by -publication date, with the most recent first: - -.. parsed-literal:: - - book_info = { - "queryset" : Book.objects.all().order_by("-publication_date"), - } - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info), - **(r'^books/$', list_detail.object_list, book_info),** - ) - - -That's a pretty simple example, but it illustrates the idea nicely. Of course, -you'll usually want to do more than just reorder objects. If you want to -present a list of books by a particular publisher, you can use the same -technique: - -.. parsed-literal:: - - **acme_books = {** - **"queryset": Book.objects.filter(publisher__name="Acme Publishing"),** - **"template_name" : "books/acme_list.html"** - **}** - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info), - **(r'^books/acme/$', list_detail.object_list, acme_books),** - ) - -Notice that along with a filtered ``queryset``, we're also using a custom -template name. If we didn't, the generic view would use the same template as the -"vanilla" object list, which might not be what we want. - -Also notice that this isn't a very elegant way of doing publisher-specific -books. If we want to add another publisher page, we'd need another handful of -lines in the URLconf, and more than a few publishers would get unreasonable. -We'll deal with this problem in the next section. - -.. note:: - - If you get a 404 when requesting ``/books/acme/``, check to ensure you - actually have a Publisher with the name 'ACME Publishing'. Generic - views have an ``allow_empty`` parameter for this case. See the - :doc:`generic views reference</ref/generic-views>` for more details. - -Complex filtering with wrapper functions ----------------------------------------- - -Another common need is to filter down the objects given in a list page by some -key in the URL. Earlier we hard-coded the publisher's name in the URLconf, but -what if we wanted to write a view that displayed all the books by some arbitrary -publisher? We can "wrap" the ``object_list`` generic view to avoid writing a lot -of code by hand. As usual, we'll start by writing a URLconf: - -.. parsed-literal:: - - from books.views import books_by_publisher - - urlpatterns = patterns('', - (r'^publishers/$', list_detail.object_list, publisher_info), - **(r'^books/(\\w+)/$', books_by_publisher),** - ) - -Next, we'll write the ``books_by_publisher`` view itself:: - - from django.http import Http404 - from django.views.generic import list_detail - from books.models import Book, Publisher - - def books_by_publisher(request, name): - - # Look up the publisher (and raise a 404 if it can't be found). - try: - publisher = Publisher.objects.get(name__iexact=name) - except Publisher.DoesNotExist: - raise Http404 - - # Use the object_list view for the heavy lifting. - return list_detail.object_list( - request, - queryset = Book.objects.filter(publisher=publisher), - template_name = "books/books_by_publisher.html", - template_object_name = "books", - extra_context = {"publisher" : publisher} - ) - -This works because there's really nothing special about generic views -- they're -just Python functions. Like any view function, generic views expect a certain -set of arguments and return ``HttpResponse`` objects. Thus, it's incredibly easy -to wrap a small function around a generic view that does additional work before -(or after; see the next section) handing things off to the generic view. - -.. note:: - - Notice that in the preceding example we passed the current publisher being - displayed in the ``extra_context``. This is usually a good idea in wrappers - of this nature; it lets the template know which "parent" object is currently - being browsed. - -Performing extra work ---------------------- - -The last common pattern we'll look at involves doing some extra work before -or after calling the generic view. - -Imagine we had a ``last_accessed`` field on our ``Author`` object that we were -using to keep track of the last time anybody looked at that author:: - - # models.py - - class Author(models.Model): - salutation = models.CharField(max_length=10) - first_name = models.CharField(max_length=30) - last_name = models.CharField(max_length=40) - email = models.EmailField() - headshot = models.ImageField(upload_to='/tmp') - last_accessed = models.DateTimeField() - -The generic ``object_detail`` view, of course, wouldn't know anything about this -field, but once again we could easily write a custom view to keep that field -updated. - -First, we'd need to add an author detail bit in the URLconf to point to a -custom view: - -.. parsed-literal:: - - from books.views import author_detail - - urlpatterns = patterns('', - #... - **(r'^authors/(?P<author_id>\\d+)/$', author_detail),** - ) - -Then we'd write our wrapper function:: - - import datetime - from books.models import Author - from django.views.generic import list_detail - from django.shortcuts import get_object_or_404 - - def author_detail(request, author_id): - # Look up the Author (and raise a 404 if she's not found) - author = get_object_or_404(Author, pk=author_id) - - # Record the last accessed date - author.last_accessed = datetime.datetime.now() - author.save() - - # Show the detail page - return list_detail.object_detail( - request, - queryset = Author.objects.all(), - object_id = author_id, - ) - -.. note:: - - This code won't actually work unless you create a - ``books/author_detail.html`` template. - -We can use a similar idiom to alter the response returned by the generic view. -If we wanted to provide a downloadable plain-text version of the list of -authors, we could use a view like this:: - - def author_list_plaintext(request): - response = list_detail.object_list( - request, - queryset = Author.objects.all(), - mimetype = "text/plain", - template_name = "books/author_list.txt" - ) - response["Content-Disposition"] = "attachment; filename=authors.txt" - return response - -This works because the generic views return simple ``HttpResponse`` objects -that can be treated like dictionaries to set HTTP headers. This -``Content-Disposition`` business, by the way, instructs the browser to -download and save the page instead of displaying it in the browser. diff --git a/parts/django/docs/topics/http/_images/middleware.png b/parts/django/docs/topics/http/_images/middleware.png Binary files differdeleted file mode 100644 index 505c70a..0000000 --- a/parts/django/docs/topics/http/_images/middleware.png +++ /dev/null diff --git a/parts/django/docs/topics/http/file-uploads.txt b/parts/django/docs/topics/http/file-uploads.txt deleted file mode 100644 index a06a1ca..0000000 --- a/parts/django/docs/topics/http/file-uploads.txt +++ /dev/null @@ -1,394 +0,0 @@ -============ -File Uploads -============ - -.. currentmodule:: django.core.files - -.. versionadded:: 1.0 - -When Django handles a file upload, the file data ends up placed in -:attr:`request.FILES <django.http.HttpRequest.FILES>` (for more on the -``request`` object see the documentation for :doc:`request and response objects -</ref/request-response>`). This document explains how files are stored on disk -and in memory, and how to customize the default behavior. - -Basic file uploads -================== - -Consider a simple form containing a :class:`~django.forms.FileField`:: - - from django import forms - - class UploadFileForm(forms.Form): - title = forms.CharField(max_length=50) - file = forms.FileField() - -A view handling this form will receive the file data in -:attr:`request.FILES <django.http.HttpRequest.FILES>`, which is a dictionary -containing a key for each :class:`~django.forms.FileField` (or -:class:`~django.forms.ImageField`, or other :class:`~django.forms.FileField` -subclass) in the form. So the data from the above form would -be accessible as ``request.FILES['file']``. - -Note that :attr:`request.FILES <django.http.HttpRequest.FILES>` will only -contain data if the request method was ``POST`` and the ``<form>`` that posted -the request has the attribute ``enctype="multipart/form-data"``. Otherwise, -``request.FILES`` will be empty. - -Most of the time, you'll simply pass the file data from ``request`` into the -form as described in :ref:`binding-uploaded-files`. This would look -something like:: - - from django.http import HttpResponseRedirect - from django.shortcuts import render_to_response - - # Imaginary function to handle an uploaded file. - from somewhere import handle_uploaded_file - - def upload_file(request): - if request.method == 'POST': - form = UploadFileForm(request.POST, request.FILES) - if form.is_valid(): - handle_uploaded_file(request.FILES['file']) - return HttpResponseRedirect('/success/url/') - else: - form = UploadFileForm() - return render_to_response('upload.html', {'form': form}) - -Notice that we have to pass :attr:`request.FILES <django.http.HttpRequest.FILES>` -into the form's constructor; this is how file data gets bound into a form. - -Handling uploaded files ------------------------ - -The final piece of the puzzle is handling the actual file data from -:attr:`request.FILES <django.http.HttpRequest.FILES>`. Each entry in this -dictionary is an ``UploadedFile`` object -- a simple wrapper around an uploaded -file. You'll usually use one of these methods to access the uploaded content: - - ``UploadedFile.read()`` - Read the entire uploaded data from the file. Be careful with this - method: if the uploaded file is huge it can overwhelm your system if you - try to read it into memory. You'll probably want to use ``chunks()`` - instead; see below. - - ``UploadedFile.multiple_chunks()`` - Returns ``True`` if the uploaded file is big enough to require - reading in multiple chunks. By default this will be any file - larger than 2.5 megabytes, but that's configurable; see below. - - ``UploadedFile.chunks()`` - A generator returning chunks of the file. If ``multiple_chunks()`` is - ``True``, you should use this method in a loop instead of ``read()``. - - In practice, it's often easiest simply to use ``chunks()`` all the time; - see the example below. - - ``UploadedFile.name`` - The name of the uploaded file (e.g. ``my_file.txt``). - - ``UploadedFile.size`` - The size, in bytes, of the uploaded file. - -There are a few other methods and attributes available on ``UploadedFile`` -objects; see `UploadedFile objects`_ for a complete reference. - -Putting it all together, here's a common way you might handle an uploaded file:: - - def handle_uploaded_file(f): - destination = open('some/file/name.txt', 'wb+') - for chunk in f.chunks(): - destination.write(chunk) - destination.close() - -Looping over ``UploadedFile.chunks()`` instead of using ``read()`` ensures that -large files don't overwhelm your system's memory. - -Where uploaded data is stored ------------------------------ - -Before you save uploaded files, the data needs to be stored somewhere. - -By default, if an uploaded file is smaller than 2.5 megabytes, Django will hold -the entire contents of the upload in memory. This means that saving the file -involves only a read from memory and a write to disk and thus is very fast. - -However, if an uploaded file is too large, Django will write the uploaded file -to a temporary file stored in your system's temporary directory. On a Unix-like -platform this means you can expect Django to generate a file called something -like ``/tmp/tmpzfp6I6.upload``. If an upload is large enough, you can watch this -file grow in size as Django streams the data onto disk. - -These specifics -- 2.5 megabytes; ``/tmp``; etc. -- are simply "reasonable -defaults". Read on for details on how you can customize or completely replace -upload behavior. - -Changing upload handler behavior --------------------------------- - -Three settings control Django's file upload behavior: - - :setting:`FILE_UPLOAD_MAX_MEMORY_SIZE` - The maximum size, in bytes, for files that will be uploaded into memory. - Files larger than :setting:`FILE_UPLOAD_MAX_MEMORY_SIZE` will be - streamed to disk. - - Defaults to 2.5 megabytes. - - :setting:`FILE_UPLOAD_TEMP_DIR` - The directory where uploaded files larger than - :setting:`FILE_UPLOAD_MAX_MEMORY_SIZE` will be stored. - - Defaults to your system's standard temporary directory (i.e. ``/tmp`` on - most Unix-like systems). - - :setting:`FILE_UPLOAD_PERMISSIONS` - The numeric mode (i.e. ``0644``) to set newly uploaded files to. For - more information about what these modes mean, see the `documentation for - os.chmod`_ - - If this isn't given or is ``None``, you'll get operating-system - dependent behavior. On most platforms, temporary files will have a mode - of ``0600``, and files saved from memory will be saved using the - system's standard umask. - - .. warning:: - - If you're not familiar with file modes, please note that the leading - ``0`` is very important: it indicates an octal number, which is the - way that modes must be specified. If you try to use ``644``, you'll - get totally incorrect behavior. - - **Always prefix the mode with a 0.** - - :setting:`FILE_UPLOAD_HANDLERS` - The actual handlers for uploaded files. Changing this setting allows - complete customization -- even replacement -- of Django's upload - process. See `upload handlers`_, below, for details. - - Defaults to:: - - ("django.core.files.uploadhandler.MemoryFileUploadHandler", - "django.core.files.uploadhandler.TemporaryFileUploadHandler",) - - Which means "try to upload to memory first, then fall back to temporary - files." - -.. _documentation for os.chmod: http://docs.python.org/library/os.html#os.chmod - -``UploadedFile`` objects -======================== - -.. class:: UploadedFile - -In addition to those inherited from :class:`File`, all ``UploadedFile`` objects -define the following methods/attributes: - - ``UploadedFile.content_type`` - The content-type header uploaded with the file (e.g. ``text/plain`` or - ``application/pdf``). Like any data supplied by the user, you shouldn't - trust that the uploaded file is actually this type. You'll still need to - validate that the file contains the content that the content-type header - claims -- "trust but verify." - - ``UploadedFile.charset`` - For ``text/*`` content-types, the character set (i.e. ``utf8``) supplied - by the browser. Again, "trust but verify" is the best policy here. - - ``UploadedFile.temporary_file_path()`` - Only files uploaded onto disk will have this method; it returns the full - path to the temporary uploaded file. - -.. note:: - - Like regular Python files, you can read the file line-by-line simply by - iterating over the uploaded file: - - .. code-block:: python - - for line in uploadedfile: - do_something_with(line) - - However, *unlike* standard Python files, :class:`UploadedFile` only - understands ``\n`` (also known as "Unix-style") line endings. If you know - that you need to handle uploaded files with different line endings, you'll - need to do so in your view. - -Upload Handlers -=============== - -When a user uploads a file, Django passes off the file data to an *upload -handler* -- a small class that handles file data as it gets uploaded. Upload -handlers are initially defined in the ``FILE_UPLOAD_HANDLERS`` setting, which -defaults to:: - - ("django.core.files.uploadhandler.MemoryFileUploadHandler", - "django.core.files.uploadhandler.TemporaryFileUploadHandler",) - -Together the ``MemoryFileUploadHandler`` and ``TemporaryFileUploadHandler`` -provide Django's default file upload behavior of reading small files into memory -and large ones onto disk. - -You can write custom handlers that customize how Django handles files. You -could, for example, use custom handlers to enforce user-level quotas, compress -data on the fly, render progress bars, and even send data to another storage -location directly without storing it locally. - -Modifying upload handlers on the fly ------------------------------------- - -Sometimes particular views require different upload behavior. In these cases, -you can override upload handlers on a per-request basis by modifying -``request.upload_handlers``. By default, this list will contain the upload -handlers given by ``FILE_UPLOAD_HANDLERS``, but you can modify the list as you -would any other list. - -For instance, suppose you've written a ``ProgressBarUploadHandler`` that -provides feedback on upload progress to some sort of AJAX widget. You'd add this -handler to your upload handlers like this:: - - request.upload_handlers.insert(0, ProgressBarUploadHandler()) - -You'd probably want to use ``list.insert()`` in this case (instead of -``append()``) because a progress bar handler would need to run *before* any -other handlers. Remember, the upload handlers are processed in order. - -If you want to replace the upload handlers completely, you can just assign a new -list:: - - request.upload_handlers = [ProgressBarUploadHandler()] - -.. note:: - - You can only modify upload handlers *before* accessing - ``request.POST`` or ``request.FILES`` -- it doesn't make sense to - change upload handlers after upload handling has already - started. If you try to modify ``request.upload_handlers`` after - reading from ``request.POST`` or ``request.FILES`` Django will - throw an error. - - Thus, you should always modify uploading handlers as early in your view as - possible. - - Also, ``request.POST`` is accessed by - :class:`~django.middleware.csrf.CsrfViewMiddleware` which is enabled by - default. This means you will probably need to use - :func:`~django.views.decorators.csrf.csrf_exempt` on your view to allow you - to change the upload handlers. Assuming you do need CSRF protection, you - will then need to use :func:`~django.views.decorators.csrf.csrf_protect` on - the function that actually processes the request. Note that this means that - the handlers may start receiving the file upload before the CSRF checks have - been done. Example code: - - .. code-block:: python - - from django.views.decorators.csrf import csrf_exempt, csrf_protect - - @csrf_exempt - def upload_file_view(request): - request.upload_handlers.insert(0, ProgressBarUploadHandler()) - return _upload_file_view(request) - - @csrf_protect - def _upload_file_view(request): - ... # Process request - - -Writing custom upload handlers ------------------------------- - -All file upload handlers should be subclasses of -``django.core.files.uploadhandler.FileUploadHandler``. You can define upload -handlers wherever you wish. - -Required methods -~~~~~~~~~~~~~~~~ - -Custom file upload handlers **must** define the following methods: - - ``FileUploadHandler.receive_data_chunk(self, raw_data, start)`` - Receives a "chunk" of data from the file upload. - - ``raw_data`` is a byte string containing the uploaded data. - - ``start`` is the position in the file where this ``raw_data`` chunk - begins. - - The data you return will get fed into the subsequent upload handlers' - ``receive_data_chunk`` methods. In this way, one handler can be a - "filter" for other handlers. - - Return ``None`` from ``receive_data_chunk`` to sort-circuit remaining - upload handlers from getting this chunk.. This is useful if you're - storing the uploaded data yourself and don't want future handlers to - store a copy of the data. - - If you raise a ``StopUpload`` or a ``SkipFile`` exception, the upload - will abort or the file will be completely skipped. - - ``FileUploadHandler.file_complete(self, file_size)`` - Called when a file has finished uploading. - - The handler should return an ``UploadedFile`` object that will be stored - in ``request.FILES``. Handlers may also return ``None`` to indicate that - the ``UploadedFile`` object should come from subsequent upload handlers. - -Optional methods -~~~~~~~~~~~~~~~~ - -Custom upload handlers may also define any of the following optional methods or -attributes: - - ``FileUploadHandler.chunk_size`` - Size, in bytes, of the "chunks" Django should store into memory and feed - into the handler. That is, this attribute controls the size of chunks - fed into ``FileUploadHandler.receive_data_chunk``. - - For maximum performance the chunk sizes should be divisible by ``4`` and - should not exceed 2 GB (2\ :sup:`31` bytes) in size. When there are - multiple chunk sizes provided by multiple handlers, Django will use the - smallest chunk size defined by any handler. - - The default is 64*2\ :sup:`10` bytes, or 64 KB. - - ``FileUploadHandler.new_file(self, field_name, file_name, content_type, content_length, charset)`` - Callback signaling that a new file upload is starting. This is called - before any data has been fed to any upload handlers. - - ``field_name`` is a string name of the file ``<input>`` field. - - ``file_name`` is the unicode filename that was provided by the browser. - - ``content_type`` is the MIME type provided by the browser -- E.g. - ``'image/jpeg'``. - - ``content_length`` is the length of the image given by the browser. - Sometimes this won't be provided and will be ``None``. - - ``charset`` is the character set (i.e. ``utf8``) given by the browser. - Like ``content_length``, this sometimes won't be provided. - - This method may raise a ``StopFutureHandlers`` exception to prevent - future handlers from handling this file. - - ``FileUploadHandler.upload_complete(self)`` - Callback signaling that the entire upload (all files) has completed. - - ``FileUploadHandler.handle_raw_input(self, input_data, META, content_length, boundary, encoding)`` - Allows the handler to completely override the parsing of the raw - HTTP input. - - ``input_data`` is a file-like object that supports ``read()``-ing. - - ``META`` is the same object as ``request.META``. - - ``content_length`` is the length of the data in ``input_data``. Don't - read more than ``content_length`` bytes from ``input_data``. - - ``boundary`` is the MIME boundary for this request. - - ``encoding`` is the encoding of the request. - - Return ``None`` if you want upload handling to continue, or a tuple of - ``(POST, FILES)`` if you want to return the new data structures suitable - for the request directly. diff --git a/parts/django/docs/topics/http/generic-views.txt b/parts/django/docs/topics/http/generic-views.txt deleted file mode 100644 index 15f895e..0000000 --- a/parts/django/docs/topics/http/generic-views.txt +++ /dev/null @@ -1,5 +0,0 @@ -============= -Generic views -============= - -See :doc:`/ref/generic-views`. diff --git a/parts/django/docs/topics/http/index.txt b/parts/django/docs/topics/http/index.txt deleted file mode 100644 index 5ef776d..0000000 --- a/parts/django/docs/topics/http/index.txt +++ /dev/null @@ -1,15 +0,0 @@ -Handling HTTP requests -====================== - -Information on handling HTTP requests in Django: - -.. toctree:: - :maxdepth: 1 - - urls - views - file-uploads - shortcuts - generic-views - middleware - sessions diff --git a/parts/django/docs/topics/http/middleware.txt b/parts/django/docs/topics/http/middleware.txt deleted file mode 100644 index d376c6b..0000000 --- a/parts/django/docs/topics/http/middleware.txt +++ /dev/null @@ -1,179 +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 how middleware works, how you activate middleware, and -how to write your own middleware. Django ships with some built-in middleware -you can use right out of the box; they're documented in the :doc:`built-in -middleware reference </ref/middleware>`. - -Activating middleware -===================== - -To activate a middleware component, add it to the :setting:`MIDDLEWARE_CLASSES` -list in your Django settings. In :setting:`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 :setting:`MIDDLEWARE_CLASSES` -created by :djadmin:`django-admin.py startproject <startproject>`:: - - MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - ) - -During the request phases (:meth:`process_request` and :meth:`process_view` -middleware), Django applies middleware in the order it's defined in -:setting:`MIDDLEWARE_CLASSES`, top-down. During the response phases -(:meth:`process_response` and :meth:`process_exception` middleware), the -classes are applied in reverse order, from the bottom up. You can think of it -like an onion: each middleware class is a "layer" that wraps the view: - -.. image:: _images/middleware.png - :width: 502 - :height: 417 - :alt: Middleware application order. - -A Django installation doesn't require any middleware -- e.g., -:setting:`MIDDLEWARE_CLASSES` can be empty, if you'd like -- but it's strongly -suggested that you at least use -:class:`~django.middleware.common.CommonMiddleware`. - -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: - -.. _request-middleware: - -``process_request`` -------------------- - -.. method:: process_request(self, request) - -``request`` is an :class:`~django.http.HttpRequest` object. This method is -called on each request, before Django decides which view to execute. - -``process_request()`` should return either ``None`` or an -:class:`~django.http.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 :class:`~django.http.HttpResponse` object, -Django won't bother calling ANY other request, view or exception middleware, or -the appropriate view; it'll return that :class:`~django.http.HttpResponse`. -Response middleware is always called on every response. - -.. _view-middleware: - -``process_view`` ----------------- - -.. method:: process_view(self, request, view_func, view_args, view_kwargs) - -``request`` is an :class:`~django.http.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 :class:`~django.http.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 :class:`~django.http.HttpResponse` object, Django won't bother -calling ANY other request, view or exception middleware, or the appropriate -view; it'll return that :class:`~django.http.HttpResponse`. Response -middleware is always called on every response. - -.. _response-middleware: - -``process_response`` --------------------- - -.. method:: process_response(self, request, response) - -``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the -:class:`~django.http.HttpResponse` object returned by a Django view. - -``process_response()`` must return an :class:`~django.http.HttpResponse` -object. It could alter the given ``response``, or it could create and return a -brand-new :class:`~django.http.HttpResponse`. - -Unlike the ``process_request()`` and ``process_view()`` methods, the -``process_response()`` method is always called, even if the ``process_request()`` -and ``process_view()`` methods of the same middleware class were skipped because -an earlier middleware method returned an :class:`~django.http.HttpResponse` -(this means that your ``process_response()`` method cannot rely on setup done in -``process_request()``, for example). In addition, during the response phase the -classes are applied in reverse order, from the bottom up. This means classes -defined at the end of :setting:`MIDDLEWARE_CLASSES` will be run first. - -.. _exception-middleware: - -``process_exception`` ---------------------- - -.. method:: process_exception(self, request, exception) - -``request`` is an :class:`~django.http.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 -:class:`~django.http.HttpResponse` object. If it returns an -:class:`~django.http.HttpResponse` object, the response will be returned to -the browser. Otherwise, default exception handling kicks in. - -Again, middleware are run in reverse order during the response phase, which -includes ``process_exception``. If an exception middleware return a response, -the middleware classes above that middleware will not be called at all. - -``__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 :setting:`MIDDLEWARE_CLASSES` setting includes - the path to it. - - * Feel free to look at :doc:`Django's available middleware - </ref/middleware>` for examples. - - * If you write a middleware component that you think would be useful to - other people, contribute to the community! :doc:`Let us know - </internals/contributing>`, and we'll consider adding it to Django. diff --git a/parts/django/docs/topics/http/sessions.txt b/parts/django/docs/topics/http/sessions.txt deleted file mode 100644 index 8a0f0d4..0000000 --- a/parts/django/docs/topics/http/sessions.txt +++ /dev/null @@ -1,529 +0,0 @@ -=================== -How to use sessions -=================== - -.. module:: django.contrib.sessions - :synopsis: Provides session management for Django projects. - -Django provides full support for anonymous sessions. The session framework lets -you store and retrieve arbitrary data on a per-site-visitor basis. It stores -data on the server side and abstracts the sending and receiving of cookies. -Cookies contain a session ID -- not the data itself. - -Enabling sessions -================= - -Sessions are implemented via a piece of :doc:`middleware </ref/middleware>`. - -To enable session functionality, do the following: - - * Edit the ``MIDDLEWARE_CLASSES`` setting and make sure - ``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``. - The default ``settings.py`` created by ``django-admin.py startproject`` has - ``SessionMiddleware`` activated. - -If you don't want to use sessions, you might as well remove the -``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'`` -from your ``INSTALLED_APPS``. It'll save you a small bit of overhead. - -Configuring the session engine -============================== - -.. versionadded:: 1.0 - -By default, Django stores sessions in your database (using the model -``django.contrib.sessions.models.Session``). Though this is convenient, in -some setups it's faster to store session data elsewhere, so Django can be -configured to store session data on your filesystem or in your cache. - -Using database-backed sessions ------------------------------- - -If you want to use a database-backed session, you need to add -``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting. - -Once you have configured your installation, run ``manage.py syncdb`` -to install the single database table that stores session data. - -Using cached sessions ---------------------- - -For better performance, you may want to use a cache-based session backend. - -.. versionchanged:: 1.1 - Django 1.0 did not include the ``cached_db`` session backend. - -To store session data using Django's cache system, you'll first need to make -sure you've configured your cache; see the :doc:`cache documentation -</topics/cache>` for details. - -.. warning:: - - You should only use cache-based sessions if you're using the Memcached - cache backend. The local-memory cache backend doesn't retain data long - enough to be a good choice, and it'll be faster to use file or database - sessions directly instead of sending everything through the file or - database cache backends. - -Once your cache is configured, you've got two choices for how to store data in -the cache: - - * Set :setting:`SESSION_ENGINE` to - ``"django.contrib.sessions.backends.cache"`` for a simple caching session - store. Session data will be stored directly your cache. However, session - data may not be persistent: cached data can be evicted if the cache fills - up or if the cache server is restarted. - - * For persistent, cached data, set :setting:`SESSION_ENGINE` to - ``"django.contrib.sessions.backends.cached_db"``. This uses a - write-through cache -- every write to the cache will also be written to - the database. Session reads only use the database if the data is not - already in the cache. - -Both session stores are quite fast, but the simple cache is faster because it -disregards persistence. In most cases, the ``cached_db`` backend will be fast -enough, but if you need that last bit of performance, and are willing to let -session data be expunged from time to time, the ``cache`` backend is for you. - -If you use the ``cached_db`` session backend, you also need to follow the -configuration instructions for the `using database-backed sessions`_. - -Using file-based sessions -------------------------- - -To use file-based sessions, set the ``SESSION_ENGINE`` setting to -``"django.contrib.sessions.backends.file"``. - -You might also want to set the ``SESSION_FILE_PATH`` setting (which defaults -to output from ``tempfile.gettempdir()``, most likely ``/tmp``) to control -where Django stores session files. Be sure to check that your Web server has -permissions to read and write to this location. - - -Using sessions in views -======================= - -When ``SessionMiddleware`` is activated, each ``HttpRequest`` object -- the -first argument to any Django view function -- will have a ``session`` -attribute, which is a dictionary-like object. You can read it and write to it. - -A session object has the following standard dictionary methods: - - * ``__getitem__(key)`` - - Example: ``fav_color = request.session['fav_color']`` - - * ``__setitem__(key, value)`` - - Example: ``request.session['fav_color'] = 'blue'`` - - * ``__delitem__(key)`` - - Example: ``del request.session['fav_color']``. This raises ``KeyError`` - if the given ``key`` isn't already in the session. - - * ``__contains__(key)`` - - Example: ``'fav_color' in request.session`` - - * ``get(key, default=None)`` - - Example: ``fav_color = request.session.get('fav_color', 'red')`` - - * ``keys()`` - - * ``items()`` - - * ``setdefault()`` - - * ``clear()`` - -.. versionadded:: 1.0 - ``setdefault()`` and ``clear()`` are new in this version. - -It also has these methods: - - * ``flush()`` - - .. versionadded:: 1.0 - - Delete the current session data from the session and regenerate the - session key value that is sent back to the user in the cookie. This is - used if you want to ensure that the previous session data can't be - accessed again from the user's browser (for example, the - :func:`django.contrib.auth.logout()` function calls it). - - * ``set_test_cookie()`` - - Sets a test cookie to determine whether the user's browser supports - cookies. Due to the way cookies work, you won't be able to test this - until the user's next page request. See `Setting test cookies`_ below for - more information. - - * ``test_cookie_worked()`` - - Returns either ``True`` or ``False``, depending on whether the user's - browser accepted the test cookie. Due to the way cookies work, you'll - have to call ``set_test_cookie()`` on a previous, separate page request. - See `Setting test cookies`_ below for more information. - - * ``delete_test_cookie()`` - - Deletes the test cookie. Use this to clean up after yourself. - - * ``set_expiry(value)`` - - .. versionadded:: 1.0 - - Sets the expiration time for the session. You can pass a number of - different values: - - * If ``value`` is an integer, the session will expire after that - many seconds of inactivity. For example, calling - ``request.session.set_expiry(300)`` would make the session expire - in 5 minutes. - - * If ``value`` is a ``datetime`` or ``timedelta`` object, the - session will expire at that specific date/time. - - * If ``value`` is ``0``, the user's session cookie will expire - when the user's Web browser is closed. - - * If ``value`` is ``None``, the session reverts to using the global - session expiry policy. - - Reading a session is not considered activity for expiration - purposes. Session expiration is computed from the last time the - session was *modified*. - - * ``get_expiry_age()`` - - .. versionadded:: 1.0 - - Returns the number of seconds until this session expires. For sessions - with no custom expiration (or those set to expire at browser close), this - will equal ``settings.SESSION_COOKIE_AGE``. - - * ``get_expiry_date()`` - - .. versionadded:: 1.0 - - Returns the date this session will expire. For sessions with no custom - expiration (or those set to expire at browser close), this will equal the - date ``settings.SESSION_COOKIE_AGE`` seconds from now. - - * ``get_expire_at_browser_close()`` - - .. versionadded:: 1.0 - - Returns either ``True`` or ``False``, depending on whether the user's - session cookie will expire when the user's Web browser is closed. - -You can edit ``request.session`` at any point in your view. You can edit it -multiple times. - -Session object guidelines -------------------------- - - * Use normal Python strings as dictionary keys on ``request.session``. This - is more of a convention than a hard-and-fast rule. - - * Session dictionary keys that begin with an underscore are reserved for - internal use by Django. - - * Don't override ``request.session`` with a new object, and don't access or - set its attributes. Use it like a Python dictionary. - -Examples --------- - -This simplistic view sets a ``has_commented`` variable to ``True`` after a user -posts a comment. It doesn't let a user post a comment more than once:: - - def post_comment(request, new_comment): - if request.session.get('has_commented', False): - return HttpResponse("You've already commented.") - c = comments.Comment(comment=new_comment) - c.save() - request.session['has_commented'] = True - return HttpResponse('Thanks for your comment!') - -This simplistic view logs in a "member" of the site:: - - def login(request): - m = Member.objects.get(username=request.POST['username']) - if m.password == request.POST['password']: - request.session['member_id'] = m.id - return HttpResponse("You're logged in.") - else: - return HttpResponse("Your username and password didn't match.") - -...And this one logs a member out, according to ``login()`` above:: - - def logout(request): - try: - del request.session['member_id'] - except KeyError: - pass - return HttpResponse("You're logged out.") - -The standard ``django.contrib.auth.logout()`` function actually does a bit -more than this to prevent inadvertent data leakage. It calls -``request.session.flush()``. We are using this example as a demonstration of -how to work with session objects, not as a full ``logout()`` implementation. - -Setting test cookies -==================== - -As a convenience, Django provides an easy way to test whether the user's -browser accepts cookies. Just call ``request.session.set_test_cookie()`` in a -view, and call ``request.session.test_cookie_worked()`` in a subsequent view -- -not in the same view call. - -This awkward split between ``set_test_cookie()`` and ``test_cookie_worked()`` -is necessary due to the way cookies work. When you set a cookie, you can't -actually tell whether a browser accepted it until the browser's next request. - -It's good practice to use ``delete_test_cookie()`` to clean up after yourself. -Do this after you've verified that the test cookie worked. - -Here's a typical usage example:: - - def login(request): - if request.method == 'POST': - if request.session.test_cookie_worked(): - request.session.delete_test_cookie() - return HttpResponse("You're logged in.") - else: - return HttpResponse("Please enable cookies and try again.") - request.session.set_test_cookie() - return render_to_response('foo/login_form.html') - -Using sessions out of views -=========================== - -.. versionadded:: 1.0 - -An API is available to manipulate session data outside of a view:: - - >>> from django.contrib.sessions.backends.db import SessionStore - >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead') - >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10) - >>> s['last_login'] - datetime.datetime(2005, 8, 20, 13, 35, 0) - >>> s.save() - -If you're using the ``django.contrib.sessions.backends.db`` backend, each -session is just a normal Django model. The ``Session`` model is defined in -``django/contrib/sessions/models.py``. Because it's a normal model, you can -access sessions using the normal Django database API:: - - >>> from django.contrib.sessions.models import Session - >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead') - >>> s.expire_date - datetime.datetime(2005, 8, 20, 13, 35, 12) - -Note that you'll need to call ``get_decoded()`` to get the session dictionary. -This is necessary because the dictionary is stored in an encoded format:: - - >>> s.session_data - 'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...' - >>> s.get_decoded() - {'user_id': 42} - -When sessions are saved -======================= - -By default, Django only saves to the session database when the session has been -modified -- that is if any of its dictionary values have been assigned or -deleted:: - - # Session is modified. - request.session['foo'] = 'bar' - - # Session is modified. - del request.session['foo'] - - # Session is modified. - request.session['foo'] = {} - - # Gotcha: Session is NOT modified, because this alters - # request.session['foo'] instead of request.session. - request.session['foo']['bar'] = 'baz' - -In the last case of the above example, we can tell the session object -explicitly that it has been modified by setting the ``modified`` attribute on -the session object:: - - request.session.modified = True - -To change this default behavior, set the ``SESSION_SAVE_EVERY_REQUEST`` setting -to ``True``. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django will save -the session to the database on every single request. - -Note that the session cookie is only sent when a session has been created or -modified. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, the session cookie -will be sent on every request. - -Similarly, the ``expires`` part of a session cookie is updated each time the -session cookie is sent. - -Browser-length sessions vs. persistent sessions -=============================================== - -You can control whether the session framework uses browser-length sessions vs. -persistent sessions with the ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` setting. - -By default, ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``False``, which -means session cookies will be stored in users' browsers for as long as -``SESSION_COOKIE_AGE``. Use this if you don't want people to have to log in -every time they open a browser. - -If ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``True``, Django will use -browser-length cookies -- cookies that expire as soon as the user closes his or -her browser. Use this if you want people to have to log in every time they open -a browser. - -.. versionadded:: 1.0 - -This setting is a global default and can be overwritten at a per-session level -by explicitly calling ``request.session.set_expiry()`` as described above in -`using sessions in views`_. - -Clearing the session table -========================== - -If you're using the database backend, note that session data can accumulate in -the ``django_session`` database table and Django does *not* provide automatic -purging. Therefore, it's your job to purge expired sessions on a regular basis. - -To understand this problem, consider what happens when a user uses a session. -When a user logs in, Django adds a row to the ``django_session`` database -table. Django updates this row each time the session data changes. If the user -logs out manually, Django deletes the row. But if the user does *not* log out, -the row never gets deleted. - -Django provides a sample clean-up script: ``django-admin.py cleanup``. -That script deletes any session in the session table whose ``expire_date`` is -in the past -- but your application may have different requirements. - -Settings -======== - -A few :doc:`Django settings </ref/settings>` give you control over session behavior: - -SESSION_ENGINE --------------- - -.. versionadded:: 1.0 - -.. versionchanged:: 1.1 - The ``cached_db`` backend was added - -Default: ``django.contrib.sessions.backends.db`` - -Controls where Django stores session data. Valid values are: - - * ``'django.contrib.sessions.backends.db'`` - * ``'django.contrib.sessions.backends.file'`` - * ``'django.contrib.sessions.backends.cache'`` - * ``'django.contrib.sessions.backends.cached_db'`` - -See `configuring the session engine`_ for more details. - -SESSION_FILE_PATH ------------------ - -.. versionadded:: 1.0 - -Default: ``/tmp/`` - -If you're using file-based session storage, this sets the directory in -which Django will store session data. - -SESSION_COOKIE_AGE ------------------- - -Default: ``1209600`` (2 weeks, in seconds) - -The age of session cookies, in seconds. - -SESSION_COOKIE_DOMAIN ---------------------- - -Default: ``None`` - -The domain to use for session cookies. Set this to a string such as -``".lawrence.com"`` (note the leading dot!) for cross-domain cookies, or use -``None`` for a standard domain cookie. - -SESSION_COOKIE_NAME -------------------- - -Default: ``'sessionid'`` - -The name of the cookie to use for sessions. This can be whatever you want. - -SESSION_COOKIE_PATH -------------------- - -.. versionadded:: 1.0 - -Default: ``'/'`` - -The path set on the session cookie. This should either match the URL path of -your Django installation or be parent of that path. - -This is useful if you have multiple Django instances running under the same -hostname. They can use different cookie paths, and each instance will only see -its own session cookie. - -SESSION_COOKIE_SECURE ---------------------- - -Default: ``False`` - -Whether to use a secure cookie for the session cookie. If this is set to -``True``, the cookie will be marked as "secure," which means browsers may -ensure that the cookie is only sent under an HTTPS connection. - -SESSION_EXPIRE_AT_BROWSER_CLOSE -------------------------------- - -Default: ``False`` - -Whether to expire the session when the user closes his or her browser. See -"Browser-length sessions vs. persistent sessions" above. - -SESSION_SAVE_EVERY_REQUEST --------------------------- - -Default: ``False`` - -Whether to save the session data on every request. If this is ``False`` -(default), then the session data will only be saved if it has been modified -- -that is, if any of its dictionary values have been assigned or deleted. - -.. _Django settings: ../settings/ - -Technical details -================= - - * The session dictionary should accept any pickleable Python object. See - `the pickle module`_ for more information. - - * Session data is stored in a database table named ``django_session`` . - - * Django only sends a cookie if it needs to. If you don't set any session - data, it won't send a session cookie. - -.. _`the pickle module`: http://docs.python.org/library/pickle.html - -Session IDs in URLs -=================== - -The Django sessions framework is entirely, and solely, cookie-based. It does -not fall back to putting session IDs in URLs as a last resort, as PHP does. -This is an intentional design decision. Not only does that behavior make URLs -ugly, it makes your site vulnerable to session-ID theft via the "Referer" -header. diff --git a/parts/django/docs/topics/http/shortcuts.txt b/parts/django/docs/topics/http/shortcuts.txt deleted file mode 100644 index 315460e..0000000 --- a/parts/django/docs/topics/http/shortcuts.txt +++ /dev/null @@ -1,229 +0,0 @@ -========================= -Django shortcut functions -========================= - -.. module:: django.shortcuts - :synopsis: - Convience shortcuts that spam multiple levels of Django's MVC stack. - -.. index:: shortcuts - -The package ``django.shortcuts`` collects helper functions and classes that -"span" multiple levels of MVC. In other words, these functions/classes -introduce controlled coupling for convenience's sake. - -``render_to_response`` -====================== - -.. function:: render_to_response(template[, dictionary][, context_instance][, mimetype]) - - Renders a given template with a given context dictionary and returns an - :class:`~django.http.HttpResponse` object with that rendered text. - -Required arguments ------------------- - -``template`` - The full name of a template to use or sequence of template names. If a - sequence is given, the first template that exists will be used. See the - :ref:`template loader documentation <ref-templates-api-the-python-api>` - for more information on how templates are found. - -Optional arguments ------------------- - -``dictionary`` - 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 - view will call it just before rendering the template. - -``context_instance`` - The context instance to render the template with. By default, the template - will be rendered with a :class:`~django.template.Context` instance (filled - with values from ``dictionary``). If you need to use :ref:`context - processors <subclassing-context-requestcontext>`, render the template with - a :class:`~django.template.RequestContext` instance instead. Your code - might look something like this:: - - return render_to_response('my_template.html', - my_data_dictionary, - context_instance=RequestContext(request)) - -``mimetype`` - The MIME type to use for the resulting document. Defaults to the value of - the :setting:`DEFAULT_CONTENT_TYPE` setting. - -Example -------- - -The following example renders the template ``myapp/index.html`` with the -MIME type ``application/xhtml+xml``:: - - from django.shortcuts import render_to_response - - def my_view(request): - # View code here... - return render_to_response('myapp/index.html', {"foo": "bar"}, - mimetype="application/xhtml+xml") - -This example is equivalent to:: - - from django.http import HttpResponse - from django.template import Context, loader - - def my_view(request): - # View code here... - t = loader.get_template('myapp/template.html') - c = Context({'foo': 'bar'}) - return HttpResponse(t.render(c), - mimetype="application/xhtml+xml") - -``redirect`` -============ - -.. function:: redirect(to[, permanent=False], *args, **kwargs) - - .. versionadded:: 1.1 - - Returns an :class:`~django.http.HttpResponseRedirect` to the appropriate URL - for the arguments passed. - - The arguments could be: - - * A model: the model's `get_absolute_url()` function will be called. - - * A view name, possibly with arguments: `urlresolvers.reverse()` will - be used to reverse-resolve the name. - - * A URL, which will be used as-is for the redirect location. - - By default issues a temporary redirect; pass ``permanent=True`` to issue a - permanent redirect - -Examples --------- - -You can use the :func:`redirect` function in a number of ways. - - 1. By passing some object; that object's - :meth:`~django.db.models.Model.get_absolute_url` method will be called - to figure out the redirect URL:: - - def my_view(request): - ... - object = MyModel.objects.get(...) - return redirect(object) - - 2. By passing the name of a view and optionally some positional or - keyword arguments; the URL will be reverse resolved using the - :func:`~django.core.urlresolvers.reverse` method:: - - def my_view(request): - ... - return redirect('some-view-name', foo='bar') - - 3. By passing a hardcoded URL to redirect to:: - - def my_view(request): - ... - return redirect('/some/url/') - - This also works with full URLs:: - - def my_view(request): - ... - return redirect('http://example.com/') - -By default, :func:`redirect` returns a temporary redirect. All of the above -forms accept a ``permanent`` argument; if set to ``True`` a permanent redirect -will be returned:: - - def my_view(request): - ... - object = MyModel.objects.get(...) - return redirect(object, permanent=True) - -``get_object_or_404`` -===================== - -.. function:: get_object_or_404(klass, *args, **kwargs) - - Calls :meth:`~django.db.models.QuerySet.get()` on a given model manager, - but it raises :class:`~django.http.Http404` instead of the model's - :class:`~django.core.exceptions.DoesNotExist` exception. - -Required arguments ------------------- - -``klass`` - A :class:`~django.db.models.Model`, :class:`~django.db.models.Manager` or - :class:`~django.db.models.QuerySet` instance from which to get the object. - -``**kwargs`` - Lookup parameters, which should be in the format accepted by ``get()`` and - ``filter()``. - -Example -------- - -The following example gets the object with the primary key of 1 from -``MyModel``:: - - from django.shortcuts import get_object_or_404 - - def my_view(request): - my_object = get_object_or_404(MyModel, pk=1) - -This example is equivalent to:: - - from django.http import Http404 - - def my_view(request): - try: - my_object = MyModel.objects.get(pk=1) - except MyModel.DoesNotExist: - raise Http404 - -Note: As with ``get()``, a -:class:`~django.core.exceptions.MultipleObjectsReturned` exception -will be raised if more than one object is found. - -``get_list_or_404`` -=================== - -.. function:: get_list_or_404(klass, *args, **kwargs) - - Returns the result of :meth:`~django.db.models.QuerySet.filter()` on a - given model manager, raising :class:`~django.http.Http404` if the resulting - list is empty. - -Required arguments ------------------- - -``klass`` - A :class:`~django.db.models.Model`, :class:`~django.db.models.Manager` or - :class:`~django.db.models.query.QuerySet` instance from which to get the - list. - -``**kwargs`` - Lookup parameters, which should be in the format accepted by ``get()`` and - ``filter()``. - -Example -------- - -The following example gets all published objects from ``MyModel``:: - - from django.shortcuts import get_list_or_404 - - def my_view(request): - my_objects = get_list_or_404(MyModel, published=True) - -This example is equivalent to:: - - from django.http import Http404 - - def my_view(request): - my_objects = list(MyModel.objects.filter(published=True)) - if not my_objects: - raise Http404 diff --git a/parts/django/docs/topics/http/urls.txt b/parts/django/docs/topics/http/urls.txt deleted file mode 100644 index 2361297..0000000 --- a/parts/django/docs/topics/http/urls.txt +++ /dev/null @@ -1,890 +0,0 @@ -============== -URL dispatcher -============== - -.. module:: django.core.urlresolvers - -A clean, elegant URL scheme is an important detail in a high-quality Web -application. Django lets you design URLs however you want, with no framework -limitations. - -There's no ``.php`` or ``.cgi`` required, and certainly none of that -``0,2097,1-1-1928,00`` nonsense. - -See `Cool URIs don't change`_, by World Wide Web creator Tim Berners-Lee, for -excellent arguments on why URLs should be clean and usable. - -.. _Cool URIs don't change: http://www.w3.org/Provider/Style/URI - -Overview -======== - -To design URLs for an app, you create a Python module informally called a -**URLconf** (URL configuration). This module is pure Python code and -is a simple mapping between URL patterns (as simple regular expressions) to -Python callback functions (your views). - -This mapping can be as short or as long as needed. It can reference other -mappings. And, because it's pure Python code, it can be constructed -dynamically. - -.. _how-django-processes-a-request: - -How Django processes a request -============================== - -When a user requests a page from your Django-powered site, this is the -algorithm the system follows to determine which Python code to execute: - - 1. Django determines the root URLconf module to use. Ordinarily, - this is the value of the :setting:`ROOT_URLCONF` setting, but if the incoming - ``HttpRequest`` object has an attribute called ``urlconf`` (set by - middleware :ref:`request processing <request-middleware>`), its value - will be used in place of the :setting:`ROOT_URLCONF` setting. - - 2. Django loads that Python module and looks for the variable - ``urlpatterns``. This should be a Python list, in the format returned by - the function :func:`django.conf.urls.defaults.patterns`. - - 3. Django runs through each URL pattern, in order, and stops at the first - one that matches the requested URL. - - 4. Once one of the regexes matches, Django imports and calls the given - view, which is a simple Python function. The view gets passed an - :class:`~django.http.HttpRequest` as its first argument and any values - captured in the regex as remaining arguments. - -Example -======= - -Here's a sample URLconf:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^articles/2003/$', 'news.views.special_case_2003'), - (r'^articles/(\d{4})/$', 'news.views.year_archive'), - (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), - (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), - ) - -Notes: - - * ``from django.conf.urls.defaults import *`` makes the ``patterns()`` - function available. - - * To capture a value from the URL, just put parenthesis around it. - - * There's no need to add a leading slash, because every URL has that. For - example, it's ``^articles``, not ``^/articles``. - - * The ``'r'`` in front of each regular expression string is optional but - recommended. It tells Python that a string is "raw" -- that nothing in - the string should be escaped. See `Dive Into Python's explanation`_. - -Example requests: - - * A request to ``/articles/2005/03/`` would match the third entry in the - list. Django would call the function - ``news.views.month_archive(request, '2005', '03')``. - - * ``/articles/2005/3/`` would not match any URL patterns, because the - third entry in the list requires two digits for the month. - - * ``/articles/2003/`` would match the first pattern in the list, not the - second one, because the patterns are tested in order, and the first one - is the first test to pass. Feel free to exploit the ordering to insert - special cases like this. - - * ``/articles/2003`` would not match any of these patterns, because each - pattern requires that the URL end with a slash. - - * ``/articles/2003/03/3/`` would match the final pattern. Django would call - the function ``news.views.article_detail(request, '2003', '03', '3')``. - -.. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3 - -Named groups -============ - -The above example used simple, *non-named* regular-expression groups (via -parenthesis) to capture bits of the URL and pass them as *positional* arguments -to a view. In more advanced usage, it's possible to use *named* -regular-expression groups to capture URL bits and pass them as *keyword* -arguments to a view. - -In Python regular expressions, the syntax for named regular-expression groups -is ``(?P<name>pattern)``, where ``name`` is the name of the group and -``pattern`` is some pattern to match. - -Here's the above example URLconf, rewritten to use named groups:: - - urlpatterns = patterns('', - (r'^articles/2003/$', 'news.views.special_case_2003'), - (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), - (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'), - (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'), - ) - -This accomplishes exactly the same thing as the previous example, with one -subtle difference: The captured values are passed to view functions as keyword -arguments rather than positional arguments. For example: - - * A request to ``/articles/2005/03/`` would call the function - ``news.views.month_archive(request, year='2005', month='03')``, instead - of ``news.views.month_archive(request, '2005', '03')``. - - * A request to ``/articles/2003/03/3/`` would call the function - ``news.views.article_detail(request, year='2003', month='03', day='3')``. - -In practice, this means your URLconfs are slightly more explicit and less prone -to argument-order bugs -- and you can reorder the arguments in your views' -function definitions. Of course, these benefits come at the cost of brevity; -some developers find the named-group syntax ugly and too verbose. - -The matching/grouping algorithm -------------------------------- - -Here's the algorithm the URLconf parser follows, with respect to named groups -vs. non-named groups in a regular expression: - -If there are any named arguments, it will use those, ignoring non-named arguments. -Otherwise, it will pass all non-named arguments as positional arguments. - -In both cases, it will pass any extra keyword arguments as keyword arguments. -See "Passing extra options to view functions" below. - -What the URLconf searches against -================================= - -The URLconf searches against the requested URL, as a normal Python string. This -does not include GET or POST parameters, or the domain name. - -For example, in a request to ``http://www.example.com/myapp/``, the URLconf -will look for ``myapp/``. - -In a request to ``http://www.example.com/myapp/?page=3``, the URLconf will look -for ``myapp/``. - -The URLconf doesn't look at the request method. In other words, all request -methods -- ``POST``, ``GET``, ``HEAD``, etc. -- will be routed to the same -function for the same URL. - -Syntax of the urlpatterns variable -================================== - -``urlpatterns`` should be a Python list, in the format returned by the function -:func:`django.conf.urls.defaults.patterns`. Always use ``patterns()`` to create -the ``urlpatterns`` variable. - -Convention is to use ``from django.conf.urls.defaults import *`` at the top of -your URLconf. This gives your module access to these objects: - -.. module:: django.conf.urls.defaults - -patterns --------- - -.. function:: patterns(prefix, pattern_description, ...) - -A function that takes a prefix, and an arbitrary number of URL patterns, and -returns a list of URL patterns in the format Django needs. - -The first argument to ``patterns()`` is a string ``prefix``. See -`The view prefix`_ below. - -The remaining arguments should be tuples in this format:: - - (regular expression, Python callback function [, optional dictionary [, optional name]]) - -...where ``optional dictionary`` and ``optional name`` are optional. (See -`Passing extra options to view functions`_ below.) - -.. note:: - Because `patterns()` is a function call, it accepts a maximum of 255 - arguments (URL patterns, in this case). This is a limit for all Python - function calls. This is rarely a problem in practice, because you'll - typically structure your URL patterns modularly by using `include()` - sections. However, on the off-chance you do hit the 255-argument limit, - realize that `patterns()` returns a Python list, so you can split up the - construction of the list. - - :: - - urlpatterns = patterns('', - ... - ) - urlpatterns += patterns('', - ... - ) - - Python lists have unlimited size, so there's no limit to how many URL - patterns you can construct. The only limit is that you can only create 254 - at a time (the 255th argument is the initial prefix argument). - -url ---- - -.. versionadded:: 1.0 - -.. function:: url(regex, view, kwargs=None, name=None, prefix='') - -You can use the ``url()`` function, instead of a tuple, as an argument to -``patterns()``. This is convenient if you want to specify a name without the -optional extra arguments dictionary. For example:: - - urlpatterns = patterns('', - url(r'^index/$', index_view, name="main-view"), - ... - ) - -This function takes five arguments, most of which are optional:: - - url(regex, view, kwargs=None, name=None, prefix='') - -See `Naming URL patterns`_ for why the ``name`` parameter is useful. - -The ``prefix`` parameter has the same meaning as the first argument to -``patterns()`` and is only relevant when you're passing a string as the -``view`` parameter. - -handler404 ----------- - -.. data:: handler404 - -A callable, or a string representing the full Python import path to the view -that should be called if none of the URL patterns match. - -By default, this is ``'django.views.defaults.page_not_found'``. That default -value should suffice. - -.. versionchanged:: 1.2 - Previous versions of Django only accepted strings representing import paths. - -handler500 ----------- - -.. data:: handler500 - -A callable, or a string representing the full Python import path to the view -that should be called in case of server errors. Server errors happen when you -have runtime errors in view code. - -By default, this is ``'django.views.defaults.server_error'``. That default -value should suffice. - -.. versionchanged:: 1.2 - Previous versions of Django only accepted strings representing import paths. - -include -------- - -.. function:: include(<module or pattern_list>) - -A function that takes a full Python import path to another URLconf module that -should be "included" in this place. - -.. versionadded:: 1.1 - -:func:`include` also accepts as an argument an iterable that returns URL -patterns. - -See `Including other URLconfs`_ below. - -Notes on capturing text in URLs -=============================== - -Each captured argument is sent to the view as a plain Python string, regardless -of what sort of match the regular expression makes. For example, in this -URLconf line:: - - (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), - -...the ``year`` argument to ``news.views.year_archive()`` will be a string, not -an integer, even though the ``\d{4}`` will only match integer strings. - -A convenient trick is to specify default parameters for your views' arguments. -Here's an example URLconf and view:: - - # URLconf - urlpatterns = patterns('', - (r'^blog/$', 'blog.views.page'), - (r'^blog/page(?P<num>\d+)/$', 'blog.views.page'), - ) - - # View (in blog/views.py) - def page(request, num="1"): - # Output the appropriate page of blog entries, according to num. - -In the above example, both URL patterns point to the same view -- -``blog.views.page`` -- but the first pattern doesn't capture anything from the -URL. If the first pattern matches, the ``page()`` function will use its -default argument for ``num``, ``"1"``. If the second pattern matches, -``page()`` will use whatever ``num`` value was captured by the regex. - -Performance -=========== - -Each regular expression in a ``urlpatterns`` is compiled the first time it's -accessed. This makes the system blazingly fast. - -The view prefix -=============== - -You can specify a common prefix in your ``patterns()`` call, to cut down on -code duplication. - -Here's the example URLconf from the :doc:`Django overview </intro/overview>`:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^articles/(\d{4})/$', 'news.views.year_archive'), - (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), - (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), - ) - -In this example, each view has a common prefix -- ``'news.views'``. -Instead of typing that out for each entry in ``urlpatterns``, you can use the -first argument to the ``patterns()`` function to specify a prefix to apply to -each view function. - -With this in mind, the above example can be written more concisely as:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('news.views', - (r'^articles/(\d{4})/$', 'year_archive'), - (r'^articles/(\d{4})/(\d{2})/$', 'month_archive'), - (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'), - ) - -Note that you don't put a trailing dot (``"."``) in the prefix. Django puts -that in automatically. - -Multiple view prefixes ----------------------- - -In practice, you'll probably end up mixing and matching views to the point -where the views in your ``urlpatterns`` won't have a common prefix. However, -you can still take advantage of the view prefix shortcut to remove duplication. -Just add multiple ``patterns()`` objects together, like this: - -Old:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^$', 'django.views.generic.date_based.archive_index'), - (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'django.views.generic.date_based.archive_month'), - (r'^tag/(?P<tag>\w+)/$', 'weblog.views.tag'), - ) - -New:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('django.views.generic.date_based', - (r'^$', 'archive_index'), - (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month'), - ) - - urlpatterns += patterns('weblog.views', - (r'^tag/(?P<tag>\w+)/$', 'tag'), - ) - -Including other URLconfs -======================== - -At any point, your ``urlpatterns`` can "include" other URLconf modules. This -essentially "roots" a set of URLs below other ones. - -For example, here's the URLconf for the `Django Web site`_ itself. It includes a -number of other URLconfs:: - - from django.conf.urls.defaults import * - - urlpatterns = patterns('', - (r'^weblog/', include('django_website.apps.blog.urls.blog')), - (r'^documentation/', include('django_website.apps.docs.urls.docs')), - (r'^comments/', include('django.contrib.comments.urls')), - ) - -Note that the regular expressions in this example don't have a ``$`` -(end-of-string match character) but do include a 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. - -.. versionadded:: 1.1 - -Another possibility is to include additional URL patterns not by specifying the -URLconf Python module defining them as the `include`_ argument but by using -directly the pattern list as returned by `patterns`_ instead. For example:: - - from django.conf.urls.defaults import * - - extra_patterns = patterns('', - url(r'reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'), - url(r'charge/$', 'credit.views.charge', name='credit-charge'), - ) - - urlpatterns = patterns('', - url(r'^$', 'apps.main.views.homepage', name='site-homepage'), - (r'^help/', include('apps.help.urls')), - (r'^credit/', include(extra_patterns)), - ) - -This approach can be seen in use when you deploy an instance of the Django -Admin application. The Django Admin is deployed as instances of a -:class:`~django.contrib.admin.AdminSite`; each -:class:`~django.contrib.admin.AdminSite` instance has an attribute ``urls`` -that returns the url patterns available to that instance. It is this attribute -that you ``include()`` into your projects ``urlpatterns`` when you deploy the -admin instance. - -.. _`Django Web site`: http://www.djangoproject.com/ - -Captured parameters -------------------- - -An included URLconf receives any captured parameters from parent URLconfs, so -the following example is valid:: - - # In settings/urls/main.py - urlpatterns = patterns('', - (r'^(?P<username>\w+)/blog/', include('foo.urls.blog')), - ) - - # In foo/urls/blog.py - urlpatterns = patterns('foo.views', - (r'^$', 'blog.index'), - (r'^archive/$', 'blog.archive'), - ) - -In the above example, the captured ``"username"`` variable is passed to the -included URLconf, as expected. - -.. _topics-http-defining-url-namespaces: - -Defining URL Namespaces ------------------------ - -When you need to deploy multiple instances of a single application, it can be -helpful to be able to differentiate between instances. This is especially -important when using :ref:`named URL patterns <naming-url-patterns>`, since -multiple instances of a single application will share named URLs. Namespaces -provide a way to tell these named URLs apart. - -A URL namespace comes in two parts, both of which are strings: - - * An **application namespace**. This describes the name of the application - that is being deployed. Every instance of a single application will have - the same application namespace. For example, Django's admin application - has the somewhat predictable application namespace of ``admin``. - - * An **instance namespace**. This identifies a specific instance of an - application. Instance namespaces should be unique across your entire - project. However, an instance namespace can be the same as the - application namespace. This is used to specify a default instance of an - application. For example, the default Django Admin instance has an - instance namespace of ``admin``. - -URL Namespaces can be specified in two ways. - -Firstly, you can provide the application and instance namespace as arguments -to ``include()`` when you construct your URL patterns. For example,:: - - (r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')), - -This will include the URLs defined in ``apps.help.urls`` into the application -namespace ``bar``, with the instance namespace ``foo``. - -Secondly, you can include an object that contains embedded namespace data. If -you ``include()`` a ``patterns`` object, that object will be added to the -global namespace. However, you can also ``include()`` an object that contains -a 3-tuple containing:: - - (<patterns object>, <application namespace>, <instance namespace>) - -This will include the nominated URL patterns into the given application and -instance namespace. For example, the ``urls`` attribute of Django's -:class:`~django.contrib.admin.AdminSite` object returns a 3-tuple that contains -all the patterns in an admin site, plus the name of the admin instance, and the -application namespace ``admin``. - -Once you have defined namespaced URLs, you can reverse them. For details on -reversing namespaced urls, see the documentation on :ref:`reversing namespaced -URLs <topics-http-reversing-url-namespaces>`. - -Passing extra options to view functions -======================================= - -URLconfs have a hook that lets you pass extra arguments to your view functions, -as a Python dictionary. - -Any URLconf tuple can have an optional third element, which should be a -dictionary of extra keyword arguments to pass to the view function. - -For example:: - - urlpatterns = patterns('blog.views', - (r'^blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}), - ) - -In this example, for a request to ``/blog/2005/``, Django will call the -``blog.views.year_archive()`` view, passing it these keyword arguments:: - - year='2005', foo='bar' - -This technique is used in :doc:`generic views </ref/generic-views>` and in the -:doc:`syndication framework </ref/contrib/syndication>` to pass metadata and -options to views. - -.. admonition:: Dealing with conflicts - - It's possible to have a URL pattern which captures named keyword arguments, - and also passes arguments with the same names in its dictionary of extra - arguments. When this happens, the arguments in the dictionary will be used - instead of the arguments captured in the URL. - -Passing extra options to ``include()`` --------------------------------------- - -Similarly, you can pass extra options to ``include()``. When you pass extra -options to ``include()``, *each* line in the included URLconf will be passed -the extra options. - -For example, these two URLconf sets are functionally identical: - -Set one:: - - # main.py - urlpatterns = patterns('', - (r'^blog/', include('inner'), {'blogid': 3}), - ) - - # inner.py - urlpatterns = patterns('', - (r'^archive/$', 'mysite.views.archive'), - (r'^about/$', 'mysite.views.about'), - ) - -Set two:: - - # main.py - urlpatterns = patterns('', - (r'^blog/', include('inner')), - ) - - # inner.py - urlpatterns = patterns('', - (r'^archive/$', 'mysite.views.archive', {'blogid': 3}), - (r'^about/$', 'mysite.views.about', {'blogid': 3}), - ) - -Note that extra options will *always* be passed to *every* line in the included -URLconf, regardless of whether the line's view actually accepts those options -as valid. For this reason, this technique is only useful if you're certain that -every view in the included URLconf accepts the extra options you're passing. - -Passing callable objects instead of strings -=========================================== - -Some developers find it more natural to pass the actual Python function object -rather than a string containing the path to its module. This alternative is -supported -- you can pass any callable object as the view. - -For example, given this URLconf in "string" notation:: - - urlpatterns = patterns('', - (r'^archive/$', 'mysite.views.archive'), - (r'^about/$', 'mysite.views.about'), - (r'^contact/$', 'mysite.views.contact'), - ) - -You can accomplish the same thing by passing objects rather than strings. Just -be sure to import the objects:: - - from mysite.views import archive, about, contact - - urlpatterns = patterns('', - (r'^archive/$', archive), - (r'^about/$', about), - (r'^contact/$', contact), - ) - -The following example is functionally identical. It's just a bit more compact -because it imports the module that contains the views, rather than importing -each view individually:: - - from mysite import views - - urlpatterns = patterns('', - (r'^archive/$', views.archive), - (r'^about/$', views.about), - (r'^contact/$', views.contact), - ) - -The style you use is up to you. - -Note that if you use this technique -- passing objects rather than strings -- -the view prefix (as explained in "The view prefix" above) will have no effect. - -.. _naming-url-patterns: - -Naming URL patterns -=================== - -.. versionadded:: 1.0 - -It's fairly common to use the same view function in multiple URL patterns in -your URLconf. For example, these two URL patterns both point to the ``archive`` -view:: - - urlpatterns = patterns('', - (r'^archive/(\d{4})/$', archive), - (r'^archive-summary/(\d{4})/$', archive, {'summary': True}), - ) - -This is completely valid, but it leads to problems when you try to do reverse -URL matching (through the ``permalink()`` decorator or the :ttag:`url` template -tag). Continuing this example, if you wanted to retrieve the URL for the -``archive`` view, Django's reverse URL matcher would get confused, because *two* -URLpatterns point at that view. - -To solve this problem, Django supports **named URL patterns**. That is, you can -give a name to a URL pattern in order to distinguish it from other patterns -using the same view and parameters. Then, you can use this name in reverse URL -matching. - -Here's the above example, rewritten to use named URL patterns:: - - urlpatterns = patterns('', - url(r'^archive/(\d{4})/$', archive, name="full-archive"), - url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}, "arch-summary"), - ) - -With these names in place (``full-archive`` and ``arch-summary``), you can -target each pattern individually by using its name: - -.. code-block:: html+django - - {% url arch-summary 1945 %} - {% url full-archive 2007 %} - -Even though both URL patterns refer to the ``archive`` view here, using the -``name`` parameter to ``url()`` allows you to tell them apart in templates. - -The string used for the URL name can contain any characters you like. You are -not restricted to valid Python names. - -.. note:: - - When you name your URL patterns, make sure you use names that are unlikely - to clash with any other application's choice of names. If you call your URL - pattern ``comment``, and another application does the same thing, there's - no guarantee which URL will be inserted into your template when you use - this name. - - Putting a prefix on your URL names, perhaps derived from the application - name, will decrease the chances of collision. We recommend something like - ``myapp-comment`` instead of ``comment``. - -.. _topics-http-reversing-url-namespaces: - -URL namespaces --------------- - -.. versionadded:: 1.1 - -Namespaced URLs are specified using the ``:`` operator. For example, the main -index page of the admin application is referenced using ``admin:index``. This -indicates a namespace of ``admin``, and a named URL of ``index``. - -Namespaces can also be nested. The named URL ``foo:bar:whiz`` would look for -a pattern named ``whiz`` in the namespace ``bar`` that is itself defined within -the top-level namespace ``foo``. - -When given a namespaced URL (e.g. ``myapp:index``) to resolve, Django splits -the fully qualified name into parts, and then tries the following lookup: - - 1. First, Django looks for a matching application namespace (in this - example, ``myapp``). This will yield a list of instances of that - application. - - 2. If there is a *current* application defined, Django finds and returns - the URL resolver for that instance. The *current* application can be - specified as an attribute on the template context - applications that - expect to have multiple deployments should set the ``current_app`` - attribute on any ``Context`` or ``RequestContext`` that is used to - render a template. - - The current application can also be specified manually as an argument - to the :func:`reverse()` function. - - 3. If there is no current application. Django looks for a default - application instance. The default application instance is the instance - that has an instance namespace matching the application namespace (in - this example, an instance of the ``myapp`` called ``myapp``). - - 4. If there is no default application instance, Django will pick the last - deployed instance of the application, whatever its instance name may be. - - 5. If the provided namespace doesn't match an application namespace in - step 1, Django will attempt a direct lookup of the namespace as an - instance namespace. - -If there are nested namespaces, these steps are repeated for each part of the -namespace until only the view name is unresolved. The view name will then be -resolved into a URL in the namespace that has been found. - -To show this resolution strategy in action, consider an example of two instances -of ``myapp``: one called ``foo``, and one called ``bar``. ``myapp`` has a main -index page with a URL named `index`. Using this setup, the following lookups are -possible: - - * If one of the instances is current - say, if we were rendering a utility page - in the instance ``bar`` - ``myapp:index`` will resolve to the index page of - the instance ``bar``. - - * If there is no current instance - say, if we were rendering a page - somewhere else on the site - ``myapp:index`` will resolve to the last - registered instance of ``myapp``. Since there is no default instance, - the last instance of ``myapp`` that is registered will be used. This could - be ``foo`` or ``bar``, depending on the order they are introduced into the - urlpatterns of the project. - - * ``foo:index`` will always resolve to the index page of the instance ``foo``. - -If there was also a default instance - i.e., an instance named `myapp` - the -following would happen: - - * If one of the instances is current - say, if we were rendering a utility page - in the instance ``bar`` - ``myapp:index`` will resolve to the index page of - the instance ``bar``. - - * If there is no current instance - say, if we were rendering a page somewhere - else on the site - ``myapp:index`` will resolve to the index page of the - default instance. - - * ``foo:index`` will again resolve to the index page of the instance ``foo``. - - -Utility methods -=============== - -reverse() ---------- - -If you need to use something similar to the :ttag:`url` template tag in -your code, Django provides the following method (in the -``django.core.urlresolvers`` module): - -.. function:: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None) - -``viewname`` is either the function name (either a function reference, or the -string version of the name, if you used that form in ``urlpatterns``) or the -`URL pattern name`_. Normally, you won't need to worry about the -``urlconf`` parameter and will only pass in the positional and keyword -arguments to use in the URL matching. For example:: - - from django.core.urlresolvers import reverse - - def myview(request): - return HttpResponseRedirect(reverse('arch-summary', args=[1945])) - -.. _URL pattern name: `Naming URL patterns`_ - -The ``reverse()`` function can reverse a large variety of regular expression -patterns for URLs, but not every possible one. The main restriction at the -moment is that the pattern cannot contain alternative choices using the -vertical bar (``"|"``) character. You can quite happily use such patterns for -matching against incoming URLs and sending them off to views, but you cannot -reverse such patterns. - -.. versionadded:: 1.1 - -The ``current_app`` argument allows you to provide a hint to the resolver -indicating the application to which the currently executing view belongs. -This ``current_app`` argument is used as a hint to resolve application -namespaces into URLs on specific application instances, according to the -:ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`. - -.. admonition:: Make sure your views are all correct. - - As part of working out which URL names map to which patterns, the - ``reverse()`` function has to import all of your URLconf files and examine - the name of each view. This involves importing each view function. If - there are *any* errors whilst importing any of your view functions, it - will cause ``reverse()`` to raise an error, even if that view function is - not the one you are trying to reverse. - - Make sure that any views you reference in your URLconf files exist and can - be imported correctly. Do not include lines that reference views you - haven't written yet, because those views will not be importable. - -resolve() ---------- - -The :func:`django.core.urlresolvers.resolve` function can be used for resolving -URL paths to the corresponding view functions. It has the following signature: - -.. function:: resolve(path, urlconf=None) - -``path`` is the URL path you want to resolve. As with -:func:`~django.core.urlresolvers.reverse`, you don't need to -worry about the ``urlconf`` parameter. The function returns -the triple (view function, arguments, keyword arguments). - -If the URL does not resolve, the function raises an -:class:`~django.http.Http404` exception. - -For example, it can be used for testing if a view would raise a ``Http404`` -error before redirecting to it:: - - from urlparse import urlparse - from django.core.urlresolvers import resolve - from django.http import HttpResponseRedirect, Http404 - - def myview(request): - next = request.META.get('HTTP_REFERER', None) or '/' - response = HttpResponseRedirect(next) - - # modify the request and response as required, e.g. change locale - # and set corresponding locale cookie - - view, args, kwargs = resolve(urlparse(next)[2]) - kwargs['request'] = request - try: - view(*args, **kwargs) - except Http404: - return HttpResponseRedirect('/') - return response - -permalink() ------------ - -The :func:`django.db.models.permalink` decorator is useful for writing short -methods that return a full URL path. For example, a model's -``get_absolute_url()`` method. See :func:`django.db.models.permalink` for more. - -get_script_prefix() -------------------- - -.. function:: get_script_prefix() - -.. versionadded:: 1.0 - -Normally, you should always use :func:`~django.core.urlresolvers.reverse` or -:func:`~django.db.models.permalink` to define URLs within your application. -However, if your application constructs part of the URL hierarchy itself, you -may occasionally need to generate URLs. In that case, you need to be able to -find the base URL of the Django project within its web server -(normally, :func:`~django.core.urlresolvers.reverse` takes care of this for -you). In that case, you can call ``get_script_prefix()``, which will return the -script prefix portion of the URL for your Django project. If your Django -project is at the root of its webserver, this is always ``"/"``, but it can be -changed, for instance by using ``django.root`` (see :ref:`How to use -Django with Apache and mod_python <howto-deployment-modpython>`).
\ No newline at end of file diff --git a/parts/django/docs/topics/http/views.txt b/parts/django/docs/topics/http/views.txt deleted file mode 100644 index 2818f42..0000000 --- a/parts/django/docs/topics/http/views.txt +++ /dev/null @@ -1,202 +0,0 @@ -============= -Writing Views -============= - -A view function, or *view* for short, is simply a Python function that takes a -Web request and returns a Web response. This response can be the HTML contents -of a Web page, or a redirect, or a 404 error, or an XML document, or an image . -. . or anything, really. The view itself contains whatever arbitrary logic is -necessary to return that response. This code can live anywhere you want, as long -as it's on your Python path. There's no other requirement--no "magic," so to -speak. For the sake of putting the code *somewhere*, let's create a file called -``views.py`` in the ``mysite`` directory, which you created in the previous -chapter. - -A simple view -============= - -Here's a view that returns the current date and time, as an HTML document: - -.. code-block:: python - - from django.http import HttpResponse - import datetime - - def current_datetime(request): - now = datetime.datetime.now() - html = "<html><body>It is now %s.</body></html>" % now - return HttpResponse(html) - -Let's step through this code one line at a time: - - * First, we import the class :class:`~django.http.HttpResponse` from the - :mod:`django.http` module, along with Python's ``datetime`` library. - - * Next, we define a function called ``current_datetime``. This is the view - function. Each view function takes an :class:`~django.http.HttpRequest` - object as its first parameter, which is typically named ``request``. - - Note that the name of the view function doesn't matter; it doesn't have to - be named in a certain way in order for Django to recognize it. We're - calling it ``current_datetime`` here, because that name clearly indicates - what it does. - - * The view returns an :class:`~django.http.HttpResponse` object that - contains the generated response. Each view function is responsible for - returning an :class:`~django.http.HttpResponse` object. (There are - exceptions, but we'll get to those later.) - -.. admonition:: Django's Time Zone - - Django includes a ``TIME_ZONE`` setting that defaults to - ``America/Chicago``. This probably isn't where you live, so you might want - to change it in your settings file. - -Mapping URLs to Views -===================== - -So, to recap, this view function returns an HTML page that includes the current -date and time. To display this view at a particular URL, you'll need to create a -*URLconf*; see :doc:`/topics/http/urls` for instructions. - -Returning errors -================ - -Returning HTTP error codes in Django is easy. There are subclasses of -:class:`~django.http.HttpResponse` for a number of common HTTP status codes -other than 200 (which means *"OK"*). You can find the full list of available -subclasses in the :ref:`request/response <ref-httpresponse-subclasses>` -documentation. Just return an instance of one of those subclasses instead of -a normal :class:`~django.http.HttpResponse` in order to signify an error. For -example:: - - def my_view(request): - # ... - if foo: - return HttpResponseNotFound('<h1>Page not found</h1>') - else: - return HttpResponse('<h1>Page was found</h1>') - -There isn't a specialized subclass for every possible HTTP response code, -since many of them aren't going to be that common. However, as documented in -the :class:`~django.http.HttpResponse` documentation, you can also pass the -HTTP status code into the constructor for :class:`~django.http.HttpResponse` -to create a return class for any status code you like. For example:: - - def my_view(request): - # ... - - # Return a "created" (201) response code. - return HttpResponse(status=201) - -Because 404 errors are by far the most common HTTP error, there's an easier way -to handle those errors. - -The Http404 exception ---------------------- - -.. class:: django.http.Http404() - -When you return an error such as :class:`~django.http.HttpResponseNotFound`, -you're responsible for defining the HTML of the resulting error page:: - - return HttpResponseNotFound('<h1>Page not found</h1>') - -For convenience, and because it's a good idea to have a consistent 404 error page -across your site, Django provides an ``Http404`` exception. If you raise -``Http404`` at any point in a view function, Django will catch it and return the -standard error page for your application, along with an HTTP error code 404. - -Example usage:: - - from django.http import Http404 - - def detail(request, poll_id): - try: - p = Poll.objects.get(pk=poll_id) - except Poll.DoesNotExist: - raise Http404 - return render_to_response('polls/detail.html', {'poll': p}) - -In order to use the ``Http404`` exception to its fullest, you should create a -template that is displayed when a 404 error is raised. This template should be -called ``404.html`` and located in the top level of your template tree. - -Customizing error views -======================= - -The 404 (page not found) view ------------------------------ - -When you raise an ``Http404`` exception, Django loads a special view devoted -to handling 404 errors. By default, it's the view -``django.views.defaults.page_not_found``, which loads and renders the template -``404.html``. - -This means you need to define a ``404.html`` template in your root template -directory. This template will be used for all 404 errors. - -This ``page_not_found`` view should suffice for 99% of Web applications, but if -you want to override the 404 view, you can specify ``handler404`` in your -URLconf, like so:: - - handler404 = 'mysite.views.my_custom_404_view' - -Behind the scenes, Django determines the 404 view by looking for ``handler404``. -By default, URLconfs contain the following line:: - - from django.conf.urls.defaults import * - -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. - -Three 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: - you must create a ``404.html`` template in the root of your - template directory. The default 404 view will use that template - for all 404 errors. The default 404 view will pass one variable - to the template: ``request_path``, which is the URL that resulted - in the 404. - - * The 404 view is passed a :class:`~django.template.RequestContext` and - will have access to variables supplied by your - :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting (e.g., - :setting:`MEDIA_URL`). - - * 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. - -The 500 (server error) view ----------------------------- - -Similarly, Django executes special-case behavior in the case of runtime errors -in view code. If a view results in an exception, Django will, by default, call -the view ``django.views.defaults.server_error``, which loads and renders the -template ``500.html``. - -This means you need to define a ``500.html`` template in your root template -directory. This template will be used for all server errors. The default 500 -view passes no variables to this template and is rendered with an empty -``Context`` to lessen the chance of additional errors. - -This ``server_error`` view should suffice for 99% of Web applications, but if -you want to override the view, you can specify ``handler500`` in your -URLconf, like so:: - - handler500 = 'mysite.views.my_custom_error_view' - -Behind the scenes, Django determines the error view by looking for ``handler500``. -By default, URLconfs contain the following line:: - - from django.conf.urls.defaults import * - -That takes care of setting ``handler500`` in the current module. As you can see -in ``django/conf/urls/defaults.py``, ``handler500`` is set to -``'django.views.defaults.server_error'`` by default. diff --git a/parts/django/docs/topics/i18n/deployment.txt b/parts/django/docs/topics/i18n/deployment.txt deleted file mode 100644 index 4727841..0000000 --- a/parts/django/docs/topics/i18n/deployment.txt +++ /dev/null @@ -1,191 +0,0 @@ -========================== -Deployment of translations -========================== - -If you don't need internationalization -====================================== - -Django's internationalization hooks are on by default, and that means there's a -bit of i18n-related overhead in certain places of the framework. If you don't -use internationalization, you should take the two seconds to set -:setting:`USE_I18N = False <USE_I18N>` in your settings file. If -:setting:`USE_I18N` is set to ``False``, then Django will make some -optimizations so as not to load the internationalization machinery. - -You'll probably also want to remove ``'django.core.context_processors.i18n'`` -from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting. - -.. note:: - - There is also an independent but related :setting:`USE_L10N` setting that - controls if Django should implement format localization. - - If :setting:`USE_L10N` is set to ``True``, Django will handle numbers times, - and dates in the format of the current locale. That includes representation - of these field types on templates and allowed input formats for dates, - times on model forms. - - See :ref:`format-localization` for more details. - -If you do need internationalization -=================================== - -.. _how-django-discovers-language-preference: - -How Django discovers language preference ----------------------------------------- - -Once you've prepared your translations -- or, if you just want to use the -translations that come with Django -- you'll just need to activate translation -for your app. - -Behind the scenes, Django has a very flexible model of deciding which language -should be used -- installation-wide, for a particular user, or both. - -To set an installation-wide language preference, set :setting:`LANGUAGE_CODE`. -Django uses this language as the default translation -- the final attempt if no -other translator finds a translation. - -If all you want to do is run Django with your native language, and a language -file is available for it, all you need to do is set ``LANGUAGE_CODE``. - -If you want to let each individual user specify which language he or she -prefers, use ``LocaleMiddleware``. ``LocaleMiddleware`` enables language -selection based on data from the request. It customizes content for each user. - -To use ``LocaleMiddleware``, add ``'django.middleware.locale.LocaleMiddleware'`` -to your ``MIDDLEWARE_CLASSES`` setting. Because middleware order matters, you -should follow these guidelines: - - * Make sure it's one of the first middlewares installed. - * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` - makes use of session data. - * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it. - -For example, your ``MIDDLEWARE_CLASSES`` might look like this:: - - MIDDLEWARE_CLASSES = ( - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.common.CommonMiddleware', - ) - -(For more on middleware, see the :doc:`middleware documentation -</topics/http/middleware>`.) - -``LocaleMiddleware`` tries to determine the user's language preference by -following this algorithm: - - * First, it looks for a ``django_language`` key in the current user's - session. - - * Failing that, it looks for a cookie. - - .. versionchanged:: 1.0 - - In Django version 0.96 and before, the cookie's name is hard-coded to - ``django_language``. In Django 1,0, The cookie name is set by the - ``LANGUAGE_COOKIE_NAME`` setting. (The default name is - ``django_language``.) - - * Failing that, it looks at the ``Accept-Language`` HTTP header. This - header is sent by your browser and tells the server which language(s) you - prefer, in order by priority. Django tries each language in the header - until it finds one with available translations. - - * Failing that, it uses the global ``LANGUAGE_CODE`` setting. - -.. _locale-middleware-notes: - -Notes: - - * In each of these places, the language preference is expected to be in the - standard :term:`language format<language code>`, as a string. For example, - Brazilian Portuguese is ``pt-br``. - - * If a base language is available but the sublanguage specified is not, - Django uses the base language. For example, if a user specifies ``de-at`` - (Austrian German) but Django only has ``de`` available, Django uses - ``de``. - - * Only languages listed in the :setting:`LANGUAGES` setting can be selected. - If you want to restrict the language selection to a subset of provided - languages (because your application doesn't provide all those languages), - set ``LANGUAGES`` to a list of languages. For example:: - - LANGUAGES = ( - ('de', _('German')), - ('en', _('English')), - ) - - This example restricts languages that are available for automatic - selection to German and English (and any sublanguage, like de-ch or - en-us). - - * If you define a custom ``LANGUAGES`` setting, as explained in the - previous bullet, it's OK to mark the languages as translation strings - -- but use a "dummy" ``ugettext()`` function, not the one in - ``django.utils.translation``. You should *never* import - ``django.utils.translation`` from within your settings file, because that - module in itself depends on the settings, and that would cause a circular - import. - - The solution is to use a "dummy" ``ugettext()`` function. Here's a sample - settings file:: - - ugettext = lambda s: s - - LANGUAGES = ( - ('de', ugettext('German')), - ('en', ugettext('English')), - ) - - With this arrangement, ``django-admin.py makemessages`` will still find - and mark these strings for translation, but the translation won't happen - at runtime -- so you'll have to remember to wrap the languages in the - *real* ``ugettext()`` in any code that uses ``LANGUAGES`` at runtime. - - * The ``LocaleMiddleware`` can only select languages for which there is a - Django-provided base translation. If you want to provide translations - for your application that aren't already in the set of translations - in Django's source tree, you'll want to provide at least a basic - one as described in the :ref:`Locale restrictions<locale-restrictions>` - note. - -Once ``LocaleMiddleware`` determines the user's preference, it makes this -preference available as ``request.LANGUAGE_CODE`` for each -:class:`~django.http.HttpRequest`. Feel free to read this value in your view -code. Here's a simple example:: - - def hello_world(request, count): - if request.LANGUAGE_CODE == 'de-at': - return HttpResponse("You prefer to read Austrian German.") - else: - return HttpResponse("You prefer to read another language.") - -Note that, with static (middleware-less) translation, the language is in -``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's -in ``request.LANGUAGE_CODE``. - -.. _settings file: ../settings/ -.. _middleware documentation: ../middleware/ -.. _session: ../sessions/ -.. _request object: ../request_response/#httprequest-objects - -How Django discovers translations ---------------------------------- - -As described in :ref:`using-translations-in-your-own-projects`, -at runtime, Django looks for translations by following this algorithm: - - * First, it looks for a ``locale`` directory in the directory containing - your settings file. - * Second, it looks for a ``locale`` directory in the project directory. - * Third, it looks for a ``locale`` directory in each of the installed apps. - It does this in the reverse order of INSTALLED_APPS - * Finally, it checks the Django-provided base translation in - ``django/conf/locale``. - -In all cases the name of the directory containing the translation is expected to -be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``, -etc. diff --git a/parts/django/docs/topics/i18n/index.txt b/parts/django/docs/topics/i18n/index.txt deleted file mode 100644 index 9c25192..0000000 --- a/parts/django/docs/topics/i18n/index.txt +++ /dev/null @@ -1,113 +0,0 @@ -===================================== -Internationalization and localization -===================================== - -Overview -======== - -Django has full support for internationalization of text in code and -templates, and format localization of dates and numbers. Here's how it works. - -Essentially, Django does two things: - - * It allows developers and template authors to specify which parts of - their apps should be translatable. - * It uses these hooks to translate Web apps for particular users according - to their language preferences. - -The complete process can be seen as divided in three stages. It is also possible -to identify an identical number of roles with very well defined responsibilities -associated with each of these tasks (although it's perfectly normal if you -find yourself performing more than one of these roles): - - * For application authors wishing to make sure their Django apps can be - used in different locales: :doc:`/topics/i18n/internationalization`. - * For translators wanting to translate Django apps: :doc:`/topics/i18n/localization`. - * For system administrators/final users setting up internationalized apps or - developers integrating third party apps: :doc:`/topics/i18n/deployment`. - -.. toctree:: - :hidden: - :maxdepth: 1 - - internationalization - localization - deployment - -.. _ seealso:: - -For more general information about the topic, see the `GNU gettext documentation`_ -and the `Wikipedia article`_. - -.. _GNU gettext documentation: http://www.gnu.org/software/gettext/manual/gettext.html#Concepts -.. _Wikipedia article: http://en.wikipedia.org/wiki/Internationalization_and_localization - -Glossary -======== - -First lets define some terms that will help us to handle a common language: - -.. glossary:: - - locale name - A locale name, either a language specification of the form ``ll`` or a - combined language and country specification of the form ``ll_CC``. - Examples: ``it``, ``de_AT``, ``es``, ``pt_BR``. Note the underscore in - some of them and the case of the part located to its right. - - language code - Represents the name of a language. Browsers send the names of the - languages they accept in the ``Accept-Language`` HTTP header using this - format. Examples: ``it``, ``de-at``, ``es``, ``pt-br``. Note the ``-`` - separator. - - message file - A message file is a plain-text file, representing a single language, - that contains all available :term:`translation strings - <translation string>` and how they should be represented in the given - language. Message files have a ``.po`` file extension. - - translation string - A literal that can be translated. - -.. _specialties-of-django-i18n: - -Specialties of Django translation -================================= - -Django's translation machinery uses the standard ``gettext`` module that comes -with Python. If you know ``gettext``, you might note these specialties in the -way Django does translation: - - * The string domain is ``django`` or ``djangojs``. This string domain is - used to differentiate between different programs that store their data - in a common message-file library (usually ``/usr/share/locale/``). The - ``django`` domain is used for python and template translation strings - and is loaded into the global translation catalogs. The ``djangojs`` - domain is only used for JavaScript translation catalogs to make sure - that those are as small as possible. - * Django doesn't use ``xgettext`` alone. It uses Python wrappers around - ``xgettext`` and ``msgfmt``. This is mostly for convenience. - -.. _technical-messages: - -Django technical message IDs ----------------------------- - -.. versionchanged:: 1.2 - Starting with Django 1.2, technical message IDs are being replaced by :ref:`format-localization` - -Django uses technical message IDs to translate date formats and time formats. -Technical message IDs are :term:`translation strings <translation string>` and -can be easily recognized; they're all upper case. You don't translate the -message ID as with other translation strings, you provide the correct local -variant on the provided English value. The format is identical to the format -strings used by the ``now`` template tag. - -For example, with ``DATETIME_FORMAT`` (or ``DATE_FORMAT`` or ``TIME_FORMAT``), -this would be the format string that you want to use in your language. A Django -contributor localizing it to Spanish probably would provide a ``"j N Y P"`` -"translation" for it in the relevant ``django.po`` file:: - - msgid "DATETIME_FORMAT" - msgstr "j N Y P" diff --git a/parts/django/docs/topics/i18n/internationalization.txt b/parts/django/docs/topics/i18n/internationalization.txt deleted file mode 100644 index b6847ea..0000000 --- a/parts/django/docs/topics/i18n/internationalization.txt +++ /dev/null @@ -1,624 +0,0 @@ -==================== -Internationalization -==================== - -Overview -======== - -The goal of internationalization is to allow a single Web application to offer -its content and functionality in multiple languages and locales. - -For text translations, you, the Django developer, can accomplish this goal by -adding a minimal amount of hooks to your Python and templates. These hooks -are called **translation strings**. They tell Django: "This text should be -translated into the end user's language, if a translation for this text is -available in that language." It's your responsibility to mark translatable -strings; the system can only translate strings it knows about. - -Django takes care of using these hooks to translate Web apps, on the fly, -according to users' language preferences. - -Specifying translation strings: In Python code -============================================== - -Standard translation --------------------- - -Specify a translation string by using the function ``ugettext()``. It's -convention to import this as a shorter alias, ``_``, to save typing. - -.. note:: - Python's standard library ``gettext`` module installs ``_()`` into the - global namespace, as an alias for ``gettext()``. In Django, we have chosen - not to follow this practice, for a couple of reasons: - - 1. For international character set (Unicode) support, ``ugettext()`` is - more useful than ``gettext()``. Sometimes, you should be using - ``ugettext_lazy()`` as the default translation method for a particular - file. Without ``_()`` in the global namespace, the developer has to - think about which is the most appropriate translation function. - - 2. The underscore character (``_``) is used to represent "the previous - result" in Python's interactive shell and doctest tests. Installing a - global ``_()`` function causes interference. Explicitly importing - ``ugettext()`` as ``_()`` avoids this problem. - -.. highlightlang:: python - -In this example, the text ``"Welcome to my site."`` is marked as a translation -string:: - - from django.utils.translation import ugettext as _ - - def my_view(request): - output = _("Welcome to my site.") - return HttpResponse(output) - -Obviously, you could code this without using the alias. This example is -identical to the previous one:: - - from django.utils.translation import ugettext - - def my_view(request): - output = ugettext("Welcome to my site.") - return HttpResponse(output) - -Translation works on computed values. This example is identical to the previous -two:: - - def my_view(request): - words = ['Welcome', 'to', 'my', 'site.'] - output = _(' '.join(words)) - return HttpResponse(output) - -Translation works on variables. Again, here's an identical example:: - - def my_view(request): - sentence = 'Welcome to my site.' - output = _(sentence) - return HttpResponse(output) - -(The caveat with using variables or computed values, as in the previous two -examples, is that Django's translation-string-detecting utility, -``django-admin.py makemessages``, won't be able to find these strings. More on -``makemessages`` later.) - -The strings you pass to ``_()`` or ``ugettext()`` can take placeholders, -specified with Python's standard named-string interpolation syntax. Example:: - - def my_view(request, m, d): - output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d} - return HttpResponse(output) - -This technique lets language-specific translations reorder the placeholder -text. For example, an English translation may be ``"Today is November 26."``, -while a Spanish translation may be ``"Hoy es 26 de Noviembre."`` -- with the -the month and the day placeholders swapped. - -For this reason, you should use named-string interpolation (e.g., ``%(day)s``) -instead of positional interpolation (e.g., ``%s`` or ``%d``) whenever you -have more than a single parameter. If you used positional interpolation, -translations wouldn't be able to reorder placeholder text. - -Marking strings as no-op ------------------------- - -Use the function ``django.utils.translation.ugettext_noop()`` to mark a string -as a translation string without translating it. The string is later translated -from a variable. - -Use this if you have constant strings that should be stored in the source -language because they are exchanged over systems or users -- such as strings in -a database -- but should be translated at the last possible point in time, such -as when the string is presented to the user. - -Pluralization -------------- - -Use the function ``django.utils.translation.ungettext()`` to specify pluralized -messages. - -``ungettext`` takes three arguments: the singular translation string, the plural -translation string and the number of objects. - -This function is useful when you need your Django application to be localizable -to languages where the number and complexity of `plural forms -<http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms>`_ is -greater than the two forms used in English ('object' for the singular and -'objects' for all the cases where ``count`` is different from zero, irrespective -of its value.) - -For example:: - - from django.utils.translation import ungettext - def hello_world(request, count): - page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % { - 'count': count, - } - return HttpResponse(page) - -In this example the number of objects is passed to the translation languages as -the ``count`` variable. - -Lets see a slightly more complex usage example:: - - from django.utils.translation import ungettext - - count = Report.objects.count() - if count == 1: - name = Report._meta.verbose_name - else: - name = Report._meta.verbose_name_plural - - text = ungettext( - 'There is %(count)d %(name)s available.', - 'There are %(count)d %(name)s available.', - count - ) % { - 'count': count, - 'name': name - } - -Here we reuse localizable, hopefully already translated literals (contained in -the ``verbose_name`` and ``verbose_name_plural`` model ``Meta`` options) for -other parts of the sentence so all of it is consistently based on the -cardinality of the elements at play. - -.. _pluralization-var-notes: - -.. note:: - - When using this technique, make sure you use a single name for every - extrapolated variable included in the literal. In the example above note how - we used the ``name`` Python variable in both translation strings. This - example would fail:: - - from django.utils.translation import ungettext - from myapp.models import Report - - count = Report.objects.count() - d = { - 'count': count, - 'name': Report._meta.verbose_name, - 'plural_name': Report._meta.verbose_name_plural - } - text = ungettext( - 'There is %(count)d %(name)s available.', - 'There are %(count)d %(plural_name)s available.', - count - ) % d - - You would get a ``a format specification for argument 'name', as in - 'msgstr[0]', doesn't exist in 'msgid'`` error when running - ``django-admin.py compilemessages``. - -.. _lazy-translations: - -Lazy translation ----------------- - -Use the function ``django.utils.translation.ugettext_lazy()`` to translate -strings lazily -- when the value is accessed rather than when the -``ugettext_lazy()`` function is called. - -For example, to translate a model's ``help_text``, do the following:: - - from django.utils.translation import ugettext_lazy - - class MyThing(models.Model): - name = models.CharField(help_text=ugettext_lazy('This is the help text')) - -In this example, ``ugettext_lazy()`` stores a lazy reference to the string -- -not the actual translation. The translation itself will be done when the string -is used in a string context, such as template rendering on the Django admin -site. - -The result of a ``ugettext_lazy()`` call can be used wherever you would use a -unicode string (an object with type ``unicode``) in Python. If you try to use -it where a bytestring (a ``str`` object) is expected, things will not work as -expected, since a ``ugettext_lazy()`` object doesn't know how to convert -itself to a bytestring. You can't use a unicode string inside a bytestring, -either, so this is consistent with normal Python behavior. For example:: - - # This is fine: putting a unicode proxy into a unicode string. - u"Hello %s" % ugettext_lazy("people") - - # This will not work, since you cannot insert a unicode object - # into a bytestring (nor can you insert our unicode proxy there) - "Hello %s" % ugettext_lazy("people") - -If you ever see output that looks like ``"hello -<django.utils.functional...>"``, you have tried to insert the result of -``ugettext_lazy()`` into a bytestring. That's a bug in your code. - -If you don't like the verbose name ``ugettext_lazy``, you can just alias it as -``_`` (underscore), like so:: - - from django.utils.translation import ugettext_lazy as _ - - class MyThing(models.Model): - name = models.CharField(help_text=_('This is the help text')) - -Always use lazy translations in :doc:`Django models </topics/db/models>`. -Field names and table names should be marked for translation (otherwise, they -won't be translated in the admin interface). This means writing explicit -``verbose_name`` and ``verbose_name_plural`` options in the ``Meta`` class, -though, rather than relying on Django's default determination of -``verbose_name`` and ``verbose_name_plural`` by looking at the model's class -name:: - - from django.utils.translation import ugettext_lazy as _ - - class MyThing(models.Model): - name = models.CharField(_('name'), help_text=_('This is the help text')) - class Meta: - verbose_name = _('my thing') - verbose_name_plural = _('mythings') - -Working with lazy translation objects -------------------------------------- - -.. highlightlang:: python - -Using ``ugettext_lazy()`` and ``ungettext_lazy()`` to mark strings in models -and utility functions is a common operation. When you're working with these -objects elsewhere in your code, you should ensure that you don't accidentally -convert them to strings, because they should be converted as late as possible -(so that the correct locale is in effect). This necessitates the use of a -couple of helper functions. - -Joining strings: string_concat() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Standard Python string joins (``''.join([...])``) will not work on lists -containing lazy translation objects. Instead, you can use -``django.utils.translation.string_concat()``, which creates a lazy object that -concatenates its contents *and* converts them to strings only when the result -is included in a string. For example:: - - from django.utils.translation import string_concat - ... - name = ugettext_lazy(u'John Lennon') - instrument = ugettext_lazy(u'guitar') - result = string_concat(name, ': ', instrument) - -In this case, the lazy translations in ``result`` will only be converted to -strings when ``result`` itself is used in a string (usually at template -rendering time). - -The allow_lazy() decorator -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Django offers many utility functions (particularly in ``django.utils``) that -take a string as their first argument and do something to that string. These -functions are used by template filters as well as directly in other code. - -If you write your own similar functions and deal with translations, you'll -face the problem of what to do when the first argument is a lazy translation -object. You don't want to convert it to a string immediately, because you might -be using this function outside of a view (and hence the current thread's locale -setting will not be correct). - -For cases like this, use the ``django.utils.functional.allow_lazy()`` -decorator. It modifies the function so that *if* it's called with a lazy -translation as the first argument, the function evaluation is delayed until it -needs to be converted to a string. - -For example:: - - from django.utils.functional import allow_lazy - - def fancy_utility_function(s, ...): - # Do some conversion on string 's' - ... - fancy_utility_function = allow_lazy(fancy_utility_function, unicode) - -The ``allow_lazy()`` decorator takes, in addition to the function to decorate, -a number of extra arguments (``*args``) specifying the type(s) that the -original function can return. Usually, it's enough to include ``unicode`` here -and ensure that your function returns only Unicode strings. - -Using this decorator means you can write your function and assume that the -input is a proper string, then add support for lazy translation objects at the -end. - -.. _specifying-translation-strings-in-template-code: - -Specifying translation strings: In template code -================================================ - -.. highlightlang:: html+django - -Translations in :doc:`Django templates </topics/templates>` uses two template -tags and a slightly different syntax than in Python code. To give your template -access to these tags, put ``{% load i18n %}`` toward the top of your template. - -``trans`` template tag ----------------------- - -The ``{% trans %}`` template tag translates either a constant string -(enclosed in single or double quotes) or variable content:: - - <title>{% trans "This is the title." %}</title> - <title>{% trans myvar %}</title> - -If the ``noop`` option is present, variable lookup still takes place but the -translation is skipped. This is useful when "stubbing out" content that will -require translation in the future:: - - <title>{% trans "myvar" noop %}</title> - -Internally, inline translations use an ``ugettext`` call. - -In case a template var (``myvar`` above) is passed to the tag, the tag will -first resolve such variable to a string at run-time and then look up that -string in the message catalogs. - -It's not possible to mix a template variable inside a string within ``{% trans -%}``. If your translations require strings with variables (placeholders), use -``{% blocktrans %}`` instead. - -``blocktrans`` template tag ---------------------------- - -Contrarily to the ``trans`` tag, the ``blocktrans`` tag allows you to mark -complex sentences consisting of literals and variable content for translation -by making use of placeholders:: - - {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %} - -To translate a template expression -- say, accessing object attributes or -using template filters -- you need to bind the expression to a local variable -for use within the translation block. Examples:: - - {% blocktrans with article.price as amount %} - That will cost $ {{ amount }}. - {% endblocktrans %} - - {% blocktrans with value|filter as myvar %} - This will have {{ myvar }} inside. - {% endblocktrans %} - -If you need to bind more than one expression inside a ``blocktrans`` tag, -separate the pieces with ``and``:: - - {% blocktrans with book|title as book_t and author|title as author_t %} - This is {{ book_t }} by {{ author_t }} - {% endblocktrans %} - -This tag also provides for pluralization. To use it: - - * Designate and bind a counter value with the name ``count``. This value will - be the one used to select the right plural form. - - * Specify both the singular and plural forms separating them with the - ``{% plural %}`` tag within the ``{% blocktrans %}`` and - ``{% endblocktrans %}`` tags. - -An example:: - - {% blocktrans count list|length as counter %} - There is only one {{ name }} object. - {% plural %} - There are {{ counter }} {{ name }} objects. - {% endblocktrans %} - -A more complex example:: - - {% blocktrans with article.price as amount count i.length as years %} - That will cost $ {{ amount }} per year. - {% plural %} - That will cost $ {{ amount }} per {{ years }} years. - {% endblocktrans %} - -When you use both the pluralization feature and bind values to local variables -in addition to the counter value, keep in mind that the ``blocktrans`` -construct is internally converted to an ``ungettext`` call. This means the -same :ref:`notes regarding ungettext variables <pluralization-var-notes>` -apply. - -.. _template-translation-vars: - -Other tags ----------- - -Each ``RequestContext`` has access to three translation-specific variables: - - * ``LANGUAGES`` is a list of tuples in which the first element is the - :term:`language code` and the second is the language name (translated into - the currently active locale). - - * ``LANGUAGE_CODE`` is the current user's preferred language, as a string. - Example: ``en-us``. (See :ref:`how-django-discovers-language-preference`.) - - * ``LANGUAGE_BIDI`` is the current locale's direction. If True, it's a - right-to-left language, e.g.: Hebrew, Arabic. If False it's a - left-to-right language, e.g.: English, French, German etc. - -If you don't use the ``RequestContext`` extension, you can get those values with -three tags:: - - {% get_current_language as LANGUAGE_CODE %} - {% get_available_languages as LANGUAGES %} - {% get_current_language_bidi as LANGUAGE_BIDI %} - -These tags also require a ``{% load i18n %}``. - -Translation hooks are also available within any template block tag that accepts -constant strings. In those cases, just use ``_()`` syntax to specify a -translation string:: - - {% some_special_tag _("Page not found") value|yesno:_("yes,no") %} - -In this case, both the tag and the filter will see the already-translated -string, so they don't need to be aware of translations. - -.. note:: - In this example, the translation infrastructure will be passed the string - ``"yes,no"``, not the individual strings ``"yes"`` and ``"no"``. The - translated string will need to contain the comma so that the filter - parsing code knows how to split up the arguments. For example, a German - translator might translate the string ``"yes,no"`` as ``"ja,nein"`` - (keeping the comma intact). - -.. _Django templates: ../templates_python/ - -Specifying translation strings: In JavaScript code -================================================== - -Adding translations to JavaScript poses some problems: - - * JavaScript code doesn't have access to a ``gettext`` implementation. - - * JavaScript code doesn't have access to .po or .mo files; they need to be - delivered by the server. - - * The translation catalogs for JavaScript should be kept as small as - possible. - -Django provides an integrated solution for these problems: It passes the -translations into JavaScript, so you can call ``gettext``, etc., from within -JavaScript. - -The ``javascript_catalog`` view -------------------------------- - -.. module:: django.views.i18n - -.. function:: javascript_catalog(request, domain='djangojs', packages=None) - -The main solution to these problems is the :meth:`django.views.i18n.javascript_catalog` -view, which sends out a JavaScript code library with functions that mimic the -``gettext`` interface, plus an array of translation strings. Those translation -strings are taken from the application, project or Django core, according to what -you specify in either the info_dict or the URL. - -You hook it up like this:: - - js_info_dict = { - 'packages': ('your.app.package',), - } - - urlpatterns = patterns('', - (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), - ) - -Each string in ``packages`` should be in Python dotted-package syntax (the -same format as the strings in ``INSTALLED_APPS``) and should refer to a package -that contains a ``locale`` directory. If you specify multiple packages, all -those catalogs are merged into one catalog. This is useful if you have -JavaScript that uses strings from different applications. - -By default, the view uses the ``djangojs`` gettext domain. This can be -changed by altering the ``domain`` argument. - -You can make the view dynamic by putting the packages into the URL pattern:: - - urlpatterns = patterns('', - (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'), - ) - -With this, you specify the packages as a list of package names delimited by '+' -signs in the URL. This is especially useful if your pages use code from -different apps and this changes often and you don't want to pull in one big -catalog file. As a security measure, these values can only be either -``django.conf`` or any package from the ``INSTALLED_APPS`` setting. - -Using the JavaScript translation catalog ----------------------------------------- - -To use the catalog, just pull in the dynamically generated script like this:: - - <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script> - -This uses reverse URL lookup to find the URL of the JavaScript catalog view. -When the catalog is loaded, your JavaScript code can use the standard -``gettext`` interface to access it:: - - document.write(gettext('this is to be translated')); - -There is also an ``ngettext`` interface:: - - var object_cnt = 1 // or 0, or 2, or 3, ... - s = ngettext('literal for the singular case', - 'literal for the plural case', object_cnt); - -and even a string interpolation function:: - - function interpolate(fmt, obj, named); - -The interpolation syntax is borrowed from Python, so the ``interpolate`` -function supports both positional and named interpolation: - - * Positional interpolation: ``obj`` contains a JavaScript Array object - whose elements values are then sequentially interpolated in their - corresponding ``fmt`` placeholders in the same order they appear. - For example:: - - fmts = ngettext('There is %s object. Remaining: %s', - 'There are %s objects. Remaining: %s', 11); - s = interpolate(fmts, [11, 20]); - // s is 'There are 11 objects. Remaining: 20' - - * Named interpolation: This mode is selected by passing the optional - boolean ``named`` parameter as true. ``obj`` contains a JavaScript - object or associative array. For example:: - - d = { - count: 10, - total: 50 - }; - - fmts = ngettext('Total: %(total)s, there is %(count)s object', - 'there are %(count)s of a total of %(total)s objects', d.count); - s = interpolate(fmts, d, true); - -You shouldn't go over the top with string interpolation, though: this is still -JavaScript, so the code has to make repeated regular-expression substitutions. -This isn't as fast as string interpolation in Python, so keep it to those -cases where you really need it (for example, in conjunction with ``ngettext`` -to produce proper pluralizations). - -The ``set_language`` redirect view -================================== - -.. function:: set_language(request) - -As a convenience, Django comes with a view, :meth:`django.views.i18n.set_language`, -that sets a user's language preference and redirects back to the previous page. - -Activate this view by adding the following line to your URLconf:: - - (r'^i18n/', include('django.conf.urls.i18n')), - -(Note that this example makes the view available at ``/i18n/setlang/``.) - -The view expects to be called via the ``POST`` method, with a ``language`` -parameter set in request. If session support is enabled, the view -saves the language choice in the user's session. Otherwise, it saves the -language choice in a cookie that is by default named ``django_language``. -(The name can be changed through the ``LANGUAGE_COOKIE_NAME`` setting.) - -After setting the language choice, Django redirects the user, following this -algorithm: - - * Django looks for a ``next`` parameter in the ``POST`` data. - * If that doesn't exist, or is empty, Django tries the URL in the - ``Referrer`` header. - * If that's empty -- say, if a user's browser suppresses that header -- - then the user will be redirected to ``/`` (the site root) as a fallback. - -Here's example HTML template code: - -.. code-block:: html+django - - <form action="/i18n/setlang/" method="post"> - {% csrf_token %} - <input name="next" type="hidden" value="/next/page/" /> - <select name="language"> - {% for lang in LANGUAGES %} - <option value="{{ lang.0 }}">{{ lang.1 }}</option> - {% endfor %} - </select> - <input type="submit" value="Go" /> - </form> diff --git a/parts/django/docs/topics/i18n/localization.txt b/parts/django/docs/topics/i18n/localization.txt deleted file mode 100644 index 38d74e6..0000000 --- a/parts/django/docs/topics/i18n/localization.txt +++ /dev/null @@ -1,317 +0,0 @@ -============ -Localization -============ - -This document covers two localization-related topics: `Creating language -files`_ and `locale aware date, time and numbers input/output in forms`_ - -.. _`Creating language files`: how-to-create-language-files_ -.. _`locale aware date, time and numbers input/output in forms`: format-localization_ - -.. seealso:: - - The :doc:`/howto/i18n` document included with the Django HOW-TO documents collection. - -.. _how-to-create-language-files: - -How to create language files -============================ - -Once the string literals of an application have been tagged for later -translation, the translation themselves need to be written (or obtained). Here's -how that works. - -.. _locale-restrictions: - -.. admonition:: Locale restrictions - - Django does not support localizing your application into a locale for which - Django itself has not been translated. In this case, it will ignore your - translation files. If you were to try this and Django supported it, you - would inevitably see a mixture of translated strings (from your application) - and English strings (from Django itself). If you want to support a locale - for your application that is not already part of Django, you'll need to make - at least a minimal translation of the Django core. - - A good starting point is to copy the Django English ``.po`` file and to - translate at least some :term:`translation strings <translation string>`. - -Message files -------------- - -The first step is to create a :term:`message file` for a new language. A message -file is a plain-text file, representing a single language, that contains all -available translation strings and how they should be represented in the given -language. Message files have a ``.po`` file extension. - -Django comes with a tool, ``django-admin.py makemessages``, that automates the -creation and upkeep of these files. - -.. admonition:: A note to Django veterans - - The old tool ``bin/make-messages.py`` has been moved to the command - ``django-admin.py makemessages`` to provide consistency throughout Django. - -.. admonition:: Gettext utilities - - The ``makemessages`` command (and ``compilemessages`` discussed later) use - commands from the GNU gettext toolset: ``xgettext``, ``msgfmt``, - ``msgmerge`` and ``msguniq``. - - .. versionchanged:: 1.2 - - The minimum version of the ``gettext`` utilities supported is 0.15. - -To create or update a message file, run this command:: - - django-admin.py makemessages -l de - -...where ``de`` is the language code for the message file you want to create. -The language code, in this case, is in :term:`locale format<locale name>`. For -example, it's ``pt_BR`` for Brazilian Portuguese and ``de_AT`` for Austrian -German. - -The script should be run from one of two places: - - * The root directory of your Django project. - * The root directory of your Django app. - -The script runs over your project source tree or your application source tree -and pulls out all strings marked for translation. It creates (or updates) a -message file in the directory ``locale/LANG/LC_MESSAGES``. In the ``de`` -example, the file will be ``locale/de/LC_MESSAGES/django.po``. - -By default ``django-admin.py makemessages`` examines every file that has the -``.html`` file extension. In case you want to override that default, use the -``--extension`` or ``-e`` option to specify the file extensions to examine:: - - django-admin.py makemessages -l de -e txt - -Separate multiple extensions with commas and/or use ``-e`` or ``--extension`` -multiple times:: - - django-admin.py makemessages -l de -e html,txt -e xml - -When :ref:`creating message files from JavaScript source code -<creating-message-files-from-js-code>` you need to use the special 'djangojs' -domain, **not** ``-e js``. - -.. admonition:: No gettext? - - If you don't have the ``gettext`` utilities installed, ``django-admin.py - makemessages`` will create empty files. If that's the case, either install - the ``gettext`` utilities or just copy the English message file - (``locale/en/LC_MESSAGES/django.po``) if available and use it as a starting - point; it's just an empty translation file. - -.. admonition:: Working on Windows? - - If you're using Windows and need to install the GNU gettext utilities so - ``django-admin makemessages`` works see :ref:`gettext_on_windows` for more - information. - -The format of ``.po`` files is straightforward. Each ``.po`` file contains a -small bit of metadata, such as the translation maintainer's contact -information, but the bulk of the file is a list of **messages** -- simple -mappings between translation strings and the actual translated text for the -particular language. - -For example, if your Django app contained a translation string for the text -``"Welcome to my site."``, like so:: - - _("Welcome to my site.") - -...then ``django-admin.py makemessages`` will have created a ``.po`` file -containing the following snippet -- a message:: - - #: path/to/python/module.py:23 - msgid "Welcome to my site." - msgstr "" - -A quick explanation: - - * ``msgid`` is the translation string, which appears in the source. Don't - change it. - * ``msgstr`` is where you put the language-specific translation. It starts - out empty, so it's your responsibility to change it. Make sure you keep - the quotes around your translation. - * As a convenience, each message includes, in the form of a comment line - prefixed with ``#`` and located above the ``msgid`` line, the filename and - line number from which the translation string was gleaned. - -Long messages are a special case. There, the first string directly after the -``msgstr`` (or ``msgid``) is an empty string. Then the content itself will be -written over the next few lines as one string per line. Those strings are -directly concatenated. Don't forget trailing spaces within the strings; -otherwise, they'll be tacked together without whitespace! - -.. admonition:: Mind your charset - - When creating a PO file with your favorite text editor, first edit - the charset line (search for ``"CHARSET"``) and set it to the charset - you'll be using to edit the content. Due to the way the ``gettext`` tools - work internally and because we want to allow non-ASCII source strings in - Django's core and your applications, you **must** use UTF-8 as the encoding - for your PO file. This means that everybody will be using the same - encoding, which is important when Django processes the PO files. - -To reexamine all source code and templates for new translation strings and -update all message files for **all** languages, run this:: - - django-admin.py makemessages -a - -Compiling message files ------------------------ - -After you create your message file -- and each time you make changes to it -- -you'll need to compile it into a more efficient form, for use by ``gettext``. -Do this with the ``django-admin.py compilemessages`` utility. - -This tool runs over all available ``.po`` files and creates ``.mo`` files, which -are binary files optimized for use by ``gettext``. In the same directory from -which you ran ``django-admin.py makemessages``, run ``django-admin.py -compilemessages`` like this:: - - django-admin.py compilemessages - -That's it. Your translations are ready for use. - -.. admonition:: A note to Django veterans - - The old tool ``bin/compile-messages.py`` has been moved to the command - ``django-admin.py compilemessages`` to provide consistency throughout - Django. - -.. admonition:: Working on Windows? - - If you're using Windows and need to install the GNU gettext utilities so - ``django-admin compilemessages`` works see :ref:`gettext_on_windows` for more - information. - -.. admonition:: .po files: Encoding and BOM usage. - - Django only supports ``.po`` files encoded in UTF-8 and without any BOM - (Byte Order Mark) so if your text editor adds such marks to the beginning of - files by default then you will need to reconfigure it. - -.. _creating-message-files-from-js-code: - -Creating message files from JavaScript source code -================================================== - -You create and update the message files the same way as the other Django message -files -- with the ``django-admin.py makemessages`` tool. The only difference is -you need to provide a ``-d djangojs`` parameter, like this:: - - django-admin.py makemessages -d djangojs -l de - -This would create or update the message file for JavaScript for German. -After updating message files, just run ``django-admin.py compilemessages`` -the same way as you do with normal Django message files. - -.. _gettext_on_windows: - -``gettext`` on Windows -====================== - -This is only needed for people who either want to extract message IDs or compile -message files (``.po``). Translation work itself just involves editing existing -files of this type, but if you want to create your own message files, or want to -test or compile a changed message file, you will need the ``gettext`` utilities: - - * Download the following zip files from the GNOME servers - http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one - of its mirrors_ - - * ``gettext-runtime-X.zip`` - * ``gettext-tools-X.zip`` - - ``X`` is the version number, we are requiring ``0.15`` or higher. - - * Extract the contents of the ``bin\`` directories in both files to the - same folder on your system (i.e. ``C:\Program Files\gettext-utils``) - - * Update the system PATH: - - * ``Control Panel > System > Advanced > Environment Variables``. - * In the ``System variables`` list, click ``Path``, click ``Edit``. - * Add ``;C:\Program Files\gettext-utils\bin`` at the end of the - ``Variable value`` field. - -.. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS - -You may also use ``gettext`` binaries you have obtained elsewhere, so long as -the ``xgettext --version`` command works properly. Do not attempt to use Django -translation utilities with a ``gettext`` package if the command ``xgettext ---version`` entered at a Windows command prompt causes a popup window saying -"xgettext.exe has generated errors and will be closed by Windows". - -.. _format-localization: - -Format localization -=================== - -.. versionadded:: 1.2 - -Django's formatting system is disabled by default. To enable it, it's -necessary to set :setting:`USE_L10N = True <USE_L10N>` in your settings file. - -.. note:: - The default :file:`settings.py` file created by - :djadmin:`django-admin.py startproject <startproject>` includes - :setting:`USE_L10N = True <USE_L10N>` for convenience. - -When using Django's formatting system, dates and numbers on templates will be -displayed using the format specified for the current locale. Two users -accessing the same content, but in different language, will see date and -number fields formatted in different ways, depending on the format for their -current locale. - -Django will also use localized formats when parsing data in forms. That means -Django uses different formats for different locales when guessing the format -used by the user when inputting data on forms. - -.. note:: - Django uses different formats for displaying data to those it uses for - parsing data. Most notably, the formats for parsing dates can't use the - ``%a`` (abbreviated weekday name), ``%A`` (full weekday name), - ``%b`` (abbreviated month name), ``%B`` (full month name), - or ``%p`` (AM/PM). - -To enable a form field to localize input and output data simply use its -``localize`` argument:: - - class CashRegisterForm(forms.Form): - product = forms.CharField() - revenue = forms.DecimalField(max_digits=4, decimal_places=2, localize=True) - -Creating custom format files ----------------------------- - -Django provides format definitions for many locales, but sometimes you might -want to create your own, because a format files doesn't exist for your locale, -or because you want to overwrite some of the values. - -To use custom formats, first thing to do, is to specify the path where you'll -place format files. To do that, just set your :setting:`FORMAT_MODULE_PATH` -setting to the path (in the format ``'foo.bar.baz``) where format files -will exists. - -Files are not placed directly in this directory, but in a directory named as -the locale, and must be named ``formats.py``. - -To customize the English formats, a structure like this would be needed:: - - mysite/ - formats/ - __init__.py - en/ - __init__.py - formats.py - -where :file:`formats.py` contains custom format definitions. For example:: - - THOUSAND_SEPARATOR = ' ' - -to use a space as a thousand separator, instead of the default for English, -a comma. diff --git a/parts/django/docs/topics/index.txt b/parts/django/docs/topics/index.txt deleted file mode 100644 index 4c6b7fc..0000000 --- a/parts/django/docs/topics/index.txt +++ /dev/null @@ -1,27 +0,0 @@ -Using Django -============ - -Introductions to all the key parts of Django you'll need to know: - -.. toctree:: - :maxdepth: 1 - - install - db/index - http/index - forms/index - forms/modelforms - templates - generic-views - files - testing - auth - cache - conditional-view-processing - email - i18n/index - pagination - serialization - settings - signals - diff --git a/parts/django/docs/topics/install.txt b/parts/django/docs/topics/install.txt deleted file mode 100644 index 20c8074..0000000 --- a/parts/django/docs/topics/install.txt +++ /dev/null @@ -1,298 +0,0 @@ -===================== -How to install Django -===================== - -This document will get you up and running with Django. - -Install Python -============== - -Being a Python Web framework, Django requires Python. - -It works with any Python version from 2.4 to 2.7 (due to backwards -incompatibilities in Python 3.0, Django does not currently work with -Python 3.0; see :doc:`the Django FAQ </faq/install>` for more -information on supported Python versions and the 3.0 transition). - -Get Python at http://www.python.org. If you're running Linux or Mac OS X, you -probably already have it installed. - -.. admonition:: Django on Jython - - If you use Jython_ (a Python implementation for the Java platform), you'll - need to follow a few additional steps. See :doc:`/howto/jython` for details. - -.. _jython: http://jython.org/ - -Install Apache and mod_wsgi -============================= - -If you just want to experiment with Django, skip ahead to the next section; -Django includes a lightweight Web server you can use for testing, so you won't -need to set up Apache until you're ready to deploy Django in production. - -If you want to use Django on a production site, use Apache with `mod_wsgi`_. -mod_wsgi 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. Make sure you have Apache installed, with the -mod_wsgi module activated. Django will work with any version of Apache that -supports mod_wsgi. - -See :doc:`How to use Django with mod_wsgi </howto/deployment/modwsgi>` for -information on how to configure mod_wsgi once you have it installed. - -If you can't use mod_wsgi for some reason, fear not: Django supports many other -deployment options. A great second choice is :doc:`mod_python -</howto/deployment/modpython>`, the predecessor to mod_wsgi. Additionally, Django -follows the WSGI_ spec, which allows it to run on a variety of server platforms. -See the `server-arrangements wiki page`_ for specific installation instructions -for each platform. - -.. _Apache: http://httpd.apache.org/ -.. _mod_wsgi: http://code.google.com/p/modwsgi/ -.. _WSGI: http://www.python.org/dev/peps/pep-0333/ -.. _server-arrangements wiki page: http://code.djangoproject.com/wiki/ServerArrangements - -.. _database-installation: - -Get your database running -========================= - -If you plan to use Django's database API functionality, you'll need to make -sure a database server is running. Django supports many different database -servers and is officially supported with PostgreSQL_, MySQL_, Oracle_ and -SQLite_ (although SQLite doesn't require a separate server to be running). - -In addition to the officially supported databases, there are backends provided -by 3rd parties that allow you to use other databases with Django: - -* `Sybase SQL Anywhere`_ -* `IBM DB2`_ -* `Microsoft SQL Server 2005`_ -* Firebird_ -* ODBC_ - -The Django versions and ORM features supported by these unofficial backends -vary considerably. Queries regarding the specific capabilities of these -unofficial backends, along with any support queries, should be directed to the -support channels provided by each 3rd party project. - -In addition to a database backend, you'll need to make sure your Python -database bindings are installed. - -* If you're using PostgreSQL, you'll need the psycopg_ package. Django supports - both version 1 and 2. (When you configure Django's database layer, specify - either ``postgresql`` [for version 1] or ``postgresql_psycopg2`` [for version 2].) - You might want to refer to our :ref:`PostgreSQL notes <postgresql-notes>` for - further technical details specific to this database. - - If you're on Windows, check out the unofficial `compiled Windows version`_. - -* If you're using MySQL, you'll need MySQLdb_, version 1.2.1p2 or higher. You - will also want to read the database-specific :ref:`notes for the MySQL - backend <mysql-notes>`. - -* If you're using SQLite and Python 2.4, you'll need pysqlite_. Use version - 2.0.3 or higher. Python 2.5 ships with an SQLite wrapper in the standard - library, so you don't need to install anything extra in that case. Please - read the :ref:`SQLite backend notes <sqlite-notes>`. - -* If you're using Oracle, you'll need a copy of cx_Oracle_, but please - read the database-specific :ref:`notes for the Oracle backend <oracle-notes>` - for important information regarding supported versions of both Oracle and - ``cx_Oracle``. - -* If you're using an unofficial 3rd party backend, please consult the - documentation provided for any additional requirements. - -If you plan to use Django's ``manage.py syncdb`` command to -automatically create database tables for your models, you'll need to -ensure that Django has permission to create and alter tables in the -database you're using; if you plan to manually create the tables, you -can simply grant Django ``SELECT``, ``INSERT``, ``UPDATE`` and -``DELETE`` permissions. On some databases, Django will need -``ALTER TABLE`` privileges during ``syncdb`` but won't issue -``ALTER TABLE`` statements on a table once ``syncdb`` has created it. - -If you're using Django's :doc:`testing framework</topics/testing>` to test database queries, -Django will need permission to create a test database. - -.. _PostgreSQL: http://www.postgresql.org/ -.. _MySQL: http://www.mysql.com/ -.. _psycopg: http://initd.org/pub/software/psycopg/ -.. _compiled Windows version: http://stickpeople.com/projects/python/win-psycopg/ -.. _MySQLdb: http://sourceforge.net/projects/mysql-python -.. _SQLite: http://www.sqlite.org/ -.. _pysqlite: http://trac.edgewall.org/wiki/PySqlite -.. _cx_Oracle: http://cx-oracle.sourceforge.net/ -.. _Oracle: http://www.oracle.com/ -.. _Sybase SQL Anywhere: http://code.google.com/p/sqlany-django/ -.. _IBM DB2: http://code.google.com/p/ibm-db/ -.. _Microsoft SQL Server 2005: http://code.google.com/p/django-mssql/ -.. _Firebird: http://code.google.com/p/django-firebird/ -.. _ODBC: http://code.google.com/p/django-pyodbc/ -.. _removing-old-versions-of-django: - -Remove any old versions of Django -================================= - -If you are upgrading your installation of Django from a previous version, -you will need to uninstall the old Django version before installing the -new version. - -If you installed Django using ``setup.py install``, uninstalling -is as simple as deleting the ``django`` directory from your Python -``site-packages``. - -If you installed Django from a Python egg, remove the Django ``.egg`` file, -and remove the reference to the egg in the file named ``easy-install.pth``. -This file should also be located in your ``site-packages`` directory. - -.. admonition:: Where are my ``site-packages`` stored? - - The location of the ``site-packages`` directory depends on the operating - system, and the location in which Python was installed. To find out your - system's ``site-packages`` location, execute the following: - - .. code-block:: bash - - python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" - - (Note that this should be run from a shell prompt, not a Python interactive - prompt.) - -.. _install-django-code: - -Install the Django code -======================= - -Installation instructions are slightly different depending on whether you're -installing a distribution-specific package, downloading the latest official -release, or fetching the latest development version. - -It's easy, no matter which way you choose. - -Installing a distribution-specific package -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Check the :doc:`distribution specific notes </misc/distributions>` to see if your -platform/distribution provides official Django packages/installers. -Distribution-provided packages will typically allow for automatic installation -of dependencies and easy upgrade paths. - -.. _installing-official-release: - -Installing an official release -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - 1. Download the latest release from our `download page`_. - - 2. Untar the downloaded file (e.g. ``tar xzvf Django-NNN.tar.gz``, - where ``NNN`` is the version number of the latest release). - If you're using Windows, you can download the command-line tool - bsdtar_ to do this, or you can use a GUI-based tool such as 7-zip_. - - 3. Change into the directory created in step 2 (e.g. ``cd Django-NNN``). - - 4. If you're using Linux, Mac OS X or some other flavor of Unix, enter - the command ``sudo python setup.py install`` at the shell prompt. - If you're using Windows, start up a command shell with administrator - privileges and run the command ``setup.py install``. - -These commands will install Django in your Python installation's -``site-packages`` directory. - -.. _bsdtar: http://gnuwin32.sourceforge.net/packages/bsdtar.htm -.. _7-zip: http://www.7-zip.org/ - -.. _installing-development-version: - -Installing the development version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. admonition:: Tracking Django development - - If you decide to use the latest development version of Django, - you'll want to pay close attention to `the development timeline`_, - and you'll want to keep an eye on `the list of - backwards-incompatible changes`_. This will help you stay on top - of any new features you might want to use, as well as any changes - you'll need to make to your code when updating your copy of Django. - (For stable releases, any necessary changes are documented in the - release notes.) - -.. _the development timeline: http://code.djangoproject.com/timeline -.. _the list of backwards-incompatible changes: http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges - -If you'd like to be able to update your Django code occasionally with the -latest bug fixes and improvements, follow these instructions: - -1. Make sure that you have Subversion_ installed, and that you can run its - commands from a shell. (Enter ``svn help`` at a shell prompt to test - this.) - -2. Check out Django's main development branch (the 'trunk') like so: - - .. code-block:: bash - - svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk - -3. Next, make sure that the Python interpreter can load Django's code. There - are various ways of accomplishing this. One of the most convenient, on - Linux, Mac OSX or other Unix-like systems, is to use a symbolic link: - - .. code-block:: bash - - ln -s WORKING-DIR/django-trunk/django SITE-PACKAGES-DIR/django - - (In the above line, change ``SITE-PACKAGES-DIR`` to match the location of - your system's ``site-packages`` directory, as explained in the - "Where are my ``site-packages`` stored?" section above. Change WORKING-DIR - to match the full path to your new ``django-trunk`` directory.) - - Alternatively, you can define your ``PYTHONPATH`` environment variable - so that it includes the ``django-trunk`` directory. This is perhaps the - most convenient solution on Windows systems, which don't support symbolic - links. (Environment variables can be defined on Windows systems `from the - Control Panel`_.) - - .. admonition:: What about Apache and mod_python? - - If you take the approach of setting ``PYTHONPATH``, you'll need to - remember to do the same thing in your Apache configuration once you - deploy your production site. Do this by setting ``PythonPath`` in your - Apache configuration file. - - More information about deployment is available, of course, in our - :doc:`How to use Django with mod_python </howto/deployment/modpython>` - documentation. - -4. On Unix-like systems, create a symbolic link to the file - ``django-trunk/django/bin/django-admin.py`` in a directory on your system - path, such as ``/usr/local/bin``. For example: - - .. code-block:: bash - - ln -s WORKING-DIR/django-trunk/django/bin/django-admin.py /usr/local/bin - - (In the above line, change WORKING-DIR to match the full path to your new - ``django-trunk`` directory.) - - This simply lets you type ``django-admin.py`` from within any directory, - rather than having to qualify the command with the full path to the file. - - On Windows systems, the same result can be achieved by copying the file - ``django-trunk/django/bin/django-admin.py`` to somewhere on your system - path, for example ``C:\Python24\Scripts``. - -You *don't* have to run ``python setup.py install``, because you've already -carried out the equivalent actions in steps 3 and 4. - -When you want to update your copy of the Django source code, just run the -command ``svn update`` from within the ``django-trunk`` directory. When you do -this, Subversion will automatically download any changes. - -.. _`download page`: http://www.djangoproject.com/download/ -.. _Subversion: http://subversion.tigris.org/ -.. _from the Control Panel: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/sysdm_advancd_environmnt_addchange_variable.mspx diff --git a/parts/django/docs/topics/pagination.txt b/parts/django/docs/topics/pagination.txt deleted file mode 100644 index ee8a433..0000000 --- a/parts/django/docs/topics/pagination.txt +++ /dev/null @@ -1,281 +0,0 @@ -========== -Pagination -========== - -.. module:: django.core.paginator - :synopsis: Classes to help you easily manage paginated data. - -.. versionchanged:: 1.0 - Pagination facilities have been almost fully reworked. - -Django provides a few classes that help you manage paginated data -- that is, -data that's split across several pages, with "Previous/Next" links. These -classes live in :file:`django/core/paginator.py`. - -Example -======= - -Give :class:`Paginator` a list of objects, plus the number of items you'd like to -have on each page, and it gives you methods for accessing the items for each -page:: - - >>> from django.core.paginator import Paginator - >>> objects = ['john', 'paul', 'george', 'ringo'] - >>> p = Paginator(objects, 2) - - >>> p.count - 4 - >>> p.num_pages - 2 - >>> p.page_range - [1, 2] - - >>> page1 = p.page(1) - >>> page1 - <Page 1 of 2> - >>> page1.object_list - ['john', 'paul'] - - >>> page2 = p.page(2) - >>> page2.object_list - ['george', 'ringo'] - >>> page2.has_next() - False - >>> page2.has_previous() - True - >>> page2.has_other_pages() - True - >>> page2.next_page_number() - 3 - >>> page2.previous_page_number() - 1 - >>> page2.start_index() # The 1-based index of the first item on this page - 3 - >>> page2.end_index() # The 1-based index of the last item on this page - 4 - - >>> p.page(0) - Traceback (most recent call last): - ... - EmptyPage: That page number is less than 1 - >>> p.page(3) - Traceback (most recent call last): - ... - EmptyPage: That page contains no results - -.. note:: - - Note that you can give ``Paginator`` a list/tuple, a Django ``QuerySet``, or - any other object with a ``count()`` or ``__len__()`` method. When - determining the number of objects contained in the passed object, - ``Paginator`` will first try calling ``count()``, then fallback to using - ``len()`` if the passed object has no ``count()`` method. This allows - objects such as Django's ``QuerySet`` to use a more efficient ``count()`` - method when available. - - -Using ``Paginator`` in a view -============================== - -Here's a slightly more complex example using :class:`Paginator` in a view to -paginate a queryset. We give both the view and the accompanying template to -show how you can display the results. This example assumes you have a -``Contacts`` model that has already been imported. - -The view function looks like this:: - - from django.core.paginator import Paginator, InvalidPage, EmptyPage - - def listing(request): - contact_list = Contacts.objects.all() - paginator = Paginator(contact_list, 25) # Show 25 contacts per page - - # Make sure page request is an int. If not, deliver first page. - try: - page = int(request.GET.get('page', '1')) - except ValueError: - page = 1 - - # If page request (9999) is out of range, deliver last page of results. - try: - contacts = paginator.page(page) - except (EmptyPage, InvalidPage): - contacts = paginator.page(paginator.num_pages) - - return render_to_response('list.html', {"contacts": contacts}) - -In the template :file:`list.html`, you'll want to include navigation between -pages along with any interesting information from the objects themselves:: - - {% for contact in contacts.object_list %} - {# Each "contact" is a Contact model object. #} - {{ contact.full_name|upper }}<br /> - ... - {% endfor %} - - <div class="pagination"> - <span class="step-links"> - {% if contacts.has_previous %} - <a href="?page={{ contacts.previous_page_number }}">previous</a> - {% endif %} - - <span class="current"> - Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}. - </span> - - {% if contacts.has_next %} - <a href="?page={{ contacts.next_page_number }}">next</a> - {% endif %} - </span> - </div> - - -``Paginator`` objects -===================== - -The :class:`Paginator` class has this constructor: - -.. class:: Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True) - -Required arguments ------------------- - -``object_list`` - A list, tuple, Django ``QuerySet``, or other sliceable object with a - ``count()`` or ``__len__()`` method. - -``per_page`` - The maximum number of items to include on a page, not including orphans - (see the ``orphans`` optional argument below). - -Optional arguments ------------------- - -``orphans`` - The minimum number of items allowed on the last page, defaults to zero. - Use this when you don't want to have a last page with very few items. - If the last page would normally have a number of items less than or equal - to ``orphans``, then those items will be added to the previous page (which - becomes the last page) instead of leaving the items on a page by - themselves. For example, with 23 items, ``per_page=10``, and - ``orphans=3``, there will be two pages; the first page with 10 items and - the second (and last) page with 13 items. - -``allow_empty_first_page`` - Whether or not the first page is allowed to be empty. If ``False`` and - ``object_list`` is empty, then an ``EmptyPage`` error will be raised. - -Methods -------- - -.. method:: Paginator.page(number) - - Returns a :class:`Page` object with the given 1-based index. Raises - :exc:`InvalidPage` if the given page number doesn't exist. - -Attributes ----------- - -.. attribute:: Paginator.count - - The total number of objects, across all pages. - - .. note:: - - When determining the number of objects contained in ``object_list``, - ``Paginator`` will first try calling ``object_list.count()``. If - ``object_list`` has no ``count()`` method, then ``Paginator`` will - fallback to using ``object_list.__len__()``. This allows objects, such - as Django's ``QuerySet``, to use a more efficient ``count()`` method - when available. - -.. attribute:: Paginator.num_pages - - The total number of pages. - -.. attribute:: Paginator.page_range - - A 1-based range of page numbers, e.g., ``[1, 2, 3, 4]``. - -``InvalidPage`` exceptions -========================== - -The ``page()`` method raises ``InvalidPage`` if the requested page is invalid -(i.e., not an integer) or contains no objects. Generally, it's enough to trap -the ``InvalidPage`` exception, but if you'd like more granularity, you can trap -either of the following exceptions: - -``PageNotAnInteger`` - Raised when ``page()`` is given a value that isn't an integer. - -``EmptyPage`` - Raised when ``page()`` is given a valid value but no objects exist on that - page. - -Both of the exceptions are subclasses of ``InvalidPage``, so you can handle -them both with a simple ``except InvalidPage``. - - -``Page`` objects -================ - -.. class:: Page(object_list, number, paginator) - -You usually won't construct :class:`Pages <Page>` by hand -- you'll get them -using :meth:`Paginator.page`. - - -Methods -------- - -.. method:: Page.has_next() - - Returns ``True`` if there's a next page. - -.. method:: Page.has_previous() - - Returns ``True`` if there's a previous page. - -.. method:: Page.has_other_pages() - - Returns ``True`` if there's a next *or* previous page. - -.. method:: Page.next_page_number() - - Returns the next page number. Note that this is "dumb" and will return the - next page number regardless of whether a subsequent page exists. - -.. method:: Page.previous_page_number() - - Returns the previous page number. Note that this is "dumb" and will return - the previous page number regardless of whether a previous page exists. - -.. method:: Page.start_index() - - Returns the 1-based index of the first object on the page, relative to all - of the objects in the paginator's list. For example, when paginating a list - of 5 objects with 2 objects per page, the second page's :meth:`~Page.start_index` - would return ``3``. - -.. method:: Page.end_index() - - Returns the 1-based index of the last object on the page, relative to all of - the objects in the paginator's list. For example, when paginating a list of - 5 objects with 2 objects per page, the second page's :meth:`~Page.end_index` - would return ``4``. - -Attributes ----------- - -.. attribute:: Page.object_list - - The list of objects on this page. - -.. attribute:: Page.number - - The 1-based page number for this page. - -.. attribute:: Page.paginator - - The associated :class:`Paginator` object. - diff --git a/parts/django/docs/topics/serialization.txt b/parts/django/docs/topics/serialization.txt deleted file mode 100644 index c8acc85..0000000 --- a/parts/django/docs/topics/serialization.txt +++ /dev/null @@ -1,402 +0,0 @@ -========================== -Serializing Django objects -========================== - -Django's serialization framework provides a mechanism for "translating" Django -objects into other formats. Usually these other formats will be text-based and -used for sending Django objects over a wire, but it's possible for a -serializer to handle any format (text-based or not). - -.. seealso:: - - If you just want to get some data from your tables into a serialized - form, you could use the :djadmin:`dumpdata` management command. - -Serializing data ----------------- - -At the highest level, serializing data is a very simple operation:: - - from django.core import serializers - data = serializers.serialize("xml", SomeModel.objects.all()) - -The arguments to the ``serialize`` function are the format to serialize the data -to (see `Serialization formats`_) and a :class:`~django.db.models.QuerySet` to -serialize. (Actually, the second argument can be any iterator that yields Django -objects, but it'll almost always be a QuerySet). - -You can also use a serializer object directly:: - - XMLSerializer = serializers.get_serializer("xml") - xml_serializer = XMLSerializer() - xml_serializer.serialize(queryset) - data = xml_serializer.getvalue() - -This is useful if you want to serialize data directly to a file-like object -(which includes an :class:`~django.http.HttpResponse`):: - - out = open("file.xml", "w") - xml_serializer.serialize(SomeModel.objects.all(), stream=out) - -Subset of fields -~~~~~~~~~~~~~~~~ - -If you only want a subset of fields to be serialized, you can -specify a ``fields`` argument to the serializer:: - - from django.core import serializers - data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size')) - -In this example, only the ``name`` and ``size`` attributes of each model will -be serialized. - -.. note:: - - Depending on your model, you may find that it is not possible to - deserialize a model that only serializes a subset of its fields. If a - serialized object doesn't specify all the fields that are required by a - model, the deserializer will not be able to save deserialized instances. - -Inherited Models -~~~~~~~~~~~~~~~~ - -If you have a model that is defined using an :ref:`abstract base class -<abstract-base-classes>`, you don't have to do anything special to serialize -that model. Just call the serializer on the object (or objects) that you want to -serialize, and the output will be a complete representation of the serialized -object. - -However, if you have a model that uses :ref:`multi-table inheritance -<multi-table-inheritance>`, you also need to serialize all of the base classes -for the model. This is because only the fields that are locally defined on the -model will be serialized. For example, consider the following models:: - - class Place(models.Model): - name = models.CharField(max_length=50) - - class Restaurant(Place): - serves_hot_dogs = models.BooleanField() - -If you only serialize the Restaurant model:: - - data = serializers.serialize('xml', Restaurant.objects.all()) - -the fields on the serialized output will only contain the `serves_hot_dogs` -attribute. The `name` attribute of the base class will be ignored. - -In order to fully serialize your Restaurant instances, you will need to -serialize the Place models as well:: - - all_objects = list(Restaurant.objects.all()) + list(Place.objects.all()) - data = serializers.serialize('xml', all_objects) - -Deserializing data ------------------- - -Deserializing data is also a fairly simple operation:: - - for obj in serializers.deserialize("xml", data): - do_something_with(obj) - -As you can see, the ``deserialize`` function takes the same format argument as -``serialize``, a string or stream of data, and returns an iterator. - -However, here it gets slightly complicated. The objects returned by the -``deserialize`` iterator *aren't* simple Django objects. Instead, they are -special ``DeserializedObject`` instances that wrap a created -- but unsaved -- -object and any associated relationship data. - -Calling ``DeserializedObject.save()`` saves the object to the database. - -This ensures that deserializing is a non-destructive operation even if the -data in your serialized representation doesn't match what's currently in the -database. Usually, working with these ``DeserializedObject`` instances looks -something like:: - - for deserialized_object in serializers.deserialize("xml", data): - if object_should_be_saved(deserialized_object): - deserialized_object.save() - -In other words, the usual use is to examine the deserialized objects to make -sure that they are "appropriate" for saving before doing so. Of course, if you -trust your data source you could just save the object and move on. - -The Django object itself can be inspected as ``deserialized_object.object``. - -.. _serialization-formats: - -Serialization formats ---------------------- - -Django supports a number of serialization formats, some of which require you -to install third-party Python modules: - - ========== ============================================================== - Identifier Information - ========== ============================================================== - ``xml`` Serializes to and from a simple XML dialect. - - ``json`` Serializes to and from JSON_ (using a version of simplejson_ - bundled with Django). - - ``yaml`` Serializes to YAML (YAML Ain't a Markup Language). This - serializer is only available if PyYAML_ is installed. - ========== ============================================================== - -.. _json: http://json.org/ -.. _simplejson: http://undefined.org/python/#simplejson -.. _PyYAML: http://www.pyyaml.org/ - -Notes for specific serialization formats -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -json -^^^^ - -If you're using UTF-8 (or any other non-ASCII encoding) data with the JSON -serializer, you must pass ``ensure_ascii=False`` as a parameter to the -``serialize()`` call. Otherwise, the output won't be encoded correctly. - -For example:: - - json_serializer = serializers.get_serializer("json")() - json_serializer.serialize(queryset, ensure_ascii=False, stream=response) - -The Django source code includes the simplejson_ module. However, if you're -using Python 2.6 or later (which includes a builtin version of the module), Django will -use the builtin ``json`` module automatically. If you have a system installed -version that includes the C-based speedup extension, or your system version is -more recent than the version shipped with Django (currently, 2.0.7), the -system version will be used instead of the version included with Django. - -Be aware that if you're serializing using that module directly, not all Django -output can be passed unmodified to simplejson. In particular, :ref:`lazy -translation objects <lazy-translations>` need a `special encoder`_ written for -them. Something like this will work:: - - from django.utils.functional import Promise - from django.utils.encoding import force_unicode - - class LazyEncoder(simplejson.JSONEncoder): - def default(self, obj): - if isinstance(obj, Promise): - return force_unicode(obj) - return super(LazyEncoder, self).default(obj) - -.. _special encoder: http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.7/docs/index.html - -.. _topics-serialization-natural-keys: - -Natural keys ------------- - -.. versionadded:: 1.2 - - The ability to use natural keys when serializing/deserializing data was - added in the 1.2 release. - -The default serialization strategy for foreign keys and many-to-many -relations is to serialize the value of the primary key(s) of the -objects in the relation. This strategy works well for most types of -object, but it can cause difficulty in some circumstances. - -Consider the case of a list of objects that have foreign key on -:class:`ContentType`. If you're going to serialize an object that -refers to a content type, you need to have a way to refer to that -content type. Content Types are automatically created by Django as -part of the database synchronization process, so you don't need to -include content types in a fixture or other serialized data. As a -result, the primary key of any given content type isn't easy to -predict - it will depend on how and when :djadmin:`syncdb` was -executed to create the content types. - -There is also the matter of convenience. An integer id isn't always -the most convenient way to refer to an object; sometimes, a -more natural reference would be helpful. - -It is for these reasons that Django provides *natural keys*. A natural -key is a tuple of values that can be used to uniquely identify an -object instance without using the primary key value. - -Deserialization of natural keys -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Consider the following two models:: - - from django.db import models - - class Person(models.Model): - first_name = models.CharField(max_length=100) - last_name = models.CharField(max_length=100) - - birthdate = models.DateField() - - class Meta: - unique_together = (('first_name', 'last_name'),) - - class Book(models.Model): - name = models.CharField(max_length=100) - author = models.ForeignKey(Person) - -Ordinarily, serialized data for ``Book`` would use an integer to refer to -the author. For example, in JSON, a Book might be serialized as:: - - ... - { - "pk": 1, - "model": "store.book", - "fields": { - "name": "Mostly Harmless", - "author": 42 - } - } - ... - -This isn't a particularly natural way to refer to an author. It -requires that you know the primary key value for the author; it also -requires that this primary key value is stable and predictable. - -However, if we add natural key handling to Person, the fixture becomes -much more humane. To add natural key handling, you define a default -Manager for Person with a ``get_by_natural_key()`` method. In the case -of a Person, a good natural key might be the pair of first and last -name:: - - from django.db import models - - class PersonManager(models.Manager): - def get_by_natural_key(self, first_name, last_name): - return self.get(first_name=first_name, last_name=last_name) - - class Person(models.Model): - objects = PersonManager() - - first_name = models.CharField(max_length=100) - last_name = models.CharField(max_length=100) - - birthdate = models.DateField() - - class Meta: - unique_together = (('first_name', 'last_name'),) - -Now books can use that natural key to refer to ``Person`` objects:: - - ... - { - "pk": 1, - "model": "store.book", - "fields": { - "name": "Mostly Harmless", - "author": ["Douglas", "Adams"] - } - } - ... - -When you try to load this serialized data, Django will use the -``get_by_natural_key()`` method to resolve ``["Douglas", "Adams"]`` -into the primary key of an actual ``Person`` object. - -.. note:: - - Whatever fields you use for a natural key must be able to uniquely - identify an object. This will usually mean that your model will - have a uniqueness clause (either unique=True on a single field, or - ``unique_together`` over multiple fields) for the field or fields - in your natural key. However, uniqueness doesn't need to be - enforced at the database level. If you are certain that a set of - fields will be effectively unique, you can still use those fields - as a natural key. - -Serialization of natural keys -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -So how do you get Django to emit a natural key when serializing an object? -Firstly, you need to add another method -- this time to the model itself:: - - class Person(models.Model): - objects = PersonManager() - - first_name = models.CharField(max_length=100) - last_name = models.CharField(max_length=100) - - birthdate = models.DateField() - - def natural_key(self): - return (self.first_name, self.last_name) - - class Meta: - unique_together = (('first_name', 'last_name'),) - -That method should always return a natural key tuple -- in this -example, ``(first name, last name)``. Then, when you call -``serializers.serialize()``, you provide a ``use_natural_keys=True`` -argument:: - - >>> serializers.serialize('json', [book1, book2], indent=2, use_natural_keys=True) - -When ``use_natural_keys=True`` is specified, Django will use the -``natural_key()`` method to serialize any reference to objects of the -type that defines the method. - -If you are using :djadmin:`dumpdata` to generate serialized data, you -use the `--natural` command line flag to generate natural keys. - -.. note:: - - You don't need to define both ``natural_key()`` and - ``get_by_natural_key()``. If you don't want Django to output - natural keys during serialization, but you want to retain the - ability to load natural keys, then you can opt to not implement - the ``natural_key()`` method. - - Conversely, if (for some strange reason) you want Django to output - natural keys during serialization, but *not* be able to load those - key values, just don't define the ``get_by_natural_key()`` method. - -Dependencies during serialization -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Since natural keys rely on database lookups to resolve references, it -is important that data exists before it is referenced. You can't make -a `forward reference` with natural keys - the data you are referencing -must exist before you include a natural key reference to that data. - -To accommodate this limitation, calls to :djadmin:`dumpdata` that use -the :djadminopt:`--natural` option will serialize any model with a -``natural_key()`` method before it serializes normal key objects. - -However, this may not always be enough. If your natural key refers to -another object (by using a foreign key or natural key to another object -as part of a natural key), then you need to be able to ensure that -the objects on which a natural key depends occur in the serialized data -before the natural key requires them. - -To control this ordering, you can define dependencies on your -``natural_key()`` methods. You do this by setting a ``dependencies`` -attribute on the ``natural_key()`` method itself. - -For example, consider the ``Permission`` model in ``contrib.auth``. -The following is a simplified version of the ``Permission`` model:: - - class Permission(models.Model): - name = models.CharField(max_length=50) - content_type = models.ForeignKey(ContentType) - codename = models.CharField(max_length=100) - # ... - def natural_key(self): - return (self.codename,) + self.content_type.natural_key() - -The natural key for a ``Permission`` is a combination of the codename for the -``Permission``, and the ``ContentType`` to which the ``Permission`` applies. This means -that ``ContentType`` must be serialized before ``Permission``. To define this -dependency, we add one extra line:: - - class Permission(models.Model): - # ... - def natural_key(self): - return (self.codename,) + self.content_type.natural_key() - natural_key.dependencies = ['contenttypes.contenttype'] - -This definition ensures that ``ContentType`` models are serialized before -``Permission`` models. In turn, any object referencing ``Permission`` will -be serialized after both ``ContentType`` and ``Permission``. diff --git a/parts/django/docs/topics/settings.txt b/parts/django/docs/topics/settings.txt deleted file mode 100644 index 59c02c3..0000000 --- a/parts/django/docs/topics/settings.txt +++ /dev/null @@ -1,255 +0,0 @@ -=============== -Django settings -=============== - -A Django settings file contains all the configuration of your Django -installation. This document explains how settings work and which settings are -available. - -The basics -========== - -A settings file is just a Python module with module-level variables. - -Here are a couple of example settings:: - - DEBUG = False - DEFAULT_FROM_EMAIL = 'webmaster@example.com' - TEMPLATE_DIRS = ('/home/templates/mike', '/home/templates/john') - -Because a settings file is a Python module, the following apply: - - * It doesn't allow for Python syntax errors. - * It can assign settings dynamically using normal Python syntax. - For example:: - - MY_SETTING = [str(i) for i in range(30)] - - * It can import values from other settings files. - -.. _django-settings-module: - -Designating the settings -======================== - -When you use Django, you have to tell it which settings you're using. Do this -by using an environment variable, ``DJANGO_SETTINGS_MODULE``. - -The value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax, e.g. -``mysite.settings``. Note that the settings module should be on the -Python `import search path`_. - -.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html - -The django-admin.py utility ---------------------------- - -When using :doc:`django-admin.py </ref/django-admin>`, you can either set the -environment variable once, or explicitly pass in the settings module each time -you run the utility. - -Example (Unix Bash shell):: - - export DJANGO_SETTINGS_MODULE=mysite.settings - django-admin.py runserver - -Example (Windows shell):: - - set DJANGO_SETTINGS_MODULE=mysite.settings - django-admin.py runserver - -Use the ``--settings`` command-line argument to specify the settings manually:: - - django-admin.py runserver --settings=mysite.settings - -.. _django-admin.py: ../django-admin/ - -On the server (mod_python) --------------------------- - -In your live server environment, you'll need to tell Apache/mod_python which -settings file to use. Do that with ``SetEnv``:: - - <Location "/mysite/"> - SetHandler python-program - PythonHandler django.core.handlers.modpython - SetEnv DJANGO_SETTINGS_MODULE mysite.settings - </Location> - -Read the :doc:`Django mod_python documentation </howto/deployment/modpython>` for -more information. - -Default settings -================ - -A Django settings file doesn't have to define any settings if it doesn't need -to. Each setting has a sensible default value. These defaults live in the -module :file:`django/conf/global_settings.py`. - -Here's the algorithm Django uses in compiling settings: - - * Load settings from ``global_settings.py``. - * Load settings from the specified settings file, overriding the global - settings as necessary. - -Note that a settings file should *not* import from ``global_settings``, because -that's redundant. - -Seeing which settings you've changed ------------------------------------- - -There's an easy way to view which of your settings deviate from the default -settings. The command ``python manage.py diffsettings`` displays differences -between the current settings file and Django's default settings. - -For more, see the :djadmin:`diffsettings` documentation. - -Using settings in Python code -============================= - -In your Django apps, use settings by importing the object -``django.conf.settings``. Example:: - - from django.conf import settings - - if settings.DEBUG: - # Do something - -Note that ``django.conf.settings`` isn't a module -- it's an object. So -importing individual settings is not possible:: - - from django.conf.settings import DEBUG # This won't work. - -Also note that your code should *not* import from either ``global_settings`` or -your own settings file. ``django.conf.settings`` abstracts the concepts of -default settings and site-specific settings; it presents a single interface. -It also decouples the code that uses settings from the location of your -settings. - -Altering settings at runtime -============================ - -You shouldn't alter settings in your applications at runtime. For example, -don't do this in a view:: - - from django.conf import settings - - settings.DEBUG = True # Don't do this! - -The only place you should assign to settings is in a settings file. - -Security -======== - -Because a settings file contains sensitive information, such as the database -password, you should make every attempt to limit access to it. For example, -change its file permissions so that only you and your Web server's user can -read it. This is especially important in a shared-hosting environment. - -Available settings -================== - -For a full list of available settings, see the :doc:`settings reference </ref/settings>`. - -Creating your own settings -========================== - -There's nothing stopping you from creating your own settings, for your own -Django apps. Just follow these conventions: - - * Setting names are in all uppercase. - * Don't reinvent an already-existing setting. - -For settings that are sequences, Django itself uses tuples, rather than lists, -but this is only a convention. - -.. _settings-without-django-settings-module: - -Using settings without setting DJANGO_SETTINGS_MODULE -===================================================== - -In some cases, you might want to bypass the ``DJANGO_SETTINGS_MODULE`` -environment variable. For example, if you're using the template system by -itself, you likely don't want to have to set up an environment variable -pointing to a settings module. - -In these cases, you can configure Django's settings manually. Do this by -calling: - -.. function:: django.conf.settings.configure(default_settings, **settings) - -Example:: - - from django.conf import settings - - settings.configure(DEBUG=True, TEMPLATE_DEBUG=True, - TEMPLATE_DIRS=('/home/web-apps/myapp', '/home/web-apps/base')) - -Pass ``configure()`` as many keyword arguments as you'd like, with each keyword -argument representing a setting and its value. Each argument name should be all -uppercase, with the same name as the settings described above. If a particular -setting is not passed to ``configure()`` and is needed at some later point, -Django will use the default setting value. - -Configuring Django in this fashion is mostly necessary -- and, indeed, -recommended -- when you're using a piece of the framework inside a larger -application. - -Consequently, when configured via ``settings.configure()``, Django will not -make any modifications to the process environment variables (see the -documentation of :setting:`TIME_ZONE` for why this would normally occur). It's -assumed that you're already in full control of your environment in these -cases. - -Custom default settings ------------------------ - -If you'd like default values to come from somewhere other than -``django.conf.global_settings``, you can pass in a module or class that -provides the default settings as the ``default_settings`` argument (or as the -first positional argument) in the call to ``configure()``. - -In this example, default settings are taken from ``myapp_defaults``, and the -``DEBUG`` setting is set to ``True``, regardless of its value in -``myapp_defaults``:: - - from django.conf import settings - from myapp import myapp_defaults - - settings.configure(default_settings=myapp_defaults, DEBUG=True) - -The following example, which uses ``myapp_defaults`` as a positional argument, -is equivalent:: - - settings.configure(myapp_defaults, DEBUG = True) - -Normally, you will not need to override the defaults in this fashion. The -Django defaults are sufficiently tame that you can safely use them. Be aware -that if you do pass in a new default module, it entirely *replaces* the Django -defaults, so you must specify a value for every possible setting that might be -used in that code you are importing. Check in -``django.conf.settings.global_settings`` for the full list. - -Either configure() or DJANGO_SETTINGS_MODULE is required --------------------------------------------------------- - -If you're not setting the ``DJANGO_SETTINGS_MODULE`` environment variable, you -*must* call ``configure()`` at some point before using any code that reads -settings. - -If you don't set ``DJANGO_SETTINGS_MODULE`` and don't call ``configure()``, -Django will raise an ``ImportError`` exception the first time a setting -is accessed. - -If you set ``DJANGO_SETTINGS_MODULE``, access settings values somehow, *then* -call ``configure()``, Django will raise a ``RuntimeError`` indicating -that settings have already been configured. - -Also, it's an error to call ``configure()`` more than once, or to call -``configure()`` after any setting has been accessed. - -It boils down to this: Use exactly one of either ``configure()`` or -``DJANGO_SETTINGS_MODULE``. Not both, and not neither. - -.. _@login_required: ../authentication/#the-login-required-decorator - diff --git a/parts/django/docs/topics/signals.txt b/parts/django/docs/topics/signals.txt deleted file mode 100644 index 35e111d..0000000 --- a/parts/django/docs/topics/signals.txt +++ /dev/null @@ -1,255 +0,0 @@ -======= -Signals -======= - -.. module:: django.dispatch - :synopsis: Signal dispatch - -Django includes a "signal dispatcher" which helps allow decoupled applications -get notified when actions occur elsewhere in the framework. In a nutshell, -signals allow certain *senders* to notify a set of *receivers* that some action -has taken place. They're especially useful when many pieces of code may be -interested in the same events. - -Django provides a :doc:`set of built-in signals </ref/signals>` that let user -code get notified by Django itself of certain actions. These include some useful -notifications: - - * :data:`django.db.models.signals.pre_save` & - :data:`django.db.models.signals.post_save` - - Sent before or after a model's :meth:`~django.db.models.Model.save` method - is called. - - * :data:`django.db.models.signals.pre_delete` & - :data:`django.db.models.signals.post_delete` - - Sent before or after a model's :meth:`~django.db.models.Model.delete` - method is called. - - * :data:`django.db.models.signals.m2m_changed` - - Sent when a :class:`ManyToManyField` on a model is changed. - - * :data:`django.core.signals.request_started` & - :data:`django.core.signals.request_finished` - - Sent when Django starts or finishes an HTTP request. - -See the :doc:`built-in signal documentation </ref/signals>` for a complete list, -and a complete explanation of each signal. - -You can also `define and send your own custom signals`_; see below. - -.. _define and send your own custom signals: `defining and sending signals`_ - -Listening to signals -==================== - -To receive a signal, you need to register a *receiver* function that gets -called when the signal is sent by using the -:meth:`.Signal.connect` method: - -.. method:: Signal.connect(receiver, [sender=None, weak=True, dispatch_uid=None]) - - :param receiver: The callback function which will be connected to this - signal. See :ref:`receiver-functions` for more information. - - :param sender: Specifies a particular sender to receive signals from. See - :ref:`connecting-to-specific-signals` for more information. - - :param weak: Django stores signal handlers as weak references by - default. Thus, if your receiver is a local function, it may be - garbage collected. To prevent this, pass ``weak=False`` when you call - the signal's ``connect()`` method. - - :param dispatch_uid: A unique identifier for a signal receiver in cases - where duplicate signals may be sent. See - :ref:`preventing-duplicate-signals` for more information. - -Let's see how this works by registering a signal that -gets called after each HTTP request is finished. We'll be connecting to the -:data:`~django.core.signals.request_finished` signal. - -.. _receiver-functions: - -Receiver functions ------------------- - -First, we need to define a receiver function. A receiver can be any Python -function or method: - -.. code-block:: python - - def my_callback(sender, **kwargs): - print "Request finished!" - -Notice that the function takes a ``sender`` argument, along with wildcard -keyword arguments (``**kwargs``); all signal handlers must take these arguments. - -We'll look at senders `a bit later`_, but right now look at the ``**kwargs`` -argument. All signals send keyword arguments, and may change those keyword -arguments at any time. In the case of -:data:`~django.core.signals.request_finished`, it's documented as sending no -arguments, which means we might be tempted to write our signal handling as -``my_callback(sender)``. - -.. _a bit later: `connecting to signals sent by specific senders`_ - -This would be wrong -- in fact, Django will throw an error if you do so. That's -because at any point arguments could get added to the signal and your receiver -must be able to handle those new arguments. - -.. _connecting-receiver-functions: - -Connecting receiver functions ------------------------------ - -Next, we'll need to connect our receiver to the signal: - -.. code-block:: python - - from django.core.signals import request_finished - - request_finished.connect(my_callback) - -Now, our ``my_callback`` function will be called each time a request finishes. - -.. admonition:: Where should this code live? - - You can put signal handling and registration code anywhere you like. - However, you'll need to make sure that the module it's in gets imported - early on so that the signal handling gets registered before any signals need - to be sent. This makes your app's ``models.py`` a good place to put - registration of signal handlers. - -.. _connecting-to-specific-signals: - -Connecting to signals sent by specific senders ----------------------------------------------- - -Some signals get sent many times, but you'll only be interested in receiving a -certain subset of those signals. For example, consider the -:data:`django.db.models.signals.pre_save` signal sent before a model gets saved. -Most of the time, you don't need to know when *any* model gets saved -- just -when one *specific* model is saved. - -In these cases, you can register to receive signals sent only by particular -senders. In the case of :data:`django.db.models.signals.pre_save`, the sender -will be the model class being saved, so you can indicate that you only want -signals sent by some model: - -.. code-block:: python - - from django.db.models.signals import pre_save - from myapp.models import MyModel - - def my_handler(sender, **kwargs): - ... - - pre_save.connect(my_handler, sender=MyModel) - -The ``my_handler`` function will only be called when an instance of ``MyModel`` -is saved. - -Different signals use different objects as their senders; you'll need to consult -the :doc:`built-in signal documentation </ref/signals>` for details of each -particular signal. - -.. _preventing-duplicate-signals: - -Preventing duplicate signals ----------------------------- - -In some circumstances, the module in which you are connecting signals may be -imported multiple times. This can cause your receiver function to be -registered more than once, and thus called multiples times for a single signal -event. - -If this behavior is problematic (such as when using signals to -send an e-mail whenever a model is saved), pass a unique identifier as -the ``dispatch_uid`` argument to identify your receiver function. This -identifier will usually be a string, although any hashable object will -suffice. The end result is that your receiver function will only be -bound to the signal once for each unique ``dispatch_uid`` value. - -.. code-block:: python - - from django.core.signals import request_finished - - request_finished.connect(my_callback, dispatch_uid="my_unique_identifier") - -Defining and sending signals -============================ - -Your applications can take advantage of the signal infrastructure and provide -its own signals. - -Defining signals ----------------- - -.. class:: Signal([providing_args=list]) - -All signals are :class:`django.dispatch.Signal` instances. The -``providing_args`` is a list of the names of arguments the signal will provide -to listeners. - -For example: - -.. code-block:: python - - import django.dispatch - - pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) - -This declares a ``pizza_done`` signal that will provide receivers with -``toppings`` and ``size`` arguments. - -Remember that you're allowed to change this list of arguments at any time, so getting the API right on the first try isn't necessary. - -Sending signals ---------------- - -There are two ways to send send signals in Django. - -.. method:: Signal.send(sender, **kwargs) -.. method:: Signal.send_robust(sender, **kwargs) - -To send a signal, call either :meth:`Signal.send` or :meth:`Signal.send_robust`. -You must provide the ``sender`` argument, and may provide as many other keyword -arguments as you like. - -For example, here's how sending our ``pizza_done`` signal might look: - -.. code-block:: python - - class PizzaStore(object): - ... - - def send_pizza(self, toppings, size): - pizza_done.send(sender=self, toppings=toppings, size=size) - ... - -Both ``send()`` and ``send_robust()`` return a list of tuple pairs -``[(receiver, response), ... ]``, representing the list of called receiver -functions and their response values. - -``send()`` differs from ``send_robust()`` in how exceptions raised by receiver -functions are handled. ``send()`` does *not* catch any exceptions raised by -receivers; it simply allows errors to propagate. Thus not all receivers may -be notified of a signal in the face of an error. - -``send_robust()`` catches all errors derived from Python's ``Exception`` class, -and ensures all receivers are notified of the signal. If an error occurs, the -error instance is returned in the tuple pair for the receiver that raised the error. - -Disconnecting signals -===================== - -.. method:: Signal.disconnect([receiver=None, sender=None, weak=True, dispatch_uid=None]) - -To disconnect a receiver from a signal, call :meth:`Signal.disconnect`. The -arguments are as described in :meth:`.Signal.connect`. - -The *receiver* argument indicates the registered receiver to disconnect. It may -be ``None`` if ``dispatch_uid`` is used to identify the receiver. diff --git a/parts/django/docs/topics/templates.txt b/parts/django/docs/topics/templates.txt deleted file mode 100644 index d249bd3..0000000 --- a/parts/django/docs/topics/templates.txt +++ /dev/null @@ -1,617 +0,0 @@ -============================ -The Django template language -============================ - -.. admonition:: About this document - - This document explains the language syntax of the Django template system. If - you're looking for a more technical perspective on how it works and how to - extend it, see :doc:`/ref/templates/api`. - -Django's template language is designed to strike a balance between power and -ease. It's designed to feel comfortable to those used to working with HTML. If -you have any exposure to other text-based template languages, such as Smarty_ -or CheetahTemplate_, you should feel right at home with Django's templates. - -.. admonition:: Philosophy - - If you have a background in programming, or if you're used to languages - like PHP which mix programming code directly into HTML, you'll want to - bear in mind that the Django template system is not simply Python embedded - into HTML. This is by design: the template system is meant to express - presentation, not program logic. - - The Django template system provides tags which function similarly to some - programming constructs -- an :ttag:`if` tag for boolean tests, a :ttag:`for` - tag for looping, etc. -- but these are not simply executed as the - corresponding Python code, and the template system will not execute - arbitrary Python expressions. Only the tags, filters and syntax listed below - are supported by default (although you can add :doc:`your own extensions - </howto/custom-template-tags>` to the template language as needed). - -.. _`The Django template language: For Python programmers`: ../templates_python/ -.. _Smarty: http://smarty.php.net/ -.. _CheetahTemplate: http://www.cheetahtemplate.org/ - -Templates -========= - -.. highlightlang:: html+django - -A template is simply a text file. It can generate any text-based format (HTML, -XML, CSV, etc.). - -A template contains **variables**, which get replaced with values when the -template is evaluated, and **tags**, which control the logic of the template. - -Below is a minimal template that illustrates a few basics. Each element will be -explained later in this document.:: - - {% extends "base_generic.html" %} - - {% block title %}{{ section.title }}{% endblock %} - - {% block content %} - <h1>{{ section.title }}</h1> - - {% for story in story_list %} - <h2> - <a href="{{ story.get_absolute_url }}"> - {{ story.headline|upper }} - </a> - </h2> - <p>{{ story.tease|truncatewords:"100" }}</p> - {% endfor %} - {% endblock %} - -.. admonition:: Philosophy - - Why use a text-based template instead of an XML-based one (like Zope's - TAL)? We wanted Django's template language to be usable for more than - just XML/HTML templates. At World Online, we use it for e-mails, - JavaScript and CSV. You can use the template language for any text-based - format. - - Oh, and one more thing: Making humans edit XML is sadistic! - -Variables -========= - -Variables look like this: ``{{ variable }}``. When the template engine -encounters a variable, it evaluates that variable and replaces it with the -result. - -Use a dot (``.``) to access attributes of a variable. - -.. admonition:: Behind the scenes - - Technically, when the template system encounters a dot, it tries the - following lookups, in this order: - - * Dictionary lookup - * Attribute lookup - * Method call - * List-index lookup - -In the above example, ``{{ section.title }}`` will be replaced with the -``title`` attribute of the ``section`` object. - -If you use a variable that doesn't exist, the template system will insert -the value of the ``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` -(the empty string) by default. - -Filters -======= - -You can modify variables for display by using **filters**. - -Filters look like this: ``{{ name|lower }}``. This displays the value of the -``{{ name }}`` variable after being filtered through the ``lower`` filter, -which converts text to lowercase. Use a pipe (``|``) to apply a filter. - -Filters can be "chained." The output of one filter is applied to the next. -``{{ text|escape|linebreaks }}`` is a common idiom for escaping text contents, -then converting line breaks to ``<p>`` tags. - -Some filters take arguments. A filter argument looks like this: ``{{ -bio|truncatewords:30 }}``. This will display the first 30 words of the ``bio`` -variable. - -Filter arguments that contain spaces must be quoted; for example, to join a list -with commas and spaced you'd use ``{{ list|join:", " }}``. - -Django provides about thirty built-in template filters. You can read all about -them in the :ref:`built-in filter reference <ref-templates-builtins-filters>`. -To give you a taste of what's available, here are some of the more commonly used -template filters: - - :tfilter:`default` - If a variable is false or empty, use given default. Otherwise, use the - value of the variable - - For example:: - - {{ value|default:"nothing" }} - - If ``value`` isn't provided or is empty, the above will display - "``nothing``". - - :tfilter:`length` - Returns the length of the value. This works for both strings and lists; - for example:: - - {{ value|length }} - - If ``value`` is ``['a', 'b', 'c', 'd']``, the output will be ``4``. - - :tfilter:`striptags` - Strips all [X]HTML tags. For example:: - - {{ value|striptags }} - - If ``value`` is ``"<b>Joel</b> <button>is</button> a - <span>slug</span>"``, the output will be ``"Joel is a slug"``. - -Again, these are just a few examples; see the :ref:`built-in filter reference -<ref-templates-builtins-filters>` for the complete list. - -You can also create your own custom template filters; see -:doc:`/howto/custom-template-tags`. - -.. seealso:: - - Django's admin interface can include a complete reference of all template - tags and filters available for a given site. See - :doc:`/ref/contrib/admin/admindocs`. - -Tags -==== - -Tags look like this: ``{% tag %}``. Tags are more complex than variables: Some -create text in the output, some control flow by performing loops or logic, and -some load external information into the template to be used by later variables. - -Some tags require beginning and ending tags (i.e. ``{% tag %} ... tag contents -... {% endtag %}``). - -Django ships with about two dozen built-in template tags. You can read all about -them in the :ref:`built-in tag reference <ref-templates-builtins-tags>`. To give -you a taste of what's available, here are some of the more commonly used -tags: - - :ttag:`for` - Loop over each item in an array. For example, to display a list of athletes - provided in ``athlete_list``:: - - <ul> - {% for athlete in athlete_list %} - <li>{{ athlete.name }}</li> - {% endfor %} - </ul> - - :ttag:`if` and ``else`` - Evaluates a variable, and if that variable is "true" the contents of the - block are displayed:: - - {% if athlete_list %} - Number of athletes: {{ athlete_list|length }} - {% else %} - No athletes. - {% endif %} - - In the above, if ``athlete_list`` is not empty, the number of athletes - will be displayed by the ``{{ athlete_list|length }}`` variable. - - You can also use filters and various operators in the ``if`` tag:: - - {% if athlete_list|length > 1 %} - Team: {% for athlete in athlete_list %} ... {% endfor %} - {% else %} - Athlete: {{ athlete_list.0.name }} - {% endif %} - - :ttag:`block` and :ttag:`extends` - Set up `template inheritance`_ (see below), a powerful way - of cutting down on "boilerplate" in templates. - -Again, the above is only a selection of the whole list; see the :ref:`built-in -tag reference <ref-templates-builtins-tags>` for the complete list. - -You can also create your own custom template tags; see -:doc:`/howto/custom-template-tags`. - -.. seealso:: - - Django's admin interface can include a complete reference of all template - tags and filters available for a given site. See - :doc:`/ref/contrib/admin/admindocs`. - -Comments -======== - -To comment-out part of a line in a template, use the comment syntax: ``{# #}``. - -For example, this template would render as ``'hello'``:: - - {# greeting #}hello - -A comment can contain any template code, invalid or not. For example:: - - {# {% if foo %}bar{% else %} #} - -This syntax can only be used for single-line comments (no newlines are permitted -between the ``{#`` and ``#}`` delimiters). If you need to comment out a -multiline portion of the template, see the :ttag:`comment` tag. - -.. _template-inheritance: - -Template inheritance -==================== - -The most powerful -- and thus the most complex -- part of Django's template -engine is template inheritance. Template inheritance allows you to build a base -"skeleton" template that contains all the common elements of your site and -defines **blocks** that child templates can override. - -It's easiest to understand template inheritance by starting with an example:: - - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - <head> - <link rel="stylesheet" href="style.css" /> - <title>{% block title %}My amazing site{% endblock %}</title> - </head> - - <body> - <div id="sidebar"> - {% block sidebar %} - <ul> - <li><a href="/">Home</a></li> - <li><a href="/blog/">Blog</a></li> - </ul> - {% endblock %} - </div> - - <div id="content"> - {% block content %}{% endblock %} - </div> - </body> - </html> - -This template, which we'll call ``base.html``, defines a simple HTML skeleton -document that you might use for a simple two-column page. It's the job of -"child" templates to fill the empty blocks with content. - -In this example, the ``{% block %}`` tag defines three blocks that child -templates can fill in. All the ``block`` tag does is to tell the template -engine that a child template may override those portions of the template. - -A child template might look like this:: - - {% extends "base.html" %} - - {% block title %}My amazing blog{% endblock %} - - {% block content %} - {% for entry in blog_entries %} - <h2>{{ entry.title }}</h2> - <p>{{ entry.body }}</p> - {% endfor %} - {% endblock %} - -The ``{% extends %}`` tag is the key here. It tells the template engine that -this template "extends" another template. When the template system evaluates -this template, first it locates the parent -- in this case, "base.html". - -At that point, the template engine will notice the three ``{% block %}`` tags -in ``base.html`` and replace those blocks with the contents of the child -template. Depending on the value of ``blog_entries``, the output might look -like:: - - <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - <head> - <link rel="stylesheet" href="style.css" /> - <title>My amazing blog</title> - </head> - - <body> - <div id="sidebar"> - <ul> - <li><a href="/">Home</a></li> - <li><a href="/blog/">Blog</a></li> - </ul> - </div> - - <div id="content"> - <h2>Entry one</h2> - <p>This is my first entry.</p> - - <h2>Entry two</h2> - <p>This is my second entry.</p> - </div> - </body> - </html> - -Note that since the child template didn't define the ``sidebar`` block, the -value from the parent template is used instead. Content within a ``{% block %}`` -tag in a parent template is always used as a fallback. - -You can use as many levels of inheritance as needed. One common way of using -inheritance is the following three-level approach: - - * Create a ``base.html`` template that holds the main look-and-feel of your - site. - * Create a ``base_SECTIONNAME.html`` template for each "section" of your - site. For example, ``base_news.html``, ``base_sports.html``. These - templates all extend ``base.html`` and include section-specific - styles/design. - * Create individual templates for each type of page, such as a news - article or blog entry. These templates extend the appropriate section - template. - -This approach maximizes code reuse and makes it easy to add items to shared -content areas, such as section-wide navigation. - -Here are some tips for working with inheritance: - - * If you use ``{% extends %}`` in a template, it must be the first template - tag in that template. Template inheritance won't work, otherwise. - - * More ``{% block %}`` tags in your base templates are better. Remember, - child templates don't have to define all parent blocks, so you can fill - in reasonable defaults in a number of blocks, then only define the ones - you need later. It's better to have more hooks than fewer hooks. - - * If you find yourself duplicating content in a number of templates, it - probably means you should move that content to a ``{% block %}`` in a - parent template. - - * If you need to get the content of the block from the parent template, - the ``{{ block.super }}`` variable will do the trick. This is useful - if you want to add to the contents of a parent block instead of - completely overriding it. Data inserted using ``{{ block.super }}`` will - not be automatically escaped (see the `next section`_), since it was - already escaped, if necessary, in the parent template. - - * For extra readability, you can optionally give a *name* to your - ``{% endblock %}`` tag. For example:: - - {% block content %} - ... - {% endblock content %} - - In larger templates, this technique helps you see which ``{% block %}`` - tags are being closed. - -Finally, note that you can't define multiple ``{% block %}`` tags with the same -name in the same template. This limitation exists because a block tag works in -"both" directions. That is, a block tag doesn't just provide a hole to fill -- -it also defines the content that fills the hole in the *parent*. If there were -two similarly-named ``{% block %}`` tags in a template, that template's parent -wouldn't know which one of the blocks' content to use. - -.. _next section: #automatic-html-escaping -.. _automatic-html-escaping: - -Automatic HTML escaping -======================= - -.. versionadded:: 1.0 - -When generating HTML from templates, there's always a risk that a variable will -include characters that affect the resulting HTML. For example, consider this -template fragment:: - - Hello, {{ name }}. - -At first, this seems like a harmless way to display a user's name, but consider -what would happen if the user entered his name as this:: - - <script>alert('hello')</script> - -With this name value, the template would be rendered as:: - - Hello, <script>alert('hello')</script> - -...which means the browser would pop-up a JavaScript alert box! - -Similarly, what if the name contained a ``'<'`` symbol, like this? - - <b>username - -That would result in a rendered template like this:: - - Hello, <b>username - -...which, in turn, would result in the remainder of the Web page being bolded! - -Clearly, user-submitted data shouldn't be trusted blindly and inserted directly -into your Web pages, because a malicious user could use this kind of hole to -do potentially bad things. This type of security exploit is called a -`Cross Site Scripting`_ (XSS) attack. - -To avoid this problem, you have two options: - - * One, you can make sure to run each untrusted variable through the - ``escape`` filter (documented below), which converts potentially harmful - HTML characters to unharmful ones. This was the default solution - in Django for its first few years, but the problem is that it puts the - onus on *you*, the developer / template author, to ensure you're escaping - everything. It's easy to forget to escape data. - - * Two, you can take advantage of Django's automatic HTML escaping. The - remainder of this section describes how auto-escaping works. - -By default in Django, every template automatically escapes the output -of every variable tag. Specifically, these five characters are -escaped: - - * ``<`` is converted to ``<`` - * ``>`` is converted to ``>`` - * ``'`` (single quote) is converted to ``'`` - * ``"`` (double quote) is converted to ``"`` - * ``&`` is converted to ``&`` - -Again, we stress that this behavior is on by default. If you're using Django's -template system, you're protected. - -.. _Cross Site Scripting: http://en.wikipedia.org/wiki/Cross-site_scripting - -How to turn it off ------------------- - -If you don't want data to be auto-escaped, on a per-site, per-template level or -per-variable level, you can turn it off in several ways. - -Why would you want to turn it off? Because sometimes, template variables -contain data that you *intend* to be rendered as raw HTML, in which case you -don't want their contents to be escaped. For example, you might store a blob of -HTML in your database and want to embed that directly into your template. Or, -you might be using Django's template system to produce text that is *not* HTML --- like an e-mail message, for instance. - -For individual variables -~~~~~~~~~~~~~~~~~~~~~~~~ - -To disable auto-escaping for an individual variable, use the ``safe`` filter:: - - This will be escaped: {{ data }} - This will not be escaped: {{ data|safe }} - -Think of *safe* as shorthand for *safe from further escaping* or *can be -safely interpreted as HTML*. In this example, if ``data`` contains ``'<b>'``, -the output will be:: - - This will be escaped: <b> - This will not be escaped: <b> - -For template blocks -~~~~~~~~~~~~~~~~~~~ - -To control auto-escaping for a template, wrap the template (or just a -particular section of the template) in the ``autoescape`` tag, like so:: - - {% autoescape off %} - Hello {{ name }} - {% endautoescape %} - -The ``autoescape`` tag takes either ``on`` or ``off`` as its argument. At -times, you might want to force auto-escaping when it would otherwise be -disabled. Here is an example template:: - - Auto-escaping is on by default. Hello {{ name }} - - {% autoescape off %} - This will not be auto-escaped: {{ data }}. - - Nor this: {{ other_data }} - {% autoescape on %} - Auto-escaping applies again: {{ name }} - {% endautoescape %} - {% endautoescape %} - -The auto-escaping tag passes its effect onto templates that extend the -current one as well as templates included via the ``include`` tag, just like -all block tags. For example:: - - # base.html - - {% autoescape off %} - <h1>{% block title %}{% endblock %}</h1> - {% block content %} - {% endblock %} - {% endautoescape %} - - - # child.html - - {% extends "base.html" %} - {% block title %}This & that{% endblock %} - {% block content %}{{ greeting }}{% endblock %} - -Because auto-escaping is turned off in the base template, it will also be -turned off in the child template, resulting in the following rendered -HTML when the ``greeting`` variable contains the string ``<b>Hello!</b>``:: - - <h1>This & that</h1> - <b>Hello!</b> - -Notes ------ - -Generally, template authors don't need to worry about auto-escaping very much. -Developers on the Python side (people writing views and custom filters) need to -think about the cases in which data shouldn't be escaped, and mark data -appropriately, so things Just Work in the template. - -If you're creating a template that might be used in situations where you're -not sure whether auto-escaping is enabled, then add an ``escape`` filter to any -variable that needs escaping. When auto-escaping is on, there's no danger of -the ``escape`` filter *double-escaping* data -- the ``escape`` filter does not -affect auto-escaped variables. - -String literals and automatic escaping --------------------------------------- - -As we mentioned earlier, filter arguments can be strings:: - - {{ data|default:"This is a string literal." }} - -All string literals are inserted **without** any automatic escaping into the -template -- they act as if they were all passed through the ``safe`` filter. -The reasoning behind this is that the template author is in control of what -goes into the string literal, so they can make sure the text is correctly -escaped when the template is written. - -This means you would write :: - - {{ data|default:"3 < 2" }} - -...rather than :: - - {{ data|default:"3 < 2" }} <-- Bad! Don't do this. - -This doesn't affect what happens to data coming from the variable itself. -The variable's contents are still automatically escaped, if necessary, because -they're beyond the control of the template author. - -.. _loading-custom-template-libraries: - -Custom tag and filter libraries -=============================== - -Certain applications provide custom tag and filter libraries. To access them in -a template, use the ``{% load %}`` tag:: - - {% load comments %} - - {% comment_form for blogs.entries entry.id with is_public yes %} - -In the above, the ``load`` tag loads the ``comments`` tag library, which then -makes the ``comment_form`` tag available for use. Consult the documentation -area in your admin to find the list of custom libraries in your installation. - -The ``{% load %}`` tag can take multiple library names, separated by spaces. -Example:: - - {% load comments i18n %} - -See :doc:`/howto/custom-template-tags` for information on writing your own custom -template libraries. - -Custom libraries and template inheritance ------------------------------------------ - -When you load a custom tag or filter library, the tags/filters are only made -available to the current template -- not any parent or child templates along -the template-inheritance path. - -For example, if a template ``foo.html`` has ``{% load comments %}``, a child -template (e.g., one that has ``{% extends "foo.html" %}``) will *not* have -access to the comments template tags and filters. The child template is -responsible for its own ``{% load comments %}``. - -This is a feature for the sake of maintainability and sanity. diff --git a/parts/django/docs/topics/testing.txt b/parts/django/docs/topics/testing.txt deleted file mode 100644 index 155f758..0000000 --- a/parts/django/docs/topics/testing.txt +++ /dev/null @@ -1,1613 +0,0 @@ -=========================== -Testing Django applications -=========================== - -.. module:: django.test - :synopsis: Testing tools for Django applications. - -Automated testing is an extremely useful bug-killing tool for the modern -Web developer. You can use a collection of tests -- a **test suite** -- to -solve, or avoid, a number of problems: - - * When you're writing new code, you can use tests to validate your code - works as expected. - - * When you're refactoring or modifying old code, you can use tests to - ensure your changes haven't affected your application's behavior - unexpectedly. - -Testing a Web application is a complex task, because a Web application is made -of several layers of logic -- from HTTP-level request handling, to form -validation and processing, to template rendering. With Django's test-execution -framework and assorted utilities, you can simulate requests, insert test data, -inspect your application's output and generally verify your code is doing what -it should be doing. - -The best part is, it's really easy. - -This document is split into two primary sections. First, we explain how to -write tests with Django. Then, we explain how to run them. - -Writing tests -============= - -There are two primary ways to write tests with Django, corresponding to the -two test frameworks that ship in the Python standard library. The two -frameworks are: - - * **Doctests** -- tests that are embedded in your functions' docstrings and - are written in a way that emulates a session of the Python interactive - interpreter. For example:: - - def my_func(a_list, idx): - """ - >>> a = ['larry', 'curly', 'moe'] - >>> my_func(a, 0) - 'larry' - >>> my_func(a, 1) - 'curly' - """ - return a_list[idx] - - * **Unit tests** -- tests that are expressed as methods on a Python class - that subclasses ``unittest.TestCase``. For example:: - - import unittest - - class MyFuncTestCase(unittest.TestCase): - def testBasic(self): - a = ['larry', 'curly', 'moe'] - self.assertEquals(my_func(a, 0), 'larry') - self.assertEquals(my_func(a, 1), 'curly') - -You can choose the test framework you like, depending on which syntax you -prefer, or you can mix and match, using one framework for some of your code and -the other framework for other code. You can also use any *other* Python test -frameworks, as we'll explain in a bit. - -Writing doctests ----------------- - -Doctests use Python's standard doctest_ module, which searches your docstrings -for statements that resemble a session of the Python interactive interpreter. -A full explanation of how doctest works is out of the scope of this document; -read Python's official documentation for the details. - -.. admonition:: What's a **docstring**? - - A good explanation of docstrings (and some guidelines for using them - effectively) can be found in :pep:`257`: - - A docstring is a string literal that occurs as the first statement in - a module, function, class, or method definition. Such a docstring - becomes the ``__doc__`` special attribute of that object. - - For example, this function has a docstring that describes what it does:: - - def add_two(num): - "Return the result of adding two to the provided number." - return num + 2 - - Because tests often make great documentation, putting tests directly in - your docstrings is an effective way to document *and* test your code. - -For a given Django application, the test runner looks for doctests in two -places: - - * The ``models.py`` file. You can define module-level doctests and/or a - doctest for individual models. It's common practice to put - application-level doctests in the module docstring and model-level - doctests in the model docstrings. - - * A file called ``tests.py`` in the application directory -- i.e., the - directory that holds ``models.py``. This file is a hook for any and all - doctests you want to write that aren't necessarily related to models. - -Here is an example model doctest:: - - # models.py - - from django.db import models - - class Animal(models.Model): - """ - An animal that knows how to make noise - - # Create some animals - >>> lion = Animal.objects.create(name="lion", sound="roar") - >>> cat = Animal.objects.create(name="cat", sound="meow") - - # Make 'em speak - >>> lion.speak() - 'The lion says "roar"' - >>> cat.speak() - 'The cat says "meow"' - """ - name = models.CharField(max_length=20) - sound = models.CharField(max_length=20) - - def speak(self): - return 'The %s says "%s"' % (self.name, self.sound) - -When you :ref:`run your tests <running-tests>`, the test runner will find this -docstring, notice that portions of it look like an interactive Python session, -and execute those lines while checking that the results match. - -In the case of model tests, note that the test runner takes care of creating -its own test database. That is, any test that accesses a database -- by -creating and saving model instances, for example -- will not affect your -production database. However, the database is not refreshed between doctests, -so if your doctest requires a certain state you should consider flushing the -database or loading a fixture. (See the section on fixtures, below, for more -on this.) Note that to use this feature, the database user Django is connecting -as must have ``CREATE DATABASE`` rights. - -For more details about how doctest works, see the `standard library -documentation for doctest`_. - -.. _doctest: http://docs.python.org/library/doctest.html -.. _standard library documentation for doctest: doctest_ - -Writing unit tests ------------------- - -Like doctests, Django's unit tests use a standard library module: unittest_. -This module uses a different way of defining tests, taking a class-based -approach. - -As with doctests, for a given Django application, the test runner looks for -unit tests in two places: - - * The ``models.py`` file. The test runner looks for any subclass of - ``unittest.TestCase`` in this module. - - * A file called ``tests.py`` in the application directory -- i.e., the - directory that holds ``models.py``. Again, the test runner looks for any - subclass of ``unittest.TestCase`` in this module. - -This example ``unittest.TestCase`` subclass is equivalent to the example given -in the doctest section above:: - - import unittest - from myapp.models import Animal - - class AnimalTestCase(unittest.TestCase): - def setUp(self): - self.lion = Animal.objects.create(name="lion", sound="roar") - self.cat = Animal.objects.create(name="cat", sound="meow") - - def testSpeaking(self): - self.assertEquals(self.lion.speak(), 'The lion says "roar"') - self.assertEquals(self.cat.speak(), 'The cat says "meow"') - -When you :ref:`run your tests <running-tests>`, the default behavior of the -test utility is to find all the test cases (that is, subclasses of -``unittest.TestCase``) in ``models.py`` and ``tests.py``, automatically build a -test suite out of those test cases, and run that suite. - -There is a second way to define the test suite for a module: if you define a -function called ``suite()`` in either ``models.py`` or ``tests.py``, the -Django test runner will use that function to construct the test suite for that -module. This follows the `suggested organization`_ for unit tests. See the -Python documentation for more details on how to construct a complex test -suite. - -For more details about ``unittest``, see the `standard library unittest -documentation`_. - -.. _unittest: http://docs.python.org/library/unittest.html -.. _standard library unittest documentation: unittest_ -.. _suggested organization: http://docs.python.org/library/unittest.html#organizing-tests - -Which should I use? -------------------- - -Because Django supports both of the standard Python test frameworks, it's up to -you and your tastes to decide which one to use. You can even decide to use -*both*. - -For developers new to testing, however, this choice can seem confusing. Here, -then, are a few key differences to help you decide which approach is right for -you: - - * If you've been using Python for a while, ``doctest`` will probably feel - more "pythonic". It's designed to make writing tests as easy as possible, - so it requires no overhead of writing classes or methods. You simply put - tests in docstrings. This has the added advantage of serving as - documentation (and correct documentation, at that!). - - If you're just getting started with testing, using doctests will probably - get you started faster. - - * The ``unittest`` framework will probably feel very familiar to developers - coming from Java. ``unittest`` is inspired by Java's JUnit, so you'll - feel at home with this method if you've used JUnit or any test framework - inspired by JUnit. - - * If you need to write a bunch of tests that share similar code, then - you'll appreciate the ``unittest`` framework's organization around - classes and methods. This makes it easy to abstract common tasks into - common methods. The framework also supports explicit setup and/or cleanup - routines, which give you a high level of control over the environment - in which your test cases are run. - -Again, remember that you can use both systems side-by-side (even in the same -app). In the end, most projects will eventually end up using both. Each shines -in different circumstances. - -.. _running-tests: - -Running tests -============= - -Once you've written tests, run them using the :djadmin:`test` command of -your project's ``manage.py`` utility:: - - $ ./manage.py test - -By default, this will run every test in every application in -:setting:`INSTALLED_APPS`. If you only want to run tests for a particular -application, add the application name to the command line. For example, if your -:setting:`INSTALLED_APPS` contains ``'myproject.polls'`` and -``'myproject.animals'``, you can run the ``myproject.animals`` unit tests alone -with this command:: - - $ ./manage.py test animals - -Note that we used ``animals``, not ``myproject.animals``. - -.. versionadded:: 1.0 - You can now choose which test to run. - -You can be even *more* specific by naming an individual test case. To -run a single test case in an application (for example, the -``AnimalTestCase`` described in the "Writing unit tests" section), add -the name of the test case to the label on the command line:: - - $ ./manage.py test animals.AnimalTestCase - -And it gets even more granular than that! To run a *single* test -method inside a test case, add the name of the test method to the -label:: - - $ ./manage.py test animals.AnimalTestCase.testFluffyAnimals - -.. versionadded:: 1.2 - The ability to select individual doctests was added. - -You can use the same rules if you're using doctests. Django will use the -test label as a path to the test method or class that you want to run. -If your ``models.py`` or ``tests.py`` has a function with a doctest, or -class with a class-level doctest, you can invoke that test by appending the -name of the test method or class to the label:: - - $ ./manage.py test animals.classify - -If you want to run the doctest for a specific method in a class, add the -name of the method to the label:: - - $ ./manage.py test animals.Classifier.run - -If you're using a ``__test__`` dictionary to specify doctests for a -module, Django will use the label as a key in the ``__test__`` dictionary -for defined in ``models.py`` and ``tests.py``. - -.. versionadded:: 1.2 - You can now trigger a graceful exit from a test run by pressing ``Ctrl-C``. - -If you press ``Ctrl-C`` while the tests are running, the test runner will -wait for the currently running test to complete and then exit gracefully. -During a graceful exit the test runner will output details of any test -failures, report on how many tests were run and how many errors and failures -were encountered, and destroy any test databases as usual. Thus pressing -``Ctrl-C`` can be very useful if you forget to pass the :djadminopt:`--failfast` -option, notice that some tests are unexpectedly failing, and want to get details -on the failures without waiting for the full test run to complete. - -If you do not want to wait for the currently running test to finish, you -can press ``Ctrl-C`` a second time and the test run will halt immediately, -but not gracefully. No details of the tests run before the interruption will -be reported, and any test databases created by the run will not be destroyed. - -.. admonition:: Test with warnings enabled - - It is a good idea to run your tests with ``python -Wall manage.py - test``. This will allow you to catch any deprecation warnings that - might be in your code. Django (as well as many other libraries) use - warnings to flag when features are deprecated. It can also flag - areas in your code that are not strictly wrong, but may benefit - from a better implementation. - -Running tests outside the test runner -------------------------------------- - -If you want to run tests outside of ``./manage.py test`` -- for example, -from a shell prompt -- you will need to set up the test -environment first. Django provides a convenience method to do this:: - - >>> from django.test.utils import setup_test_environment - >>> setup_test_environment() - -This convenience method sets up the test database, and puts other -Django features into modes that allow for repeatable testing. - -The call to :meth:`~django.test.utils.setup_test_environment` is made -automatically as part of the setup of `./manage.py test`. You only -need to manually invoke this method if you're not using running your -tests via Django's test runner. - -The test database ------------------ - -Tests that require a database (namely, model tests) will not use your "real" -(production) database. Separate, blank databases are created for the tests. - -Regardless of whether the tests pass or fail, the test databases are destroyed -when all the tests have been executed. - -By default the test databases get their names by prepending ``test_`` -to the value of the :setting:`NAME` settings for the databases -defined in :setting:`DATABASES`. When using the SQLite database engine -the tests will by default use an in-memory database (i.e., the -database will be created in memory, bypassing the filesystem -entirely!). If you want to use a different database name, specify -:setting:`TEST_NAME` in the dictionary for any given database in -:setting:`DATABASES`. - -Aside from using a separate database, the test runner will otherwise -use all of the same database settings you have in your settings file: -:setting:`ENGINE`, :setting:`USER`, :setting:`HOST`, etc. The test -database is created by the user specified by ``USER``, so you'll need -to make sure that the given user account has sufficient privileges to -create a new database on the system. - -.. versionadded:: 1.0 - -For fine-grained control over the character encoding of your test -database, use the :setting:`TEST_CHARSET` option. If you're using -MySQL, you can also use the :setting:`TEST_COLLATION` option to -control the particular collation used by the test database. See the -:doc:`settings documentation </ref/settings>` for details of these -advanced settings. - -.. _topics-testing-masterslave: - -Testing master/slave configurations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2 - -If you're testing a multiple database configuration with master/slave -replication, this strategy of creating test databases poses a problem. -When the test databases are created, there won't be any replication, -and as a result, data created on the master won't be seen on the -slave. - -To compensate for this, Django allows you to define that a database is -a *test mirror*. Consider the following (simplified) example database -configuration:: - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': 'myproject', - 'HOST': 'dbmaster', - # ... plus some other settings - }, - 'slave': { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': 'myproject', - 'HOST': 'dbslave', - 'TEST_MIRROR': 'default' - # ... plus some other settings - } - } - -In this setup, we have two database servers: ``dbmaster``, described -by the database alias ``default``, and ``dbslave`` described by the -alias ``slave``. As you might expect, ``dbslave`` has been configured -by the database administrator as a read slave of ``dbmaster``, so in -normal activity, any write to ``default`` will appear on ``slave``. - -If Django created two independent test databases, this would break any -tests that expected replication to occur. However, the ``slave`` -database has been configured as a test mirror (using the -:setting:`TEST_MIRROR` setting), indicating that under testing, -``slave`` should be treated as a mirror of ``default``. - -When the test environment is configured, a test version of ``slave`` -will *not* be created. Instead the connection to ``slave`` -will be redirected to point at ``default``. As a result, writes to -``default`` will appear on ``slave`` -- but because they are actually -the same database, not because there is data replication between the -two databases. - -.. _topics-testing-creation-dependencies: - -Controlling creation order for test databases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.2.4 - -By default, Django will always create the ``default`` database first. -However, no guarantees are made on the creation order of any other -databases in your test setup. - -If your database configuration requires a specific creation order, you -can specify the dependencies that exist using the -:setting:`TEST_DEPENDENCIES` setting. Consider the following -(simplified) example database configuration:: - - DATABASES = { - 'default': { - # ... db settings - 'TEST_DEPENDENCIES': ['diamonds'] - }, - 'diamonds': { - # ... db settings - }, - 'clubs': { - # ... db settings - 'TEST_DEPENDENCIES': ['diamonds'] - }, - 'spades': { - # ... db settings - 'TEST_DEPENDENCIES': ['diamonds','hearts'] - }, - 'hearts': { - # ... db settings - 'TEST_DEPENDENCIES': ['diamonds','clubs'] - } - } - -Under this configuration, the ``diamonds`` database will be created first, -as it is the only database alias without dependencies. The ``default``` and -``clubs`` alias will be created next (although the order of creation of this -pair is not guaranteed); then ``hearts``; and finally ``spades``. - -If there are any circular dependencies in the -:setting:`TEST_DEPENDENCIES` definition, an ``ImproperlyConfigured`` -exception will be raised. - -Other test conditions ---------------------- - -Regardless of the value of the :setting:`DEBUG` setting in your configuration -file, all Django tests run with :setting:`DEBUG`\=False. This is to ensure that -the observed output of your code matches what will be seen in a production -setting. - -Understanding the test output ------------------------------ - -When you run your tests, you'll see a number of messages as the test runner -prepares itself. You can control the level of detail of these messages with the -``verbosity`` option on the command line:: - - Creating test database... - Creating table myapp_animal - Creating table myapp_mineral - Loading 'initial_data' fixtures... - No fixtures found. - -This tells you that the test runner is creating a test database, as described -in the previous section. - -Once the test database has been created, Django will run your tests. -If everything goes well, you'll see something like this:: - - ---------------------------------------------------------------------- - Ran 22 tests in 0.221s - - OK - -If there are test failures, however, you'll see full details about which tests -failed:: - - ====================================================================== - FAIL: Doctest: ellington.core.throttle.models - ---------------------------------------------------------------------- - Traceback (most recent call last): - File "/dev/django/test/doctest.py", line 2153, in runTest - raise self.failureException(self.format_failure(new.getvalue())) - AssertionError: Failed doctest test for myapp.models - File "/dev/myapp/models.py", line 0, in models - - ---------------------------------------------------------------------- - File "/dev/myapp/models.py", line 14, in myapp.models - Failed example: - throttle.check("actor A", "action one", limit=2, hours=1) - Expected: - True - Got: - False - - ---------------------------------------------------------------------- - Ran 2 tests in 0.048s - - FAILED (failures=1) - -A full explanation of this error output is beyond the scope of this document, -but it's pretty intuitive. You can consult the documentation of Python's -``unittest`` library for details. - -Note that the return code for the test-runner script is the total number of -failed and erroneous tests. If all the tests pass, the return code is 0. This -feature is useful if you're using the test-runner script in a shell script and -need to test for success or failure at that level. - -Testing tools -============= - -Django provides a small set of tools that come in handy when writing tests. - -The test client ---------------- - -.. module:: django.test.client - :synopsis: Django's test client. - -The test client is a Python class that acts as a dummy Web browser, allowing -you to test your views and interact with your Django-powered application -programmatically. - -Some of the things you can do with the test client are: - - * Simulate GET and POST requests on a URL and observe the response -- - everything from low-level HTTP (result headers and status codes) to - page content. - - * Test that the correct view is executed for a given URL. - - * Test that a given request is rendered by a given Django template, with - a template context that contains certain values. - -Note that the test client is not intended to be a replacement for Twill_, -Selenium_, or other "in-browser" frameworks. Django's test client has -a different focus. In short: - - * Use Django's test client to establish that the correct view is being - called and that the view is collecting the correct context data. - - * Use in-browser frameworks such as Twill and Selenium to test *rendered* - HTML and the *behavior* of Web pages, namely JavaScript functionality. - -A comprehensive test suite should use a combination of both test types. - -.. _Twill: http://twill.idyll.org/ -.. _Selenium: http://seleniumhq.org/ - -Overview and a quick example -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To use the test client, instantiate ``django.test.client.Client`` and retrieve -Web pages:: - - >>> from django.test.client import Client - >>> c = Client() - >>> response = c.post('/login/', {'username': 'john', 'password': 'smith'}) - >>> response.status_code - 200 - >>> response = c.get('/customer/details/') - >>> response.content - '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...' - -As this example suggests, you can instantiate ``Client`` from within a session -of the Python interactive interpreter. - -Note a few important things about how the test client works: - - * The test client does *not* require the Web server to be running. In fact, - it will run just fine with no Web server running at all! That's because - it avoids the overhead of HTTP and deals directly with the Django - framework. This helps make the unit tests run quickly. - - * When retrieving pages, remember to specify the *path* of the URL, not the - whole domain. For example, this is correct:: - - >>> c.get('/login/') - - This is incorrect:: - - >>> c.get('http://www.example.com/login/') - - The test client is not capable of retrieving Web pages that are not - powered by your Django project. If you need to retrieve other Web pages, - use a Python standard library module such as urllib_ or urllib2_. - - * To resolve URLs, the test client uses whatever URLconf is pointed-to by - your :setting:`ROOT_URLCONF` setting. - - * Although the above example would work in the Python interactive - interpreter, some of the test client's functionality, notably the - template-related functionality, is only available *while tests are - running*. - - The reason for this is that Django's test runner performs a bit of black - magic in order to determine which template was loaded by a given view. - This black magic (essentially a patching of Django's template system in - memory) only happens during test running. - - * By default, the test client will disable any CSRF checks - performed by your site. - - .. versionadded:: 1.2.2 - - If, for some reason, you *want* the test client to perform CSRF - checks, you can create an instance of the test client that - enforces CSRF checks. To do this, pass in the - ``enforce_csrf_checks`` argument when you construct your - client:: - - >>> from django.test import Client - >>> csrf_client = Client(enforce_csrf_checks=True) - - -.. _urllib: http://docs.python.org/library/urllib.html -.. _urllib2: http://docs.python.org/library/urllib2.html - -Making requests -~~~~~~~~~~~~~~~ - -Use the ``django.test.client.Client`` class to make requests. It requires no -arguments at time of construction: - -.. class:: Client() - - Once you have a ``Client`` instance, you can call any of the following - methods: - - .. method:: Client.get(path, data={}, follow=False, **extra) - - - Makes a GET request on the provided ``path`` and returns a ``Response`` - object, which is documented below. - - The key-value pairs in the ``data`` dictionary are used to create a GET - data payload. For example:: - - >>> c = Client() - >>> c.get('/customers/details/', {'name': 'fred', 'age': 7}) - - ...will result in the evaluation of a GET request equivalent to:: - - /customers/details/?name=fred&age=7 - - The ``extra`` keyword arguments parameter can be used to specify - headers to be sent in the request. For example:: - - >>> c = Client() - >>> c.get('/customers/details/', {'name': 'fred', 'age': 7}, - ... HTTP_X_REQUESTED_WITH='XMLHttpRequest') - - ...will send the HTTP header ``HTTP_X_REQUESTED_WITH`` to the - details view, which is a good way to test code paths that use the - :meth:`django.http.HttpRequest.is_ajax()` method. - - .. versionadded:: 1.1 - - If you already have the GET arguments in URL-encoded form, you can - use that encoding instead of using the data argument. For example, - the previous GET request could also be posed as:: - - >>> c = Client() - >>> c.get('/customers/details/?name=fred&age=7') - - If you provide a URL with both an encoded GET data and a data argument, - the data argument will take precedence. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - If you had an url ``/redirect_me/`` that redirected to ``/next/``, that - redirected to ``/final/``, this is what you'd see:: - - >>> response = c.get('/redirect_me/', follow=True) - >>> response.redirect_chain - [(u'http://testserver/next/', 302), (u'http://testserver/final/', 302)] - - .. method:: Client.post(path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra) - - Makes a POST request on the provided ``path`` and returns a - ``Response`` object, which is documented below. - - The key-value pairs in the ``data`` dictionary are used to submit POST - data. For example:: - - >>> c = Client() - >>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'}) - - ...will result in the evaluation of a POST request to this URL:: - - /login/ - - ...with this POST data:: - - name=fred&passwd=secret - - If you provide ``content_type`` (e.g., ``text/xml`` for an XML - payload), the contents of ``data`` will be sent as-is in the POST - request, using ``content_type`` in the HTTP ``Content-Type`` header. - - If you don't provide a value for ``content_type``, the values in - ``data`` will be transmitted with a content type of - ``multipart/form-data``. In this case, the key-value pairs in ``data`` - will be encoded as a multipart message and used to create the POST data - payload. - - To submit multiple values for a given key -- for example, to specify - the selections for a ``<select multiple>`` -- provide the values as a - list or tuple for the required key. For example, this value of ``data`` - would submit three selected values for the field named ``choices``:: - - {'choices': ('a', 'b', 'd')} - - Submitting files is a special case. To POST a file, you need only - provide the file field name as a key, and a file handle to the file you - wish to upload as a value. For example:: - - >>> c = Client() - >>> f = open('wishlist.doc') - >>> c.post('/customers/wishes/', {'name': 'fred', 'attachment': f}) - >>> f.close() - - (The name ``attachment`` here is not relevant; use whatever name your - file-processing code expects.) - - Note that if you wish to use the same file handle for multiple - ``post()`` calls then you will need to manually reset the file - pointer between posts. The easiest way to do this is to - manually close the file after it has been provided to - ``post()``, as demonstrated above. - - You should also ensure that the file is opened in a way that - allows the data to be read. If your file contains binary data - such as an image, this means you will need to open the file in - ``rb`` (read binary) mode. - - The ``extra`` argument acts the same as for :meth:`Client.get`. - - .. versionchanged:: 1.1 - - If the URL you request with a POST contains encoded parameters, these - parameters will be made available in the request.GET data. For example, - if you were to make the request:: - - >>> c.post('/login/?visitor=true', {'name': 'fred', 'passwd': 'secret'}) - - ... the view handling this request could interrogate request.POST - to retrieve the username and password, and could interrogate request.GET - to determine if the user was a visitor. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - .. method:: Client.head(path, data={}, follow=False, **extra) - - .. versionadded:: 1.1 - - Makes a HEAD request on the provided ``path`` and returns a ``Response`` - object. Useful for testing RESTful interfaces. Acts just like - :meth:`Client.get` except it does not return a message body. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - .. method:: Client.options(path, data={}, follow=False, **extra) - - .. versionadded:: 1.1 - - Makes an OPTIONS request on the provided ``path`` and returns a - ``Response`` object. Useful for testing RESTful interfaces. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - The ``extra`` argument acts the same as for :meth:`Client.get`. - - .. method:: Client.put(path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra) - - .. versionadded:: 1.1 - - Makes a PUT request on the provided ``path`` and returns a - ``Response`` object. Useful for testing RESTful interfaces. Acts just - like :meth:`Client.post` except with the PUT request method. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - .. method:: Client.delete(path, follow=False, **extra) - - .. versionadded:: 1.1 - - Makes an DELETE request on the provided ``path`` and returns a - ``Response`` object. Useful for testing RESTful interfaces. - - If you set ``follow`` to ``True`` the client will follow any redirects - and a ``redirect_chain`` attribute will be set in the response object - containing tuples of the intermediate urls and status codes. - - The ``extra`` argument acts the same as for :meth:`Client.get`. - - .. method:: Client.login(**credentials) - - .. versionadded:: 1.0 - - If your site uses Django's :doc:`authentication system</topics/auth>` - and you deal with logging in users, you can use the test client's - ``login()`` method to simulate the effect of a user logging into the - site. - - After you call this method, the test client will have all the cookies - and session data required to pass any login-based tests that may form - part of a view. - - The format of the ``credentials`` argument depends on which - :ref:`authentication backend <authentication-backends>` you're using - (which is configured by your :setting:`AUTHENTICATION_BACKENDS` - setting). If you're using the standard authentication backend provided - by Django (``ModelBackend``), ``credentials`` should be the user's - username and password, provided as keyword arguments:: - - >>> c = Client() - >>> c.login(username='fred', password='secret') - - # Now you can access a view that's only available to logged-in users. - - If you're using a different authentication backend, this method may - require different credentials. It requires whichever credentials are - required by your backend's ``authenticate()`` method. - - ``login()`` returns ``True`` if it the credentials were accepted and - login was successful. - - Finally, you'll need to remember to create user accounts before you can - use this method. As we explained above, the test runner is executed - using a test database, which contains no users by default. As a result, - user accounts that are valid on your production site will not work - under test conditions. You'll need to create users as part of the test - suite -- either manually (using the Django model API) or with a test - fixture. Remember that if you want your test user to have a password, - you can't set the user's password by setting the password attribute - directly -- you must use the - :meth:`~django.contrib.auth.models.User.set_password()` function to - store a correctly hashed password. Alternatively, you can use the - :meth:`~django.contrib.auth.models.UserManager.create_user` helper - method to create a new user with a correctly hashed password. - - .. method:: Client.logout() - - .. versionadded:: 1.0 - - If your site uses Django's :doc:`authentication system</topics/auth>`, - the ``logout()`` method can be used to simulate the effect of a user - logging out of your site. - - After you call this method, the test client will have all the cookies - and session data cleared to defaults. Subsequent requests will appear - to come from an AnonymousUser. - -Testing responses -~~~~~~~~~~~~~~~~~ - -The ``get()`` and ``post()`` methods both return a ``Response`` object. This -``Response`` object is *not* the same as the ``HttpResponse`` object returned -Django views; the test response object has some additional data useful for -test code to verify. - -Specifically, a ``Response`` object has the following attributes: - -.. class:: Response() - - .. attribute:: client - - The test client that was used to make the request that resulted in the - response. - - .. attribute:: content - - The body of the response, as a string. This is the final page content as - rendered by the view, or any error message. - - .. attribute:: context - - The template ``Context`` instance that was used to render the template that - produced the response content. - - If the rendered page used multiple templates, then ``context`` will be a - list of ``Context`` objects, in the order in which they were rendered. - - .. versionadded:: 1.1 - - Regardless of the number of templates used during rendering, you can - retrieve context values using the ``[]`` operator. For example, the - context variable ``name`` could be retrieved using:: - - >>> response = client.get('/foo/') - >>> response.context['name'] - 'Arthur' - - .. attribute:: request - - The request data that stimulated the response. - - .. attribute:: status_code - - The HTTP status of the response, as an integer. See RFC2616_ for a full - list of HTTP status codes. - - .. attribute:: template - - The ``Template`` instance that was used to render the final content. Use - ``template.name`` to get the template's file name, if the template was - loaded from a file. (The name is a string such as ``'admin/index.html'``.) - - If the rendered page used multiple templates -- e.g., using :ref:`template - inheritance<template-inheritance>` -- then ``template`` will be a list of - ``Template`` instances, in the order in which they were rendered. - -You can also use dictionary syntax on the response object to query the value -of any settings in the HTTP headers. For example, you could determine the -content type of a response using ``response['Content-Type']``. - -.. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - -Exceptions -~~~~~~~~~~ - -If you point the test client at a view that raises an exception, that exception -will be visible in the test case. You can then use a standard ``try...except`` -block or ``unittest.TestCase.assertRaises()`` to test for exceptions. - -The only exceptions that are not visible to the test client are ``Http404``, -``PermissionDenied`` and ``SystemExit``. Django catches these exceptions -internally and converts them into the appropriate HTTP response codes. In these -cases, you can check ``response.status_code`` in your test. - -Persistent state -~~~~~~~~~~~~~~~~ - -The test client is stateful. If a response returns a cookie, then that cookie -will be stored in the test client and sent with all subsequent ``get()`` and -``post()`` requests. - -Expiration policies for these cookies are not followed. If you want a cookie -to expire, either delete it manually or create a new ``Client`` instance (which -will effectively delete all cookies). - -A test client has two attributes that store persistent state information. You -can access these properties as part of a test condition. - -.. attribute:: Client.cookies - - A Python ``SimpleCookie`` object, containing the current values of all the - client cookies. See the `Cookie module documentation`_ for more. - -.. attribute:: Client.session - - A dictionary-like object containing session information. See the - :doc:`session documentation</topics/http/sessions>` for full details. - - To modify the session and then save it, it must be stored in a variable - first (because a new ``SessionStore`` is created every time this property - is accessed):: - - def test_something(self): - session = self.client.session - session['somekey'] = 'test' - session.save() - -.. _Cookie module documentation: http://docs.python.org/library/cookie.html - -Example -~~~~~~~ - -The following is a simple unit test using the test client:: - - import unittest - from django.test.client import Client - - class SimpleTest(unittest.TestCase): - def setUp(self): - # Every test needs a client. - self.client = Client() - - def test_details(self): - # Issue a GET request. - response = self.client.get('/customer/details/') - - # Check that the response is 200 OK. - self.failUnlessEqual(response.status_code, 200) - - # Check that the rendered context contains 5 customers. - self.failUnlessEqual(len(response.context['customers']), 5) - -TestCase --------- - -.. currentmodule:: django.test - -Normal Python unit test classes extend a base class of ``unittest.TestCase``. -Django provides an extension of this base class: - -.. class:: TestCase() - -This class provides some additional capabilities that can be useful for testing -Web sites. - -Converting a normal ``unittest.TestCase`` to a Django ``TestCase`` is easy: -just change the base class of your test from ``unittest.TestCase`` to -``django.test.TestCase``. All of the standard Python unit test functionality -will continue to be available, but it will be augmented with some useful -additions. - -.. versionadded:: 1.1 - -.. class:: TransactionTestCase() - -Django ``TestCase`` classes make use of database transaction facilities, if -available, to speed up the process of resetting the database to a known state -at the beginning of each test. A consequence of this, however, is that the -effects of transaction commit and rollback cannot be tested by a Django -``TestCase`` class. If your test requires testing of such transactional -behavior, you should use a Django ``TransactionTestCase``. - -``TransactionTestCase`` and ``TestCase`` are identical except for the manner -in which the database is reset to a known state and the ability for test code -to test the effects of commit and rollback. A ``TransactionTestCase`` resets -the database before the test runs by truncating all tables and reloading -initial data. A ``TransactionTestCase`` may call commit and rollback and -observe the effects of these calls on the database. - -A ``TestCase``, on the other hand, does not truncate tables and reload initial -data at the beginning of a test. Instead, it encloses the test code in a -database transaction that is rolled back at the end of the test. It also -prevents the code under test from issuing any commit or rollback operations -on the database, to ensure that the rollback at the end of the test restores -the database to its initial state. In order to guarantee that all ``TestCase`` -code starts with a clean database, the Django test runner runs all ``TestCase`` -tests first, before any other tests (e.g. doctests) that may alter the -database without restoring it to its original state. - -When running on a database that does not support rollback (e.g. MySQL with the -MyISAM storage engine), ``TestCase`` falls back to initializing the database -by truncating tables and reloading initial data. - - -.. note:: - The ``TestCase`` use of rollback to un-do the effects of the test code - may reveal previously-undetected errors in test code. For example, - test code that assumes primary keys values will be assigned starting at - one may find that assumption no longer holds true when rollbacks instead - of table truncation are being used to reset the database. Similarly, - the reordering of tests so that all ``TestCase`` classes run first may - reveal unexpected dependencies on test case ordering. In such cases a - quick fix is to switch the ``TestCase`` to a ``TransactionTestCase``. - A better long-term fix, that allows the test to take advantage of the - speed benefit of ``TestCase``, is to fix the underlying test problem. - - -Default test client -~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. attribute:: TestCase.client - -Every test case in a ``django.test.TestCase`` instance has access to an -instance of a Django test client. This client can be accessed as -``self.client``. This client is recreated for each test, so you don't have to -worry about state (such as cookies) carrying over from one test to another. - -This means, instead of instantiating a ``Client`` in each test:: - - import unittest - from django.test.client import Client - - class SimpleTest(unittest.TestCase): - def test_details(self): - client = Client() - response = client.get('/customer/details/') - self.failUnlessEqual(response.status_code, 200) - - def test_index(self): - client = Client() - response = client.get('/customer/index/') - self.failUnlessEqual(response.status_code, 200) - -...you can just refer to ``self.client``, like so:: - - from django.test import TestCase - - class SimpleTest(TestCase): - def test_details(self): - response = self.client.get('/customer/details/') - self.failUnlessEqual(response.status_code, 200) - - def test_index(self): - response = self.client.get('/customer/index/') - self.failUnlessEqual(response.status_code, 200) - -.. _topics-testing-fixtures: - -Fixture loading -~~~~~~~~~~~~~~~ - -.. attribute:: TestCase.fixtures - -A test case for a database-backed Web site isn't much use if there isn't any -data in the database. To make it easy to put test data into the database, -Django's custom ``TestCase`` class provides a way of loading **fixtures**. - -A fixture is a collection of data that Django knows how to import into a -database. For example, if your site has user accounts, you might set up a -fixture of fake user accounts in order to populate your database during tests. - -The most straightforward way of creating a fixture is to use the -:djadmin:`manage.py dumpdata <dumpdata>` command. This assumes you -already have some data in your database. See the :djadmin:`dumpdata -documentation<dumpdata>` for more details. - -.. note:: - If you've ever run :djadmin:`manage.py syncdb<syncdb>`, you've - already used a fixture without even knowing it! When you call - :djadmin:`syncdb` in the database for the first time, Django - installs a fixture called ``initial_data``. This gives you a way - of populating a new database with any initial data, such as a - default set of categories. - - Fixtures with other names can always be installed manually using - the :djadmin:`manage.py loaddata<loaddata>` command. - -Once you've created a fixture and placed it in a ``fixtures`` directory in one -of your :setting:`INSTALLED_APPS`, you can use it in your unit tests by -specifying a ``fixtures`` class attribute on your :class:`django.test.TestCase` -subclass:: - - from django.test import TestCase - from myapp.models import Animal - - class AnimalTestCase(TestCase): - fixtures = ['mammals.json', 'birds'] - - def setUp(self): - # Test definitions as before. - call_setup_methods() - - def testFluffyAnimals(self): - # A test that uses the fixtures. - call_some_test_code() - -Here's specifically what will happen: - - * At the start of each test case, before ``setUp()`` is run, Django will - flush the database, returning the database to the state it was in - directly after :djadmin:`syncdb` was called. - - * Then, all the named fixtures are installed. In this example, Django will - install any JSON fixture named ``mammals``, followed by any fixture named - ``birds``. See the :djadmin:`loaddata` documentation for more - details on defining and installing fixtures. - -This flush/load procedure is repeated for each test in the test case, so you -can be certain that the outcome of a test will not be affected by another test, -or by the order of test execution. - -URLconf configuration -~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. attribute:: TestCase.urls - -If your application provides views, you may want to include tests that use the -test client to exercise those views. However, an end user is free to deploy the -views in your application at any URL of their choosing. This means that your -tests can't rely upon the fact that your views will be available at a -particular URL. - -In order to provide a reliable URL space for your test, -``django.test.TestCase`` provides the ability to customize the URLconf -configuration for the duration of the execution of a test suite. If your -``TestCase`` instance defines an ``urls`` attribute, the ``TestCase`` will use -the value of that attribute as the ``ROOT_URLCONF`` for the duration of that -test. - -For example:: - - from django.test import TestCase - - class TestMyViews(TestCase): - urls = 'myapp.test_urls' - - def testIndexPageView(self): - # Here you'd test your view using ``Client``. - call_some_test_code() - -This test case will use the contents of ``myapp.test_urls`` as the -URLconf for the duration of the test case. - -.. _emptying-test-outbox: - -Multi-database support -~~~~~~~~~~~~~~~~~~~~~~ - -.. attribute:: TestCase.multi_db - -.. versionadded:: 1.2 - -Django sets up a test database corresponding to every database that is -defined in the :setting:`DATABASES` definition in your settings -file. However, a big part of the time taken to run a Django TestCase -is consumed by the call to ``flush`` that ensures that you have a -clean database at the start of each test run. If you have multiple -databases, multiple flushes are required (one for each database), -which can be a time consuming activity -- especially if your tests -don't need to test multi-database activity. - -As an optimization, Django only flushes the ``default`` database at -the start of each test run. If your setup contains multiple databases, -and you have a test that requires every database to be clean, you can -use the ``multi_db`` attribute on the test suite to request a full -flush. - -For example:: - - class TestMyViews(TestCase): - multi_db = True - - def testIndexPageView(self): - call_some_test_code() - -This test case will flush *all* the test databases before running -``testIndexPageView``. - -Emptying the test outbox -~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.0 - -If you use Django's custom ``TestCase`` class, the test runner will clear the -contents of the test e-mail outbox at the start of each test case. - -For more detail on e-mail services during tests, see `E-mail services`_. - -Assertions -~~~~~~~~~~ - -.. versionadded:: 1.0 - -.. versionchanged:: 1.2 - Addded ``msg_prefix`` argument. - -As Python's normal ``unittest.TestCase`` class implements assertion methods -such as ``assertTrue`` and ``assertEquals``, Django's custom ``TestCase`` class -provides a number of custom assertion methods that are useful for testing Web -applications: - -The failure messages given by the assertion methods can be customized -with the ``msg_prefix`` argument. This string will be prefixed to any -failure message generated by the assertion. This allows you to provide -additional details that may help you to identify the location and -cause of an failure in your test suite. - -.. method:: TestCase.assertContains(response, text, count=None, status_code=200, msg_prefix='') - - Asserts that a ``Response`` instance produced the given ``status_code`` and - that ``text`` appears in the content of the response. If ``count`` is - provided, ``text`` must occur exactly ``count`` times in the response. - -.. method:: TestCase.assertNotContains(response, text, status_code=200, msg_prefix='') - - Asserts that a ``Response`` instance produced the given ``status_code`` and - that ``text`` does not appears in the content of the response. - -.. method:: TestCase.assertFormError(response, form, field, errors, msg_prefix='') - - Asserts that a field on a form raises the provided list of errors when - rendered on the form. - - ``form`` is the name the ``Form`` instance was given in the template - context. - - ``field`` is the name of the field on the form to check. If ``field`` - has a value of ``None``, non-field errors (errors you can access via - ``form.non_field_errors()``) will be checked. - - ``errors`` is an error string, or a list of error strings, that are - expected as a result of form validation. - -.. method:: TestCase.assertTemplateUsed(response, template_name, msg_prefix='') - - Asserts that the template with the given name was used in rendering the - response. - - The name is a string such as ``'admin/index.html'``. - -.. method:: TestCase.assertTemplateNotUsed(response, template_name, msg_prefix='') - - Asserts that the template with the given name was *not* used in rendering - the response. - -.. method:: TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='') - - Asserts that the response return a ``status_code`` redirect status, it - redirected to ``expected_url`` (including any GET data), and the final - page was received with ``target_status_code``. - - .. versionadded:: 1.1 - - If your request used the ``follow`` argument, the ``expected_url`` and - ``target_status_code`` will be the url and status code for the final - point of the redirect chain. - -.. _topics-testing-email: - -E-mail services ---------------- - -.. versionadded:: 1.0 - -If any of your Django views send e-mail using :doc:`Django's e-mail -functionality </topics/email>`, you probably don't want to send e-mail each time -you run a test using that view. For this reason, Django's test runner -automatically redirects all Django-sent e-mail to a dummy outbox. This lets you -test every aspect of sending e-mail -- from the number of messages sent to the -contents of each message -- without actually sending the messages. - -The test runner accomplishes this by transparently replacing the normal -email backend with a testing backend. -(Don't worry -- this has no effect on any other e-mail senders outside of -Django, such as your machine's mail server, if you're running one.) - -.. currentmodule:: django.core.mail - -.. data:: django.core.mail.outbox - -During test running, each outgoing e-mail is saved in -``django.core.mail.outbox``. This is a simple list of all -:class:`~django.core.mail.EmailMessage` instances that have been sent. -The ``outbox`` attribute is a special attribute that is created *only* when -the ``locmem`` e-mail backend is used. It doesn't normally exist as part of the -:mod:`django.core.mail` module and you can't import it directly. The code -below shows how to access this attribute correctly. - -Here's an example test that examines ``django.core.mail.outbox`` for length -and contents:: - - from django.core import mail - from django.test import TestCase - - class EmailTest(TestCase): - def test_send_email(self): - # Send message. - mail.send_mail('Subject here', 'Here is the message.', - 'from@example.com', ['to@example.com'], - fail_silently=False) - - # Test that one message has been sent. - self.assertEquals(len(mail.outbox), 1) - - # Verify that the subject of the first message is correct. - self.assertEquals(mail.outbox[0].subject, 'Subject here') - -As noted :ref:`previously <emptying-test-outbox>`, the test outbox is emptied -at the start of every test in a Django ``TestCase``. To empty the outbox -manually, assign the empty list to ``mail.outbox``:: - - from django.core import mail - - # Empty the test outbox - mail.outbox = [] - -Using different testing frameworks -================================== - -Clearly, ``doctest`` and ``unittest`` are not the only Python testing -frameworks. While Django doesn't provide explicit support for alternative -frameworks, it does provide a way to invoke tests constructed for an -alternative framework as if they were normal Django tests. - -When you run ``./manage.py test``, Django looks at the :setting:`TEST_RUNNER` -setting to determine what to do. By default, :setting:`TEST_RUNNER` points to -``'django.test.simple.DjangoTestSuiteRunner'``. This class defines the default Django -testing behavior. This behavior involves: - - #. Performing global pre-test setup. - - #. Looking for unit tests and doctests in the ``models.py`` and - ``tests.py`` files in each installed application. - - #. Creating the test databases. - - #. Running ``syncdb`` to install models and initial data into the test - databases. - - #. Running the unit tests and doctests that are found. - - #. Destroying the test databases. - - #. Performing global post-test teardown. - -If you define your own test runner class and point :setting:`TEST_RUNNER` at -that class, Django will execute your test runner whenever you run -``./manage.py test``. In this way, it is possible to use any test framework -that can be executed from Python code, or to modify the Django test execution -process to satisfy whatever testing requirements you may have. - -.. _topics-testing-test_runner: - -Defining a test runner ----------------------- - -.. versionchanged:: 1.2 - Prior to 1.2, test runners were a single function, not a class. - -.. currentmodule:: django.test.simple - -A test runner is a class defining a ``run_tests()`` method. Django ships -with a ``DjangoTestSuiteRunner`` class that defines the default Django -testing behavior. This class defines the ``run_tests()`` entry point, -plus a selection of other methods that are used to by ``run_tests()`` to -set up, execute and tear down the test suite. - -.. class:: DjangoTestSuiteRunner(verbosity=1, interactive=True, failfast=True, **kwargs) - - ``verbosity`` determines the amount of notification and debug information - that will be printed to the console; ``0`` is no output, ``1`` is normal - output, and ``2`` is verbose output. - - If ``interactive`` is ``True``, the test suite has permission to ask the - user for instructions when the test suite is executed. An example of this - behavior would be asking for permission to delete an existing test - database. If ``interactive`` is ``False``, the test suite must be able to - run without any manual intervention. - - If ``failfast`` is ``True``, the test suite will stop running after the - first test failure is detected. - - Django will, from time to time, extend the capabilities of - the test runner by adding new arguments. The ``**kwargs`` declaration - allows for this expansion. If you subclass ``DjangoTestSuiteRunner`` or - write your own test runner, ensure accept and handle the ``**kwargs`` - parameter. - -.. method:: DjangoTestSuiteRunner.run_tests(test_labels, extra_tests=None, **kwargs) - - Run the test suite. - - ``test_labels`` is a list of strings describing the tests to be run. A test - label can take one of three forms: - - * ``app.TestCase.test_method`` -- Run a single test method in a test - case. - * ``app.TestCase`` -- Run all the test methods in a test case. - * ``app`` -- Search for and run all tests in the named application. - - If ``test_labels`` has a value of ``None``, the test runner should run - search for tests in all the applications in :setting:`INSTALLED_APPS`. - - ``extra_tests`` is a list of extra ``TestCase`` instances to add to the - suite that is executed by the test runner. These extra tests are run - in addition to those discovered in the modules listed in ``test_labels``. - - This method should return the number of tests that failed. - -.. method:: DjangoTestSuiteRunner.setup_test_environment(**kwargs) - - Sets up the test environment ready for testing. - -.. method:: DjangoTestSuiteRunner.build_suite(test_labels, extra_tests=None, **kwargs) - - Constructs a test suite that matches the test labels provided. - - ``test_labels`` is a list of strings describing the tests to be run. A test - label can take one of three forms: - - * ``app.TestCase.test_method`` -- Run a single test method in a test - case. - * ``app.TestCase`` -- Run all the test methods in a test case. - * ``app`` -- Search for and run all tests in the named application. - - If ``test_labels`` has a value of ``None``, the test runner should run - search for tests in all the applications in :setting:`INSTALLED_APPS`. - - ``extra_tests`` is a list of extra ``TestCase`` instances to add to the - suite that is executed by the test runner. These extra tests are run - in addition to those discovered in the modules listed in ``test_labels``. - - Returns a ``TestSuite`` instance ready to be run. - -.. method:: DjangoTestSuiteRunner.setup_databases(**kwargs) - - Creates the test databases. - - Returns a data structure that provides enough detail to undo the changes - that have been made. This data will be provided to the ``teardown_databases()`` - function at the conclusion of testing. - -.. method:: DjangoTestSuiteRunner.run_suite(suite, **kwargs) - - Runs the test suite. - - Returns the result produced by the running the test suite. - -.. method:: DjangoTestSuiteRunner.teardown_databases(old_config, **kwargs) - - Destroys the test databases, restoring pre-test conditions. - - ``old_config`` is a data structure defining the changes in the - database configuration that need to be reversed. It is the return - value of the ``setup_databases()`` method. - -.. method:: DjangoTestSuiteRunner.teardown_test_environment(**kwargs) - - Restores the pre-test environment. - -.. method:: DjangoTestSuiteRunner.suite_result(suite, result, **kwargs) - - Computes and returns a return code based on a test suite, and the result - from that test suite. - - -Testing utilities ------------------ - -.. module:: django.test.utils - :synopsis: Helpers to write custom test runners. - -To assist in the creation of your own test runner, Django provides a number of -utility methods in the ``django.test.utils`` module. - -.. function:: setup_test_environment() - - Performs any global pre-test setup, such as the installing the - instrumentation of the template rendering system and setting up - the dummy ``SMTPConnection``. - -.. function:: teardown_test_environment() - - Performs any global post-test teardown, such as removing the black - magic hooks into the template system and restoring normal e-mail - services. - -The creation module of the database backend (``connection.creation``) -also provides some utilities that can be useful during testing. - -.. function:: create_test_db(verbosity=1, autoclobber=False) - - Creates a new test database and runs ``syncdb`` against it. - - ``verbosity`` has the same behavior as in ``run_tests()``. - - ``autoclobber`` describes the behavior that will occur if a - database with the same name as the test database is discovered: - - * If ``autoclobber`` is ``False``, the user will be asked to - approve destroying the existing database. ``sys.exit`` is - called if the user does not approve. - - * If autoclobber is ``True``, the database will be destroyed - without consulting the user. - - Returns the name of the test database that it created. - - ``create_test_db()`` has the side effect of modifying the value of - :setting:`NAME` in :setting:`DATABASES` to match the name of the test - database. - - .. versionchanged:: 1.0 - ``create_test_db()`` now returns the name of the test database. - -.. function:: destroy_test_db(old_database_name, verbosity=1) - - Destroys the database whose name is in stored in :setting:`NAME` in the - :setting:`DATABASES`, and sets :setting:`NAME` to use the - provided name. - - ``verbosity`` has the same behavior as in ``run_tests()``. |