ti-enxame.com

Definir todas as páginas para exigir login, globalmente?

Desejo redirecionar o acesso de usuários não autenticados para a página de login, após o qual o usuário conectado deve ser redirecionado para a página solicitada originalmente.

De acordo com a documentação, isso é facilmente alcançado usando o @user_passes_test decorador. Mas parece que eu teria que decorar todas as visualizações, o que é loucura, há muitas e é propenso a erros.

Qual é uma boa maneira de ativar essa funcionalidade globalmente (exceto por um pequeno conjunto fixo de visualizações, como login)? Ou seja, tudo o padrão para logon somente + manipula a exibição anônima explicitamente, quando necessário.

34
user1067863
from Django.shortcuts import redirect
from Django.conf import settings


class LoginRequiredMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.login_url = settings.LOGIN_URL
        self.open_urls = [self.login_url] + \
                         getattr(settings, 'OPEN_URLS', [])

    def __call__(self, request):
        if not request.user.is_authenticated \
        and not request.path_info in self.open_urls:
            return redirect(self.login_url+'?next='+request.path)

        return self.get_response(request)
3
tulsluper

A maneira que resolvi isso foi ter uma aula de mixin, com o decorador (ou qualquer código que você precisar). Embora você precise se lembrar de chamar a função super(Class, self).get(...), acho que não é tão diferente assim.

Por outro lado, ter um conjunto de mixins que faz coisas diferentes que encontrei foi muito bom em obter uma visão muito simples de fazer muito sem muito código.

Editar

Foi assim que fiz no meu último projeto:

class BaseAuthMixin(object):
    def auth_check(self, user):
        return True

    def dispatch(self, request, *args, **kwargs):
        if not self.auth_check(request.user):
            from Django.http import HttpResponseRedirect
            from Django.contrib.auth import logout

            is_web = False
            is_live = False

            if hasattr(self, 'get_url_name'):
                from Django.core.urlresolvers import reverse
                from Django.core.urlresolvers import NoReverseMatch

                try:
                    next = reverse(self.get_url_name(), kwargs=kwargs)
                except NoReverseMatch:
                    next = ''
                else:
                    next= '?next=' + next

            logout(request)

            redirect_url = settings.LOGIN_URL
            redirect_url += next

            return HttpResponseRedirect(redirect_url)
        else:
            return super(BaseAuthMixin, self).dispatch(request, *args, **kwargs)

class LoginRequiredMixin(BaseAuthMixin):
    """
    Check if the view needs the user to be logged in.
    """
    def auth_check(self, user):
        if not super(LoginRequiredMixin, self).auth_check(user):
            return False
        else:
            if hasattr(self, 'login_required'):
                if self.login_required and not user.is_authenticated():
                    return False
        return True

class MyDefaultMixin(LoginRequiredMixin):
    """
    Mixin that inherits from all common view mixins.
    """
    pass

O acima é então usado pelas classes de exibição (eu usei Django 1.3 com visualizações baseadas em classe):

from Django.views.generic import TemplateView

class SomeViewClass(TemplateView, MyDefaultMixin):
    # Used by 'LoginRequiredMixin' to check if a user has to be logged in
    login_required = True

    # Template for the Django TemplateView
    template_name = "some_view_template.html"

Você precisa de uma visualização para manipular o logon (com URL em settings.LOGIN_URL), contendo um formulário com um campo oculto chamado next. Este campo deve ser definido por uma variável de contexto para a página a ser acessada após o login bem-sucedido.

Se todas as visualizações herdarem do mixin base (MyDefaultMixin no meu código acima), ele verificará automaticamente se o usuário está logado iv, a visualização contém um atributo chamado login_required e está definido como True.

Pode haver maneiras melhores de fazer isso, mas foi o que fiz e funcionou muito bem.

3
Some programmer dude

dê uma olhada em middleware . estas são funções executadas em vários pontos do ciclo de solicitação, por exemplo antes de cada visualização ser chamada.

como você pode excluir determinadas visualizações disso, consulte, por exemplo, como o middleware csrf funciona, junto com o decorador csrf_exempt.

vejo [SOURCE]/Django/views/decorators/csrf.py e [SOURCE]/Django/middleware/csrf.py

3
second