[Python-modules-commits] [python-django] 01/04: Imported Upstream version 1.8.2

Raphaël Hertzog hertzog at moszumanska.debian.org
Thu May 21 15:11:11 UTC 2015


This is an automated email from the git hooks/post-receive script.

hertzog pushed a commit to branch debian/experimental
in repository python-django.

commit 020728f3cafb350f274d7269a5667e73c79bc3f7
Author: Raphaël Hertzog <hertzog at debian.org>
Date:   Thu May 21 15:58:18 2015 +0200

    Imported Upstream version 1.8.2
---
 Django.egg-info/PKG-INFO                          |  2 +-
 Django.egg-info/SOURCES.txt                       |  1 +
 PKG-INFO                                          |  2 +-
 django/__init__.py                                |  2 +-
 django/contrib/admin/static/admin/css/forms.css   |  1 +
 django/contrib/admin/static/admin/css/widgets.css |  1 +
 django/contrib/gis/admin/__init__.py              | 19 ++---
 django/contrib/gis/admin/options.py               | 26 ++++---
 django/contrib/gis/geos/__init__.py               |  3 +-
 django/contrib/gis/utils/layermapping.py          |  2 +-
 django/contrib/postgres/fields/hstore.py          |  2 +-
 django/contrib/sessions/backends/cached_db.py     |  2 +-
 django/contrib/sessions/middleware.py             |  3 +-
 django/db/backends/base/creation.py               |  2 +-
 django/db/backends/base/schema.py                 | 31 ++++----
 django/db/backends/mysql/schema.py                | 18 +++++
 django/db/backends/postgresql_psycopg2/base.py    | 26 +++++++
 django/db/backends/sqlite3/schema.py              |  5 +-
 django/db/models/expressions.py                   |  5 ++
 django/db/models/fields/related.py                |  3 +
 django/db/models/options.py                       |  6 +-
 django/db/models/query_utils.py                   |  7 +-
 django/db/models/sql/compiler.py                  |  7 +-
 django/db/models/sql/query.py                     | 12 ++--
 django/template/utils.py                          |  4 +-
 docs/howto/writing-migrations.txt                 | 85 ++++++++++++++--------
 docs/intro/tutorial01.txt                         | 18 ++---
 docs/ref/contrib/admin/index.txt                  |  2 +-
 docs/ref/contrib/gis/geoquerysets.txt             |  4 +-
 docs/ref/contrib/sitemaps.txt                     |  9 +++
 docs/ref/exceptions.txt                           | 20 ++----
 docs/ref/migration-operations.txt                 | 20 ++++--
 docs/ref/models/expressions.txt                   |  2 +-
 docs/ref/models/instances.txt                     | 19 ++++-
 docs/ref/models/querysets.txt                     | 12 ++--
 docs/ref/request-response.txt                     |  8 +--
 docs/ref/settings.txt                             |  2 +-
 docs/releases/1.5.txt                             |  2 +-
 docs/releases/1.6.txt                             |  2 +-
 docs/releases/1.8.1.txt                           |  3 +-
 docs/releases/1.8.2.txt                           | 62 ++++++++++++++++
 docs/releases/1.8.txt                             |  6 +-
 docs/releases/index.txt                           |  1 +
 docs/topics/auth/customizing.txt                  | 11 +--
 docs/topics/forms/index.txt                       | 24 +++----
 docs/topics/http/sessions.txt                     |  2 +-
 docs/topics/http/shortcuts.txt                    |  2 +-
 docs/topics/http/urls.txt                         | 30 ++++----
 docs/topics/i18n/translation.txt                  |  2 +-
 docs/topics/testing/tools.txt                     | 24 ++++---
 tests/aggregation_regress/models.py               |  5 ++
 tests/aggregation_regress/tests.py                | 35 +++------
 tests/backends/tests.py                           | 26 +++++++
 tests/expressions_case/tests.py                   | 86 +++++++++++++++++++++++
 tests/file_storage/tests.py                       |  8 ++-
 tests/gis_tests/geoadmin/models.py                |  4 +-
 tests/migrations/test_state.py                    |  9 +++
 tests/model_fields/models.py                      |  8 +++
 tests/model_fields/test_uuid.py                   |  7 +-
 tests/postgres_tests/test_hstore.py               | 11 +++
 tests/schema/tests.py                             | 49 ++++++++++++-
 tests/sessions_tests/tests.py                     | 30 ++++++++
 tests/template_backends/test_dummy.py             |  1 +
 tests/template_backends/test_utils.py             |  9 +++
 tests/template_tests/tests.py                     |  4 +-
 65 files changed, 632 insertions(+), 224 deletions(-)

diff --git a/Django.egg-info/PKG-INFO b/Django.egg-info/PKG-INFO
index 46fdb92..98f4f3c 100644
--- a/Django.egg-info/PKG-INFO
+++ b/Django.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: Django
-Version: 1.8.1
+Version: 1.8.2
 Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
 Home-page: http://www.djangoproject.com/
 Author: Django Software Foundation
diff --git a/Django.egg-info/SOURCES.txt b/Django.egg-info/SOURCES.txt
index c528103..3dc6a77 100644
--- a/Django.egg-info/SOURCES.txt
+++ b/Django.egg-info/SOURCES.txt
@@ -3395,6 +3395,7 @@ docs/releases/1.7.7.txt
 docs/releases/1.7.8.txt
 docs/releases/1.7.txt
 docs/releases/1.8.1.txt
+docs/releases/1.8.2.txt
 docs/releases/1.8.txt
 docs/releases/index.txt
 docs/releases/security.txt
diff --git a/PKG-INFO b/PKG-INFO
index 46fdb92..98f4f3c 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: Django
-Version: 1.8.1
+Version: 1.8.2
 Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
 Home-page: http://www.djangoproject.com/
 Author: Django Software Foundation
diff --git a/django/__init__.py b/django/__init__.py
index 2494de9..4698fd0 100644
--- a/django/__init__.py
+++ b/django/__init__.py
@@ -1,6 +1,6 @@
 from django.utils.version import get_version
 
-VERSION = (1, 8, 1, 'final', 0)
+VERSION = (1, 8, 2, 'final', 0)
 
 __version__ = get_version(VERSION)
 
diff --git a/django/contrib/admin/static/admin/css/forms.css b/django/contrib/admin/static/admin/css/forms.css
index 199ab34..b06bbba 100644
--- a/django/contrib/admin/static/admin/css/forms.css
+++ b/django/contrib/admin/static/admin/css/forms.css
@@ -93,6 +93,7 @@ form .aligned table p {
 }
 
 form .aligned p.help {
+    clear: left;
     padding-left: 38px;
 }
 
diff --git a/django/contrib/admin/static/admin/css/widgets.css b/django/contrib/admin/static/admin/css/widgets.css
index 0ca42e6..3defc70 100644
--- a/django/contrib/admin/static/admin/css/widgets.css
+++ b/django/contrib/admin/static/admin/css/widgets.css
@@ -579,6 +579,7 @@ ul.orderer li.deleted:hover, ul.orderer li.deleted a.selector:hover {
 
 /* RELATED WIDGET WRAPPER */
 .related-widget-wrapper {
+    float: left;       /* display properly in form rows with multiple fields */
     overflow: hidden;  /* clear floated contents */
 }
 
diff --git a/django/contrib/gis/admin/__init__.py b/django/contrib/gis/admin/__init__.py
index fdf7166..79e51e4 100644
--- a/django/contrib/gis/admin/__init__.py
+++ b/django/contrib/gis/admin/__init__.py
@@ -1,21 +1,14 @@
 # Getting the normal admin routines, classes, and `site` instance.
-from django.contrib.admin import (  # NOQA: flake8 detects only the last __all__
+from django.contrib.admin import (
     autodiscover, site, AdminSite, ModelAdmin, StackedInline, TabularInline,
     HORIZONTAL, VERTICAL,
 )
 # Geographic admin options classes and widgets.
-from django.contrib.gis.admin.options import GeoModelAdmin      # NOQA
-from django.contrib.gis.admin.widgets import OpenLayersWidget   # NOQA
+from django.contrib.gis.admin.options import GeoModelAdmin, OSMGeoAdmin
+from django.contrib.gis.admin.widgets import OpenLayersWidget
 
 __all__ = [
-    "autodiscover", "site", "AdminSite", "ModelAdmin", "StackedInline",
-    "TabularInline", "HORIZONTAL", "VERTICAL",
-    "GeoModelAdmin", "OpenLayersWidget", "HAS_OSM",
+    'autodiscover', 'site', 'AdminSite', 'ModelAdmin', 'StackedInline',
+    'TabularInline', 'HORIZONTAL', 'VERTICAL', 'GeoModelAdmin', 'OSMGeoAdmin',
+    'OpenLayersWidget',
 ]
-
-try:
-    from django.contrib.gis.admin.options import OSMGeoAdmin
-    HAS_OSM = True
-    __all__ += ['OSMGeoAdmin']
-except ImportError:
-    HAS_OSM = False
diff --git a/django/contrib/gis/admin/options.py b/django/contrib/gis/admin/options.py
index f941233..dca4682 100644
--- a/django/contrib/gis/admin/options.py
+++ b/django/contrib/gis/admin/options.py
@@ -2,6 +2,9 @@ from django.contrib.admin import ModelAdmin
 from django.contrib.gis.admin.widgets import OpenLayersWidget
 from django.contrib.gis.db import models
 from django.contrib.gis.gdal import HAS_GDAL, OGRGeomType
+from django.core.exceptions import ImproperlyConfigured
+
+spherical_mercator_srid = 3857
 
 
 class GeoModelAdmin(ModelAdmin):
@@ -123,14 +126,17 @@ class GeoModelAdmin(ModelAdmin):
                       }
         return OLMap
 
-if HAS_GDAL:
-    spherical_mercator_srid = 3857
 
-    class OSMGeoAdmin(GeoModelAdmin):
-        map_template = 'gis/admin/osm.html'
-        num_zoom = 20
-        map_srid = spherical_mercator_srid
-        max_extent = '-20037508,-20037508,20037508,20037508'
-        max_resolution = '156543.0339'
-        point_zoom = num_zoom - 6
-        units = 'm'
+class OSMGeoAdmin(GeoModelAdmin):
+    map_template = 'gis/admin/osm.html'
+    num_zoom = 20
+    map_srid = spherical_mercator_srid
+    max_extent = '-20037508,-20037508,20037508,20037508'
+    max_resolution = '156543.0339'
+    point_zoom = num_zoom - 6
+    units = 'm'
+
+    def __init__(self, *args):
+        if not HAS_GDAL:
+            raise ImproperlyConfigured("OSMGeoAdmin is not usable without GDAL libs installed")
+        super(OSMGeoAdmin, self).__init__(*args)
diff --git a/django/contrib/gis/geos/__init__.py b/django/contrib/gis/geos/__init__.py
index d5fe479..6e4bf69 100644
--- a/django/contrib/gis/geos/__init__.py
+++ b/django/contrib/gis/geos/__init__.py
@@ -1,7 +1,6 @@
 """
 The GeoDjango GEOS module.  Please consult the GeoDjango documentation
-for more details:
-  http://geodjango.org/docs/geos.html
+for more details: https://docs.djangoproject.com/en/dev/ref/contrib/gis/geos/
 """
 __all__ = ['HAS_GEOS']
 
diff --git a/django/contrib/gis/utils/layermapping.py b/django/contrib/gis/utils/layermapping.py
index c9badc7..a67729d 100644
--- a/django/contrib/gis/utils/layermapping.py
+++ b/django/contrib/gis/utils/layermapping.py
@@ -4,7 +4,7 @@
  vector files (e.g. SHP files) to Geographic-enabled Django models.
 
  For more information, please consult the GeoDjango documentation:
-   http://geodjango.org/docs/layermapping.html
+   https://docs.djangoproject.com/en/dev/ref/contrib/gis/layermapping/
 """
 import sys
 from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
diff --git a/django/contrib/postgres/fields/hstore.py b/django/contrib/postgres/fields/hstore.py
index 461fa04..b8e47ed 100644
--- a/django/contrib/postgres/fields/hstore.py
+++ b/django/contrib/postgres/fields/hstore.py
@@ -78,7 +78,7 @@ class KeyTransform(Transform):
 
     def as_sql(self, compiler, connection):
         lhs, params = compiler.compile(self.lhs)
-        return "%s -> '%s'" % (lhs, self.key_name), params
+        return "(%s -> '%s')" % (lhs, self.key_name), params
 
 
 class KeyTransformFactory(object):
diff --git a/django/contrib/sessions/backends/cached_db.py b/django/contrib/sessions/backends/cached_db.py
index 03e31d8..0ba12f5 100644
--- a/django/contrib/sessions/backends/cached_db.py
+++ b/django/contrib/sessions/backends/cached_db.py
@@ -79,7 +79,7 @@ class SessionStore(DBStore):
         """
         self.clear()
         self.delete(self.session_key)
-        self._session_key = ''
+        self._session_key = None
 
 # At bottom to avoid circular import
 from django.contrib.sessions.models import Session  # isort:skip
diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py
index 69ca669..c21036b 100644
--- a/django/contrib/sessions/middleware.py
+++ b/django/contrib/sessions/middleware.py
@@ -31,7 +31,8 @@ class SessionMiddleware(object):
             # First check if we need to delete this cookie.
             # The session should be deleted only if the session is entirely empty
             if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
-                response.delete_cookie(settings.SESSION_COOKIE_NAME)
+                response.delete_cookie(settings.SESSION_COOKIE_NAME,
+                    domain=settings.SESSION_COOKIE_DOMAIN)
             else:
                 if accessed:
                     patch_vary_headers(response, ('Cookie',))
diff --git a/django/db/backends/base/creation.py b/django/db/backends/base/creation.py
index 1b05a1c..2c803e5 100644
--- a/django/db/backends/base/creation.py
+++ b/django/db/backends/base/creation.py
@@ -514,7 +514,7 @@ class BaseDatabaseCreation(object):
         # ourselves. Connect to the previous database (not the test database)
         # to do so, because it's not allowed to delete a database while being
         # connected to it.
-        with self._nodb_connection.cursor() as cursor:
+        with self.connection._nodb_connection.cursor() as cursor:
             # Wait to avoid "database is being accessed by other users" errors.
             time.sleep(1)
             cursor.execute("DROP DATABASE %s"
diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py
index 041519b..bef956c 100644
--- a/django/db/backends/base/schema.py
+++ b/django/db/backends/base/schema.py
@@ -317,15 +317,7 @@ class BaseDatabaseSchemaEditor(object):
         news = set(tuple(fields) for fields in new_unique_together)
         # Deleted uniques
         for fields in olds.difference(news):
-            columns = [model._meta.get_field(field).column for field in fields]
-            constraint_names = self._constraint_names(model, columns, unique=True)
-            if len(constraint_names) != 1:
-                raise ValueError("Found wrong number (%s) of constraints for %s(%s)" % (
-                    len(constraint_names),
-                    model._meta.db_table,
-                    ", ".join(columns),
-                ))
-            self.execute(self._delete_constraint_sql(self.sql_delete_unique, model, constraint_names[0]))
+            self._delete_composed_index(model, fields, {'unique': True}, self.sql_delete_unique)
         # Created uniques
         for fields in news.difference(olds):
             columns = [model._meta.get_field(field).column for field in fields]
@@ -341,20 +333,23 @@ class BaseDatabaseSchemaEditor(object):
         news = set(tuple(fields) for fields in new_index_together)
         # Deleted indexes
         for fields in olds.difference(news):
-            columns = [model._meta.get_field(field).column for field in fields]
-            constraint_names = self._constraint_names(model, list(columns), index=True)
-            if len(constraint_names) != 1:
-                raise ValueError("Found wrong number (%s) of constraints for %s(%s)" % (
-                    len(constraint_names),
-                    model._meta.db_table,
-                    ", ".join(columns),
-                ))
-            self.execute(self._delete_constraint_sql(self.sql_delete_index, model, constraint_names[0]))
+            self._delete_composed_index(model, fields, {'index': True}, self.sql_delete_index)
         # Created indexes
         for field_names in news.difference(olds):
             fields = [model._meta.get_field(field) for field in field_names]
             self.execute(self._create_index_sql(model, fields, suffix="_idx"))
 
+    def _delete_composed_index(self, model, fields, constraint_kwargs, sql):
+        columns = [model._meta.get_field(field).column for field in fields]
+        constraint_names = self._constraint_names(model, columns, **constraint_kwargs)
+        if len(constraint_names) != 1:
+            raise ValueError("Found wrong number (%s) of constraints for %s(%s)" % (
+                len(constraint_names),
+                model._meta.db_table,
+                ", ".join(columns),
+            ))
+        self.execute(self._delete_constraint_sql(sql, model, constraint_names[0]))
+
     def alter_db_table(self, model, old_db_table, new_db_table):
         """
         Renames the table a model points to.
diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py
index f2f3f0a..7c40959 100644
--- a/django/db/backends/mysql/schema.py
+++ b/django/db/backends/mysql/schema.py
@@ -62,6 +62,24 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
                     field.db_index = False
         return super(DatabaseSchemaEditor, self)._model_indexes_sql(model)
 
+    def _delete_composed_index(self, model, fields, *args):
+        """
+        MySQL can remove an implicit FK index on a field when that field is
+        covered by another index like a unique_together. "covered" here means
+        that the more complex index starts like the simpler one.
+        http://bugs.mysql.com/bug.php?id=37910 / Django ticket #24757
+        We check here before removing the [unique|index]_together if we have to
+        recreate a FK index.
+        """
+        first_field = model._meta.get_field(fields[0])
+        if first_field.get_internal_type() == 'ForeignKey':
+            constraint_names = self._constraint_names(model, fields[0], index=True)
+            if not constraint_names:
+                self.execute(
+                    self._create_index_sql(model, [model._meta.get_field(fields[0])], suffix="")
+                )
+        return super(DatabaseSchemaEditor, self)._delete_composed_index(model, fields, *args)
+
     def _alter_column_type_sql(self, table, old_field, new_field, new_type):
         # Keep null property of old field, if it has changed, it will be handled separately
         if old_field.null:
diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
index d110b12..a76ca3c 100644
--- a/django/db/backends/postgresql_psycopg2/base.py
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -4,10 +4,14 @@ PostgreSQL database backend for Django.
 Requires psycopg 2: http://initd.org/projects/psycopg2
 """
 
+import warnings
+
 from django.conf import settings
 from django.core.exceptions import ImproperlyConfigured
+from django.db import DEFAULT_DB_ALIAS
 from django.db.backends.base.base import BaseDatabaseWrapper
 from django.db.backends.base.validation import BaseDatabaseValidation
+from django.db.utils import DatabaseError as WrappedDatabaseError
 from django.utils.encoding import force_str
 from django.utils.functional import cached_property
 from django.utils.safestring import SafeBytes, SafeText
@@ -231,6 +235,28 @@ class DatabaseWrapper(BaseDatabaseWrapper):
             return True
 
     @cached_property
+    def _nodb_connection(self):
+        nodb_connection = super(DatabaseWrapper, self)._nodb_connection
+        try:
+            nodb_connection.ensure_connection()
+        except (DatabaseError, WrappedDatabaseError):
+            warnings.warn(
+                "Normally Django will use a connection to the 'postgres' database "
+                "to avoid running initialization queries against the production "
+                "database when it's not needed (for example, when running tests). "
+                "Django was unable to create a connection to the 'postgres' database "
+                "and will use the default database instead.",
+                RuntimeWarning
+            )
+            settings_dict = self.settings_dict.copy()
+            settings_dict['NAME'] = settings.DATABASES[DEFAULT_DB_ALIAS]['NAME']
+            nodb_connection = self.__class__(
+                self.settings_dict.copy(),
+                alias=self.alias,
+                allow_thread_sharing=False)
+        return nodb_connection
+
+    @cached_property
     def psycopg2_version(self):
         return PSYCOPG2_VERSION
 
diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py
index 5a21af7..d68312b 100644
--- a/django/db/backends/sqlite3/schema.py
+++ b/django/db/backends/sqlite3/schema.py
@@ -1,4 +1,3 @@
-import _sqlite3  # isort:skip
 import codecs
 import copy
 from decimal import Decimal
@@ -14,6 +13,10 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
     sql_create_inline_fk = "REFERENCES %(to_table)s (%(to_column)s)"
 
     def quote_value(self, value):
+        # The backend "mostly works" without this function and there are use
+        # cases for compiling Python without the sqlite3 libraries (e.g.
+        # security hardening).
+        import _sqlite3
         try:
             value = _sqlite3.adapt(value)
         except _sqlite3.ProgrammingError:
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index c6959f8..4306193 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -780,6 +780,11 @@ class Case(Expression):
         c.default = c.default.resolve_expression(query, allow_joins, reuse, summarize, for_save)
         return c
 
+    def copy(self):
+        c = super(Case, self).copy()
+        c.cases = c.cases[:]
+        return c
+
     def as_sql(self, compiler, connection, template=None, extra=None):
         connection.ops.check_expression_support(self)
         if not self.cases:
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index a499fef..6fa4695 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -1939,6 +1939,9 @@ class ForeignKey(ForeignObject):
         else:
             return self.related_field.get_db_prep_save(value, connection=connection)
 
+    def get_db_prep_value(self, value, connection, prepared=False):
+        return self.related_field.get_db_prep_value(value, connection, prepared)
+
     def value_to_string(self, obj):
         if not obj:
             # In required many-to-one fields with only one available choice,
diff --git a/django/db/models/options.py b/django/db/models/options.py
index e029ffe..0525607 100644
--- a/django/db/models/options.py
+++ b/django/db/models/options.py
@@ -727,9 +727,9 @@ class Options(object):
 
     def get_fields(self, include_parents=True, include_hidden=False):
         """
-        Returns a list of fields associated to the model. By default will only
-        return forward fields. This can be changed by enabling or disabling
-        field types using the parameters:
+        Returns a list of fields associated to the model. By default, includes
+        forward and reverse fields, fields derived from inheritance, but not
+        hidden fields. The returned fields can be changed using the parameters:
 
         - include_parents: include fields derived from inheritance
         - include_hidden:  include fields that have a related_name that
diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py
index 10580f7..eca060e 100644
--- a/django/db/models/query_utils.py
+++ b/django/db/models/query_utils.py
@@ -85,7 +85,12 @@ class Q(tree.Node):
         return clone
 
     def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
-        clause, _ = query._add_q(self, reuse, allow_joins=allow_joins)
+        # We must promote any new joins to left outer joins so that when Q is
+        # used as an expression, rows aren't filtered due to joins.
+        joins_before = query.tables[:]
+        clause, joins = query._add_q(self, reuse, allow_joins=allow_joins, split_subq=False)
+        joins_to_promote = [j for j in joins if j not in joins_before]
+        query.promote_joins(joins_to_promote)
         return clause
 
     @classmethod
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 810031f..6aab204 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -145,9 +145,12 @@ class SQLCompiler(object):
             # then also add having expressions to group by.
             pk = None
             for expr in expressions:
-                if (expr.output_field.primary_key and
-                        getattr(expr.output_field, 'model') == self.query.model):
+                # Is this a reference to query's base table primary key? If the
+                # expression isn't a Col-like, then skip the expression.
+                if (getattr(expr, 'target', None) == self.query.model._meta.pk and
+                        getattr(expr, 'alias', None) == self.query.tables[0]):
                     pk = expr
+                    break
             if pk:
                 expressions = [pk] + [expr for expr in expressions if expr in having]
         return expressions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 387b91a..6f88303 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1112,7 +1112,7 @@ class Query(object):
                 (name, lhs.output_field.__class__.__name__))
 
     def build_filter(self, filter_expr, branch_negated=False, current_negated=False,
-                     can_reuse=None, connector=AND, allow_joins=True):
+                     can_reuse=None, connector=AND, allow_joins=True, split_subq=True):
         """
         Builds a WhereNode for a single filter clause, but doesn't add it
         to this Query. Query.add_q() will then add this filter to the where
@@ -1161,7 +1161,7 @@ class Query(object):
 
         opts = self.get_meta()
         alias = self.get_initial_alias()
-        allow_many = not branch_negated
+        allow_many = not branch_negated or not split_subq
 
         try:
             field, sources, opts, join_list, path = self.setup_joins(
@@ -1309,7 +1309,7 @@ class Query(object):
         self.demote_joins(existing_inner)
 
     def _add_q(self, q_object, used_aliases, branch_negated=False,
-               current_negated=False, allow_joins=True):
+               current_negated=False, allow_joins=True, split_subq=True):
         """
         Adds a Q-object to the current filter.
         """
@@ -1323,12 +1323,14 @@ class Query(object):
             if isinstance(child, Node):
                 child_clause, needed_inner = self._add_q(
                     child, used_aliases, branch_negated,
-                    current_negated, allow_joins)
+                    current_negated, allow_joins, split_subq)
                 joinpromoter.add_votes(needed_inner)
             else:
                 child_clause, needed_inner = self.build_filter(
                     child, can_reuse=used_aliases, branch_negated=branch_negated,
-                    current_negated=current_negated, connector=connector, allow_joins=allow_joins)
+                    current_negated=current_negated, connector=connector,
+                    allow_joins=allow_joins, split_subq=split_subq,
+                )
                 joinpromoter.add_votes(needed_inner)
             target_clause.add(child_clause, connector)
         needed_inner = joinpromoter.update_join_types(self)
diff --git a/django/template/utils.py b/django/template/utils.py
index 514df91..ea72a8c 100644
--- a/django/template/utils.py
+++ b/django/template/utils.py
@@ -50,6 +50,7 @@ class EngineHandler(object):
             ]
 
         templates = OrderedDict()
+        backend_names = []
         for tpl in self._templates:
             tpl = tpl.copy()
             try:
@@ -68,8 +69,9 @@ class EngineHandler(object):
             tpl.setdefault('OPTIONS', {})
 
             templates[tpl['NAME']] = tpl
+            backend_names.append(tpl['NAME'])
 
-        counts = Counter(list(templates))
+        counts = Counter(backend_names)
         duplicates = [alias for alias, count in counts.most_common() if count > 1]
         if duplicates:
             raise ImproperlyConfigured(
diff --git a/docs/howto/writing-migrations.txt b/docs/howto/writing-migrations.txt
index 37a8b4e..2daf6ad 100644
--- a/docs/howto/writing-migrations.txt
+++ b/docs/howto/writing-migrations.txt
@@ -57,6 +57,7 @@ Then, to leverage this in your migrations, do the following::
 
     def forwards(apps, schema_editor):
         # Your migration code goes here
+        ...
 
     class Migration(migrations.Migration):
 
@@ -83,44 +84,76 @@ Therefore, the following steps should be taken. In this example, we'll add a
 non-nullable :class:`~django.db.models.UUIDField` with a default value. Modify
 the respective field according to your needs.
 
-* Add the field on your model with ``default=...`` and ``unique=True``
-  arguments. In the example, we use ``uuid.uuid4`` for the default.
+* Add the field on your model with ``default=uuid.uuid4`` and ``unique=True``
+  arguments (choose an appropriate default for the type of the field you're
+  adding).
 
-* Run the :djadmin:`makemigrations` command.
+* Run the :djadmin:`makemigrations` command. This should generate a migration
+  with an ``AddField`` operation.
 
-* Edit the created migration file.
+* Generate two empty migration files for the same app by running
+  ``makemigrations myapp --empty`` twice. We've renamed the migration files to
+  give them meaningful names in the examples below.
+
+* Copy the ``AddField`` operation from the auto-generated migration (the first
+  of the three new files) to the last migration and change ``AddField`` to
+  ``AlterField``. For example:
+
+  .. snippet::
+    :filename: 0006_remove_uuid_null.py
+
+    # -*- coding: utf-8 -*-
+    from __future__ import unicode_literals
+
+    from django.db import migrations, models
+    import uuid
 
-  The generated migration class should look similar to this::
 
     class Migration(migrations.Migration):
 
         dependencies = [
-            ('myapp', '0003_auto_20150129_1705'),
+            ('myapp', '0005_populate_uuid_values'),
         ]
 
         operations = [
-            migrations.AddField(
+            migrations.AlterField(
                 model_name='mymodel',
                 name='uuid',
-                field=models.UUIDField(max_length=32, unique=True, default=uuid.uuid4),
+                field=models.UUIDField(default=uuid.uuid4, unique=True),
             ),
         ]
 
-  You will need to make three changes:
+* Edit the first migration file. The generated migration class should look
+  similar to this:
+
+  .. snippet::
+    :filename: 0004_add_uuid_field.py
+
+    class Migration(migrations.Migration):
+
+        dependencies = [
+            ('myapp', '0003_auto_20150129_1705'),
+        ]
 
-  * Add a second :class:`~django.db.migrations.operations.AddField` operation
-    copied from the generated one and change it to
-    :class:`~django.db.migrations.operations.AlterField`.
+        operations = [
+            migrations.AddField(
+                model_name='mymodel',
+                name='uuid',
+                field=models.UUIDField(default=uuid.uuid4, unique=True),
+            ),
+        ]
 
-  * On the first operation (``AddField``), change ``unique=True`` to
-    ``null=True`` -- this will create the intermediary null field.
+  Change ``unique=True`` to ``null=True`` -- this will create the intermediary
+  null field and defer creating the unique constraint until we've populated
+  unique values on all the rows.
 
-  * Between the two operations, add a
-    :class:`~django.db.migrations.operations.RunPython` or
-    :class:`~django.db.migrations.operations.RunSQL` operation to generate a
-    unique value (UUID in the example) for each existing row.
+* In the first empty migration file, add a
+  :class:`~django.db.migrations.operations.RunPython` or
+  :class:`~django.db.migrations.operations.RunSQL` operation to generate a
+  unique value (UUID in the example) for each existing row. For example:
 
-  The resulting migration should look similar to this::
+  .. snippet::
+    :filename: 0005_populate_uuid_values.py
 
     # -*- coding: utf-8 -*-
     from __future__ import unicode_literals
@@ -137,25 +170,15 @@ the respective field according to your needs.
     class Migration(migrations.Migration):
 
         dependencies = [
-            ('myapp', '0003_auto_20150129_1705'),
+            ('myapp', '0004_add_uuid_field'),
         ]
 
         operations = [
-            migrations.AddField(
-                model_name='mymodel',
-                name='uuid',
-                field=models.UUIDField(default=uuid.uuid4, null=True),
-            ),
             # omit reverse_code=... if you don't want the migration to be reversible.
             migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop),
-            migrations.AlterField(
-                model_name='mymodel',
-                name='uuid',
-                field=models.UUIDField(default=uuid.uuid4, unique=True),
-            ),
         ]
 
-* Now you can apply the migration as usual with the :djadmin:`migrate` command.
+* Now you can apply the migrations as usual with the :djadmin:`migrate` command.
 
   Note there is a race condition if you allow objects to be created while this
   migration is running. Objects created after the ``AddField`` and before
diff --git a/docs/intro/tutorial01.txt b/docs/intro/tutorial01.txt
index b91c1da..ac0e4ff 100644
--- a/docs/intro/tutorial01.txt
+++ b/docs/intro/tutorial01.txt
@@ -121,7 +121,7 @@ These files are:
 Database setup
 --------------
 
-Now, edit :file:`mysite/settings.py`. It's a normal Python module with
+Now, open up :file:`mysite/settings.py`. It's a normal Python module with
 module-level variables representing Django settings.
 
 By default, the configuration uses SQLite. If you're new to databases, or
@@ -188,7 +188,7 @@ come with Django:
 
 These applications are included by default as a convenience for the common case.
 
-Some of these applications makes use of at least one database table, though,
+Some of these applications make 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:
 
@@ -263,7 +263,7 @@ It worked!
 
     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:
+    computers on your network), use:
 
     .. code-block:: console
 
@@ -518,8 +518,8 @@ Note the following:
 * 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 autoincrement`` (SQLite) are handled for you automatically. Same
-  goes for quoting of field names -- e.g., using double quotes or single
-  quotes.
+  goes for the quoting of field names -- e.g., using double quotes or 
+  single quotes.
 
 * The :djadmin:`sqlmigrate` command doesn't actually run the migration on your
   database - it just prints it to the screen so that you can see what SQL
@@ -565,10 +565,10 @@ but for now, remember the three-step guide to making model changes:
 * Run :djadmin:`python manage.py migrate <migrate>` to apply those changes to
   the database.
 
-The reason there's separate commands to make and apply migrations is because
-you'll commit migrations to your version control system and ship them with
-your app; they not only make your development easier, they're also useable by
-other developers and in production.
+The reason that there are separate commands to make and apply migrations is 
+because you'll commit migrations to your version control system and ship them 
+with your app; they not only make your development easier, they're also 
+useable by other developers and in production.
 
 Read the :doc:`django-admin documentation </ref/django-admin>` for full
 information on what the ``manage.py`` utility can do.
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index 0250f8d..6ae67a2 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -1294,7 +1294,7 @@ templates used by the :class:`ModelAdmin` views:
 
 .. method:: ModelAdmin.get_ordering(request)
 
-    The ``get_ordering`` method takes a``request`` as parameter and
+    The ``get_ordering`` method takes a ``request`` as parameter and
     is expected to return a ``list`` or ``tuple`` for ordering similar
     to the :attr:`ordering` attribute. For example::
 
diff --git a/docs/ref/contrib/gis/geoquerysets.txt b/docs/ref/contrib/gis/geoquerysets.txt
index ae99b3e..779f6e4 100644
--- a/docs/ref/contrib/gis/geoquerysets.txt
+++ b/docs/ref/contrib/gis/geoquerysets.txt
@@ -279,7 +279,7 @@ 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*'))
+    Zipcode.objects.filter(poly__relate=(geom, 'T*T***FF*'))
 
 PostGIS SQL equivalent::
 
@@ -301,7 +301,7 @@ strings are case-insensitive.
 
 Example::
 
-    Zipcode.objects.filter(poly__relate(geom, 'anyinteract'))
+    Zipcode.objects.filter(poly__relate=(geom, 'anyinteract'))
 
 Oracle SQL equivalent::
 
diff --git a/docs/ref/contrib/sitemaps.txt b/docs/ref/contrib/sitemaps.txt
index b28b9b4..a0490fd 100644
--- a/docs/ref/contrib/sitemaps.txt
+++ b/docs/ref/contrib/sitemaps.txt
@@ -234,6 +234,15 @@ Sitemap class reference
         sitemap was requested is used. If the sitemap is built outside the
         context of a request, the default is ``'http'``.
 
+    .. attribute:: Sitemap.limit
+
+        **Optional.**
+
+        This attribute defines the maximum number of URLs included on each page
+        of the sitemap. Its value should not exceed the default value of
+        ``50000``, which is the upper limit allowed in the `Sitemaps protocol
+        <http://www.sitemaps.org/protocol.html#index>`_.
+
     .. attribute:: Sitemap.i18n
 
         .. versionadded:: 1.8
diff --git a/docs/ref/exceptions.txt b/docs/ref/exceptions.txt
index 61f5e7f..46a0c81 100644
--- a/docs/ref/exceptions.txt
+++ b/docs/ref/exceptions.txt
@@ -12,25 +12,17 @@ Django Core Exceptions
 
 Django core exception classes are defined in ``django.core.exceptions``.
 
-``ObjectDoesNotExist`` and ``DoesNotExist``
--------------------------------------------
-
-.. exception:: DoesNotExist
-
-    The ``DoesNotExist`` exception is raised when an object is not found for
-    the given parameters of a query. Django provides a ``DoesNotExist``
-    exception as an attribute of each model class to identify the class of
-    object that could not be found and to allow you to catch a particular model
-    class with ``try/except``.
+``ObjectDoesNotExist``
+----------------------
 
 .. exception:: ObjectDoesNotExist
 
-    The base class for ``DoesNotExist`` exceptions; a ``try/except`` for
-    ``ObjectDoesNotExist`` will catch ``DoesNotExist`` exceptions for all
-    models.
+    The base class for :exc:`~django.db.models.Model.DoesNotExist` exceptions;
+    a ``try/except`` for ``ObjectDoesNotExist`` will catch
+    :exc:`~django.db.models.Model.DoesNotExist` exceptions for all models.
 
     See :meth:`~django.db.models.query.QuerySet.get()` for further information
-    on :exc:`ObjectDoesNotExist` and :exc:`DoesNotExist`.
+    on :exc:`ObjectDoesNotExist` and :exc:`~django.db.models.Model.DoesNotExist`.
 
 ``FieldDoesNotExist``
 ---------------------
diff --git a/docs/ref/migration-operations.txt b/docs/ref/migration-operations.txt
index 76e8cae..9c42f44 100644
--- a/docs/ref/migration-operations.txt
+++ b/docs/ref/migration-operations.txt
@@ -331,11 +331,23 @@ or that you use :class:`SeparateDatabaseAndState` to add in operations that will
 reflect your changes to the model state - otherwise, the versioned ORM and
 the autodetector will stop working correctly.
 
-By default, ``RunPython`` will run its contents inside a transaction even
-on databases that do not support DDL transactions (for example, MySQL and
+By default, ``RunPython`` will run its contents inside a transaction on
+databases that do not support DDL transactions (for example, MySQL and
 Oracle). This should be safe, but may cause a crash if you attempt to use
-the ``schema_editor`` provided on these backends; in this case, please
-set ``atomic=False``.
+the ``schema_editor`` provided on these backends; in this case, pass
+``atomic=False`` to the ``RunPython`` operation.
+
+On databases that do support DDL transactions (SQLite and PostgreSQL),
+``RunPython`` operations do not have any transactions automatically added
+besides the transactions created for each migration (the ``atomic`` parameter
+has no effect on these databases). Thus, on PostgreSQL, for example, you should
+avoid combining schema changes and ``RunPython`` operations in the same
+migration or you may hit errors like ``OperationalError: cannot ALTER TABLE
+"mytable" because it has pending trigger events``.
+
+If you have a different database and aren't sure if it supports DDL
+transactions, check the ``django.db.connection.features.can_rollback_ddl``
+attribute.
 
 .. warning::
 
diff --git a/docs/ref/models/expressions.txt b/docs/ref/models/expressions.txt
index f592bc3..8d6ed19 100644
--- a/docs/ref/models/expressions.txt
+++ b/docs/ref/models/expressions.txt
@@ -593,7 +593,7 @@ to play nice with other query expressions::
     def get_source_expressions(self):
         return self.expressions
 
-    def set_source_expressions(expressions):
+    def set_source_expressions(self, expressions):
         self.expressions = expressions
 
 Let's see how it works::
diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt
index c294704..da567d2 100644
--- a/docs/ref/models/instances.txt
+++ b/docs/ref/models/instances.txt
@@ -826,7 +826,7 @@ For every :class:`~django.db.models.DateField` and
 <django.db.models.Field.null>`, 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
-a :exc:`~django.core.exceptions.DoesNotExist` exception when appropriate.
+a :exc:`~django.db.models.Model.DoesNotExist` exception when appropriate.
 
 Both of these methods will perform their queries using the default
 manager for the model. If you need to emulate filtering used by a
@@ -837,3 +837,20 @@ format described in :ref:`Field lookups <field-lookups>`.
 Note that in the case of identical date values, these methods will use the
 primary key as a tie-breaker. This guarantees that no records are skipped or
 duplicated. That also means you cannot use those methods on unsaved objects.
+
+Other attributes
+================
+
+``DoesNotExist``
+----------------
+
+.. exception:: Model.DoesNotExist
+
+    This exception is raised by the ORM in a couple places, for example by
+    :meth:`QuerySet.get() <django.db.models.query.QuerySet.get>` when an object
+    is not found for the given query parameters.
+
+    Django provides a ``DoesNotExist`` exception as an attribute of each model
+    class to identify the class of object that could not be found and to allow
+    you to catch a particular model class with ``try/except``. The exception is
+    a subclass of :exc:`django.core.exceptions.ObjectDoesNotExist`.
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index e6e2335..673037e 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -1578,15 +1578,15 @@ than one object was found. The
 :exc:`~django.core.exceptions.MultipleObjectsReturned` exception is an
 attribute of the model class.
 
-``get()`` raises a :exc:`~django.core.exceptions.DoesNotExist` exception if an
-object wasn't found for the given parameters. This exception is also an
-attribute of the model class. Example::
+``get()`` raises a :exc:`~django.db.models.Model.DoesNotExist` exception if an
+object wasn't found for the given parameters. This exception is an attribute
+of the model class. Example::
 
     Entry.objects.get(id='foo') # raises Entry.DoesNotExist
 
-The :exc:`~django.core.exceptions.DoesNotExist` exception inherits from
+The :exc:`~django.db.models.Model.DoesNotExist` exception inherits from
 :exc:`django.core.exceptions.ObjectDoesNotExist`, so you can target multiple
-:exc:`~django.core.exceptions.DoesNotExist` exceptions. Example::
+:exc:`~django.db.models.Model.DoesNotExist` exceptions. Example::
 
     from django.core.exceptions import ObjectDoesNotExist
     try:
@@ -1905,7 +1905,7 @@ If your model's :ref:`Meta <meta-options>` specifies
 field specified in :attr:`~django.db.models.Options.get_latest_by` by default.
 
 Like :meth:`get()`, ``earliest()`` and ``latest()`` raise
-:exc:`~django.core.exceptions.DoesNotExist` if there is no object with the
+:exc:`~django.db.models.Model.DoesNotExist` if there is no object with the
 given parameters.
 
... 1027 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-django.git



More information about the Python-modules-commits mailing list