Читаю книжку про Django. Встретил там один интересный пример. Вопрос к профессионалам: есть ли в таком способе решения _данной конкретной задачи_ глубокий смысл, которого я не вижу, или это чисто понты для демонстрации возможностей питона? Подробности под катом, не-программистам будет неинтересно.
Итак, задача:
Есть несколько функций, у которых есть общий кусок – проверка аутентифицированности пользователя и редирект на страницу аутентификации, если он не:
def my_view1(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
# ...
return render_to_response('template1.html')
def my_view2(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
# ...
return render_to_response('template2.html')
def my_view3(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
# ...
return render_to_response('template3.html')
и, соответственно, ссылки на эти функции в URLconf:
urlpatterns = patterns('',
(r'^view1/$', my_view1),
(r'^view2/$', my_view2),
(r'^view3/$', my_view3),
)
(Для тех, кто не в курсе Django: вторым параметром в кортежах указывается ссылка на функцию-обработчик запроса.)
Это некрасиво, надо вынести этот общий кусок кода в единое место.
Как бы это сделал я: написал бы wrapper, который получал бы ссылку на одну из различающихся функций, проверял бы аутентифицированность пользователя, и либо выдавал редирект, либо вызывал нужную функцию по ссылке. Примерно так:
def requires_login(request, view):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
return view(request);
И соотетствующий URLconf:
urlpatterns = patterns('',
(r'^view1/$', requires_login, {'view': my_view1} ),
(r'^view2/$', requires_login, {'view': my_view2} ),
(r'^view3/$', requires_login, {'view': my_view3} ),
)
А в книжке приводится другой вариант решения: динамическое создание функций, каждая из которых проверяет аутентифицированность пользователя и либо выдаёт редирект, либо вызывает функцию по переданной ссылке:
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;
urlpatterns = patterns('',
(r'^view1/$', requires_login(my_view1)),
(r'^view2/$', requires_login(my_view2)),
(r'^view3/$', requires_login(my_view3)),
)
То есть, при чтении URLconf происходит три вызова requires_login(), каждый из которых возвращает ссылку на динамически сгенерированную функцию.
С моей точки зрения у такого решения [повторяю: решения данной конкретной задачи, а не вообще] есть только минусы. На каждую функцию my_view*() создаётся по одной дополнительной функции вместо единой общей, создаются они динамически, и на это тратятся лишние ресурсы. А на скорость работы это практически не влияет.
Я чего-то не заметил?
Оригинал этой записи в личном блоге.
Любые материалы из этого блога запрещается использовать на сайте livejournal.ru в любой форме и любом объёме.
no subject
П-ц какой-то, простите.
P.S.
Для версии 1.4 функция сброса пароля при повторной инсталляции удалена. Реализована функция напоминания пароля на электронную почту.
no subject
no subject
no subject
Re: П-ц какой-то, простите.