Получение списка имен slug по имени пути к url
Я занимаюсь реверс-инжинирингом urlpatterns в django. Для моей цели мне нужно динамически узнать список имен slug, которые разработчики решили использовать в url.
Пример:
path("<slug:membership_slug>/<slug:parent_slug>/data/", rzd.ReportingUnitDataView.as_view(), name="hierarchy.item.data"),
Итак, в мире, где все пишут идеальный код, моя функция принимает "hierarcy.item.data"
и выплевывает ["membership_slug", "parent_slug"]
Я посмотрел на обратную функцию, надеясь, что она вернет что-то полезное без kwargs, но это не так. Гуглил как Neo, но безрезультатно. Но надежда не покидает мое сердце... где-то в django должен храниться весь этот urlpatterns материал! Я все еще верю.
Возможно, вы можете подсказать, как получить список урлов, пусть даже в сыром формате, это уже будет помощью. Спасибо.
Найдите книгу под названием Django 2x scopes
в этой книге собрано все, что связано с лучшими практиками django и, конечно же, часть про урлы.
Эта книга поможет вам лучше понять, как думают разработчики django.
Счастливого взлома 🙃
Думаю, лучше всего написать Regex.
Из того, что я нашел в исходном коде, они используют _lazy_re_compile(r'<(?:(?P<converter>[^>:]+):)?(?P<parameter>[^>]+)>')
, который можно найти urls\resolvers.py
в _route_to_regex
вот что у меня получилось после того, как я перелопатил исходный код
def geturlnamedarguments(route):
from django.utils.regex_helper import _lazy_re_compile
named_arguments = []
while True:
match = _lazy_re_compile(r'<(?:(?P<converter>[^>:]+):)?(?P<parameter>[^>]+)>').search(route)
if not match:
break
route = route[match.end():]
parameter = match['parameter']
named_arguments.append(parameter)
return named_arguments
Вы также можете получить необработанный URL-маршрут в виде строки, выполнив
urlpatterns[index].pattern._route
Вы можете найти объект URLPattern также в urls\resolvers.py
, если хотите поиграть с ним... Я так и не нашел места, где есть имена в необработанном формате
Решено, Мне пришло в голову, что я могу просто включить urls.py и разобрать его самостоятельно :)
from myapp import urls
class UrlPatterns:
@staticmethod
def _get_params(s):
items = []
is_exp = False
is_prefix = False
type = ''
name = ''
for n in range(len(s)):
if not is_exp:
if s[n] == '<':
is_exp = True
is_prefix = True
type = ''
elif is_prefix:
if s[n] == ':':
is_prefix = False
else:
type += s[n]
else:
if s[n] == '>':
is_exp = False
items.append({
'type': type,
'name': name
})
name = ''
else:
name += s[n]
return items
@staticmethod
def _find_pattern(url_name):
for url in urls.urlpatterns:
if url.name == url_name:
return str(url.pattern)
return None
@staticmethod
def get_required_params(url_name):
url_pattern = UrlPatterns._find_pattern(url_name)
if url_pattern:
return UrlPatterns._get_params(url_pattern)
return None