user956424
user956424

Reputation: 1609

Django display user form validation error message when inherited from UserAdmin

I am using the django User model with profile to extend the User with few more attributes. I require to ensure unique email id across the users in the User table.

from django.contrib.auth.forms import UserCreationForm, UserChangeForm 
from django.contrib.auth.admin import UserAdmin

class UserForm(UserAdmin):
    class Meta:
        model = User
        fields = "__all__"

    readonly_fields = ('date_joined',)

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if email and User.objects.filter(email=email).exists():
            raise forms.ValidationError(u'Email addresses must be unique.')
        return email

This validation message is not displayed in the User form.

The custom user admin is defined as

class CustomUserAdmin(UserAdmin):

    def save(UserForm, commit=True):
        return super(UserForm, self).save(commit=False)
        if User.objects.filter(email=email).exists():
            raise forms.ValidationError(_("Email already exists ya"),
                                        code='invalid')

    inlines = (ProfileInline, )

admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)

This validation message is seen in the traceback in debug mode and not in the UserForm.

Require the message to show the error in the UserForm. I understand that there are 2 forms viz. UserCreationForm, UserChangeForm in the django auth.

Using django 3.0, python 3.7

Upvotes: 0

Views: 1069

Answers (4)

HNMN3
HNMN3

Reputation: 542

You can create your custom validator and provide it as "validators" argument in the Field Creation.

Here is the custom validator:

from django.core.exceptions import ValidationError
def email_validator(email):
    if User.objects.filter(email=email).exists():
        raise ValidationError("Email already exists ya", code='invalid')

And then in the User model's email field just provide this email_validator in the validators argument as below:

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    # other fields
    email = models.EmailField("email", unique=True, validators=[email_validator])

Django will use your custom validator and it will show the error right below the field on the User Creation Form.

Upvotes: 0

Rudra Desai
Rudra Desai

Reputation: 1

Instead of using clean_email, try using clean . Ex:

from django.contrib.auth.forms import UserCreationForm, UserChangeForm 
from django.contrib.auth.admin import UserAdmin

class UserForm(UserAdmin):
    class Meta:
        model = User
        fields = "__all__"

    readonly_fields = ('date_joined',)

    def clean(self):
        cleaned_data = super().clean()
        email = cleaned_data.get('email')
        if email and User.objects.filter(email=email).exists():
            raise forms.ValidationError(u'Email addresses must be unique.')

Upvotes: 0

Matt
Matt

Reputation: 334

If I where you I would put a unique = True on the email field on your user model. Django will then take care of the rest, no custom form validation necessary.

Upvotes: 0

Metalgear
Metalgear

Reputation: 3457

You should use clean method in Model class instead. Add this code into your User(you should customize auth's User model) in models.py.

from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError

class User(AbstractUser):
    # add clean method here
    def clean(self):
        if User.objects.filter(email=email).exists():
            raise ValidationError(_("Email already exists ya"), code='invalid')

This method is for validating field of model.

Upvotes: 6

Related Questions