Search code examples
pythondjangodjango-formsweb-frameworks

how to add "search by usernane or email address" field in django forgot password


this is a django default forgot password form. how to modify to add "search by username" feature. for example "username/email". can someone help me with this. i am a noob in django. just started learning.

def get_users(self, email):

    active_users = UserModel._default_manager.filter(**{
        '%s__iexact' % UserModel.get_email_field_name(): email,
        'is_active': True,
    })
    return (u for u in active_users if u.has_usable_password())

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):
    """
    Generate a one-use only link for resetting password and send it to the
    user.
    """
    email = self.cleaned_data["email"]
    for user in self.get_users(email):
        if not domain_override:
            current_site = get_current_site(request)
            site_name = current_site.name
            domain = current_site.domain
        else:
            site_name = domain = domain_override
        context = {
            'email': email,
            'domain': domain,
            'site_name': site_name,
            'uid': urlsafe_base64_encode(force_bytes(user.pk)),
            'user': user,
            'token': token_generator.make_token(user),
            'protocol': 'https' if use_https else 'http',
            **(extra_email_context or {}),
        }
        self.send_mail(
            subject_template_name, email_template_name, context, from_email,
            email, html_email_template_name=html_email_template_name,
        )

Solution

  • We can search both on the email field and the username field by usign Q objects [Django-doc]:

    from django.db.models import Q
    
    def get_users(self, email):
        active_users = UserModel._default_manager.filter(
            Q(**{'%s__iexact' % UserModel.get_email_field_name(): email}) |
            Q(username=email),
            is_active=True
        )
        return (u for u in active_users if u.has_usable_password())

    You can add the __iexact field lookup [Django-doc] to the username, so username__iexact=email if you want to search for usernames in a case insensitive manner.

    In the save function, you probably should use the email of the user instead:

    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):
        """
        Generate a one-use only link for resetting password and send it to the
        user.
        """
        email = self.cleaned_data["email"]
        for user in self.get_users(email):
            if not domain_override:
                current_site = get_current_site(request)
                site_name = current_site.name
                domain = current_site.domain
            else:
                site_name = domain = domain_override
            email = getattr(user, UserModel.get_email_field_name())
            context = {
                'email': email,
                'domain': domain,
                'site_name': site_name,
                'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                'user': user,
                'token': token_generator.make_token(user),
                'protocol': 'https' if use_https else 'http',
                **(extra_email_context or {}),
            }
            self.send_mail(
                subject_template_name, email_template_name, context, from_email,
                email, html_email_template_name=html_email_template_name,
            )