#23906: "ValueError: Found wrong number (0) of constraints" when migrating
backwards with from alter_unique_together migration.
-------------------------+-------------------------------------------------
Reporter: | Owner: nobody
liavkoren | Status: new
Type: Bug | Version: 1.7
Component: | Keywords: alter_unique_together migrations
Migrations | constraints valueError
Severity: Normal | Has patch: 0
Triage Stage: | UI/UX: 0
Unreviewed |
Easy pickings: 0 |
-------------------------+-------------------------------------------------
We have a database that was created with django 1.6 and south. We've
subsequently upgraded to 1.7.0, removed our south migrations and created
django-migrations.
One of our models contains a unique_together constraint that includes four
of its attributes. When I attempt to backwards migrate the app containing
this model I get "ValueError: Found wrong number (0) of constraints for
foo_model(foo, bar, baz, quux)".
I haven't been able to replicate this error by creating a test model -- it
seems possible that this may be related to models created in django
1.6/south and then migrated backwards in 1.7.
The problem seems to be in django.db.backends.schema._contraint_names,
which is supposed to return a list of relevant constrains for a set of
columns.
In order to do this, it is comparing an input set of columns against the
result returned from a call to
BaseDatabaseSchemaEditor.connection.introspection.get_constraints and
filtering the results. The first test in the filter loop is:
{{{#!python
if column_names is None or column_names == infodict['columns']:
}}}
which is failing because it involves a comparison of lists which are in
different orders:
{{{#!python
(Pdb++) column_names
[u'foo', u'bar', u'baz', u'quux']
(Pdb++) infodict['columns']
[u'baz', u'bar', u'quux', u'foo']
(Pdb++) infodict['columns'] == column_names
False
(Pdb++) sorted(infodict['columns']) == sorted(column_names)
True
}}}
I have been able to fix this and migrate backwards by changing the
django.db.backends.schema.BaseDatabaseSchemaEditor._constraint_names
method to compare sets rather than lists:
{{{#!python
def _constraint_names(self, model, column_names=None, unique=None,
primary_key=None, index=None, foreign_key=None, check=None):
"""
Returns all constraint names matching the columns and conditions
"""
# column_names = list(column_names) if column_names else None
column_names = set(column_names) if column_names else None
with self.connection.cursor() as cursor:
constraints =
self.connection.introspection.get_constraints(cursor,
model._meta.db_table)
result = []
for name, infodict in constraints.items():
# if column_names is None or column_names ==
infodict['columns']:
if column_names is None or column_names ==
set(infodict['columns']):
if unique is not None and infodict['unique'] != unique:
continue
if primary_key is not None and infodict['primary_key'] !=
primary_key:
continue
if index is not None and infodict['index'] != index:
continue
if check is not None and infodict['check'] != check:
continue
if foreign_key is not None and not
infodict['foreign_key']:
continue
result.append(name)
return result
}}}
I'm happy to submit a PR and tests for this issue, but I expect it's going
to be non-trivial to reproduce.
--
Ticket URL: <https://code.djangoproject.com/ticket/23906>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/052.385d768e46fca5dab0a268a933bad8fe%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.