November 2019

S M T W T F S
      12
34 5 678 9
10111213141516
17181920212223
24252627282930

Style Credit

Expand Cut Tags

No cut tags
Thursday, October 8th, 2009 03:13 pm

Читаю книжку про 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 в любой форме и любом объёме.

Wednesday, December 2nd, 2009 03:21 pm (UTC)
(задумчиво) запускае небольшой юниксовый серверочек, который на все DNS-запросы отвечает собственным IP-адресом и принимает почту для всех доменов, подключаем к нему машинку и.. отправляем себе пароль :)