Search code examples
pythondjangodjango-viewstwiliodjango-authentication

How to change Django Authentication View "PasswordResetView" to send resent link to mobile number and email?


I have a Custom User Model and Custom Backend for authenticating via both mobile number and email.

I want to give my users the ability to reset the password via both email and mobile number, i.e., on the PasswordResetView I want to have both options for resetting the password with the reset password link sent on the mobile number and on the email.

I have my Django project configured to send messages with Twilio.

My question is how to change the PasswordResetView to be able to do that.


Solution

  • We need to override the form_class of the view PasswordResetView.

    ####### Your views.py ####### 
    
    class PasswordResetViewOverride(auth_views.PasswordResetView):
        form_class = PasswordResetFormOverride
    

    And then to achieve the authentication custom logic we need to override the save method of this default form_class that the PasswordResetView had, i.e., PasswordResetForm. This class has a save method we need to override that. Moreover, we can write its custom clean method and add any other field, in this case, a mobile number field. After grabbing the user with the field of mobile number we can generate the token for them as shown here. With this token, we will create a link and send to users' mobile number using any messaging client(like Twilio).

    class PasswordResetFormOverride(PasswordResetForm):
        mobile_no = forms.CharField(
            label="Your Accounts' Mobile Number",
            max_length=10,
            widget=forms.NumberInput(),
            required=False,
        )
        def save(self, domain_override=None,
             subject_template_name='registration/password_reset_subject.txt',
             email_template_name='registration/password_reset_email.html',
             use_https=False, token_generator=default_token_generator,
             from_email=None, request=None, html_email_template_name=None,
             extra_email_context=None):
        mobile_no = self.cleaned_data.get("mobile_no", "")
    
        # All the previous stuff
    
        if mobile_no != "":
            # Send reset link to mobile logic
        
        # All the previous stuff