1
0
mirror of https://github.com/django/django.git synced 2025-07-05 10:19:20 +00:00

[soc2010/test-refactor] Merged up to trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2010/test-refactor@13468 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Paul McMillan 2010-08-04 18:47:42 +00:00
parent 9315b44ad1
commit 5875c4e01c
32 changed files with 437 additions and 240 deletions

View File

@ -6,7 +6,7 @@ class MySQLCreation(DatabaseCreation):
from django.contrib.gis.db.models.fields import GeometryField
output = super(MySQLCreation, self).sql_indexes_for_field(model, f, style)
if isinstance(f, GeometryField):
if isinstance(f, GeometryField) and f.spatial_index:
qn = self.connection.ops.quote_name
db_table = model._meta.db_table
idx_name = '%s_%s_id' % (db_table, f.column)

View File

@ -95,7 +95,7 @@ class GeoSQLCompiler(compiler.SQLCompiler):
return result
def get_default_columns(self, with_aliases=False, col_aliases=None,
start_alias=None, opts=None, as_pairs=False):
start_alias=None, opts=None, as_pairs=False, local_only=False):
"""
Computes the default columns for selecting every field in the base
model. Will sometimes be called to pull in related models (e.g. via
@ -121,6 +121,8 @@ class GeoSQLCompiler(compiler.SQLCompiler):
if start_alias:
seen = {None: start_alias}
for field, model in opts.get_fields_with_model():
if local_only and model is not None:
continue
if start_alias:
try:
alias = seen[model]

View File

@ -38,6 +38,11 @@ class Author(models.Model):
name = models.CharField(max_length=100)
objects = models.GeoManager()
class Article(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, unique=True)
objects = models.GeoManager()
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, related_name='books', null=True)

View File

@ -4,7 +4,7 @@ from django.contrib.gis.db.models import Collect, Count, Extent, F, Union
from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.tests.utils import mysql, oracle, postgis, spatialite, no_mysql, no_oracle, no_spatialite
from django.conf import settings
from models import City, Location, DirectoryEntry, Parcel, Book, Author
from models import City, Location, DirectoryEntry, Parcel, Book, Author, Article
cities = (('Aurora', 'TX', -97.516111, 33.058333),
('Roswell', 'NM', -104.528056, 33.387222),
@ -291,6 +291,14 @@ class RelatedGeoModelTest(unittest.TestCase):
self.assertEqual(4, len(coll))
self.assertEqual(ref_geom, coll)
def test15_invalid_select_related(self):
"Testing doing select_related on the related name manager of a unique FK. See #13934."
qs = Article.objects.select_related('author__article')
# This triggers TypeError when `get_default_columns` has no `local_only`
# keyword. The TypeError is swallowed if QuerySet is actually
# evaluated as list generation swallows TypeError in CPython.
sql = str(qs.query)
# TODO: Related tests for KML, GML, and distance lookups.
def suite():

View File

@ -1,7 +1,7 @@
from optparse import make_option
from django.conf import settings
from django.db import connections, transaction, models, DEFAULT_DB_ALIAS
from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
from django.core.management import call_command
from django.core.management.base import NoArgsCommand, CommandError
from django.core.management.color import no_style
@ -66,7 +66,13 @@ The full error: %s""" % (connection.settings_dict['NAME'], e))
# Emit the post sync signal. This allows individual
# applications to respond as if the database had been
# sync'd from scratch.
emit_post_sync_signal(models.get_models(), verbosity, interactive, db)
all_models = [
(app.__name__.split('.')[-2],
[m for m in models.get_models(app, include_auto_created=True)
if router.allow_syncdb(db, m)])
for app in models.get_apps()
]
emit_post_sync_signal(all_models, verbosity, interactive, db)
# Reinstall the initial_data fixture.
kwargs = options.copy()

View File

@ -64,7 +64,7 @@ class DatabaseCreation(BaseDatabaseCreation):
# a second index that specifies their operator class, which is
# needed when performing correct LIKE queries outside the
# C locale. See #12234.
db_type = f.db_type()
db_type = f.db_type(connection=self.connection)
if db_type.startswith('varchar'):
output.append(get_index_sql('%s_%s_like' % (db_table, f.column),
' varchar_pattern_ops'))

View File

@ -56,7 +56,8 @@ class DatabaseOperations(BaseDatabaseOperations):
def last_insert_id(self, cursor, table_name, pk_name):
# Use pg_get_serial_sequence to get the underlying sequence name
# from the table name and column name (available since PostgreSQL 8)
cursor.execute("SELECT CURRVAL(pg_get_serial_sequence('%s','%s'))" % (table_name, pk_name))
cursor.execute("SELECT CURRVAL(pg_get_serial_sequence('%s','%s'))" % (
self.quote_name(table_name), pk_name))
return cursor.fetchone()[0]
def no_limit_value(self):
@ -98,7 +99,7 @@ class DatabaseOperations(BaseDatabaseOperations):
column_name = 'id'
sql.append("%s setval(pg_get_serial_sequence('%s','%s'), 1, false);" % \
(style.SQL_KEYWORD('SELECT'),
style.SQL_TABLE(table_name),
style.SQL_TABLE(self.quote_name(table_name)),
style.SQL_FIELD(column_name))
)
return sql
@ -120,7 +121,7 @@ class DatabaseOperations(BaseDatabaseOperations):
if isinstance(f, models.AutoField):
output.append("%s setval(pg_get_serial_sequence('%s','%s'), coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
(style.SQL_KEYWORD('SELECT'),
style.SQL_TABLE(model._meta.db_table),
style.SQL_TABLE(qn(model._meta.db_table)),
style.SQL_FIELD(f.column),
style.SQL_FIELD(qn(f.column)),
style.SQL_FIELD(qn(f.column)),
@ -132,7 +133,7 @@ class DatabaseOperations(BaseDatabaseOperations):
if not f.rel.through:
output.append("%s setval(pg_get_serial_sequence('%s','%s'), coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
(style.SQL_KEYWORD('SELECT'),
style.SQL_TABLE(model._meta.db_table),
style.SQL_TABLE(qn(f.m2m_db_table())),
style.SQL_FIELD('id'),
style.SQL_FIELD(qn('id')),
style.SQL_FIELD(qn('id')),

View File

@ -812,6 +812,9 @@ class ForeignKey(RelatedField, Field):
to_field = to_field or (to._meta.pk and to._meta.pk.name)
kwargs['verbose_name'] = kwargs.get('verbose_name', None)
if 'db_index' not in kwargs:
kwargs['db_index'] = True
kwargs['rel'] = rel_class(to, to_field,
related_name=kwargs.pop('related_name', None),
limit_choices_to=kwargs.pop('limit_choices_to', None),
@ -819,8 +822,6 @@ class ForeignKey(RelatedField, Field):
parent_link=kwargs.pop('parent_link', False))
Field.__init__(self, **kwargs)
self.db_index = True
def validate(self, value, model_instance):
if self.rel.parent_link:
return

View File

@ -1090,10 +1090,7 @@ class Query(object):
# exclude the "foo__in=[]" case from this handling, because
# it's short-circuited in the Where class.
# We also need to handle the case where a subquery is provided
entry = self.where_class()
entry.add((Constraint(alias, col, None), 'isnull', True), AND)
entry.negate()
self.where.add(entry, AND)
self.where.add((Constraint(alias, col, None), 'isnull', False), AND)
if can_reuse is not None:
can_reuse.update(join_list)

View File

@ -11,9 +11,10 @@ except ImportError:
from django.template import Variable, Library
from django.conf import settings
from django.utils import formats
from django.utils.translation import ugettext, ungettext
from django.utils.encoding import force_unicode, iri_to_uri
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe, SafeData
from django.utils.translation import ugettext, ungettext
register = Library()
@ -496,10 +497,9 @@ def join(value, arg, autoescape=None):
"""
value = map(force_unicode, value)
if autoescape:
from django.utils.html import conditional_escape
value = [conditional_escape(v) for v in value]
try:
data = arg.join(value)
data = conditional_escape(arg).join(value)
except AttributeError: # fail silently but nicely
return value
return mark_safe(data)

View File

@ -12,20 +12,26 @@ 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 pickle json htmlhelp qthelp latex changes linkcheck doctest
.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 " 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 " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@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)"
@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)/*
@ -40,6 +46,11 @@ 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
@ -65,12 +76,42 @@ qthelp:
@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 all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)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

View File

@ -1,9 +1,9 @@
"""
Sphinx plugins for Django documentation.
"""
import os
import docutils.nodes
import docutils.transforms
from docutils import nodes, transforms
try:
import json
except ImportError:
@ -14,26 +14,12 @@ except ImportError:
from django.utils import simplejson as json
except ImportError:
json = None
import os
import sphinx
import sphinx.addnodes
try:
from sphinx import builders
except ImportError:
import sphinx.builder as builders
try:
import sphinx.builders.html as builders_html
except ImportError:
builders_html = builders
from sphinx import addnodes, roles
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.writers.html import SmartyPantsHTMLTranslator
from sphinx.util.console import bold
import sphinx.directives
import sphinx.environment
try:
import sphinx.writers.html as sphinx_htmlwriter
except ImportError:
import sphinx.htmlwriter as sphinx_htmlwriter
import sphinx.roles
from docutils import nodes
def setup(app):
app.add_crossref_type(
@ -74,21 +60,20 @@ def setup(app):
app.add_transform(SuppressBlockquotes)
app.add_builder(DjangoStandaloneHTMLBuilder)
# Monkeypatch PickleHTMLBuilder so that it doesn't die in Sphinx 0.4.2
if sphinx.__version__ == '0.4.2':
monkeypatch_pickle_builder()
def parse_version_directive(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
env = state.document.settings.env
is_nextversion = env.config.django_next_version == arguments[0]
ret = []
node = sphinx.addnodes.versionmodified()
node = addnodes.versionmodified()
ret.append(node)
if not is_nextversion:
if len(arguments) == 1:
linktext = 'Please, see the release notes <releases-%s>' % (arguments[0])
xrefs = sphinx.roles.xfileref_role('ref', linktext, linktext, lineno, state)
try:
xrefs = roles.XRefRole()('ref', linktext, linktext, lineno, state) # Sphinx >= 1.0
except:
xrefs = roles.xfileref_role('ref', linktext, linktext, lineno, state) # Sphinx < 1.0
node.extend(xrefs[0])
node['version'] = arguments[0]
else:
@ -103,29 +88,29 @@ def parse_version_directive(name, arguments, options, content, lineno,
env.note_versionchange(node['type'], node['version'], node, lineno)
return ret
class SuppressBlockquotes(docutils.transforms.Transform):
class SuppressBlockquotes(transforms.Transform):
"""
Remove the default blockquotes that encase indented list, tables, etc.
"""
default_priority = 300
suppress_blockquote_child_nodes = (
docutils.nodes.bullet_list,
docutils.nodes.enumerated_list,
docutils.nodes.definition_list,
docutils.nodes.literal_block,
docutils.nodes.doctest_block,
docutils.nodes.line_block,
docutils.nodes.table
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(docutils.nodes.block_quote):
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(sphinx_htmlwriter.SmartyPantsHTMLTranslator):
class DjangoHTMLTranslator(SmartyPantsHTMLTranslator):
"""
Django-specific reST to HTML tweaks.
"""
@ -133,42 +118,41 @@ class DjangoHTMLTranslator(sphinx_htmlwriter.SmartyPantsHTMLTranslator):
# 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(')')
pass
#
# Don't apply smartypants to literal blocks
#
def visit_literal_block(self, node):
self.no_smarty += 1
sphinx_htmlwriter.SmartyPantsHTMLTranslator.visit_literal_block(self, node)
SmartyPantsHTMLTranslator.visit_literal_block(self, node)
def depart_literal_block(self, node):
sphinx_htmlwriter.SmartyPantsHTMLTranslator.depart_literal_block(self, node)
SmartyPantsHTMLTranslator.depart_literal_block(self, node)
self.no_smarty -= 1
#
# Turn the "new in version" stuff (versoinadded/versionchanged) into a
# 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 chanage
# 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 and I think it'll require Sphinx 0.5 anyway.
# 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'])
@ -178,41 +162,31 @@ class DjangoHTMLTranslator(sphinx_htmlwriter.SmartyPantsHTMLTranslator):
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
# This is different on docutils 0.5 vs. 0.4...
if hasattr(sphinx_htmlwriter.SmartyPantsHTMLTranslator, 'start_tag_with_title') and sphinx.__version__ == '0.4.2':
def start_tag_with_title(self, node, tagname, **atts):
node = {
'classes': node.get('classes', []),
'ids': ['s-%s' % i for i in node.get('ids', [])]
}
return self.starttag(node, tagname, **atts)
else:
def visit_section(self, node):
old_ids = node.get('ids', [])
node['ids'] = ['s-' + i for i in old_ids]
if sphinx.__version__ != '0.4.2':
node['ids'].extend(old_ids)
sphinx_htmlwriter.SmartyPantsHTMLTranslator.visit_section(self, node)
node['ids'] = old_ids
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 += sphinx.addnodes.desc_name(title, title)
signode += addnodes.desc_name(title, title)
return sig
def parse_django_adminopt_node(env, sig, signode):
"""A copy of sphinx.directives.CmdoptionDesc.parse_signature()"""
from sphinx import addnodes
from sphinx.directives.desc import option_desc_re
try:
from sphinx.domains.std import option_desc_re # Sphinx >= 1.0
except:
from sphinx.directives.desc import option_desc_re # Sphinx < 1.0
count = 0
firstname = ''
for m in option_desc_re.finditer(sig):
@ -228,44 +202,8 @@ def parse_django_adminopt_node(env, sig, signode):
raise ValueError
return firstname
def monkeypatch_pickle_builder():
import shutil
from os import path
try:
import cPickle as pickle
except ImportError:
import pickle
def handle_finish(self):
# dump the global context
outfilename = path.join(self.outdir, 'globalcontext.pickle')
f = open(outfilename, 'wb')
try:
pickle.dump(self.globalcontext, f, 2)
finally:
f.close()
self.info(bold('dumping search index...'))
self.indexer.prune(self.env.all_docs)
f = open(path.join(self.outdir, 'searchindex.pickle'), 'wb')
try:
self.indexer.dump(f, 'pickle')
finally:
f.close()
# copy the environment file from the doctree dir to the output dir
# as needed by the web app
shutil.copyfile(path.join(self.doctreedir, builders.ENV_PICKLE_FILENAME),
path.join(self.outdir, builders.ENV_PICKLE_FILENAME))
# touch 'last build' file, used by the web application to determine
# when to reload its environment and clear the cache
open(path.join(self.outdir, builders.LAST_BUILD_FILENAME), 'w').close()
builders.PickleHTMLBuilder.handle_finish = handle_finish
class DjangoStandaloneHTMLBuilder(builders_html.StandaloneHTMLBuilder):
class DjangoStandaloneHTMLBuilder(StandaloneHTMLBuilder):
"""
Subclass to add some extra things we need.
"""
@ -278,9 +216,14 @@ class DjangoStandaloneHTMLBuilder(builders_html.StandaloneHTMLBuilder):
self.warn("cannot create templatebuiltins.js due to missing simplejson dependency")
return
self.info(bold("writing templatebuiltins.js..."))
xrefs = self.env.reftargets.keys()
templatebuiltins = dict([('ttags', [n for (t,n) in xrefs if t == 'ttag']),
('tfilters', [n for (t,n) in xrefs if t == 'tfilter'])])
try:
xrefs = self.env.reftargets.keys()
templatebuiltins = dict([('ttags', [n for (t,n) in xrefs if t == 'ttag']),
('tfilters', [n for (t,n) in xrefs if t == 'tfilter'])])
except AttributeError:
xrefs = self.env.domaindata["std"]["objects"]
templatebuiltins = dict([('ttags', [n for (t,n) in xrefs if t == 'templatetag']),
('tfilters', [n for (t,n) in xrefs if t == 'templatefilter'])])
outfilename = os.path.join(self.outdir, "templatebuiltins.js")
f = open(outfilename, 'wb')
f.write('var django_template_builtins = ')

View File

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

View File

@ -1,4 +1,4 @@
{% extends "!layout.html" %}
{% extends "basic/layout.html" %}
{%- macro secondnav() %}
{%- if prev %}
@ -61,7 +61,7 @@
<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('modindex') }}">Modules</a>
<a title="Module index" href="{{ pathto('py-modindex') }}">Modules</a>
</div>
<div class="nav">{{ secondnav() }}</div>
</div>

View File

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

View File

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

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1013 B

After

Width:  |  Height:  |  Size: 1013 B

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

4
docs/_theme/djangodocs/theme.conf vendored Normal file
View File

@ -0,0 +1,4 @@
[theme]
inherit = basic
stylesheet = default.css
pygments_style = trac

View File

@ -8,28 +8,35 @@
# 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 value; values that are commented out
# serve to show the default value.
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
# If your extensions are in another directory, add it here.
sys.path.append(os.path.join(os.path.dirname(__file__), "_ext"))
# 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
# ---------------------
# -- 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 = ["_templates"]
# 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'
@ -37,8 +44,10 @@ master_doc = 'contents'
project = 'Django'
copyright = 'Django Software Foundation and contributors'
# The default replacements for |version| and |release|, also used in various
# other places throughout the built documents.
# 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'
@ -47,14 +56,22 @@ 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 documents that shouldn't be included in the build.
#unused_docs = []
# 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
@ -75,13 +92,35 @@ pygments_style = 'trac'
# Note: exclude_dirnames is new in Sphinx 0.5
exclude_dirnames = ['.svn']
# Options for HTML output
# -----------------------
# -- Options for HTML output ---------------------------------------------------
# The style sheet to use for HTML and HTML Help pages. A file of that name
# must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path.
html_style = 'default.css'
# 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,
@ -110,17 +149,38 @@ html_translator_class = "djangodocs.DjangoHTMLTranslator"
html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
#html_domain_indices = True
# If true, the reST sources are included in the HTML build as _sources/<name>.
html_copy_source = 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
# ------------------------
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
@ -132,9 +192,24 @@ htmlhelp_basename = 'Djangodoc'
# (source start file, target name, title, author, document class [howto/manual]).
#latex_documents = []
latex_documents = [
('contents', 'django.tex', 'Django Documentation', 'Django Software Foundation', 'manual'),
('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 = ''
@ -142,10 +217,53 @@ latex_documents = [
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
#latex_domain_indices = True
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# If this isn't set to True, the LaTex writer can only handle six levels of headers.
latex_use_parts = True
# -- 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

View File

@ -15,6 +15,11 @@ __ 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::
Generation of the Django documentation will work with Sphinx version 0.6
or newer, but we recommend going straigh to Sphinx 1.0 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

View File

@ -1027,90 +1027,88 @@ The difference between these two is merely the template used to render them.
The ``InlineModelAdmin`` class is a subclass of ``ModelAdmin`` so it inherits
all the same functionality as well as some of its own:
``model``
~~~~~~~~~
.. attribute:: InlineModelAdmin.model
The model in which the inline is using. This is required.
The model in which the inline is using. This is required.
``fk_name``
~~~~~~~~~~~
.. 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.
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.
``formset``
~~~~~~~~~~~
.. 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>`.
This defaults to ``BaseInlineFormSet``. Using your own formset can give you
many possibilities of customization. Inlines are built around
:ref:`model formsets <model-formsets>`.
``form``
~~~~~~~~
.. 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.
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:
``extra``
~~~~~~~~~
.. attribute:: InlineModelAdmin.extra
This controls the number of extra forms the formset will display in addition
to the initial forms. See the
:ref:`formsets documentation <topics-forms-formsets>` for more information.
.. versionadded:: 1.2
This controls the number of extra forms the formset will display in addition
to the initial forms. See the
:ref:`formsets documentation <topics-forms-formsets>` for more information.
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.
.. versionadded:: 1.2
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.
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:
``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.
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.
``raw_id_fields``
~~~~~~~~~~~~~~~~~
.. 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.
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``::
``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",)
class BookInline(admin.TabularInline):
model = Book
raw_id_fields = ("pages",)
``template``
~~~~~~~~~~~~
The template used to render the inline on the page.
.. attribute:: InlineModelAdmin.template
``verbose_name``
~~~~~~~~~~~~~~~~
The template used to render the inline on the page.
An override to the ``verbose_name`` found in the model's inner ``Meta`` class.
.. attribute:: InlineModelAdmin.verbose_name
``verbose_name_plural``
~~~~~~~~~~~~~~~~~~~~~~~
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``.
An override to the ``verbose_name_plural`` found in the model's inner ``Meta``
class.
Working with a model with two or more foreign keys to the same parent model
---------------------------------------------------------------------------

View File

@ -107,7 +107,7 @@ 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.validators import ValidationError, NON_FIELD_ERRORS
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
try:
article.full_clean()
except ValidationError, e:

View File

@ -1,3 +1,5 @@
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.conf import settings
from django.db import models
from django.db import connection, DEFAULT_DB_ALIAS
@ -37,6 +39,21 @@ if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyField(Person,blank=True)
class Tag(models.Model):
name = models.CharField(max_length=30)
content_type = models.ForeignKey(ContentType, related_name='backend_tags')
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Post(models.Model):
name = models.CharField(max_length=30)
text = models.TextField()
tags = generic.GenericRelation('Tag')
class Meta:
db_table = 'CaseSensitive_Post'
qn = connection.ops.quote_name
__test__ = {'API_TESTS': """

View File

@ -6,7 +6,7 @@ import unittest
from django.conf import settings
from django.core import management
from django.core.management.color import no_style
from django.db import backend, connection, DEFAULT_DB_ALIAS
from django.db import backend, connection, connections, DEFAULT_DB_ALIAS
from django.db.backends.signals import connection_created
from django.test import TestCase
@ -137,6 +137,23 @@ if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
for statement in connection.ops.sql_flush(no_style(), tables, sequences):
cursor.execute(statement)
class SequenceResetTest(TestCase):
def test_generic_relation(self):
"Sequence names are correct when resetting generic relations (Ref #13941)"
# Create an object with a manually specified PK
models.Post.objects.create(id=10, name='1st post', text='hello world')
# Reset the sequences for the database
cursor = connection.cursor()
commands = connections[DEFAULT_DB_ALIAS].ops.sequence_reset_sql(no_style(), [models.Post])
for sql in commands:
cursor.execute(sql)
# If we create a new object now, it should have a PK greater
# than the PK we specified manually.
obj = models.Post.objects.create(name='New post', text='goodbye world')
self.assertTrue(obj.pk > 10)
def connection_created_test(sender, **kwargs):
print 'connection_created signal'

View File

@ -328,7 +328,12 @@ def get_filter_tests():
'join03': (r'{{ a|join:" &amp; " }}', {'a': ['alpha', 'beta & me']}, 'alpha &amp; beta &amp; me'),
'join04': (r'{% autoescape off %}{{ a|join:" &amp; " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha &amp; beta & me'),
# Test that joining with unsafe joiners don't result in unsafe strings (#11377)
'join05': (r'{{ a|join:var }}', {'a': ['alpha', 'beta & me'], 'var': ' & '}, 'alpha &amp; beta &amp; me'),
'join06': (r'{{ a|join:var }}', {'a': ['alpha', 'beta & me'], 'var': mark_safe(' & ')}, 'alpha & beta &amp; me'),
'join07': (r'{{ a|join:var|lower }}', {'a': ['Alpha', 'Beta & me'], 'var': ' & ' }, 'alpha &amp; beta &amp; me'),
'join08': (r'{{ a|join:var|lower }}', {'a': ['Alpha', 'Beta & me'], 'var': mark_safe(' & ')}, 'alpha & beta &amp; me'),
'date01': (r'{{ d|date:"m" }}', {'d': datetime(2008, 1, 1)}, '01'),
'date02': (r'{{ d|date }}', {'d': datetime(2008, 1, 1)}, 'Jan. 1, 2008'),
#Ticket 9520: Make sure |date doesn't blow up on non-dates

View File

@ -506,6 +506,17 @@ class Templates(unittest.TestCase):
'basic-syntax28': ("{{ a.b }}", {'a': SilentGetItemClass()}, ('', 'INVALID')),
'basic-syntax29': ("{{ a.b }}", {'a': SilentAttrClass()}, ('', 'INVALID')),
# Something that starts like a number but has an extra lookup works as a lookup.
'basic-syntax30': ("{{ 1.2.3 }}", {"1": {"2": {"3": "d"}}}, "d"),
'basic-syntax31': ("{{ 1.2.3 }}", {"1": {"2": ("a", "b", "c", "d")}}, "d"),
'basic-syntax32': ("{{ 1.2.3 }}", {"1": (("x", "x", "x", "x"), ("y", "y", "y", "y"), ("a", "b", "c", "d"))}, "d"),
'basic-syntax33': ("{{ 1.2.3 }}", {"1": ("xxxx", "yyyy", "abcd")}, "d"),
'basic-syntax34': ("{{ 1.2.3 }}", {"1": ({"x": "x"}, {"y": "y"}, {"z": "z", "3": "d"})}, "d"),
# Numbers are numbers even if their digits are in the context.
'basic-syntax35': ("{{ 1 }}", {"1": "abc"}, "1"),
'basic-syntax36': ("{{ 1.2 }}", {"1": "abc"}, "1.2"),
# List-index syntax allows a template to access a certain item of a subscriptable object.
'list-index01': ("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"),
@ -592,7 +603,7 @@ class Templates(unittest.TestCase):
#filters should accept empty string constants
'filter-syntax20': ('{{ ""|default_if_none:"was none" }}', {}, ""),
### COMMENT SYNTAX ########################################################
'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),
'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"),
@ -1285,7 +1296,8 @@ class Templates(unittest.TestCase):
# Regression test for #11270.
'cache17': ('{% load cache %}{% cache 10 long_cache_key poem %}Some Content{% endcache %}', {'poem': 'Oh freddled gruntbuggly/Thy micturations are to me/As plurdled gabbleblotchits/On a lurgid bee/That mordiously hath bitled out/Its earted jurtles/Into a rancid festering/Or else I shall rend thee in the gobberwarts with my blurglecruncheon/See if I dont.'}, 'Some Content'),
### AUTOESCAPE TAG ##############################################
'autoescape-tag01': ("{% autoescape off %}hello{% endautoescape %}", {}, "hello"),
'autoescape-tag02': ("{% autoescape off %}{{ first }}{% endautoescape %}", {"first": "<b>hello</b>"}, "<b>hello</b>"),
@ -1314,6 +1326,23 @@ class Templates(unittest.TestCase):
# implementation details (fortunately, the (no)autoescape block
# tags can be used in those cases)
'autoescape-filtertag01': ("{{ first }}{% filter safe %}{{ first }} x<y{% endfilter %}", {"first": "<a>"}, template.TemplateSyntaxError),
# ifqeual compares unescaped vales.
'autoescape-ifequal01': ('{% ifequal var "this & that" %}yes{% endifequal %}', { "var": "this & that" }, "yes" ),
# Arguments to filters are 'safe' and manipulate their input unescaped.
'autoescape-filters01': ('{{ var|cut:"&" }}', { "var": "this & that" }, "this that" ),
'autoescape-filters02': ('{{ var|join:" & \" }}', { "var": ("Tom", "Dick", "Harry") }, "Tom & Dick & Harry" ),
# Literal strings are safe.
'autoescape-literals01': ('{{ "this & that" }}',{}, "this & that" ),
# Iterating over strings outputs safe characters.
'autoescape-stringiterations01': ('{% for l in var %}{{ l }},{% endfor %}', {'var': 'K&R'}, "K,&amp;,R," ),
# Escape requirement survives lookup.
'autoescape-lookup01': ('{{ var.key }}', { "var": {"key": "this & that" }}, "this &amp; that" ),
}