Django - 登录前拥有多级状态的最佳方式是什么

时间:2016-10-14 06:50:51

标签: python django

我有一个场景,有一个用户注册,它应该有多个状态(可能是is_active - 但默认情况下这是布尔值)

  1. 列出项目代码 - 0 - >等待电子邮件确认
  2. 列出项目代码 - 1 - >帐户已激活/有效(仅在确认电子邮件后,管理员会批准)
  3. 列出项目代码 - 2 - >确认电子邮件
  4. 我正在使用django allauth,我正在浏览以实现它,但无法找到它的一些近似匹配。对于您的信息,我也有Profile OnetoOne model for User model

    已更新

    class CustomConfirmEmailView(ConfirmEmailView):
        def get(self):
            raise Exception('GET')
        def post(self,*args,**kwargs):
            raise Exception('POST')
    

    设置文件

    ACCOUNT_CONFIRM_EMAIL_ON_GET = True
    ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
    

2 个答案:

答案 0 :(得分:1)

您应该创建自定义User或自定义Profile(我相信使用自定义Profile会更好,以避免弄乱django User):

from itertools import compress

class CustomProfile(Profile):
    is_confirmed = models.BooleanField(default=False)

    @property
    def status(self):
        return next(compress(['Pending', 'Active', 'Confirmed'], 
                             [not self.is_confirmed, not self.is_confirmed and self.user.is_active, self.confirmed and self.user.is_active]))

您可以看到我添加了@property来回答有关用户状态的问题。

但是要设置is_confirmed,您需要查看来源,docs会引导您allauth.account.views.ConfirmEmailView查看。

我认为您需要覆盖post方法。

class CustomConfirmEmailView(ConfirmEmailView):
    def post(self, *args, **kwargs):
        self.object = confirmation = self.get_object()
        confirmation.confirm(self.request)
        get_adapter(self.request).add_message(
            self.request,
            messages.SUCCESS,
            'account/messages/email_confirmed.txt',
            {'email': confirmation.email_address.email})
        if app_settings.LOGIN_ON_EMAIL_CONFIRMATION:
            resp = self.login_on_confirm(confirmation)
            if resp is not None:
                return resp
        profile = confirmation.email_address.user.profile
        profile.is_confirmed = True
        profile.save()
        redirect_url = self.get_redirect_url()
        if not redirect_url:
            ctx = self.get_context_data()
            return self.render_to_response(ctx)
        return redirect(redirect_url)

然后你需要将该视图放在网址中。

就是这样。当然,我没有运行它。但逻辑就在这里。

答案 1 :(得分:0)

您可以将decorators用于这些类型的方案。装饰器只是接受另一个方法作为参数的方法。您需要做的是pass the get/post or any other methods together with its arguments to decorator然后检查电子邮件确认/帐户是否有效。

from functools import wraps
from .permissions import is_admin_or_manager
from .utils import get_user_on_user_identifier


def is_manager(method):
    @wraps(method)
    def wrapper(self, *args, **kwargs):
        user_identifier = kwargs.get('user_identifier') if kwargs.get('user_identifier') else args[0]
    user = get_user_on_user_identifier(user_identifier)
    if user:
        if is_admin_or_manager(user):
            return method(self, *args, **kwargs)
        else:
            return {'status': 403, 'description': 'Only Manager/Admin roles can create items.'}
    else:
        return {'status': 404, 'description': 'No user with given username/email exists.'}
return wrapper

class PermissionException(Exception):
    pass

在你的观点中,

class Home(View):
    @is_manager
    def get(self, request):
        ...

上面的代码举例说明了装饰器的用法。在您的情况下,使用args传递方法。让用户从请求arg传递给decorator,然后检查电子邮件是否已确认/帐户是否已激活。如果没有使用django messages framework返回消息,json / string也可用于传递maessages。

如果您想在基于类的视图中使用相同的视图,请考虑mixins。您可以覆盖dispatch(self, request, *args, **kwargs)方法。我认为使用装饰器/ mixins会更好,因为你用一行代码检查你写的每个视图。