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?
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... because NULL != 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 to None
)
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)
NOTE:
As pointed out by @alasdair in a comment, that bug has now been fixed - since Django 1.11 you can use CharField(unique=True, null=True, blank=True)
without having to manually convert blank values to None
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.
class MyModelChangeForm(forms.ModelForm):
class Meta:
model = models.MyModel
fields = ['email', 'name', 'something_unique_or_null',]
def clean_something_unique_or_null(self):
if self.cleaned_data['something_unique_or_null'] == "":
return None
else:
return self.cleaned_data['something_unique_or_null']
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".
Since you have null=True, blank=True
and unique=True
, django is considering None
or blank as a unique entry. Remove the unique constraint and handle the uniqueness part in the code.
In Django 1.11, form CharFields
will have an empty_value
argument, which allows you to use None
if the field is empty.
Model forms, including the Django admin, will automatically set empty_value=None
if the model's CharField
has null=True
.
Therefore, you will be able to use null=True
, blank=True
and unique=True
together in your model CharField
without the unique constraint causing problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With