Ответ находится в той части, которую вы не опубликовали. Ваш реальный код на самом деле выглядит примерно так:
def route(url, name=""):
def dec(f):
if name == "":
# here's the real issue
name = "something_" + f.__name__
urlpatterns.append(
path(url, f, name=name)
)
return f
return dec
. Присвоение name
делает его локальной переменной - Python не имеет объявления переменной, поэтому именно место, где связано имя, определяет его область действия. В вашем случае присвоение имени в dec
делает имя «имя» локальным для dec
, поэтому оно НЕ ищется в прилагаемых областях. И так как вы проверяете его («ссылка») до , который вы присваиваете ему, вы получаете очень очевидную (нет, просто шучу) «локальную переменную« имя », на которую ссылаются перед присвоением».
Решение здесь состоит в том, чтобы объявить name
как "нелокальную" в верхней части вашей dec
функции, чтобы Python знал, что ее нужно искать во вложенной области видимости (или, точнее, в ячейках замыкания, которые захватываютdec
окружение функции):
def route(url, name=""):
def dec(f):
nonlocal name
if name == "":
# here's the real issue
name = "something_" + f.__name__
urlpatterns.append(
path(url, f, name=name)
)
return f
return dec
Обратите внимание, что это работает только для Python3 - если вы используете Python2, вам придется прибегнуть к хаку, чтобы эмулировать это поведение:
def route(url, name=""):
# Py2 hack: wrap the "nonlocal" variable in
# a mutable container
name = [name]
def dec(f):
if name[0] == "":
name[0] = "something_" + f.__name__
urlpatterns.append(
path(url, f, name=name[0])
)
return f
return dec
Взлом здесь, что вы мутируете name
вместо повторного связывания, поэтому Python не помечает его как локальную переменную.
Как примечание, я бы не сталне рекомендую пытаться портировать эту @route(url)
идиому (Flask кто-нибудь?) на Django. Во-первых, потому что отделение определений представлений от отображения URL является преднамеренным дизайнерским решением, которое позволяет переназначить URL-адреса приложений третьей части на все, что мы хотим, без хаков, вилок и т. Д., А также потому, что большинство разработчиков Django ожидают, что URL-адреса будут точно определены вurls.py
модуль и будет ненавидеть вас за несоблюдение конвенции. Теперь вы, конечно, можете писать свой проект так, как вам хочется, но соблюдение соглашений облегчает задачу для всех. Мои 2 цента ...