#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 django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. 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.