Skip to content

Instantly share code, notes, and snippets.

@tuatara
Last active April 7, 2021 21:23
Show Gist options
  • Save tuatara/2c388845c28fe1985908 to your computer and use it in GitHub Desktop.
Save tuatara/2c388845c28fe1985908 to your computer and use it in GitHub Desktop.
Allow case-insensitive usernames with Django & Postgres
# Add the mixin to the default admin objects
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin as ContribUserAdmin
from django.contrib.auth.forms import UserChangeForm as ContribUserChangeForm, \
UserCreationForm as ContribUserCreationForm
from accounts.forms import CaseInsensitiveUsernameMixin # adjust if forms.py is not in `accounts` app
class UserChangeForm(CaseInsensitiveUsernameMixin, ContribUserChangeForm):
pass
class UserCreationForm(CaseInsensitiveUsernameMixin, ContribUserCreationForm):
pass
class UserAdmin(ContribUserAdmin):
add_form = UserCreationForm
form = UserChangeForm
save_on_top = True
admin.site.register(get_user_model(), UserAdmin)
from django import forms
from django.contrib.auth import get_user_model
from django.utils.translation import ugettext_lazy as _
class CaseInsensitiveUsernameMixin():
"""
Disallow a username with a case-insensitive match of existing usernames.
Add this mixin to any forms that use the User object
"""
def clean_username(self):
username = self.cleaned_data.get('username')
if get_user_model().objects.filter(username__iexact=username) \
.exclude(pk=self.instance.pk).exists():
raise forms.ValidationError(_(u'The username ‘{}’ is already in use.'.format(username)))
return username
# For use with a custom user model, based on AbstractUser
from django.contrib.auth.models import AbstractUser, UserManager
class CaseInsensitiveUserManager(UserManager):
def get_by_natural_key(self, username):
"""
By default, Django does a case-sensitive check on usernames. This is Wrong™.
Overriding this method fixes it.
"""
return self.get(**{self.model.USERNAME_FIELD + '__iexact': username})
class User(AbstractUser):
objects = CaseInsensitiveUserManager()
# etc …
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment