Django re_path для перехвата всех URL-адресов, кроме /admin/, не работает должным образом
Я пытаюсь определить re_path в Django, который перехватывает все URL-адреса, кроме тех, которые начинаются с /admin/. Моя цель - перенаправить неизвестные URL-адреса в пользовательское представление (RedirectView), гарантируя при этом, что все URL-адреса администратора (включая подпути, такие как /admin/mymodel/something/) будут исключены.
from django.urls import re_path, path
from django.contrib import admin
from . import views
urlpatterns = [
path('admin/', admin.site.urls), # Ensure Django admin URLs are handled
]
# Catch-all pattern that should exclude /admin/ URLs
urlpatterns += [
re_path(r"^.*/(?!admin/$)[^/]+/$", views.RedirectView.as_view(), name="my-view"),
]
Проблема:
URL-адреса, подобные localhost:8000/admin/mymodel/something/, корректно игнорируются, что хорошо.
Однако односегментные URL-адреса, такие как localhost:8000/что-то/, не совпадают, хотя они должны быть перенаправлены.
измените свой re_path, который должен исключать /admin/ URL-адреса
urlpatterns += [
re_path(r"^(?!admin/).*", views.RedirectView.as_view(), name="my-view"),
]
Моя цель - перенаправить неизвестные URL-адреса в пользовательское представление (RedirectView), гарантируя при этом, что все URL-адреса администратора (включая подпути, такие как /admin/mymodel/something/) будут исключены.
Хорошая новость в том, что Django сопоставляет пути сверху вниз. Поэтому, если путь равен admin/…
, сначала он будет искать admin.site.urls
. Если вы не установите для атрибута .final_catch_all_view
[Django-doc] сайта администратора значение False
, он будет содержать сводный список, который, таким образом, будет обрабатывать все пути с code/
.
Таким образом, вы можете использовать сводный список с:
from django.contrib import admin
from django.urls import path, re_path
from . import views
urlpatterns = [
path('admin/', admin.site.urls), # Ensure Django admin URLs are handled
]
urlpatterns += [
re_path(r'\A.*/\Z', views.RedirectView.as_view(), name='my-view'),
]
Я бы также добавил завершающую косую черту, чтобы логика Django APPEND_SLASH
[Django-doc] сначала позволила выполнить некоторую работу, если в пути нет завершающей косой черты. Но если нет, вы можете удалить это.
Приведенный ниже new_pattern
может помочь:
УЗОРЫ
original_pattern = r"^.*/(?!admin/$)[^/]+/$"
new_pattern = r"^[^/]*/(?!admin/)(?:[^/\n]+/)+$"
Демонстрация к оригинальному шаблону: https://regex101.com/r/fp5aYg/1
Демонстрация для new_pattern: https://regex101.com/r/2AWQcK/5
ПРИМЕЧАНИЯ
new_pattern
может начинаться с любых символов, кроме косой черты, или вообще без символов.
За первой косой чертой /
не должно следовать admin/
.
За каждой прямой косой чертой /
должен следовать, по крайней мере, один или несколько символов, отличных от прямой косой черты [^/]+
за которыми следует прямая косая черта /
: /([^/]+/)+
.
Строка ДОЛЖНА заканчиваться прямой косой чертой /$
.
В строке должно быть не менее двух прямых косых черт, разделенных символом, отличным от прямой косой черты.
Например, совпадение не будет соответствовать строкам с двумя последовательными косыми чертами, такими как эти: //something//something//
, или something/something//something
^[^/]*
Начните с начала строки. Введите 0 или более символов без косой черты[^/]
, т.е. сопоставьте все символы до первой косой черты/
./
первая косая черта.(?!admin/)
За первой косой чертой не может следоватьadmin/
(?:...)+
Группа без захвата (?:...)
, которая повторяется 1 или более раз (+
).[^/\n]+
Вводите любой символ, не заканчивающийся косой чертой[^/]
, не переводящий строку\n
, 1 или более раз. (Примечание: Мне пришлось добавить символ новой строки\n
, чтобы многострочная демонстрация работала корректно.)[^/\n]+/
За строками символов без прямой косой черты следует одна прямая косая черта/
.$
Конец строки$
следует за второй или более поздней косой чертой/$
.
ТЕСТОВЫЕ СТРОКИ:
localhost:8000/admin/mymodel/something/
localhost:8000/something
localhost:8000/something/
localhost:8000/something/something/something/
localhost:8000
something/
/someting/a/
/someting//a/a/
/someting//
/someting//something//
/someting/something//
/someting//something//
something/something/
something/admin/something/
/something/admin/something/
/admin/
/admin/green/yellow/
/admin/hello/
/admin/hello/hello/
/admin/hello/hello/hello/
/admin/hello/hello
admin/green/yellow/
admin/hello/
admin/
/notadmin/path/something/
/notadmin/path/something
/something/admin/something/
/what/is/happening/
/no_admin/yellow/
/no_admin/yellow/green/red/
СОВПАДЕНИЯ:
localhost:8000/something/
localhost:8000/something/something/something/
/someting/a/
something/something/
/something/admin/something/
admin/green/yellow/
admin/hello/
/something/admin/something/
/what/is/happening/
/no_admin/yellow/
/no_admin/yellow/green/red/
НЕСООТВЕТСТВИЯ:
localhost:8000/admin/mymodel/something/
localhost:8000/something
localhost:8000
something/
/someting//a/a/
/someting//
/someting//something//
/someting/something//
/someting//something//
something/admin/something/
/admin/
/admin/green/yellow/
/admin/hello/
/admin/hello/hello/
/admin/hello/hello/hello/
/admin/hello/hello
admin/
/notadmin/path/something