Search code examples
pythondjangorequestpython-3.8django-3.1

Django request.user not showing correct user in frontend


When user updates profile with username which is already in use ,message appear of "A user with that username already exists." but username on profile is changed to which user requested. for example: if user with username test001 update profile with already taken username "test0012"

this will happen:

error page screenshot

Notice:username is updated with "test0012"

Code in frontend for username:

<h2 id="user-name" class="account-heading user__name">@{{ user.username }}</h2>

also going on "my posts" will redirect to posts of user "test0012".

code for profile and update:

@login_required
def profile(request):
    if request.method=="POST":
        u_form=UserUpdateForm(request.POST,instance=request.user)#,op_email=request.user.email)
        p_form=ProfileUpdateForm(request.POST,request.FILES,instance=request.user.profile)

        if u_form.is_valid() and p_form.is_valid():

        
            u_form.save()
            p_form.save()
            messages.success(request,f'Your Account has been updated!')
            
            #changing email on profile
            tusername=u_form.cleaned_data.get('username')
            temail=u_form.cleaned_data.get('email')
            registeruser=User.objects.get(username=tusername)
            registeruser.email=temail
            registeruser.save()
            
            return redirect('profile')
    

    else:
          u_form=UserUpdateForm(instance=request.user)
          p_form=ProfileUpdateForm(instance=request.user.profile)

userupdateform code:

class  UserUpdateForm(forms.ModelForm):
    email=forms.EmailField()
    username=forms.CharField(required=True,validators=[username_check,])

    class Meta:
        model =User
        fields =['username','email']

ProfileUpdateForm:

class ProfileUpdateForm(forms.ModelForm):
    class Meta:
        model=Profile
        fields=['image']

username_check:

def username_check(someusername):
   if someusername!=someusername.lower():
      raise forms.ValidationError("Only Lower case allowed.")

Solution

  • The model form first does it's own cleaning / validation, after which it assigns this data to the instance that you passed to it and calls that instance's full_clean method which is what gives you the error A user with that username already exists. But as you notice this is already too late as the instance is already modified, although this does not get saved to the database you are displaying the same instance.

    The solution to this is to get a copy of the user instance from the database just to pass it to the form, so that the instance associated with the request stays unchanged and clean:

    from django.contrib.auth import get_user_model
    
    
    UserModel = get_user_model()
    
    @login_required
    def profile(request):
        user = UserModel.objects.get(pk=request.user.pk)
        if request.method == "POST":
            u_form = UserUpdateForm(request.POST, instance=user)
            p_form = ProfileUpdateForm(request.POST, request.FILES, instance=user.profile)
            ...
        else:
            u_form = UserUpdateForm(instance=user)
            p_form = ProfileUpdateForm(instance=user.profile)