skip to Main Content

How can I list all uniqueness constraints on a table and delete any ones that conflict with my Django migrations?

Lots of other StackOverflow questions have asked about "relation already exist" errors, but this is specific to the uniqueness constraints. I do NOT want the usual recommended method of faking the migration python manage.py migrate --fake. I want to just delete the conflicting constraint so the migration can proceed normally.

I tried to add a unique together constraint, it worked fine locally, but caused a "django.db.utils.ProgrammingError: relation already exists" error remotely. Specifically, I am getting an error like this.

django.db.utils.ProgrammingError: relation "api_mytable_myfield1_myfield2_cb8c1059_uniq" already exists

My migration file looks like this:


class Migration(migrations.Migration):

    dependencies = [
        ('api', '...'),
    ]

    operations = [
        migrations.AlterUniqueTogether(
            name='mytable',
            unique_together={('myfield', 'myfield2')},
        ),
    ]

How can I make things work again? I am using Postgres.

2

Answers


  1. Chosen as BEST ANSWER

    You can list the constraints on the table opening a Postgres shell and doing d mytable. Once you have found the name of the constraint, you can delete it with something like:

    ALTER TABLE mytable DROP CONSTRAINT mytable_myfield1_myfield2_cb8c1059_uniq;
    

  2. Please don’t alter the databae manually. If you later migrate another database, it will produce the same problems. The idea of migrations is to create a database, without having to interact with the database manually.

    A problem is that Django does not have a DeleteUniqueTogether, but only a AlterUniqueTogether [Django-doc] and likely this will not change in the near future: unique_together should not be used anymore. Django has a constraint framework [Django-doc].

    Your MyTable thus should use:

    class MyTable(models.Model):
        # ...
    
        class Meta:
            constraints = [
                models.UniqueConstraint(
                    fields=('myfield1', 'myfield2'),
                    name='mytable_myfield1_myfield2_cb8c1059_uniq'
                )
            ]

    If there is a specific reason why that is not possible, you should let the migration run the query:

    class Migration(migrations.Migration):
    
        dependencies = [
            ('api', '...'),
        ]
    
        operations = [
            migrations.RunSQL(
                'ALTER TABLE mytable DROP CONSTRAINT mytable_myfield1_myfield2_cb8c1059_uniq;'
            ),
            migrations.AlterUniqueTogether(
                name='mytable',
                unique_together={('myfield', 'myfield2')},
            ),
        ]
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search