Як вимагати входу для загальних переглядів Django?


87

Я хочу обмежити доступ до URL-адрес, що обробляються Django Generic Views.

Для своїх поглядів я знаю, що login_requiredдекоратор робить цю роботу. Також створіть / видаліть / оновіть загальні подання, приймаючи login_requiredаргумент, але я не міг знайти спосіб зробити це для інших загальних подань.

Відповіді:


104

Для Django <1,5 ви можете додати декоратор, обернувши функцію у ваші URL-адреси, що дозволяє обернути загальні подання:

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'}),
    )

Загальні подання на основі функцій застаріли в Django 1.4 та були вилучені в Django 1.5. Але застосовується той же принцип, просто оберніть функцію перегляду подання на основі класу login_requiredдекоратором:

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

Ось як вказати login_url login_required (TemplateView.as_view (TEMPLATE_NAME = 'foo_index.html'))
Saisiva А

101

Django 1.9 або за допомогою django-фігурних дужок

Django 1.9 представив LoginRequiredMixin, який використовується таким чином:

from django.contrib.auth.mixins import LoginRequiredMixin

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

Якщо ви використовуєте стару версію django, ви можете використовувати майже такий самий мікс від django-фігурних дужок - версія Django базувалася на версії django-фігурних дужок. django-braces 1.4.x все ще підтримує Django 1.4, тому ви можете використовувати його з досить старими версіями.

Старіші методи

Я знайшов це запитання під час пошуку в Google, як прикрасити подання на основі класу, тому додати відповідь на це:

Це висвітлено в розділі документації, присвяченому оформленню подань на основі класів . Є urls.pyобгортка, або ви можете застосувати декоратор до dispatch()методу. Приклади з документації:

Оформлення в URL конф

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())),
)

Оздоблення класу

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)

Детальніше див. У документації, на яку посилається вище.


Дивовижно! але я створив простий клас з єдиним def dispatchметодом як підкласом View. Тепер я можу зробити щось подібне:class ProtectedTemplateView(TemplateView, ProtectedView): pass
WBAR

якщо я не буду встановлювати login_url, але встановлюю це на settings.py, він перенаправлятиме на це за замовчуванням?
Марат Мкітарян

38

Загальні подання змінилися з функцій на об’єкти з версією 1.3 Django. Таким чином, для роботи з версією 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'))),
)

Також документація описує, як це зробити.


2
Будь ласка, читачу, враховуй цю відповідь, оскільки час проходить і програмне забезпечення розвивається. Перше рішення не працювало для мене.
n3storm

12

Якщо ви не хочете писати власну тонку обгортку навколо розглянутих загальних поглядів (як запропонував Амір), ви можете зробити щось подібне у своєму urls.pyфайлі:

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

Для django 1.11 ви можете використовувати LoginRequiredMixin для переглядів на основі класів

у файл налаштувань, який слід додати

LOGIN_URL="/login/"

у ваших views.py

from django.contrib.auth.mixins import LoginRequiredMixin

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

8

Інший спосіб досягти цього - нижче, мені подобається, що він дуже схожий на те, як це робиться з функціональними поданнями, і не вимагає модифікації urls.pyабо заміни dispatch:

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

3

Я хотів повторно використовувати спосіб вимагати авторизації для багатьох переглядів, похідних від загальних поглядів. Я створив функцію заміни відправлення, яку я можу додати до свого класу подання так само, як і інші декларації.

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

auth.dispatch - це місце, де ми виконуємо роботу:

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

3

У Django => 3.0 це стає досить просто:

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

@method_decorator(login_required(login_url='/login/'), name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'

для довідки: https://docs.djangoproject.com/en/3.0/topics/class-based-views/intro/#decorating-the-class


1

Використовуйте наступне:

from django.contrib.auth.decorators import login_required

@login_required
def your_view():
    # your code here

5
Виходячи з дати запитання, я припускаю, що ОП просить рішення для загальних подань на основі класу django ... а не для функціональних поглядів.
Дольф

0

Наступне може вирішити цю проблему.

// 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);
            }
        )
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.