djangodjango-authenticationreset-passworddjango-contrib

In Django's auth contrib module, how do I invoke the function that generates a password reset email?


I'm using Django 3.1.1 with the auth contrib module. I would like to send the user an email when they request their password be reset (via an API call) so I created this in my urls.py file

path('reset_password', views.ResetPasswordView.as_view(template_name='../templates/users/password_reset.html'), name='reset_password'),

and added this to my views.py file

class ResetPasswordView(SuccessMessageMixin, PasswordResetView):
    reset_password_template_name = 'templates/users/password_reset.html'
    email_template_name = 'users/password_reset_email.html'
    subject_template_name = 'users/password_reset_subject'
    success_message = "We've emailed you instructions for setting your password, " \
                      "if an account exists with the email you entered. You should receive them shortly." \
                      " If you don't receive an email, " \
                      "please make sure you've entered the address you registered with, and check your spam folder."
    success_url = reverse_lazy('users-home')

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        request.csrf_processing_done = True
        return super().dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        email = json.loads(request.body).get('username')
        try:
            if User.objects.get(email=email).is_active:
                print("email: %s " % email)
                return super(ResetPasswordView, self).post(request, *args, **kwargs)
        except:
            # this for if the email is not in the db of the system
            return super(ResetPasswordView, self).post(request, *args, **kwargs)

but when I call my reset password endpoint with a user that exists, I simply get the contents of my template returned from the endpoint. How do I configure things such that the contents of the template are emailed to the user? That is, I want the user to receive the reset password email with a valid link to reset their password.


Solution

  • Generating a reset url and sending the email is done upon save() of django.contrib.auth.forms.PasswordResetForm.

    Here is an example:

    from django.contrib.auth.forms import PasswordResetForm
    from django.http import HttpRequest
    
    form = PasswordResetForm({'email': user.email})
    if form.is_valid():
        request = HttpRequest()
        request.META['SERVER_NAME'] = 'example.com'
        request.META['SERVER_PORT'] = '443'
        # calling save() sends the email
        # check the form in the source code for the signature and defaults
        form.save(request=request,
                  use_https=True,
                  from_email="noreply@example.com", 
                  email_template_name='registration/password_reset_email.html')