AngularJS + Django: обновление URL или прямой доступ не загружается правильно
У нас есть приложение AngularJS, встроенное в наше приложение Django, с маршрутизацией URL, обработанной AngularJS ui-router. Все работает нормально, перемещаясь между частицами с помощью ui-sref и щелкая в приложении.
return $stateProvider.state('root.dashboard', {
abstract: true,
url: 'dashboard/'
}).state('root.dashboard.profile', {
url: 'profile/',
views: {
'@': {
templateUrl: Urls['dashboard:profile'](),
controller: 'ProfileController'
}
}
}).state('root.dashboard.home', {
url: '',
views: {
'@': {
templateUrl: Urls['dashboard:dashboard_home'](),
controller: 'DashboardController'
}
}
...
Проблема заключается в том, что пользователь перешел на страницу без полномочий root (например, http://example.com/dashboard/profile/
), и пользователь обновляет браузер, повторно загружает URL-адрес браузера или просто вставляет URL-адрес без корня непосредственно в браузера. В этом случае вместо загрузки страницы, сохраняющей тот же URL-адрес в браузере, пользователь перенаправляется на корневую страницу (http://example.com/dashboard/
).
Поскольку маршрутизация выполняется с помощью Angular, на стороне сервера у нас нет URL-адресов, определенных для тех URL-адресов, которые не являются корневыми; вместо этого у нас есть промежуточное программное обеспечение, которое перенаправляет 404s на корневую страницу:
class Redirect404(object):
def process_response(self, request, response):
if response.status_code != 404 or request.method != 'GET':
return response
return HttpResponsePermanentRedirect('/dashboard')
Мы ожидаем, что маршрутизатор сможет поддерживать исходный URL-адрес и вернуть пользователя на исходную страницу (т.е. "dashboard/profile
" ). Обратите внимание, что мы установили HTML5Mode в Angular следующим образом:
$locationProvider.html5Mode = true;
Есть некоторая ошибка в нашем понимании и/или настройке, и я хотел бы получить разъяснения.
Ответы
Ответ 1
Мы ожидаем, что маршрутизатор сможет поддерживать исходный URL-адрес и возвращать пользователя на исходную страницу.
Это недоразумение.
Вот последовательность событий:
- Пользователь вводит
http://example.com/dashboard/profile/
в строку местоположения.
- Браузер отправляет запрос
GET
на сервер для этого URL-адреса.
- Ваш сервер отвечает с ответом
301
с перенаправлением.
- Браузер видит ответ и отправляет новый запрос
GET
на http://example.com/dashboard/
.
- Сервер отвечает вашей страницей Angular.
- Приложение Angular запустится и просмотрит
window.href
, чтобы узнать, что такое текущий маршрут. Он видит корневой маршрут и отвечает соответствующим образом.
Другими словами, при перенаправлении вы теряете исходный URL.
Решение прост: вместо перенаправления просто верните свою страницу в ответ на любой (действительный) URL-адрес. Таким образом, запрошенный URL-адрес поддерживается, и когда Angular запускается, он сможет определить правильный маршрут. (Предполагается, что маршрутизация настроена правильно в Angular, но похоже, что вы работаете.)
Реализация также проста. Просто измените Django urls.py
на что-то вроде этого:
urlpatterns = [
url(r'^dashboard/$', my_view),
]
примерно так:
urlpatterns = [
url(r'^dashboard/.*$', my_view),
]