Як вимагати входу для загальних переглядів 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.