Подтвердить что ты не робот

Проверка подлинности Django и Ajax - URL-адреса, требующие входа в систему

Я хочу добавить Ajax - незнакомость с моим Django-кодированным сайтом.

В моем коде Django я использую декоратор @login_required от django.contrib.auth.decorators, чтобы отметить, для какого представления требуется аутентификация. Поведение по умолчанию, когда пользователь, не прошедший проверку подлинности, нажимает на него, - это перенаправить его/ее на страницу входа в систему, а затем передать целевую страницу.

То, что я видел на некоторых сайтах и ​​очень понравилось, заключается в том, что когда пользователь щелкает ссылку, ведущую к месту, ограниченному только зарегистрированным пользователям, вместо того, чтобы перенаправляться на страницу входа в систему, он получает всплывающее окно (через JavaScript) с просьбой войти в систему или зарегистрироваться. Там нет части перенаправления, поэтому пользователю не нужно использовать ключ "назад", если он/она решает, что ему действительно не нравится сайт, чтобы тратить время на регистрацию.

Итак, вопрос: как бы вы управляли задачей автоматической маркировки некоторых ссылок как "ограниченных", поэтому JavaScript может обрабатывать свое событие onclick и отображать всплывающее окно "пожалуйста, войдите в систему"?

4b9b3361

Ответ 1

Я столкнулся с той же проблемой, и, как и вы, я хотел бы, чтобы простой декоратор обернулся вокруг представления ajax Django, чтобы обрабатывать аутентификацию так же, как и другие представления. Один из подходов, который мне кажется многообещающим, заключается в использовании такого декоратора в сочетании с JavaScript, который ищет определенное значение в ответе.

Вот первый пересмотренный проект декоратора:

from functools import wraps

def ajax_login_required(view_func):
    @wraps(view_func)
    def wrapper(request, *args, **kwargs):
        if request.user.is_authenticated():
            return view_func(request, *args, **kwargs)
        json = simplejson.dumps({ 'not_authenticated': True })
        return HttpResponse(json, mimetype='application/json')
    return wrapper

Вот представление:

@ajax_login_required
def ajax_update_module(request, module_slug, action):
    # Etc ...
    return HttpResponse(json, mimetype='application/json')

И вот JavaScript (jQuery):

$.post('/restricted-url/', data, function(json) {
    if (json.not_authenticated) {
        alert('Not authorized.');  // Or something in a message DIV
        return;
    }
    // Etc ...
});

EDIT. Я попытался использовать functools.wraps, как было предложено. Я фактически не использовал этот декоратор в рабочем коде, поэтому остерегайтесь возможных ошибок.

Ответ 2

Звучит как возможность шаблона страницы.

  • Вы можете передать LINK_VIA (или что-то), которое вы предоставляете как onClick="return popup(this, 'arg')" или None. Каждая ссылка будет <A HREF="link" {{LINK_VIA}}>some text</a>.

    • Для анонимных сеансов LINK_VIA имеет значение.
    • Для зарегистрированных сеансов LINK_VIA - None
  • Вы можете использовать оператор {% if %} вокруг тэгов <A HREF=...>. Это кажется многословным.

  • Вы можете написать свой собственный тег для {% link_via %}. Я недостаточно знаком с этим, но вы можете предоставить ссылку и текст как строки, и ваш тег может генерировать один из двух видов ссылок.

Ответ 3

Я согласен с S.Lott

Сделайте проверку в шаблоне, если пользователь вошел в систему, просто поместите ссылку как обычно, если нет, поставьте что-то вроде

<a href="{{link}}" onclick="return login_popup()"> 

где login_popup вернет false, если пользователь произведет отмена.

Это можно было бы сделать намного проще в Jinja2 через macros.

Если шаблон не знает, какие URL-адреса требуют входа в систему, вам, вероятно, придется пересмотреть свой дизайн.

Если вам нужно, я думаю, вы можете сделать то же самое, что и диспетчер url django, чтобы открыть функцию просмотра.
см. django.core.urlresolvers

после того, как вы захватили функцию просмотра, вы можете проверить, украшен ли она @login_required.

Это было бы сделано в пользовательском теге, вероятно.
Если вы используете Jinja2, вам не понадобится тег, просто реализуйте эту функцию и выставляйте ее в среду, это просто, но вам нужно будет немного почитать в API Jinja2)

Ответ 4

Здесь предлагается версия декоратора с оберткой.__ doc__, wrap.__ name __

from functools import wraps

def ajax_login_required(function):
    def wrap(request, *args, **kwargs):
        if request.user.is_authenticated():
            return function(request, *args, **kwargs)
        json = simplejson.dumps({ 'not_authenticated': True })
        return HttpResponse(json, mimetype='application/json')  
    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap