Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override django 'unique' error message for username in custom UserChangeForm

I'm trying to override the default "A user with that Username already exists." error message displayed when entering an existing username in my custom UserChangeForm form. Django version used: 1.6.1

Here's my code :

class CustomUserChangeForm(forms.ModelForm):
    username = forms.RegexField(
        label="User name", max_length=30, regex=r"^[\w.@+-]+$",
        error_messages={
            'invalid': ("My message for invalid"),
            'unique': ("My message for unique") # <- THIS
        }
    )

    class Meta:
        model = get_user_model()
        fields = ('username', 'first_name', 'last_name', 'email',)

But if I enter an existing username with this code, I still get the default "A user with that Username already exists." message. Note that the custom "My message for invalid" is displayed when entering a wrong username (with invalid characters).

like image 303
Maxime Rossini Avatar asked Mar 08 '14 02:03

Maxime Rossini


3 Answers

Currently unique error message cannot be customized on a form field level, quote from docs:

class CharField(**kwargs)

...

Error message keys: required, max_length, min_length

...

class RegexField(**kwargs)

...

Error message keys: required, invalid

So, to summarize, for your username field only required, invalid, max_length, min_length error messages are customizeable.

You can only set unique error message on a model field level (see source).

Also see relevant ticket.

Also see how django.contrib.auth.forms.UserCreationForm was made (pay attention to custom duplicate_username error message) - custom error message could be an option for you too.

Hope that helps.

like image 186
alecxe Avatar answered Oct 04 '22 22:10

alecxe


According to alecxe's answer, I ended up creating a custom validation method in my form:

class CustomUserChangeForm(forms.ModelForm):
    error_messages = {
        'duplicate_username': ("My message for unique")
    }

    username = forms.RegexField(
        label="User name", max_length=30, regex=r"^[\w.@+-]+$",
        error_messages={
            'invalid': ("My message for invalid")
        }
    )

    class Meta:
        model = get_user_model()
        fields = ['username', 'first_name', 'last_name', 'email']

    def clean_username(self):
        # Since User.username is unique, this check is redundant,
        # but it sets a nicer error message than the ORM. See #13147.
        username = self.cleaned_data["username"]
        if self.instance.username == username:
            return username
        try:
            User._default_manager.get(username=username)
        except User.DoesNotExist:
            return username
        raise forms.ValidationError(
            self.error_messages['duplicate_username'],
            code='duplicate_username',
        )

See the clean_username method, taken from the existing UserCreationForm form to which I added a check to compare with the current user's username.

like image 28
Maxime Rossini Avatar answered Oct 04 '22 22:10

Maxime Rossini


at the moment it is possible to override the unique error message at the form level:

class MyForm(forms.ModelForm):

    class Meta:
        model = MyModel
        error_messages = {
            'my_unique_field': {
                'unique': 'not a snowflake after all'
            },
        }
like image 25
minusf Avatar answered Oct 04 '22 22:10

minusf