diff options
author | Arthur Koziel <arthur@arthurkoziel.com> | 2010-09-13 00:04:27 +0000 |
---|---|---|
committer | Arthur Koziel <arthur@arthurkoziel.com> | 2010-09-13 00:04:27 +0000 |
commit | dd49269c7db008b2567f50cb03c4d3d9b321daa1 (patch) | |
tree | 326dd25bb045ac016cda7966b43cbdfe1f67d699 /django/db | |
parent | c9b188c4ec939abbe48dae5a371276742e64b6b8 (diff) | |
download | django-soc2010/app-loading.tar.gz |
[soc2010/app-loading] merged trunkarchive/soc2010/app-loadingsoc2010/app-loading
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2010/app-loading@13818 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db')
-rw-r--r-- | django/db/__init__.py | 2 | ||||
-rw-r--r-- | django/db/backends/__init__.py | 5 | ||||
-rw-r--r-- | django/db/backends/creation.py | 17 | ||||
-rw-r--r-- | django/db/backends/mysql/base.py | 2 | ||||
-rw-r--r-- | django/db/backends/mysql/client.py | 5 | ||||
-rw-r--r-- | django/db/backends/oracle/base.py | 2 | ||||
-rw-r--r-- | django/db/backends/oracle/creation.py | 6 | ||||
-rw-r--r-- | django/db/backends/postgresql/base.py | 5 | ||||
-rw-r--r-- | django/db/backends/postgresql/creation.py | 5 | ||||
-rw-r--r-- | django/db/backends/postgresql/operations.py | 31 | ||||
-rw-r--r-- | django/db/backends/postgresql_psycopg2/base.py | 2 | ||||
-rw-r--r-- | django/db/backends/signals.py | 2 | ||||
-rw-r--r-- | django/db/backends/sqlite3/base.py | 2 | ||||
-rw-r--r-- | django/db/backends/sqlite3/creation.py | 6 | ||||
-rw-r--r-- | django/db/models/base.py | 15 | ||||
-rw-r--r-- | django/db/models/fields/__init__.py | 19 | ||||
-rw-r--r-- | django/db/models/fields/related.py | 23 | ||||
-rw-r--r-- | django/db/models/query.py | 5 | ||||
-rw-r--r-- | django/db/models/signals.py | 10 | ||||
-rw-r--r-- | django/db/models/sql/query.py | 5 |
20 files changed, 103 insertions, 66 deletions
diff --git a/django/db/__init__.py b/django/db/__init__.py index 4bae04ab9a..4c4faef694 100644 --- a/django/db/__init__.py +++ b/django/db/__init__.py @@ -35,6 +35,8 @@ if DEFAULT_DB_ALIAS not in settings.DATABASES: raise ImproperlyConfigured("You must default a '%s' database" % DEFAULT_DB_ALIAS) for alias, database in settings.DATABASES.items(): + if 'ENGINE' not in database: + raise ImproperlyConfigured("You must specify a 'ENGINE' for database '%s'" % alias) if database['ENGINE'] in ("postgresql", "postgresql_psycopg2", "sqlite3", "mysql", "oracle"): import warnings if 'django.contrib.gis' in settings.INSTALLED_APPS: diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index 5918935899..fe2c7c451b 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -353,6 +353,11 @@ class BaseDatabaseOperations(object): """ return "BEGIN;" + def end_transaction_sql(self, success=True): + if not success: + return "ROLLBACK;" + return "COMMIT;" + def tablespace_sql(self, tablespace, inline=False): """ Returns the SQL that will be appended to tables or rows to define diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py index 492ac1e3e9..6cdf415f7a 100644 --- a/django/db/backends/creation.py +++ b/django/db/backends/creation.py @@ -350,12 +350,17 @@ class BaseDatabaseCreation(object): can_rollback = self._rollback_works() self.connection.settings_dict["SUPPORTS_TRANSACTIONS"] = can_rollback - call_command('syncdb', verbosity=verbosity, interactive=False, database=self.connection.alias) + # Report syncdb messages at one level lower than that requested. + # This ensures we don't get flooded with messages during testing + # (unless you really ask to be flooded) + call_command('syncdb', verbosity=max(verbosity - 1, 0), interactive=False, database=self.connection.alias) if settings.CACHE_BACKEND.startswith('db://'): - from django.core.cache import parse_backend_uri - _, cache_name, _ = parse_backend_uri(settings.CACHE_BACKEND) - call_command('createcachetable', cache_name) + from django.core.cache import parse_backend_uri, cache + from django.db import router + if router.allow_syncdb(self.connection.alias, cache.cache_model_class): + _, cache_name, _ = parse_backend_uri(settings.CACHE_BACKEND) + call_command('createcachetable', cache_name, database=self.connection.alias) # Get a cursor (even though we don't need one yet). This has # the side effect of initializing the test database. @@ -388,10 +393,8 @@ class BaseDatabaseCreation(object): if autoclobber or confirm == 'yes': try: if verbosity >= 1: - print "Destroying old test database..." + print "Destroying old test database '%s'..." % self.connection.alias cursor.execute("DROP DATABASE %s" % qn(test_database_name)) - if verbosity >= 1: - print "Creating test database..." cursor.execute("CREATE DATABASE %s %s" % (qn(test_database_name), suffix)) except Exception, e: sys.stderr.write("Got an error recreating the test database: %s\n" % e) diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index e94e24bff9..a39c41f8d8 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -297,7 +297,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): self.connection = Database.connect(**kwargs) self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode] self.connection.encoders[SafeString] = self.connection.encoders[str] - connection_created.send(sender=self.__class__) + connection_created.send(sender=self.__class__, connection=self) cursor = CursorWrapper(self.connection.cursor()) return cursor diff --git a/django/db/backends/mysql/client.py b/django/db/backends/mysql/client.py index ff5b64d1e0..24dc642abe 100644 --- a/django/db/backends/mysql/client.py +++ b/django/db/backends/mysql/client.py @@ -24,7 +24,10 @@ class DatabaseClient(BaseDatabaseClient): if passwd: args += ["--password=%s" % passwd] if host: - args += ["--host=%s" % host] + if '/' in host: + args += ["--socket=%s" % host] + else: + args += ["--host=%s" % host] if port: args += ["--port=%s" % port] if db: diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py index 369e65baf7..0cf26c406d 100644 --- a/django/db/backends/oracle/base.py +++ b/django/db/backends/oracle/base.py @@ -384,7 +384,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): # Django docs specify cx_Oracle version 4.3.1 or higher, but # stmtcachesize is available only in 4.3.2 and up. pass - connection_created.send(sender=self.__class__) + connection_created.send(sender=self.__class__, connection=self) if not cursor: cursor = FormatStylePlaceholderCursor(self.connection) return cursor diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py index e6e242b9f7..8167640aac 100644 --- a/django/db/backends/oracle/creation.py +++ b/django/db/backends/oracle/creation.py @@ -61,8 +61,6 @@ class DatabaseCreation(BaseDatabaseCreation): cursor = self.connection.cursor() if self._test_database_create(): - if verbosity >= 1: - print 'Creating test database...' try: self._execute_test_db_creation(cursor, parameters, verbosity) except Exception, e: @@ -72,10 +70,8 @@ class DatabaseCreation(BaseDatabaseCreation): if autoclobber or confirm == 'yes': try: if verbosity >= 1: - print "Destroying old test database..." + print "Destroying old test database '%s'..." % self.connection.alias self._execute_test_db_destruction(cursor, parameters, verbosity) - if verbosity >= 1: - print "Creating test database..." self._execute_test_db_creation(cursor, parameters, verbosity) except Exception, e: sys.stderr.write("Got an error recreating the test database: %s\n" % e) diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py index a1c858bd8f..f84ad1da61 100644 --- a/django/db/backends/postgresql/base.py +++ b/django/db/backends/postgresql/base.py @@ -135,8 +135,9 @@ class DatabaseWrapper(BaseDatabaseWrapper): if settings_dict['PORT']: conn_string += " port=%s" % settings_dict['PORT'] self.connection = Database.connect(conn_string, **settings_dict['OPTIONS']) - self.connection.set_isolation_level(1) # make transactions transparent to all cursors - connection_created.send(sender=self.__class__) + # make transactions transparent to all cursors + self.connection.set_isolation_level(1) + connection_created.send(sender=self.__class__, connection=self) cursor = self.connection.cursor() if new_connection: if set_tz: diff --git a/django/db/backends/postgresql/creation.py b/django/db/backends/postgresql/creation.py index af26d0b78f..9984716389 100644 --- a/django/db/backends/postgresql/creation.py +++ b/django/db/backends/postgresql/creation.py @@ -1,4 +1,5 @@ from django.db.backends.creation import BaseDatabaseCreation +from django.db.backends.util import truncate_name class DatabaseCreation(BaseDatabaseCreation): # This dictionary maps Field objects to their associated PostgreSQL column @@ -51,7 +52,7 @@ class DatabaseCreation(BaseDatabaseCreation): def get_index_sql(index_name, opclass=''): return (style.SQL_KEYWORD('CREATE INDEX') + ' ' + - style.SQL_TABLE(qn(index_name)) + ' ' + + style.SQL_TABLE(qn(truncate_name(index_name,self.connection.ops.max_name_length()))) + ' ' + style.SQL_KEYWORD('ON') + ' ' + style.SQL_TABLE(qn(db_table)) + ' ' + "(%s%s)" % (style.SQL_FIELD(qn(f.column)), opclass) + @@ -63,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')) diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py index 2951c33db9..e8ce3f242b 100644 --- a/django/db/backends/postgresql/operations.py +++ b/django/db/backends/postgresql/operations.py @@ -54,7 +54,10 @@ class DatabaseOperations(BaseDatabaseOperations): return '%s' def last_insert_id(self, cursor, table_name, pk_name): - cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (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'))" % ( + self.quote_name(table_name), pk_name)) return cursor.fetchone()[0] def no_limit_value(self): @@ -90,13 +93,14 @@ class DatabaseOperations(BaseDatabaseOperations): for sequence_info in sequences: table_name = sequence_info['table'] column_name = sequence_info['column'] - if column_name and len(column_name) > 0: - sequence_name = '%s_%s_seq' % (table_name, column_name) - else: - sequence_name = '%s_id_seq' % table_name - sql.append("%s setval('%s', 1, false);" % \ + if not (column_name and len(column_name) > 0): + # This will be the case if it's an m2m using an autogenerated + # intermediate table (see BaseDatabaseIntrospection.sequence_list) + column_name = 'id' + sql.append("%s setval(pg_get_serial_sequence('%s','%s'), 1, false);" % \ (style.SQL_KEYWORD('SELECT'), - style.SQL_FIELD(self.quote_name(sequence_name))) + style.SQL_TABLE(self.quote_name(table_name)), + style.SQL_FIELD(column_name)) ) return sql else: @@ -110,11 +114,15 @@ class DatabaseOperations(BaseDatabaseOperations): # Use `coalesce` to set the sequence for each model to the max pk value if there are records, # or 1 if there are none. Set the `is_called` property (the third argument to `setval`) to true # if there are records (as the max pk value is already in use), otherwise set it to false. + # Use pg_get_serial_sequence to get the underlying sequence name from the table name + # and column name (available since PostgreSQL 8) + for f in model._meta.local_fields: if isinstance(f, models.AutoField): - output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \ + 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_FIELD(qn('%s_%s_seq' % (model._meta.db_table, f.column))), + 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)), style.SQL_KEYWORD('IS NOT'), @@ -123,9 +131,10 @@ class DatabaseOperations(BaseDatabaseOperations): break # Only one AutoField is allowed per model, so don't bother continuing. for f in model._meta.many_to_many: if not f.rel.through: - output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \ + 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_FIELD(qn('%s_id_seq' % f.m2m_db_table())), + style.SQL_TABLE(qn(f.m2m_db_table())), + style.SQL_FIELD('id'), style.SQL_FIELD(qn('id')), style.SQL_FIELD(qn('id')), style.SQL_KEYWORD('IS NOT'), diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py index 29b7e7ff1a..ce4e48330e 100644 --- a/django/db/backends/postgresql_psycopg2/base.py +++ b/django/db/backends/postgresql_psycopg2/base.py @@ -136,7 +136,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): self.connection = Database.connect(**conn_params) self.connection.set_client_encoding('UTF8') self.connection.set_isolation_level(self.isolation_level) - connection_created.send(sender=self.__class__) + connection_created.send(sender=self.__class__, connection=self) cursor = self.connection.cursor() cursor.tzinfo_factory = None if new_connection: diff --git a/django/db/backends/signals.py b/django/db/backends/signals.py index a8079d0d76..c16a63f9f6 100644 --- a/django/db/backends/signals.py +++ b/django/db/backends/signals.py @@ -1,3 +1,3 @@ from django.dispatch import Signal -connection_created = Signal() +connection_created = Signal(providing_args=["connection"]) diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index bc97f5cfd8..1ab2557627 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -176,7 +176,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): self.connection.create_function("django_extract", 2, _sqlite_extract) self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc) self.connection.create_function("regexp", 2, _sqlite_regexp) - connection_created.send(sender=self.__class__) + connection_created.send(sender=self.__class__, connection=self) return self.connection.cursor(factory=SQLiteCursorWrapper) def close(self): diff --git a/django/db/backends/sqlite3/creation.py b/django/db/backends/sqlite3/creation.py index 03897078a2..a65db1160b 100644 --- a/django/db/backends/sqlite3/creation.py +++ b/django/db/backends/sqlite3/creation.py @@ -43,14 +43,12 @@ class DatabaseCreation(BaseDatabaseCreation): if test_database_name and test_database_name != ":memory:": # Erase the old test database if verbosity >= 1: - print "Destroying old test database..." + print "Destroying old test database '%s'..." % self.connection.alias if os.access(test_database_name, os.F_OK): if not autoclobber: confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % test_database_name) if autoclobber or confirm == 'yes': try: - if verbosity >= 1: - print "Destroying old test database..." os.remove(test_database_name) except Exception, e: sys.stderr.write("Got an error deleting the old test database: %s\n" % e) @@ -58,8 +56,6 @@ class DatabaseCreation(BaseDatabaseCreation): else: print "Tests cancelled." sys.exit(1) - if verbosity >= 1: - print "Creating test database..." else: test_database_name = ":memory:" return test_database_name diff --git a/django/db/models/base.py b/django/db/models/base.py index 6304e009d3..b3deda13d4 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -1,6 +1,5 @@ import types import sys -import os from itertools import izip import django.db.models.manager # Imported to register signal handler. from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS @@ -16,7 +15,7 @@ from django.db.models.loading import register_models, get_model from django.utils.translation import ugettext_lazy as _ import django.utils.copycompat as copy from django.utils.functional import curry, update_wrapper -from django.utils.encoding import smart_str, force_unicode, smart_unicode +from django.utils.encoding import smart_str, force_unicode from django.utils.text import get_text_list, capfirst from django.conf import settings @@ -456,7 +455,7 @@ class Model(object): meta = cls._meta if origin and not meta.auto_created: - signals.pre_save.send(sender=origin, instance=self, raw=raw) + signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using) # If we are in a raw save, save the object exactly as presented. # That means that we don't try to be smart about saving attributes @@ -540,7 +539,7 @@ class Model(object): # Signal that the save is complete if origin and not meta.auto_created: signals.post_save.send(sender=origin, instance=self, - created=(not record_exists), raw=raw) + created=(not record_exists), raw=raw, using=using) save_base.alters_data = True @@ -645,6 +644,8 @@ class Model(object): return force_unicode(dict(field.flatchoices).get(value, value), strings_only=True) def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs): + if not self.pk: + raise ValueError("get_next/get_previous cannot be used on unsaved objects.") op = is_next and 'gt' or 'lt' order = not is_next and '-' or '' param = smart_str(getattr(self, field.attname)) @@ -744,11 +745,11 @@ class Model(object): continue if f.unique: unique_checks.append((model_class, (name,))) - if f.unique_for_date: + if f.unique_for_date and f.unique_for_date not in exclude: date_checks.append((model_class, 'date', name, f.unique_for_date)) - if f.unique_for_year: + if f.unique_for_year and f.unique_for_year not in exclude: date_checks.append((model_class, 'year', name, f.unique_for_year)) - if f.unique_for_month: + if f.unique_for_month and f.unique_for_month not in exclude: date_checks.append((model_class, 'month', name, f.unique_for_month)) return unique_checks, date_checks diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 65b60a0173..3c58873035 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -459,6 +459,9 @@ class AutoField(Field): kwargs['blank'] = True Field.__init__(self, *args, **kwargs) + def get_internal_type(self): + return "AutoField" + def to_python(self, value): if value is None: return value @@ -795,6 +798,14 @@ class EmailField(CharField): kwargs['max_length'] = kwargs.get('max_length', 75) CharField.__init__(self, *args, **kwargs) + def formfield(self, **kwargs): + # As with CharField, this will cause email validation to be performed twice + defaults = { + 'form_class': forms.EmailField, + } + defaults.update(kwargs) + return super(EmailField, self).formfield(**defaults) + class FilePathField(Field): description = _("File path") @@ -1105,6 +1116,14 @@ class URLField(CharField): CharField.__init__(self, verbose_name, name, **kwargs) self.validators.append(validators.URLValidator(verify_exists=verify_exists)) + def formfield(self, **kwargs): + # As with CharField, this will cause URL validation to be performed twice + defaults = { + 'form_class': forms.URLField, + } + defaults.update(kwargs) + return super(URLField, self).formfield(**defaults) + class XMLField(TextField): description = _("XML text") diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 5830a794df..1634d7d974 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -566,7 +566,7 @@ def create_many_related_manager(superclass, rel=False): # duplicate data row for symmetrical reverse entries. signals.m2m_changed.send(sender=rel.through, action='pre_add', instance=self.instance, reverse=self.reverse, - model=self.model, pk_set=new_ids) + model=self.model, pk_set=new_ids, using=db) # Add the ones that aren't there already for obj_id in new_ids: self.through._default_manager.using(db).create(**{ @@ -578,7 +578,7 @@ def create_many_related_manager(superclass, rel=False): # duplicate data row for symmetrical reverse entries. signals.m2m_changed.send(sender=rel.through, action='post_add', instance=self.instance, reverse=self.reverse, - model=self.model, pk_set=new_ids) + model=self.model, pk_set=new_ids, using=db) def _remove_items(self, source_field_name, target_field_name, *objs): # source_col_name: the PK colname in join_table for the source object @@ -594,14 +594,16 @@ def create_many_related_manager(superclass, rel=False): old_ids.add(obj.pk) else: old_ids.add(obj) + # Work out what DB we're operating on + db = router.db_for_write(self.through.__class__, instance=self.instance) + # Send a signal to the other end if need be. if self.reverse or source_field_name == self.source_field_name: # Don't send the signal when we are deleting the # duplicate data row for symmetrical reverse entries. signals.m2m_changed.send(sender=rel.through, action="pre_remove", instance=self.instance, reverse=self.reverse, - model=self.model, pk_set=old_ids) + model=self.model, pk_set=old_ids, using=db) # Remove the specified objects from the join table - db = router.db_for_write(self.through.__class__, instance=self.instance) self.through._default_manager.using(db).filter(**{ source_field_name: self._pk_val, '%s__in' % target_field_name: old_ids @@ -611,17 +613,17 @@ def create_many_related_manager(superclass, rel=False): # duplicate data row for symmetrical reverse entries. signals.m2m_changed.send(sender=rel.through, action="post_remove", instance=self.instance, reverse=self.reverse, - model=self.model, pk_set=old_ids) + model=self.model, pk_set=old_ids, using=db) def _clear_items(self, source_field_name): + db = router.db_for_write(self.through.__class__, instance=self.instance) # source_col_name: the PK colname in join_table for the source object if self.reverse or source_field_name == self.source_field_name: # Don't send the signal when we are clearing the # duplicate data rows for symmetrical reverse entries. signals.m2m_changed.send(sender=rel.through, action="pre_clear", instance=self.instance, reverse=self.reverse, - model=self.model, pk_set=None) - db = router.db_for_write(self.through.__class__, instance=self.instance) + model=self.model, pk_set=None, using=db) self.through._default_manager.using(db).filter(**{ source_field_name: self._pk_val }).delete() @@ -630,7 +632,7 @@ def create_many_related_manager(superclass, rel=False): # duplicate data rows for symmetrical reverse entries. signals.m2m_changed.send(sender=rel.through, action="post_clear", instance=self.instance, reverse=self.reverse, - model=self.model, pk_set=None) + model=self.model, pk_set=None, using=db) return ManyRelatedManager @@ -812,6 +814,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 +824,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 diff --git a/django/db/models/query.py b/django/db/models/query.py index d9fbd9b8cb..9ecfb745fd 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -1311,7 +1311,8 @@ def delete_objects(seen_objs, using): # Pre-notify all instances to be deleted. for pk_val, instance in items: if not cls._meta.auto_created: - signals.pre_delete.send(sender=cls, instance=instance) + signals.pre_delete.send(sender=cls, instance=instance, + using=using) pk_list = [pk for pk,instance in items] @@ -1343,7 +1344,7 @@ def delete_objects(seen_objs, using): setattr(instance, field.attname, None) if not cls._meta.auto_created: - signals.post_delete.send(sender=cls, instance=instance) + signals.post_delete.send(sender=cls, instance=instance, using=using) setattr(instance, cls._meta.pk.attname, None) if forced_managed: diff --git a/django/db/models/signals.py b/django/db/models/signals.py index cd0350bc01..48872e7e7f 100644 --- a/django/db/models/signals.py +++ b/django/db/models/signals.py @@ -5,12 +5,12 @@ class_prepared = Signal(providing_args=["class"]) pre_init = Signal(providing_args=["instance", "args", "kwargs"]) post_init = Signal(providing_args=["instance"]) -pre_save = Signal(providing_args=["instance", "raw"]) -post_save = Signal(providing_args=["instance", "raw", "created"]) +pre_save = Signal(providing_args=["instance", "raw", "using"]) +post_save = Signal(providing_args=["instance", "raw", "created", "using"]) -pre_delete = Signal(providing_args=["instance"]) -post_delete = Signal(providing_args=["instance"]) +pre_delete = Signal(providing_args=["instance", "using"]) +post_delete = Signal(providing_args=["instance", "using"]) post_syncdb = Signal(providing_args=["class", "app", "created_models", "verbosity", "interactive"]) -m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set"]) +m2m_changed = Signal(providing_args=["action", "instance", "reverse", "model", "pk_set", "using"]) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 0913399e2a..ec477447f3 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -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) |