Django: перенаправление между двумя приложениями из views.py

#django

#django

Вопрос:

Есть два приложения: app_user и app_test . app_user содержит login.html (с пользовательскими формами входа). Вход в систему осуществляется с помощью POST-запроса в JS, который вызывает функцию api_login в app_user.views.py .

Это моя очень простая функция входа (для тестирования):

 def api_login(request):
    # Get post data
    post = json.loads(request.body)
    # Get username and password
    username = post.get('username', None)
    password = post.get('password', None)
    # Returned data object
    data = {
        "success": False,
        "username": username,
    }
    # Username and password
    if username == "" or password == "":
        data['success'] = False
        return JsonResponse(data)
    # Check if input is correct
    user = authenticate(username=username, password=password)
    if user is not None:
        data['success'] = True
        login(request, user)
        # return JsonResponse(data) <-- No data response, there should be a redirect 
        return redirect('app_test:test-home')
    else:
        data['success'] = False
    return JsonResponse(data)
  

Это работает хорошо, но я хочу сделать перенаправление с http://localhost:8000/login/ (включено app_user ) на http://localhost:8000/test/ (включено app_test ), когда вход в систему был успешным.

Мой основной шаблон URL ( urls.py ).

 from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test/', include('app_test.urls'), name='app_test'),
    path('login/', include('app_user.urls'), name='app_login'),
]
  

Шаблон URL из app_user

 from django.urls import path
from . import views

urlpatterns = [
    path('', views.view_login, name='user-login'),
    path('api/login', views.api_login, name='user-api-login'),
]
  

Шаблон URL из app_test

 from django.urls import path
from . import views

urlpatterns = [
    path('', views.view_test, name='test-home'),
]
  

Настройка JS:

 function login() {
    let url = 'api/login';
    let data = {
        username: inputUsername.getValue(),
        password: inputPassword.getValue()
    };
    let onSuccess = function (data) {
        console.log('>> Success!');
        console.log(data);
    }
    let onServerError = function () {
        console.log('>> onServerError!');
        console.log(data);
    }
    let onError = function () {
        console.log('>> onError!');
        console.log(data);
    }
    request('POST', url, data, onSuccess, onServerError, onError);
}
  
 function request(method, url, data, onSuccess, onServerError, onError) {
    let request = new XMLHttpRequest();
    request.open(method, url, true);
    request.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    request.setRequestHeader("Content-type", "application/json")
    request.responseType = 'json';
    request.onload = function () {
        if (request.status >= 200 amp;amp; request.status < 400) {
            // Success!
            console.log('Status: '   request.status);
            onSuccess(request.response);
        } else {
            console.log('Status: '   request.status);
            // We reached our target server, but it returned an error
            onServerError(request.response);
        }
    };

    request.onerror = function () {
        console.log('Status: '   request.status);
        // There was a connection error of some sort
        onError(request.response);
    };
    if (method === 'GET') {
        console.log('>> GET');
        request.send();
    } else {
        console.log('>> POST');
        request.send(JSON.stringify(data));
    }
}
  

Перенаправление в api_login не работает с использованием:
redirect('test-home') или redirect('app_test:test-home') (для этого я добавил app_name = 'app_test' в app_test.py . Итак, как я могу сделать перенаправление api_login между двумя приложениями?

Комментарии:

1. добавьте также соответствующий js-скрипт

2. Я добавил настройку JS. Функция getCookie('csrftoken') возвращает токен csrf. Без перенаправления он работает правильно. Таким образом, возвращаемый объект данных содержит success = true при успешном входе в систему и false при сбое входа в систему.

Ответ №1:

Ответом, который вы получите для действительного входа, будет HTML-страница для URL ‘app_test:test-home’. Вы можете проверить это в инструментах разработчика браузера. Необходимо получить JsonResponse для запроса даже для действительного входа в систему. Добавьте URL-адрес перенаправления в ответ и перенаправьте вместо этого с помощью js.

Использование reverse() для создания URL-адреса перенаправления. Документы

Если вам нужно использовать что-то похожее на тег шаблона URL в вашем коде

 from django.urls import reverse

def api_login(request):
    # Get post data
    post = json.loads(request.body)
    # Get username and password
    username = post.get('username', None)
    password = post.get('password', None)
    # Returned data object
    data = {
        "success": False,
        "username": username,
    }
    # Username and password
    if username == "" or password == "":
        data['success'] = False
        return JsonResponse(data)
    # Check if input is correct
    user = authenticate(username=username, password=password)
    if user is not None:
        data['success'] = True
        login(request, user)
        data['redirect'] = reverse('test-home') # import reverse from django.urls
        return JsonResponse(data) # return response with the redirect url
    else:
        data['success'] = False
    return JsonResponse(data)
  

В js перенаправление проверяет данные ответа

 if( 'redirect' in data) {
    window.location = data['redirect'];
}
  

Вы можете добавить это либо в

         if (request.status >= 200 amp;amp; request.status < 400) {
            // Success!
            console.log('Status: '   request.status);
            if( 'redirect' in request.response) {
                window.location = data['redirect'];
            }
            onSuccess(request.response);
        }
  

или

     let onSuccess = function (data) {
        console.log('>> Success!');
        if( 'redirect' in data) {
            window.location = data.redirect;
        }
        console.log(data);
    }
  

Комментарии:

1. Просто попробовал и получил ошибку сервера django.urls.exceptions.NoReverseMatch: 'app_test' is not a registered namespace . Как написано, я добавил app_name = 'app_test' в app_test.views.py . Или мне нужно импортировать другой скрипт из `app_test«`?

2. @MichaelT достаточно указать имя URL-адреса, или вы можете добавить app_name в app.urls и попробовать. Вам не нужно импортировать из представлений

3. С Django 3.1.1 кажется, что мне не нужно использовать app_test в reverse инструкции. Это работает: data['redirect'] = reverse('test-home') . Спасибо!