Animesh D
Animesh D

Reputation: 5002

Updating custom user profile

In my web app, I need two users, regular site users and employees. I am using a custom user based on AbstractUser to achieve this.

class CustomUser(AbstractUser):
    pass

class Employee(CustomUser):
    user = models.OneToOneField(settings.AUTH_USER_MODEL)
    # other fields

In settings.py I have:

AUTH_USER_MODEL = 'app.CustomUser'

I want to provide a profile page for both the regular site user and the Employee user.

First, I created a form called UserProfileEditForm for regular site users:

class UserProfileEditForm(forms.ModelForm):
    email = forms.EmailField(required=True)
    first_name = forms.CharField(required=False)
    last_name = forms.CharField(required=False)

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

    def clean_email(self):
        username = self.cleaned_data.get('username')
        email = self.cleaned_data.get('email')

        if email and get_user_model().objects.filter(email=email).exclude(username=username).count():
            raise forms.ValidationError('This email address is already in use. Please supply a different email address.')
        return email

    def save(self, commit=True):
        user = super(UserProfileEditForm, self).save(commit=False)
        user.email = self.cleaned_data['email']

        if commit:
            user.save()

        return user

the corresponding view:

@login_required
def user_profile_edit(request):
    user = get_user_model()
    if request.method == 'POST':
        form = UserProfileEditForm(request.POST, instance=request.user)
        if form.is_valid():
            user = form.save(commit=False)
            user.is_active = False
            user.save()
            return redirect('user_profile')
    else:
        form = UserProfileEditForm(instance=request.user)
    return render(request, 'user/user_profile_edit.html', {
        'form': form
    })

and the form:

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Update Information</button>
</form>

In the edit user profile page, I see the email rightly populated into the email field. When I click submit, I get a validation error message:

This email address is already in use. Please supply a different email address.

It is as if the update form is trying to create a new user. What do I do to fix this?

Bonus question: does the same solution work for the user profile page of the Employee user?

Upvotes: 0

Views: 608

Answers (1)

Satendra
Satendra

Reputation: 6865

Remove .exclude(username=username) from your query in if clause inside clean_email method.

As the form class UserProfileEditForm has no username field in it so fetching username from cleandata is useless it will always be None

Also add self.instance.email != email to if clause, So current user will able update his profile info.

if email and self.instance.email != email and get_user_model().objects.filter(email=email).count():

UPDATE 2

The logged out issue is due to following code inside your user_profile_edit method

if form.is_valid():
   user = form.save(commit=False)
   # below line of code deactivating user and hence user got logged out, remove these lines 
   user.is_active = False
   user.save()

Change above line of code with

# You have already mentioned a save method inside UserProfileEditForm class
if form.is_valid():
   form.save()

Upvotes: 1

Related Questions