37

I'm learning Django from Tango with Django but I keep getting this error when I type:

python manage.py makemigrations rango
python manage.py migrate

This is the output:

django.db.utils.IntegrityError: UNIQUE constraint failed: rango_category__new.slug

Models.py:

from django.db import models
from django.template.defaultfilters import slugify

class Category(models.Model):
    name = models.CharField(max_length=128, unique=True)
    views = models.IntegerField(default=0)
    likes = models.IntegerField(default=0)
    slug = models.SlugField(unique=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super(Category, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.name


class Page(models.Model):
    category = models.ForeignKey(Category)
    title = models.CharField(max_length=128)
    url = models.URLField()
    views = models.IntegerField(default=0)

    def __unicode__(self):
        return self.title
Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
ArrowsX
  • 505
  • 1
  • 4
  • 9
  • 5
    It's general etiquette to mark an answer as accepted if it worked for you. I had the same problem and @ruddra'a answer worked for me. – user1048839 Jun 25 '15 at 13:28

13 Answers13

46

The reason for this constrain could be that you didn't have any field called slug in Category class when you have initially migrated it (First Migration), and after adding this field in the model, when you ran makemigrations, you have set default value to something static value(i.e None or '' etc), and which broke the unique constrain for the Category's table's slug column in which slug should be unique but it isn't because all the entry will get that default value.

To solve this, you can either drop the database and migration files and re-run makemigrations and migrate or set a unique default value like this:

slug = models.SlugField(unique=True, default=uuid.uuid1)

Edit:

According to Migrations that add unique fields, modify your migration file to overcome unique constrain. For example, modify your migration file (which added the slug field to the model) like this:

import uuid
from app.models import Category  # where app == tango_app_name

class Migration(migrations.Migration):

    dependencies = [
        ('yourproject', '0003_remove_category_slug'),
    ]

    def gen_uuid(apps, schema_editor):
        for row in Category.objects.all():
            row.slug = uuid.uuid4()
            row.save()

    operations = [
        migrations.AddField(
            model_name='category',
            name='slug',
            field=models.SlugField(default=uuid.uuid4),
            preserve_default=True,
        ),
        migrations.RunPython(gen_uuid),

        migrations.AlterField(
            model_name='category',
            name='slug',
            field=models.SlugField(default=uuid.uuid4, unique=True),
        ),
    ]
ruddra
  • 50,746
  • 7
  • 78
  • 101
  • The first one gave me error in the admin page: u"Key 'slug' not found in 'CategoryForm'". I couldn't use uuid.uuid1 because I don't know where to import it, it gave 'uuid' is not defined. – ArrowsX Mar 31 '15 at 17:16
  • 1
    for the first problem, check this: http://stackoverflow.com/questions/2685383/hide-fields-in-django-admin, and for 2nd, use `import uuid`, and for 2nd solution, don't forget to remove the last migration file from migrations directory(ie `005_add_slug.py`) of the app and rerun makemigrations/migrate command. – ruddra Mar 31 '15 at 17:23
  • 1
    thank you that helped, but just in case i want to add, i have to delete the last migrations files from the folder as i was still having this issue until i delete the files when i migrate the first time with the issue – Manza Aug 01 '18 at 20:35
  • 1
    @ruddra This is amazing!!! Thank you soo much for this answer...it fixed my problem! – Trilla Aug 20 '19 at 12:56
  • I think this should be noted that sometimes drop the db or delete everything is **overkill**, you should check that existing data doesn't mess with the new constraint. – d6bels Nov 08 '22 at 14:55
20

I got a field with attribute unique, which was not unique [eg 2-time same value]

python3 manage.py migrate --fake

then

python3 manage.py makemigrations

python3 manage.py migrate

this did the trick

Nils Zenker
  • 659
  • 7
  • 11
2

This means a slug should be unique. You may have some data in your model. You need to delete all the data in that model and you need to migrate again.

In this situation, you have two ways to fix the error;

  1. You need to delete it from the Django admin site. More often than not, it may give an error when you are trying to open the model.

  2. Open command prompt

move to project -> py manage.py shell -> from yourappname.models import modelname -> modelname.objects.delete()

Here if you define a product manager for your model. Then you have to define a delete function. Later you should makemigrate, migrate and continue with the second way

Toluwalemi
  • 391
  • 5
  • 16
1

I just met this simiilar error: Django UNIQUE constraint failed. I tried examine the code for very long time, but didn't solve it. I finally used SQLiteStudio to examine the data, and found the data is problematic: I unintentionally added two SAME instances which violates the UNIQUE constraint. To be frank I haven't thought the error could be this naive and simple, and because so it took me a lot of time to find out!

  • Save me a lot of time. Same thing here, everything was fine but I was messing with migrations and I tried to make something unique, but some data in the db didn't match the requirement. – d6bels Nov 08 '22 at 14:53
1

I had the same problem and tried all the suggested answers. What finally worked for me was, after I defined the slug field as a URL in models, and ran the makemigrations. I edited the file in makemigrations adding a random number at the end of a basic URL, like this

Generated by Django 3.2.3 on 2022-02-02 20:58

from django.db import migrations, models from random import randint

class Migration(migrations.Migration):

dependencies = [
    ('blog', '0002_remove_post_slug1'),
]

operations = [
    migrations.AddField(
        model_name='post',
        name='slug',
        field=models.URLField(blank=True, default='http:/salpimientapa.com/' + str(randint(100000,999999))),
    ),
]

After I ran python manage.py migrate

I edit the slug as a SlugModel and ran the makemigrations and migrate again

bortons
  • 11
  • 3
0

What worked for me was going to the admin and changing the value of duplicate slug, before running the migrations again.

sxmmie
  • 76
  • 1
  • 5
0

Just delete the last migration in the migration folder

Then run

python manage.py makemigrations 
python manage.py migrate
Swatantra Kumar
  • 1,324
  • 5
  • 24
  • 32
0

I faced the same issue and solved by populating my slugfied thro' the admin with unique values and without leaving any of them blank.

0

Basically: You add the field without unique=true in one operation, make a data migration that generates the correct shortuuids for you, and then change the field too unique again.

0

i have this error too , i did delete my database in djangoProject ( for example db.sqlite3 ) and then run

python manage.py makemigrations

python manage.py migrate
0

It's an Integrity Error probably because the migration will temper with the already exiting data in the database. I had this error and here's what I did:

  • Enter in the project folder directory

  • Open the python interpreter

py manage.py shell

  • Import your Models

from yourappname.models import model

  • Delete existing data records in the model

model.objects.all().delete()

  • Exit the Python Interpreter

exit()

.

Another thing you could do is to set unique="false" on the affecting field. I think this should work; not so sure.

0

Deleting migration is not always the best way! In the event, you wish to maintain your db and want to add unique filed to an existing table. Here is a step to bypass the error and still maintain your db records.

  1. Run makemigrations
  2. Edited the migration file and removed unique=True (0039_alter_course_options_rename_created_course_timestamp_and_more).

eg: Before

 migrations.AddField(
        model_name='content',
        name='uuid',
        field=models.UUIDField(default=uuid.uuid4, unique=True),
    ),

After

 migrations.AddField(
        model_name='content',
        name='uuid',
        field=models.UUIDField(default=uuid.uuid4),
    ),
  1. Now if you migrate, it should run fine. Next, you need to update all previous records.

Create a custom managements

courses/
├── __init__.py
├── management/
│   ├── __init__.py
│   └── commands/
│       ├── __init__.py
│       └── check_uuid_uniqueness.py
├── models.py
├── ...
└── ...

Mine looks like so in the check_uuid_uniqueness.py

from django.apps import apps
from django.core.management.base import BaseCommand
import uuid

class Command(BaseCommand):
 help = 'Check the uniqueness of uuid fields in models and generate unique values if necessary.'

 def handle(self, *args, **options):
     app_name = 'courses'
     models = apps.get_app_config(app_name).get_models()

     for model in models:
         if hasattr(model, 'uuid'):
             instances = model.objects.all()
             for instance in instances:
                 list_item = instances.filter(uuid=instance.uuid)
                 if not instance.uuid or len(list_item)>1:
                     instance.uuid = uuid.uuid4()
                     instance.save()
                     print(model, ' updated: ', instance.uuid)

     self.stdout.write(self.style.SUCCESS('UUID uniqueness check completed.'))

Remember, in my case, I was targeting uuid, yours could be slug.

  1. Finally, run the custom command (make sure your python venv is activated)

python manage.py check_uuid_uniqueness

0
python manage.py dbshell
>> DROP TABLE rango_category__new.slug;

delete associated migration file;

python manage.py makemigration
python manage.py migrate
Smaug
  • 1
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 11 '23 at 23:10