В главе 8 книги Django существует пример, показывающий, что фундаментальное представление переносит метод, который получает другой метод просмотра, переданный в от любого единственного произвольного URLconf:
def requires_login(view):
def new_view(request, *args, **kwargs):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
return view(request, *args, **kwargs)
return new_view
Я следую за большей частью логики здесь, но что я не понимаю, то, как вложенный new_view
определение получает запрос, *args и ** kwargs, поскольку это явно не передается в requires_login
определение.
Как точно new_view
определение, получающее эти аргументы?
new_view
Давайте сначала рассмотрим функцию new_view
:
def new_view(request, *args, **kwargs):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
return view(request, *args, **kwargs)
Когда вызывается new_view
, она проверяет, аутентифицирован ли пользователь. Если пользователь аутентифицирован, то new_view
вызывает view
и передает ему все аргументы (request
, позиционные аргументы и аргументы ключевых слов).
new_view
не выполняется автоматически. Мы используем def
для определения функции, но не выполняем ее сразу. Вместо этого мы возвращаем new_view
как функцию. Представьте себе следующий код:
def my_view(request):
# ... some view stuff happens here
my_new_view = requires_login(my_view)
Теперь my_new_view
- это функция. Я могу вызывать ее так же, как и любую другую функцию. До сих пор эта новая функция не была вызвана ни разу.
Когда my_new_view
вызывается, она получает все свои аргументы. Затем она вызывает my_view
, передавая все аргументы (request
, позиционные аргументы и аргументы ключевых слов) в my_view
.
(Все это, конечно, предполагает, что пользователь аутентифицирован. Иначе при вызове my_new_view
вы получили бы HttpResponseRedirect
, а my_view
никогда бы не был вызван.)
view
в качестве аргумента requires_login
получает функцию view
. view
ссылается на функцию, но мы еще не выполняем эту функцию. view
выполняется только при выполнении new_view
.