Case insensitive unique model fields in Django?

django case insensitive username
django model case insensitive
django model fields
django model filter case sensitive
django email case-insensitive
django model choice field
array model field django
django model query lowercase

I have basically a username is unique (case insensitive), but the case matters when displaying as provided by the user.

I have the following requirements:

  • field is CharField compatible
  • field is unique, but case insensitive
  • field needs to be searchable ignoring case (avoid using iexact, easily forgotten)
  • field is stored with case intact
  • preferably enforced on database level
  • preferably avoid storing an extra field

Is this possible in Django?

The only solution I came up with is "somehow" override the Model manager, use an extra field, or always use 'iexact' in searches.

I'm on Django 1.3 and PostgreSQL 8.4.2.

Store the original mixed-case string in a plain text column. Use the data type text or varchar without length modifier rather than varchar(n). They are essentially the same, but with varchar(n) you have to set an arbitrary length limit, that can be a pain if you want to change later. Read more about that in the manual or in this related answer by Peter Eisentraut @serverfault.SE.

Create a functional unique index on lower(string). That's the major point here:

CREATE UNIQUE INDEX my_idx ON mytbl(lower(name));

If you try to INSERT a mixed case name that's already there in lower case you get a unique key violation error. For fast equality searches use a query like this:

SELECT * FROM mytbl WHERE lower(name) = 'foo' --'foo' is lower case, of course.

Use the same expression you have in the index (so the query planner recognizes the compatibility) and this will be very fast.


As an aside: you may want to upgrade to a more recent version of PostgreSQL. There have been lots of important fixes since 8.4.2. More on the official Postgres versioning site.

Case-Insensitive Fields in Django Models, Case insensitive unique model fields in Django? field is CharField compatible. field is unique, but case insensitive. field needs to be searchable ignoring case (avoid using iexact, easily forgotten) field is stored with case intact. preferably enforced on database level. preferably avoid storing an extra field. Case-Insensitive Fields in Django Models If you are trying to figure out how to create a case-insensitive field for your Django models, there are several ways to go about it. If you don’t care about preserving the actual mixed-case version, you can simply convert your strings to lowercase before they get saved to the model.

As of Django 1.11, you can use CITextField, a Postgres-specific Field for case-insensitive text backed by the citext type.

from django.db import models
from django.contrib.postgres.fields import CITextField

class Something(models.Model):
    foo = CITextField()

Django also provides CIEmailField and CICharField, which are case-insensitive versions of EmailField and CharField.

Case insensitive unique model fields in Django?, add this to your model before the save method and use "unique=True" in the model field.. it will capitalize the entry and check if it already exists. def clean(self​): self  There doesn't seem to exist a case independent model.CharField() in Django? That makes case independent unique values and list look-ups somewhat difficult. For example, I am trying to do a Model.o

With overriding the model manager, you have two options. First is to just create a new lookup method:

class MyModelManager(models.Manager):
   def get_by_username(self, username):
       return self.get(username__iexact=username)

class MyModel(models.Model):
   ...
   objects = MyModelManager()

Then, you use get_by_username('blah') instead of get(username='blah'), and you don't have to worry about forgetting iexact. Of course that then requires that you remember to use get_by_username.

The second option is much hackier and convoluted. I'm hesitant to even suggest it, but for completeness sake, I will: override filter and get such that if you forget iexact when querying by username, it will add it for you.

class MyModelManager(models.Manager):
    def filter(self, **kwargs):
        if 'username' in kwargs:
            kwargs['username__iexact'] = kwargs['username']
            del kwargs['username']
        return super(MyModelManager, self).filter(**kwargs)

    def get(self, **kwargs):
        if 'username' in kwargs:
            kwargs['username__iexact'] = kwargs['username']
            del kwargs['username']
        return super(MyModelManager, self).get(**kwargs)

class MyModel(models.Model):
   ...
   objects = MyModelManager()

No duplicate (case-insensitive) entries django model · GitHub, Model): name = models.CharField(max_length=50, unique=True) The uniqueness would be case-sensitive in postgres; that is, postgres would allow the user to  Django Model - Case-insensitive Query / Filtering. Django-case insensitive string comparison in django template. 1. lower() in django model. 0.

You can use citext postgres type instead and not bother anymore with any sort of iexact. Just make a note in model that underlying field is case insensitive. Much easier solution.

Unique model field in Django and case sensitivity (postgres), If not, how can this be handled so that case-sensitive email addresses are /​7773341/case-insensitive-unique-model-fields-in-django Using this feature in  Email field in the Django(3.0) Custom User Model is case sensitive, I tried various ways to make it case-insensitive but no success so far. ### Code. forms.py. class UserCreationForm(UserCreationForm): class Meta: model = User. fields = ('first_name','last_name','username','email','password1','password2') class UserChangeForm(UserChangeForm): class Meta:

Since a username is always lowercase, it's recommended to use a custom lowercase model field in Django. For the ease of access and code-tidiness, create a new file fields.py in your app folder.

from django.db import models
from django.utils.six import with_metaclass

# Custom lowecase CharField

class LowerCharField(with_metaclass(models.SubfieldBase, models.CharField)):
    def __init__(self, *args, **kwargs):
        self.is_lowercase = kwargs.pop('lowercase', False)
        super(LowerCharField, self).__init__(*args, **kwargs)

    def get_prep_value(self, value):
        value = super(LowerCharField, self).get_prep_value(value)
        if self.is_lowercase:
            return value.lower()
        return value

Usage in models.py

from django.db import models
from your_app_name.fields import LowerCharField

class TheUser(models.Model):
    username = LowerCharField(max_length=128, lowercase=True, null=False, unique=True)

End Note : You can use this method to store lowercase values in the database, and not worry about __iexact.

EmailField(unique=True) and case sensitivity : django, Should it be possible to specify a case insensitive match for unique-together fields? Create a model with a slugfield; Add a unique_together constraint on it​  Option 1: Extending The User Model. This is the best option if your project is in the beginning and you can afford swapping the authentication User. Actually any of the strategies described in the How to Extend Django User Model will work (except for the Proxy model, because the AUTH_USER_MODEL can’t be a Proxy).

#14564 (case insensitive unique_together) – Django, db lookup methods not case sensitive on mysql i noticed that the methods field​__exact and field__iexact match case insensitive on mysql **kwargs) File "/​Library/Python/2.5/site-packages/django/db/models/query.py", line 300, in get  When using model forms, the Field needs to know which form field it should be represented by: formfield ( form_class=None, choices_form_class=None, **kwargs) ¶. Returns the default django.forms.Field of this field for ModelForm. By default, if both form_class and choices_form_class are None, it uses CharField.

#2170 (db lookup methods not case sensitive on mysql) – Django, Unique model field and case sensitivity (postgres) one go about providing case​-INsenstitive uniqueness with Django and. Postgres. I'm on mobile and can't really answer your question but I'd just convert all email addresses to lower case in (or just before) form validation and let django check uniqueness normally. In my opinion unique email address shoud be case-insensitive anyway.

Unique model field and case sensitivity (postgres), Model): some_field = models. Is there some way to force sqlite to perform a case insensitive comparison when checking for uniqueness? I can't seem to find an option for this in Django's docs and I'm wondering if there's Perhaps you can create and use a custom model field; it would be a subclass of CharField but​  GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together. Sign up This is example code for a blog post about creating a case-insensitive model field in Django.

Comments
  • possible duplicate of Unique model field in Django and case sensitivity (postgres)
  • Thank you for the solution. I ended up using this one and the one below so now you can't just work around the code.
  • Great solution. Is there a way to do this using Django ORM? Or should I do it in PostgreSQL directly?
  • @fcrazy: I am no expert with Django, but a single raw SQL call for the CREATE UNIQUE INDEX ... statement should do the job.
  • @ErwinBrandstetter Thanks Erwin, I made my own research and seems that a good place to do this in Django is adding the file <appname>/sql/<modelname>.sql, where <appname> is the given app, just as explain it here: docs.djangoproject.com/en/1.5/ref/django-admin/…
  • Minor suggestion: Django maps iexact to UPPER. Shouldn't the functional index recommended for Django be UPPER?
  • I like the hackier version better than custom method version +1 for hackiness!
  • I prefer this method, especially the hackier version, over the accepted answer because this is DBMS-agnostic. It makes you stick with Django's case-insensitive QuerySet methods in the end, so Django can still generate the SQL statements with the proper collation coercion, regardless of the DBMS backend.
  • It may be database agnostic, but it doesn't prevent you from inserting the same value with different case. So it is not a complete solution to case-insensitive unique model fields. You could always convert to lower case before storing the object in the database, but then you loose the original case, which is not necessarily acceptable.