django.db.utils.IntegrityError: (1062, “Duplicate entry '' for key 'slug'”)

守給你的承諾、 提交于 2019-11-29 16:16:31

Let's analyse it step by step:

  1. You're adding slug field with unique = True, that means: each record must have different value, there can't be two records with same value in slug
  2. You're creating migration: django asks you for default value for fields that exists already in database, so you provided '' (empty string) as that value.
  3. Now django is trying to migrate your database. In database we have at least 2 records
  4. First record is migrated, slug column is populated with empty string. That's good because no other record is having empty string in slug field
  5. Second record is migrated, slug column is populated with empty string. That fails, because first record already have empty string in slug field. Exception is raised and migration is aborted.

That's why your migration fails. All you should do is to edit migration, copy migrations.AlterField operation twice, in first operation remove unique=True. Between that operations you should put migrations.RunPython operation and provide 2 parameters into that: generate_slugs and migrations.RunPython.noop.

Now you must create inside your migration function BEFORE migration class, name that function generate_slugs. Function should take 2 arguments: apps and schema_editor. In your function put at first line:

Category = apps.get_model('your_app_name', 'Category')

and now use Category.objects.all() to loop all your records and provide unique slug for each of them.

If you have more than one category in your table, then you cannot have unique=True and default='', because then you will have more than one category with slug=''. If your tutorial says to do this, then it's bad advice, although it might work in SQLite.

The correct approach to add a unique field to a model is:

  1. Delete your current migration that isn't working.
  2. Add the slug field, with unique=False. Create a new migration and run it.
  3. Set a unique slug for every category. It sounds like the rango populate script might do this. Alternatively, you could write a migration to set the slugs, or even set them manually in the Django admin.
  4. Change the slug field to unique=True. Create a new migration and run it.

If that's too difficult, then you could delete all your categories from your database except one. Then your current migration will run without having problems with the unique constraint. You can add the categories again afterwards.

You must have rows in your table already with empty slugs, which is a violation of the mysql unique constraint you created. You can update them manually by running manage.py dbshell to get to the mysql client, then updating the offending rows, e.g.

update table rango_category set slug = name where slug = '';

(assuming the rows with blank slugs have names). Or you can delete the rows with

delete from rango_category where slug = '';

After that, you should be able to run your migrations.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!