如何允许用户在Django allauth中删除账户?

3
我正在尝试找出使用django-allauth允许用户删除或停用其帐户的最佳方法,并且我假设我需要将is_active字段设置为False。
我的解决方案有几个问题: 1)呈现的复选框字段is_active显示文本“指定是否应将此用户视为活动状态。取消选择以替代删除帐户。”如何将此文本更改为“如果您确定要删除此帐户,请选中此框。”?
更新:刚才意识到,勾选该框会将is_active设置为True,而取消勾选该框会将其设置为False,因此也许我需要使用不同的字段来验证表单?
2)如何在提交时注销用户?
forms.py:
class DeactivateUserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['is_active']

views.py:

login_required(login_url='/accounts/login/')
def deactivate_user_view(request):  
    pk = request.user.id
    user = User.objects.get(pk=pk)
    user_form = DeactivateUserForm(instance=user)
    if request.user.is_authenticated() and request.user.id == user.id:
        if request.method == "POST":
            user_form = DeactivateUserForm(request.POST, instance=user)
            if user_form.is_valid():
                deactivate_user = user_form.save(commit=False)
                user.is_active = False
                deactivate_user.save()
        return render(request, "account/userprofile_del.html", {
            "user_form": user_form,
        })
    else:
        raise PermissionDenied

userprofile_del.html:

<h2>Delete your account</h2>
<hr>
<form action="." method="POST" class="padding">{% csrf_token %}
    {{ user_form.as_p}}
    <button class="btn btn-primary" type="submit" name="action">{% trans "Confirm" %}</button>
</form>

渲染: 确认删除


4
请注意,在某些司法管辖区(即至少包括整个欧盟),用户有权要求真正删除其账户,而不仅仅是将其停用。因此,根据您的服务类型,清楚地说明账户是被停用还是被删除,并提供执行真正删除的选项可能是明智之举。 - Bakuriu
谢谢提出。我需要对用户的删除方法进行一些研究。 - bayman
2个回答

6

我想提供一个可能的答案,以便用户可以停用和删除账号。

# forms.py

from django import forms

class UserDeactivateForm(forms.Form):
    """
    Simple form that provides a checkbox that signals deactivation.
    """
    deactivate = forms.BooleanField(required=True)


class UserDeleteForm(forms.Form):
    """
    Simple form that provides a checkbox that signals deletion.
    """
    delete = forms.BooleanField(required=True)

# views.py

# You could make this DRYer, but sometimes repeating yourself
# for explicitness makes sense.

from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from django.contrib.auth import logout
from django.shortcuts import redirect, render
from django.urls import reverse
from django.views.generic import View

from .forms import UserDeactivateForm, UserDeleteForm

class UserDeactivateView(LoginRequiredMixin, View):
    """
    Deactivates the currently signed-in user by setting is_active to False.
    """
    def get(self, request, *args, **kwargs):
        form = UserDeactivateForm()
        return render(request, 'users/user_deactivation.html', {'form': form})

    def post(self, request, *args, **kwargs):
        form = UserDeactivateForm(request.POST)
        # Form will be valid if checkbox is checked.
        if form.is_valid():
            # Make user inactive and save to database.
            request.user.is_active = False
            request.user.save()
            # Log user out.
            logout(request)
            # Give them a success message.
            messages.success(request, 'Account successfully deactivated')
            # Redirect to home page.
            return redirect(reverse('home'))
        return render(request, 'users/user_deactivation.html', {'form': form})


class UserDeleteView(LoginRequiredMixin, View):
    """
    Deletes the currently signed-in user and all associated data.
    """
    def get(self, request, *args, **kwargs):
        form = UserDeleteForm()
        return render(request, 'users/user_deletion.html', {'form': form})

    def post(self, request, *args, **kwargs):
        form = UserDeleteForm(request.POST)
        # Form will be valid if checkbox is checked.
        if form.is_valid():
            user = request.user
            # Logout before we delete. This will make request.user
            # unavailable (or actually, it points to AnonymousUser).
            logout(request)
            # Delete user (and any associated ForeignKeys, according to
            # on_delete parameters).
            user.delete()
            messages.success(request, 'Account successfully deleted')
            return redirect(reverse('home'))
        return render(request, 'users/user_deletion.html', {'form': form})

然后您需要创建每个模板和URL路由,但这些应该相当简单。


3

针对问题1,您可以在ModelForm的init方法中覆盖此字段的help-text属性。

class DeactivateUserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['is_active']

    def __init__(self, *args, **kwargs):
        super(DeactivateUserForm, self).__init__(*args, **kwargs)
        self.fields['is_active'].help_text = "Check this box if you are sure you want to delete this account."

    def clean_is_active(self):  
        # Reverses true/false for your form prior to validation
        #
        # You can also raise a ValidationError here if you receive 
        # a value you don't want, to prevent the form's is_valid 
        # method from return true if, say, the user hasn't chosen 
        # to deactivate their account
        is_active = not(self.cleaned_data["is_active"])
        return is_active

针对第二个问题,您可能需要禁用allauth中介注销页面。在您的设置中:

ACCOUNT_LOGOUT_ON_GET = True

在您的视图逻辑中重定向到注销页面。

from django.shortcuts import HttpResponseRedirect
from django.core.urlresolvers import reverse_lazy

    # ... in your view
    if user_form.is_valid():
        deactivate_user = user_form.save(commit=False)
        user.is_active = False
        deactivate_user.save()
        return HttpResponseRedirect(reverse_lazy('account_logout')) 

这将重定向到注销URL,然后通过ACCOUNT_LOGOUT_REDIRECT_URL在您的设置中设置的URL将用户转发到该URL。您的用户帐户现已停用并已注销。


你对第二个问题的解决方案可行,但我刚意识到在第一个问题中,勾选该框会将is_active设置为True,而取消勾选则会将其设置为False,因此如果帮助文本显示“勾选此框以删除”,可能需要使用不同的复选框字段来验证表单。我希望不要在帮助文本中显示“取消勾选此框以确认删除您的帐户”。 - bayman
一个自定义清理方法可以让您撤销复选框的选择。将添加在上面 :) - Ian Price

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接