diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index 1f2a2db981..9172d938d2 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -73,7 +73,7 @@ class Command(BaseCommand): model_list = get_models(app) for model in model_list: - objects.extend(model.objects.all()) + objects.extend(model._default_manager.all()) try: return serializers.serialize(format, objects, indent=indent) diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py index fe945baff7..3caa13e0bf 100644 --- a/django/db/backends/creation.py +++ b/django/db/backends/creation.py @@ -25,6 +25,10 @@ class BaseDatabaseCreation(object): def __init__(self, connection): self.connection = connection + def _digest(self, *args): + "Generate a 32 bit digest of a set of arguments that can be used to shorten identifying names" + return '%x' % (abs(hash(args)) % (1<<32)) + def sql_create_model(self, model, style, known_models=set()): """ Returns the SQL required to create a single model, as a tuple of: @@ -128,7 +132,7 @@ class BaseDatabaseCreation(object): col = opts.get_field(f.rel.field_name).column # For MySQL, r_name must be unique in the first 64 characters. # So we are careful with character usage here. - r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) + r_name = '%s_refs_%s_%s' % (r_col, col, self._digest(r_table, table)) final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ (qn(r_table), qn(truncate_name(r_name, self.connection.ops.max_name_length())), qn(r_col), qn(table), qn(col), @@ -187,8 +191,7 @@ class BaseDatabaseCreation(object): output.append('\n'.join(table_output)) for r_table, r_col, table, col in deferred: - r_name = '%s_refs_%s_%x' % (r_col, col, - abs(hash((r_table, table)))) + r_name = '%s_refs_%s_%s' % (r_col, col, self._digest(r_table, table)) output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % (qn(r_table), qn(truncate_name(r_name, self.connection.ops.max_name_length())), @@ -289,7 +292,7 @@ class BaseDatabaseCreation(object): col = f.column r_table = model._meta.db_table r_col = model._meta.get_field(f.rel.field_name).column - r_name = '%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table)))) + r_name = '%s_refs_%s_%s' % (col, r_col, self._digest(table, r_table)) output.append('%s %s %s %s;' % \ (style.SQL_KEYWORD('ALTER TABLE'), style.SQL_TABLE(qn(table)), diff --git a/django/db/models/base.py b/django/db/models/base.py index 12e84625a7..c7596b37b7 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -411,32 +411,40 @@ class Model(object): save.alters_data = True - def save_base(self, raw=False, cls=None, force_insert=False, + def save_base(self, raw=False, cls=None, origin=None, force_insert=False, force_update=False, using=None): """ Does the heavy-lifting involved in saving. Subclasses shouldn't need to override this method. It's separate from save() in order to hide the need for overrides of save() to pass around internal-only parameters - ('raw' and 'cls'). + ('raw', 'cls', and 'origin'). """ if using is None: using = DEFAULT_DB_ALIAS connection = connections[using] assert not (force_insert and force_update) - if not cls: + if cls is None: cls = self.__class__ - meta = self._meta - signal = True - signals.pre_save.send(sender=self.__class__, instance=self, raw=raw) + meta = cls._meta + if not meta.proxy: + origin = cls else: meta = cls._meta - signal = False + + if origin: + signals.pre_save.send(sender=origin, instance=self, raw=raw) # 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 # that might have come from the parent class - we just save the # attributes we have been given to the class we have been given. - if not raw: + # We also go through this process to defer the save of proxy objects + # to their actual underlying model. + if not raw or meta.proxy: + if meta.proxy: + org = cls + else: + org = None for parent, field in meta.parents.items(): # At this point, parent's primary key field may be unknown # (for example, from administration form which doesn't fill @@ -444,7 +452,8 @@ class Model(object): if field and getattr(self, parent._meta.pk.attname) is None and getattr(self, field.attname) is not None: setattr(self, parent._meta.pk.attname, getattr(self, field.attname)) - self.save_base(cls=parent, using=using) + self.save_base(cls=parent, origin=org, using=using) + if field: setattr(self, field.attname, self._get_pk_val(parent._meta)) if meta.proxy: @@ -496,8 +505,8 @@ class Model(object): setattr(self, meta.pk.attname, result) transaction.commit_unless_managed(using=using) - if signal: - signals.post_save.send(sender=self.__class__, instance=self, + if origin: + signals.post_save.send(sender=origin, instance=self, created=(not record_exists), raw=raw) save_base.alters_data = True diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 2adbaffca8..4e2c962cbc 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -132,12 +132,13 @@ class RelatedField(object): v, field = getattr(v, v._meta.pk.name), v._meta.pk except AttributeError: pass - if field: - if lookup_type in ('range', 'in'): - v = [v] - v = field.get_db_prep_lookup(lookup_type, v) - if isinstance(v, list): - v = v[0] + if not field: + field = self.rel.get_related_field() + if lookup_type in ('range', 'in'): + v = [v] + v = field.get_db_prep_lookup(lookup_type, v) + if isinstance(v, list): + v = v[0] return v if hasattr(value, 'as_sql') or hasattr(value, '_as_sql'): diff --git a/docs/intro/tutorial04.txt b/docs/intro/tutorial04.txt index 07aa477d67..28ace85ca8 100644 --- a/docs/intro/tutorial04.txt +++ b/docs/intro/tutorial04.txt @@ -20,7 +20,7 @@ tutorial, so that the template contains an HTML ``