#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')
. Спасибо!