Да, функция может ссылаться на нее, глядя на себя.
конец декоратора. он просто берет атрибуты и устанавливает их в функции
если это выглядит немного сложно, это потому, что декораторам, которые принимают параметры, нужна эта конкретная структура для работы. см. Декораторы с параметрами?
def declare_view(**kwds):
"""declaratively assocatiate a Django View function with resources
"""
def actual_decorator(func):
for k, v in kwds.items():
setattr(func, k, v)
return func
return actual_decorator
вызов декоратора
@declare_view(
x=2
)
def decorated_func():
#the function can look at its own name, because the function exists
#by the time it gets called.
print("x in decorated_func:", decorated_func.x)
decorated_func()
выход
x in decorated_func: 2
На практике я использовал это совсем немного. Идея для меня заключается в том, чтобы связать функции представления Django с конкретными классами данных и шаблонами, с которыми они должны сотрудничать. Поскольку он декларативный, я могу анализировать все представления Django и отслеживать связанные с ними URL-адреса, а также настраиваемые объекты данных и шаблоны. Работает очень хорошо, но да, функция ожидает, что определенные атрибуты будут существовать сами по себе. Он не знает, что их установил декоратор.
О, и в моем случае нет веской причины для того, чтобы они передавались в качестве параметров в моих случаях использования, эти переменные содержат в основном жестко закодированные значения, которые никогда не меняются, от POV функции.
Поначалу странно, но довольно мощно и не имеет недостатков времени выполнения или обслуживания.
Вот несколько примеров из жизни.
@declare_view(
viewmanager_cls=backend.VueManagerDetailPSCLASSDEFN,
template_name="pssecurity/detail.html",
objecttype=constants.OBJECTTYPE_PERMISSION_LIST[0],
bundle_name="pssecurity/detail.psclassdefn",
)
def psclassdefn_detail(request, CLASSID, dbr=None, PORTAL_NAME="EMPLOYEE"):
"""
"""
f_view = psclassdefn_detail
viewmanager = f_view.viewmanager_cls(request, mdb, f_view=f_view)
...do things based on the parameters...
return viewmanager.HttpResponse(f_view.template_name)