如何手动发送重设密码邮件?

How to manually send a reset-password email?

我需要在创建新用户时手动发送密码重置电子邮件。我按照描述的步骤 并创建了一个 drive-by HttpRequest (pwreset_request = HttpRequest()) 来执行此操作,但是我在 return 中调用 PasswordResetView.as_view()(pwreset_request) 时得到的只是一个 403,因为无效的 CSRF 令牌。

尽管如此(并因此收到了那封电子邮件),页面上没有任何错误并且一切正常。

from django.http import HttpResponseForbidden, HttpResponse, HttpRequest
from django.middleware.csrf import get_token

@login_required
@permission_required(["abonnenten.verlag_sachbearbeiter_fullaccess"])
def sachbearbeiter_create_or_edit(request, username=None):
    mode = "create" if username is None else "edit"

    if mode == "create":
        user = None
        sachbearbeiter = None
    else:
        user = get_object_or_404(User, username=username)
        sachbearbeiter = user.sachbearbeiter

        if user.is_superuser or user.is_staff:
            raise PermissionDenied

    user_form = UserForm(request.POST or None, instance=user)
    sachbearbeiter_form = SachbearbeiterForm(request.POST or None, instance=sachbearbeiter)

    if request.method == 'POST':
        if mode == "create":
            if user_form.is_valid() and sachbearbeiter_form.is_valid():
                user = user_form.save(commit=False)
                user.email = user.username
                user.save()
                sachbearbeiter = sachbearbeiter_form.save(commit=False)
                sachbearbeiter.user = user
                sachbearbeiter.save()

                # Manually send password reset mail
                # TODO Fix this shit (403)
                pwreset_request = HttpRequest()
                pwreset_request.method = 'POST'
                pwreset_request.META['HTTP_HOST'] = request.META['HTTP_HOST']
                pwreset_request.POST = {'email': user.email, 'csrfmiddlewaretoken': get_token(HttpRequest())}
                PasswordResetView.as_view()(pwreset_request)

                messages.success(request, 'Der Datensatz wurde erfolgreich gespeichert.')
                return redirect('sachbearbeiter_edit', username=user.username)
        elif mode == "edit":
            if user_form.is_valid() and sachbearbeiter_form.is_valid():
                user = user_form.save(commit=False)
                user.email = user.username
                user.save()
                sachbearbeiter_form.save()
                messages.success(request, 'Der Datensatz wurde erfolgreich gespeichert.')
                return redirect('sachbearbeiter_edit', username=user.username)
        else:
            raise ValueError("Variable `mode` must be 'create' or 'edit'")

    return render(request,
                  'sachbearbeiter/edit_or_create.html',
                  {'mode': mode,
                   'user': user,
                   'user_form': user_form,
                   'sachbearbeiter_form': sachbearbeiter_form})

有什么解决办法吗?

为什么要手动创建一个新的 Request 对象,调用密码重置视图,而您只能使用此视图使用的 PasswordResetForm

所以替换下面的所有代码:

# Manually send password reset mail
# TODO Fix this shit (403)
pwreset_request = HttpRequest()
pwreset_request.method = 'POST'
pwreset_request.META['HTTP_HOST'] = request.META['HTTP_HOST']
pwreset_request.POST = {'email': user.email, 'csrfmiddlewaretoken': get_token(HttpRequest())}
PasswordResetView.as_view()(pwreset_request)

通过此代码:

from django.contrib.auth.forms import PasswordResetForm

reset_password_form = PasswordResetForm(data={'email': user.email})
if reset_password_form.is_valid():
     reset_password_form.save(request=request) # The save method will send the email