Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IntegrityError: column slug is not unique

Tags:

python

django

i'm studying django by tangowithdjango tutorials, and there on 7-th chapter I've stacked.

i'm trying to include a slug field in my model and override save method to make it all working. After migrate I have an integrity error.

models.py:

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)

    class Meta:
        verbose_name_plural = "Categories"

    def __unicode__(self):
        return self.name

Thanks!

like image 357
alohamaloha Avatar asked Jan 09 '23 03:01

alohamaloha


1 Answers

Listen to the error. You have the slug attribute specified as unique, but you must have the same slug value for multiple instances of your Category class.

This can easily happen if you add a unique attribute column to a table that already has data, because any constant default you use will automatically break the unique constraint.

To make the migration...

You're going to need to first migrate to just add the slug-field, without specifying it as unqiue, then set a unique slug for each Category in the database, then you can add the unique constraint and migrate again.

Open your most recent migration in the migrations directory of your app and edit the line that looks similar to

migrations.AddField(
    model_name='category',
    name='slug',
    field=models.SlugField(unique=True),
    preserve_default=False,
),

so that it is just

migrations.AddField(
    model_name='category',
    name='slug',
    field=models.SlugField(null=True, blank=True),
    preserve_default=False,
),

Then run the migration with python manage.py migrate (if you're using django 1.7. Otherwise use South for migrations), then open the django shell with python manage.py shell, import your Category model and run

for cat in Category.objects.all():
    cat.slug = cat.name
    cat.save()

This will set the slug for each category to be the category's name. Now, assuming all names are unique, you can create your migrations again and successfully migrate so that the DB will force unique slugs.

like image 162
rfj001 Avatar answered Jan 16 '23 20:01

rfj001