42. Changing logged in account data and password

Next, we will implement the functionalities that allow users to update their account information and change their password.

To implement these functionalities, we'll start by editing the your_account view function. This function will handle the processing of the forms for updating account information and changing the password.

views.py
@login_required
def your_account(request):
    error = None
    altered_account = False
    altered_password = False
    if request.method == 'POST':
        data = request.POST.dict()
        #? email and password are outside to diferentiate what forms is submitted
        if data.get('current_password'):
            #? is modifying the password
            current_password = data.get("current_password")
            new_password = data.get("new_password")
            confirm_new_password = data.get("confirm_new_password")
            if current_password != new_password and confirm_new_password != current_password:
                if secure_password(new_password) :
                    if new_password == confirm_new_password :
                        #? verify current password
                        user = authenticate(request, username=request.user.email, password=current_password)
                        if user:
                            #? correct password, change password
                            user.set_password(new_password)
                            user.save()
                            altered_password = True
                        else :
                            error = "invalid_current_password"
                    else :
                        error = "different_passwords"
                else :
                    error = "weak_password"
            else :
                error = "same_password"

        elif data.get("email") : 
            #? is modifying the account data
            email = data.get("email")
            phone = data.get("phone")
            name = data.get("name")
            if email != request.user.email :
                users = User.objects.filter(email=email)
                if len(users) > 0 :
                    error = "email_exists"
            if not error :
                client = request.user.client
                client.email = email
                request.user.username = email
                request.user.email = email #? also changing from the user, they are different things
                client.name = name
                client.phone = phone
                client.save()
                request.user.save()
                altered_account = True
        else :
            error = "invalid_changes"

    context = {"error" : error, "altered_account" : altered_account, "altered_password" : altered_password}
    return render(request, 'user/your_account.html', context) 

Below is a explanation of the code:

  • Decorator: @login_required

    • Ensures that only authenticated users can access this view.

  • Function Definition: def your_account(request)

    • Defines the view function handling the user's account page.

  • Initialization:

    • error = None: Initializes an error variable to store any error messages.

    • altered_account = False and altered_password = False: Initialize flags to indicate if the account or password was successfully altered.

  • Check Request Method: if request.method == 'POST'

    • Handles form submission, which is sent via POST.

  • Extract Data: data = request.POST.dict()

    • Converts the POST data into a dictionary for easier manipulation.

  • Password Modification Check: if data.get('current_password')

    • Checks if the form contains password modification fields.

    • Password Validation:

      • Ensures that the new password is different from the current one and that both new passwords match.

      • Calls secure_password(new_password) to check the strength of the new password.

      • If validation passes, authenticates the user with their current password:

        • user = authenticate(request, username=request.user.email, password=current_password): Authenticates the user.

        • If successful, updates the user's password and sets altered_password = True.

        • If unsuccessful, sets an appropriate error message.

  • Account Data Modification Check: elif data.get("email")

    • Checks if the form is modifying account data (email, name, phone).

    • Email Validation:

      • If the email has changed, checks if the new email already exists in the database.

      • If the email is unique, updates the client and user objects with the new email, name, and phone number, and sets altered_account = True.

      • If the email exists, sets an appropriate error message.

  • Error Handling: else: error = "invalid_changes"

    • If the form submission doesn't contain valid data for either password or account modification, sets an error message.

  • Context Preparation: context = {"error": error, "altered_account": altered_account, "altered_password": altered_password}

    • Prepares a context dictionary containing any error messages and flags indicating successful updates.

  • Render Template: return render(request, 'user/your_account.html', context)

    • Renders the your_account.html template with the context, displaying any messages or updates.

Inside the your_account.html file, we will implement the error messages by displaying them from the view function's context. This will allow users to see any validation errors or other issues that arise when they try to update their account information or change their password.

{% if altered_account %}
<p>Account information succesfully saved</p>
{% endif %}
{% if altered_password %}
<p>Password succesfully altered</p>
{% endif %}

{% if error == "invalid_current_password" %}
<p>Wrong current password</p>
{% endif %}

{% if error == "different_passwords" %}
<p>Password confirmation doesn't match</p>
{% endif %}

{% if error == "email_exists" %}
<p>Email in use</p>
{% endif %}

{% if error == "invalid_changes" %}
<p>Invalid changes, try again</p>
{% endif %}

{% if error == "weak_password" %}
<p>Invalid password. Ensure it has 8 to 20 characters, with least one upper, lower, numeric and special</p>
{% endif %}

{% if error == "same_password" %}
<p>New password is the same as the previous one</p>
{% endif %}
Now, the functionalities to update client information and change passwords are working as intended, with appropriate error messages displayed when necessary.

Last updated