Login

UsernameField (for clean error messages)

Author:
davepeck
Posted:
August 6, 2009
Language:
Python
Version:
1.1
Tags:
authorization field users username forms user auth fields form
Score:
0 (after 2 ratings)

This is a username field that matches (and slightly tightens) the constraints on usernames in Django's User model.

Most people use RegexField, which is totally fine -- but it can't provide the fine-grained and user friendly messages that come from this field.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import re

from django import forms
from django.forms import ValidationError
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _

class UsernameField(forms.CharField):
    default_error_messages = {
        'username_too_short': _(u'Usernames must be at least three characters long.'),
        'username_too_long': _(u'Usernames can be at most thirty characters long.'),
        'bad_username_start': _(u'Usernames must start with a letter from the alphabet.'),
        'invalid_username': _(u'Usernames can only have letters, digits, and underscores.'),
    }
    
    MIN_USERNAME_SIZE = 3
    MAX_USERNAME_SIZE = 30
    
    def __init__(self, *args, **kwargs):
        super(UsernameField, self).__init__(*args, **kwargs)
        
    def clean(self, value):
        super_clean = super(UsernameField, self).clean(value)
        
        # We could do this all with one regular expression:
        #    ^[A-za-z]\w{1,29}$
        # but to be kind to our users we do it with increasingly 
        # restrictive tests that give increasingly more detailed error feedback.
        
        if len(super_clean) < UsernameField.MIN_USERNAME_SIZE:
            raise ValidationError(self.error_messages['username_too_short'])            
        if len(super_clean) > UsernameField.MAX_USERNAME_SIZE:
            raise ValidationError(self.error_messages['username_too_long'])        
        if re.match(r'^[A-Za-z]', super_clean) is None:
            raise ValidationError(self.error_messages['bad_username_start'])
        if re.match(r'^[A-Za-z]\w+$', super_clean) is None:
            raise ValidationError(self.error_messages['invalid_username'])
        return super_clean

More like this

  1. Username form field by sma 6 years, 3 months ago
  2. PatchModelForm - A ModelForm subclass with the semantics of the PATCH HTTP method by gnrfan 2 years, 9 months ago
  3. Convert an instance to a dictionary for use in newforms by SmileyChris 7 years, 10 months ago
  4. Replace slugfield validation for User username in Admin form with a CharField by dodgyville 6 years ago
  5. Severity codes in user messages by cconnell 6 years, 1 month ago

Comments

diverman (on August 11, 2009):

Look at RegexField...

#

davepeck (on August 12, 2009):

diverman: You missed the point. :-)

Sometimes you've got to return precise, friendly error messages. This is especially true when you want your users to actually have a shot at signing in. You could use a RegexField, and if it doesn't validate you could always display the same error message regardless of the root cause. Or you could use this class to get easier to understand fine-grained error messages for entered user names.

RegexField is not the solution to all the world's woes -- especially where human factors are involved.

#

Please login first before commenting.