Каков наилучший способ обработки тайм-аутов сеанса в запросах ajax?

Рассмотрим это представление Django, которое получит список элементов, связанных с текущим пользователем:

@login_required
def list_items(request, page_number=0):
    items = Paginator(request.user.items, 5).page(page_number).object_list
    return HttpResponse(cjson.encode(items))

Очевидно, что он хочет использоватьlogin_required декоратор, чтобы ограничить доступ к представлению для вошедших в систему пользователей.

Что значитlogin_required делать, когда неаутентифицированный пользователь пытается получить доступ к представлению? ВозвращаетHttpResponseRedirect кsettings.LOGIN_URL.

Рассмотрим этот код JavaScript, который вызывает представление:

var getPage = function(pageNumber) {
    $.ajax({
        url: "/list_items/" + pageNumber + "/",
        success: function(data) {
            $("#list_container").html(formatData(data))
        }
    });
};

предполагатьsettings.SESSION_COOKIE_AGE = 60 секунд.

Если пользователь переходит на страницу 1, читает ее в течение 61 секунды, а затем нажимает кнопку для страницы 2, Djangologin_required декоратор обнаружит, что сеанс больше не активен, и вернетHttpResponseRedirect(settings.LOGIN_URL), который вызоветsuccess обратный вызов для получения страницы входа в HTML вместо списка в кодировке JSON.

Вот где это происходит.
Это называетсяuser_passes_test Вот.

Какой лучший способ справиться с этим?

Вот несколько вещей, о которых я подумал:

1. success Обратный вызов должен проверить ответ и посмотреть, получит ли он страницу входа любым способом (проверить, является ли тип содержимого html, проверить содержимое и т. д.). Но это означает, что мы должны обернуть все вызовы AJAX оболочкой обратного вызова следующим образом:

    $.ajax({
        url: "/list_items/" + pageNumber + "/",
        success: sessionExpiryCallbackWrapper(function(data) {
            $("#list_container").html(formatData(data))
        })
    });

Но это ужасно, и разработчики могут забыть сделать это везде.

2. использование$.ajaxComplete обрабатывать все запросы.

    $.ajaxComplete(globalCompleteCallback);
    $.ajax({
        success: successCallback,
        complete: completeCallback
    });

Но это порядок звонков:

    successCallback(); // success is called before complete
    completeCallback();
    globalCompleteCallback(); // this is called after the local callback

Таким образом, мы получаем переадресацию только после сбоя successCallback и, возможно, с ошибками JS из-за неверных данных, которые он получил.

3. Еслиlogin_required вернет 403 на запросы AJAX:

    if not user.is_authenticated():
        if request.is_ajax():
            # send 403 to ajax calls
            return HttpResponse403("you are not logged in")
        else:
            # regular code path
            return HttpResponseRedirect(settings.LOGIN_URL)

Ноlogin_required просто используетuser_passes_test который не делает этого.

user_passes_test там много функциональности, так что переопределять его не очень хорошая идея.

Какой лучший способ справиться с таймаутами для вызовов AJAX?

Ответы на вопрос(2)

Ваш ответ на вопрос