case-insensitive username

35 views
Skip to first unread message

Mike Dewhirst

unread,
Nov 20, 2017, 2:41:45 AM11/20/17
to Django users
I have seen the two tickets and read the developer list thread[1]on this
subject. Is there a best-practice approach to preventing usernames which
are case-insensitively equivalent

I'm hoping someone has achieved this and might be willing to share.

My common.User inherits auth.models.AbstractUser unchanged and
CommonUserCreationForm inherits auth.forms.UserCreationForm unchanged.

Thanks

Mike

[1] #2273 and #25617 and
https://groups.google.com/d/topic/django-developers/a4I7rHuT4Dw/discussion

Mike Dewhirst

unread,
Nov 20, 2017, 10:46:48 PM11/20/17
to Django users
On 20/11/2017 6:40 PM, Mike Dewhirst wrote:
> I have seen the two tickets and read the developer list thread[1]on
> this subject. Is there a best-practice approach to preventing
> usernames which are case-insensitively equivalent
>
> I'm hoping someone has achieved this and might be willing to share.

This is working so I would appreciate any constructive criticism leading
to a better approach.

Thanks

Mike

# common.models
from django.contrib.auth.models import AbstractUser, UserManager
from django.utils.encoding import python_2_unicode_compatible


class InsensitiveUserManager(UserManager):

def get_by_natural_key(self, username):
return self.get(**{'username__iexact': username})


@python_2_unicode_compatible
class User(AbstractUser):

objects = InsensitiveUserManager()

def __str__(self):
return u'%s' % self.username

def save(self, *args, **kwargs):
super(User, self).save(*args, **kwargs)
# not sure whether to use the post-save signal or just save it here
profile = UserProfile.objects.get_or_create(user=self)[0]
profile.save()


# common.forms
from django.contrib.auth.forms import UserCreationForm
from .models import User


class CommonUserCreationForm(UserCreationForm):
"""
https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#
custom-users-and-the-built-in-auth-forms
"""
first_name = forms.CharField(
max_length=30,
required=False,
help_text='Optional',
)
last_name = forms.CharField(
max_length=30,
required=False,
help_text='Optional'
)
email = forms.EmailField(
max_length=254,
help_text='Required'
)

class Meta(UserCreationForm.Meta):
model = User
fields = UserCreationForm.Meta.fields



# common.views
from django.contrib.auth import authenticate, get_user_model, login
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
from .exceptions import ValidationError
from .forms import CommonUserCreationForm

def register_user(request):
if request.method == 'POST':
form = CommonUserCreationForm(request.POST)
username = form.data.get('username')
try:
User = get_user_model()
i_username = User.objects.get(username__iexact=username).username
if i_username.lower() == username.lower():
form.add_error(
'username',
ValidationError('{} already exists'.format(i_username))
)
except User.DoesNotExist:
pass # bonus!
if form.is_valid():
username = form.cleaned_data.get('username')
form.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(user)
return redirect('common.views.homepage')
else:
form = CommonUserCreationForm()
return render(request, 'register.html', {'form': form})


# templates/register.html
{% extends 'base_site.html' %}

{% block content %}
<h2>Register</h2>
<form method="post">
{% csrf_token %}
{% if form.errors %}
{{ form.errors }}
{% endif %}
<table>
{% for field in form %}
<tr>
<td width='154px'>{{ field.label }}:</td>
<td width='170px'>{{ field }}</td>
<td>{{ field.help_text | safe }}</td>
</tr>
{% endfor %}
</table>
<button type="submit">Register</button>
</form>
{% endblock %}
Reply all
Reply to author
Forward
0 new messages