Como requerer login para visualizações genéricas do Django?


87

Eu quero restringir o acesso a URLs manipulados por visualizações genéricas do Django.

Para minhas visualizações, eu sei que o login_requireddecorador faz o trabalho. Criar / excluir / atualizar visualizações genéricas também aceita o login_requiredargumento, mas não consegui encontrar uma maneira de fazer isso para outras visualizações genéricas.

Respostas:


104

Para Django <1.5, você pode adicionar um decorador envolvendo a função em seus urls, o que permite envolver as visualizações genéricas:

from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
    (r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
    )

As visualizações genéricas baseadas em funções estão obsoletas no Django 1.4 e foram removidas no Django 1.5. Mas o mesmo princípio se aplica, apenas envolva a função de visualização da visualização baseada em classe com o login_requireddecorador:

login_required(TemplateView.as_view(template_name='foo_index.html'))

Aqui, como especificar login_url login_required (TemplateView.as_view (template_name = 'foo_index.html'))
Saisiva A

101

Django 1.9 ou usando django-braces

Django 1.9 introduziu um LoginRequiredMixin que é usado assim:

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

Se você estiver usando uma versão mais antiga do django, você pode usar praticamente o mesmo mixin do django-braces - a versão do Django foi baseada na versão django-braces. django-braces 1.4.x ainda suporta Django 1.4, então você pode usá-lo com versões bem antigas.

Métodos Antigos

Eu encontrei esta pergunta ao pesquisar no Google como decorar visualizações baseadas em classe, para adicionar a resposta para isso:

Isso é abordado na seção de documentação sobre a decoração de visualizações baseadas em classe . Existe o urls.pywrapper, ou você pode aplicar o decorador ao dispatch()método. Exemplos da documentação:

Decoração em URL conf

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView

from .views import VoteView

urlpatterns = patterns('',
    (r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
    (r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
)

Decorar a aula

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView

class ProtectedView(TemplateView):
    template_name = 'secret.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(ProtectedView, self).dispatch(*args, **kwargs)

Consulte a documentação vinculada acima para obter mais detalhes.


IMPRESSIONANTE! mas fiz uma classe simples com apenas o def dispatchmétodo como subclasse de View. Agora posso simplesmente fazer algo assim:class ProtectedTemplateView(TemplateView, ProtectedView): pass
WBAR

se eu não definir o login_url, mas definir em settings.py, ele redirecionará para este por padrão?
Marat Mkitaryan

38

As visualizações genéricas mudaram de funções para objetos com a versão 1.3 do Django. Como tal, há uma pequena mudança necessária para que as respostas de Will McCutchen e Will Hardy funcionem com a versão 1.3:

from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView

urlpatterns = patterns('',
    (r'^foo/$', login_required(TemplateView.as_view(template_name='foo_index.html'))),
)

Além disso, a documentação descreve como fazer isso também.


2
Por favor, leitor, leve em consideração esta resposta porque o tempo passa e o software evolui. A primeira solução não estava funcionando para mim.
n3 tempestade de

12

Se você não quiser escrever seu próprio wrapper fino em torno das visualizações genéricas em questão (como Aamir sugeriu), você também pode fazer algo assim em seu urls.pyarquivo:

from django.conf.urls.defaults import *

# Directly import whatever generic views you're using and the login_required
# decorator
from django.views.generic.simple import direct_to_template
from django.contrib.auth.decorators import login_required

# In your urlpatterns, wrap the generic view with the decorator
urlpatterns = patterns('',
    (r'', login_required(direct_to_template), {'template': 'index.html'}),
    # etc
)

8

Para django 1.11, você pode usar LoginRequiredMixin para visualizações baseadas em classe

no arquivo de configurações você deve adicionar

LOGIN_URL="/login/"

em suas views.py

from django.contrib.auth.mixins import LoginRequiredMixin

class RestaurantLocationCreateView(LoginRequiredMixin,CreateView):
    ....

8

Outra maneira de conseguir isso está abaixo, eu gosto que é bastante semelhante a como é feito com visualizações baseadas em função e não requer modificação urls.pyou substituição dispatch:

@method_decorator(login_required, name='dispatch')
class YourGenericViewSubclass(TemplateView):
    #
    # View methods
    #

3

Eu queria uma maneira reutilizável de exigir autenticação em muitas visualizações derivadas de visualizações genéricas. Eu criei uma função de despacho de substituição que posso adicionar à minha classe de exibição da mesma forma que em outras declarações.

class Index(generic.ListView):
    model = models.HomePage
    dispatch = auth.dispatch

auth.dispatch é onde fazemos o trabalho:

def dispatch(self, request, *args, **kw):
    """Mix-in for generic views"""
    if userSession(request):
        return  super(self.__class__, self).dispatch(request, *args, **kw)

    # auth failed, return login screen
    response = user(request)
    response.set_cookie('afterauth', value=request.path_info)
    return response


1

Use o seguinte:

from django.contrib.auth.decorators import login_required

@login_required
def your_view():
    # your code here

5
Com base na data da pergunta, suponho que o OP está pedindo uma solução para as visões genéricas baseadas em classes do Django ... não as visões baseadas em funções.
Dolph

0

O seguinte pode resolver este problema.

// in views.py:
class LoginAuthenAJAX(View):
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated:
            jsonr = json.dumps({'authenticated': True})
        else:
            jsonr = json.dumps({'authenticated': False})
        return HttpResponse(jsonr, content_type='application/json')

// in urls.py
    path('login_auth', views.LoginAuthenAJAX.as_view(), name="user_verify"),

//in xxx.html
<script src = “{% static “xxx/script.js” %}” 
var login_auth_link = “{%  url ‘user_verify’ %}”
</script>

// in script.js
        $.get(login_auth_link, {
            'csrfmiddlewaretoken' : csrf_token,
            },
            function(ret){
                if (ret.authenticated == false) {
                    window.location.pathname="/accounts/login/"
                }
                $("#message").html(ret.result);
            }
        )
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.