Проверка подлинности Django и Ajax - URL-адреса, требующие входа в систему
Я хочу добавить Ajax - незнакомость с моим Django-кодированным сайтом.
В моем коде Django я использую декоратор @login_required
от django.contrib.auth.decorators
, чтобы отметить, для какого представления требуется аутентификация. Поведение по умолчанию, когда пользователь, не прошедший проверку подлинности, нажимает на него, - это перенаправить его/ее на страницу входа в систему, а затем передать целевую страницу.
То, что я видел на некоторых сайтах и очень понравилось, заключается в том, что когда пользователь щелкает ссылку, ведущую к месту, ограниченному только зарегистрированным пользователям, вместо того, чтобы перенаправляться на страницу входа в систему, он получает всплывающее окно (через JavaScript) с просьбой войти в систему или зарегистрироваться. Там нет части перенаправления, поэтому пользователю не нужно использовать ключ "назад", если он/она решает, что ему действительно не нравится сайт, чтобы тратить время на регистрацию.
Итак, вопрос: как бы вы управляли задачей автоматической маркировки некоторых ссылок как "ограниченных", поэтому JavaScript может обрабатывать свое событие onclick
и отображать всплывающее окно "пожалуйста, войдите в систему"?
Ответы
Ответ 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