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 %}





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


--
You received this message because you are subscribed to the Google Groups "Django 
users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/8c56c0b3-fffc-f1cb-23a0-b1ee15234733%40dewhirst.com.au.
For more options, visit https://groups.google.com/d/optout.

Reply via email to