Masih Bahmani
Masih Bahmani

Reputation: 173

Django password reset with email using REST APIs

I'm developing a website using DjangoRest and Flutter and I want to add password reset using email.

I know that django.contrib.auth has views that help with password reset (PasswordResetView, PasswordResetDoneView, etc). But as long as I see, they return HTML files as a response when you call them in Postman.

Is there any way to use the same easy-to-use views but instead of getting HTML files, get an HTTP response so it can be called by the Flutter app?

Upvotes: 2

Views: 4924

Answers (1)

Faisal Nazik
Faisal Nazik

Reputation: 2863

This can be handled in basically Two Steps:

1. One is to send anything like OTP or Reset Link view email

2. The second is to verify whether the OTP/link either is valid or not with a new password.

This can be achieved via simple function-based API views: I can demonstrate the simplest form using OTP for basic understanding, as u said you are using flutter at frontend and that will be easier to manage otp instead of link

Step 1: Add a top Field into User Model. Let's say we have field otp in the user model. Later we use it for verification purposes.

class CustomerUser(models.Model):
    #...
    otp = models.CharField(
        max_length=6, null=True, blank=True)
    
    # Method to Put a Random OTP in the CustomerUser table.
    def save(self, *args, **kwargs):
        number_list = [x for x in range(10)]  # Use of list comprehension
        code_items_for_otp = []

        for i in range(6):
            num = random.choice(number_list)
            code_items_for_otp.append(num)

        code_string = "".join(str(item)
                                        for item in code_items_for_otp)  # list comprehension again
        # A six digit random number from the list will be saved in top field
        self.otp = code_string
        super().save(*args, **kwargs)

Step:2: Function to send Email with OTP on User Request

@api_view(['POST'])
def reset_request(request):
    data = request.data
    email = data['email']
    user = CustomUser.objects.get(email=email)
    if CustomUser.objects.filter(email=email).exists():
        # send email with otp
        send_mail(
        'Subject here',
        f'Here is the message with {user.otp}.',
        '[email protected]',
        [user.email],
        fail_silently=False,
        )
        message = {
            'detail': 'Success Message'}
        return Response(message, status=status.HTTP_200_OK)
    else:
        message = {
            'detail': 'Some Error Message'}
        return Response(message, status=status.HTTP_400_BAD_REQUEST)

Last Step: Verify OTP And reset Password

@api_view(['PUT'])
def reset_password(request):
    """reset_password with email, OTP and new password"""
    data = request.data
    user = CustomUser.objects.get(email=data['email'])
    if user.is_active:
        # Check if otp is valid
        if data['otp'] == user.opt:
            if new_password != '':
                # Change Password
                user.set_password(data['password'])
                user.save() # Here user otp will also be changed on save automatically 
                return Response('any response or you can add useful information with response as well. ')
            else:
                message = {
                    'detail': 'Password cant be empty'}
                return Response(message, status=status.HTTP_400_BAD_REQUEST)
        else:
            message = {
                'detail': 'OTP did not matched'}
            return Response(message, status=status.HTTP_400_BAD_REQUEST)
    else:
        message = {
            'detail': 'Something went wrong'}
        return Response(message, status=status.HTTP_400_BAD_REQUEST)

So you can replicate it with your custom approach as well and can refactor it easily. I have used Simple API views in these examples you can check the detailed information in DRF DOCS Requests and Response Section as well

So You don't have to use HTML at all, just can work with Response, HttpResponse whatever you prefer.

Upvotes: 3

Related Questions