发送自定义密码重置表单

2 投票
2 回答
2000 浏览
提问于 2025-05-10 15:22

我想在Django应用中通过访问某个网址,并使用POST方法传递电子邮件来重置密码。这是因为我想在一个安卓应用中使用这个功能,安卓应用会有自己的表单。所以,我想创建一个自定义的密码重置表单,然后保存它,但这并没有成功。

from django.contrib.auth.forms import PasswordResetForm

class Custom_password_reset_form(PasswordResetForm):
    def __init__(self, email, **kwargs):
        super(Custom_password_reset_form, self).__init__(**kwargs)
        self.email = forms.EmailField(initial=email, max_length=254)


def mobile_password_reset(request):
    """Sends mail with password reset link."""
    email = request.POST.get('email')
    my_form = Custom_password_reset_form(email)

    if my_form.is_valid():
        print 'valid'
        my_form.save()
    else:
        print 'not valid'
        print my_form._errors
    return render(...)

验证总是失败,返回一个空的 my_form._errors 列表。我在这里漏掉了什么吗?或者说有没有更好的方法来实现这个?

正确的代码:

其实自定义的类是多余的,应该去掉。密码重置的方法应该像这样:

def mobile_password_reset(request):
    """Sends mail with password reset link."""
    my_form = PasswordResetForm(request.POST)
    if my_form.is_valid():
        my_form.save()
        return JsonResponse({'success': True})
    else:
        return JsonResponse({'success': False})

需要注意的是,如果没有在设置中添加 django.contrib.sites 应用, my_form.save() 是无法工作的。你也可以通过添加这个参数来解决这个问题: my_form.save(request=request)

相关文章:

  • 暂无相关问题
暂无标签

2 个回答

0

你可以通过重写Django的认证模块来实现这个功能。

在你的urls.py文件中添加以下网址配置:

url(r'^password_reset/$', PasswordReset.as_view(is_admin_site=True),
    {'is_admin_site': 'True'}),

接下来,添加以下视图函数:

class PasswordReset(RedirectView):
is_admin_site = False
template_name = 'forget_password.html'
email_template_name = 'password_reset_email.html'
subject_template_name = 'password_reset_subject.html'
token_generator = default_token_generator
post_reset_redirect = None
from_email = None,
current_app = None,
extra_context = None

def get(self, request, *args, **kwargs):

    form = YourCustomPasswordResetForm()
    context = {
        'form': form,
    }
    if self.extra_context is not None:
        context.update(self.extra_context)
    return TemplateResponse(request, self.template_name, context,
                            current_app=self.current_app)

def post(self, request, *args, **kwargs):
    form = YourCustomPasswordResetForm(request.POST)
    if form.is_valid():
        if self.from_email is not None:
            from_email = 'From Email'
        opts = {
            'use_https': request.is_secure(),
            'token_generator': self.token_generator,
            'from_email': self.from_email,
            'email_template_name': self.email_template_name,
            'subject_template_name': self.subject_template_name,
            'request': request,
        }
        if self.is_admin_site:
            opts = dict(opts, domain_override=request.get_host())
        form.save(**opts)
        return HttpResponseRedirect(self.post_reset_redirect)
    context = {
        'form': form,
    }
    if self.extra_context is not None:
        context.update(self.extra_context)
    return TemplateResponse(request, self.template_name, context,
                            current_app=self.current_app)

在你的表单中,添加你的表单,并在里面加入以下保存方法。

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):
    """
    Generates a one-use only link for resetting password and sends to the
    user.
    """
    from_email = 'From Email'
    from django.core.mail import send_mail

    user = User.objects.get(username=request.POST['username'])
    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
        c = {
            'email': user.email,
            'domain': domain,
            'site_name': site_name,
            'uid': int_to_base36(user.id),
            'user': user,
            'token': token_generator.make_token(user),
            'protocol': use_https and 'https' or 'http',
        }
    subject = loader.render_to_string(subject_template_name, c)
    # Email subject *must not* contain newlines
    subject = ''.join(subject.splitlines())
    email = loader.render_to_string(email_template_name, c)
    send_mail(subject, email, from_email, [user.email])

当你提交这个表单时,用户会收到一封电子邮件,里面有一个包含令牌的链接。这个链接只能使用一次。

2

一个表单要有效,必须与数据绑定。你传递了邮箱参数,但没有提供data,所以这个表单总是处于未绑定状态。对于未绑定的表单,is_valid()会返回False,但不会有错误信息。

我不太明白你为什么需要自定义表单。如果emailrequest.POST里,为什么不直接把request.POST传给普通的PasswordRestForm呢?

my_form = PasswordResetForm(request.POST)

撰写回答