I've been getting the most weird error ever. I have a Person model
class Person(models.Model):
user = models.OneToOneField(User, primary_key=True)
facebook_id = models.CharField(max_length=225, unique=True, null=True, blank=True)
twitter_id = models.CharField(max_length=225, unique=True, null=True, blank=True)
suggested_person = models.BooleanField(default=False)
I recently added the twitter_id field. When I access the Django admin page, and try to change the 'person' into a suggested_person, I get the following error:
Person with this Twitter id already exists.
I find this error to be extremely strange because the Facebook_id field is designed the exact same way as the Twitter_id field.
What could be the reason for this?
Since you have
null=True, blank=True
andunique=True
, django is consideringNone
or blank as a unique entry. Remove the unique constraint and handle the uniqueness part in the code.you are accepting blank values and expect them to be unique. this means there can only be ONE entry with a blank twitter_id
you can
In Django 1.11, form
CharFields
will have anempty_value
argument, which allows you to useNone
if the field is empty.Model forms, including the Django admin, will automatically set
empty_value=None
if the model'sCharField
hasnull=True
.Therefore, you will be able to use
null=True
,blank=True
andunique=True
together in your modelCharField
without the unique constraint causing problems.None of the answers clearly describe the root of the problem.
Normally in the db you can make a field
null=True, unique=True
and it will work... becauseNULL != NULL
. So each blank value is still considered unique.But unfortunately for
CharField
s Django will save an empty string""
(because when you submit a form everything comes into Django as strings, and you may have really wanted to save an empty string""
- Django doesn't know if it should convert toNone
)This basically means you shouldn't use
CharField(unique=True, null=True, blank=True)
in Django. As others have noted you probably have to give up the db-level unique constraint and do your own unique checks in the model.For further reference, see here: https://code.djangoproject.com/ticket/4136
(unfortunately no good solution decided at time of writing)
It's important to solve this at the model level, not at the form level, since data can enter through APIs, through import scripts, from the shell, etc. The downside of setting
null=True
on a CharField is that the column could end up with both empty strings and NULLs, which is slightly ambiguous but not generally a problem in my experience. If you're willing to live with that ambiguity, here's how to do it in a few steps:1) Set
null=True, blank=True
on the field and migrate in the change.2) Massage your data so that all existing empty strings are changed to NULLs:
3) Add a custom
save()
method to your model:4) Set
unique=True
on the field and migrate that in as well.Now you'll be able to store
somefield
as empty or as a unique value whether you're using the admin or any other data entry method.If you prefer not to have several migrations, here's an example of how to do it in a single migration:
This is an old one but I had a similar issue just now and though I would provide an alternative solution.
I am in a situation where I need to be able to have a CharField with null=True, blank=True and unique=True. If I submit an empty string in the admin panel it will not submit because the blank string is not unique.
To fix this, I override the 'clean' function in the ModelForm, and in there I check if it's a blank string and return the result accordinly.
This fixed the problem for me without having to sacrifice the unique attribute on the model field.
Hope this helps.
EDIT: You need to change where I have put "something_unique_or_null" to the name of your field. For example "clean_twitter_id".