Русские документы
Ежедневные компьютерные новости RSS rusdoc.ru  Найти :
http://www.rusdoc.ru. Версия для печати.

Автоматическая привязка URL к view

Раздел: Programming / Python @ 07.05.2008 | Ключевые слова: python django url view

Автор: lomeolomeo
Источник: habrahabr

Я недавно "подсел" на Django и мне очень нравится этот фреймворк. Однако есть деталь, которая доставляет беспокойство. Это одновременное редактирование файла с моими views и файла urls.py при создании нового view. Я понимаю, что это связано с тем, что URL-ы и views вещи достаточно разные и для большей модульности лучше держать их раздельно, однако для небольших проектов было бы очень удобно иметь возможность править view и его настройки в одном месте.

Здесь я предлагаю такое решение, конечно же, завязанное на декораторах.

Итак, что в конечном итоге мы хотим получить? Допустим, нам нужно нарисовать новый view. Хочется дописать к этой функции декоратор with_url:


@with_url(r`^my/cool/url/`)
def my_cool_view(request):
    ...


чтобы он сам всё подвязал, а нам не пришлось лазать руками в urls.py.

Для этой цели служит небольшой модуль easyurls из пакета, назовём его, djangoutils:


urlpatterns = []


def with_url(url, context={}):
    def decorator(fun):
        global urlpatterns
        urlpatterns.append((url, fun, context))

        return fun

    return decorator


def load_patterns(module_name):
    from django.conf.urls.defaults import patterns
    __import__(module_name)

    return patterns(module_name, *urlpatterns)


Что он делает? Декоратор with_url добавляет в глобальную переменную urlpatterns привязку URL к нашему view. А функция load_patterns просто импортирует модуль views, чтобы все декораторы сработали, после чего возвращает заполненный urlpatterns.

Используется это следующим образом. В файле urls.py мы пишем


from djangoutils.easyurls import load_patterns

urlpatterns = load_patterns(`app.views`) + patterns(...)


где app.views - модуль views нашего приложения. Больше мы в этот файл не заглядываем.

В модуль app.views импортируем декоратор:


from djangoutils.easyurls import with_url


и теперь новые view можно писать примерно таким образом:


# простой пример
@with_url(r`^json/list/items/`)
@json_http
@in_list
def json_list_items(request, list):
    ...

# чуть сложнее :-)
@with_url(r`^$`)
@with_url(r`^start/`, {`is_root`: False})
def start(request, is_root=True):
    ...


Отступление: вообще, я активно пользуюсь декораторами для облегчения написания однотипного кода. Например, здесь декоратор json_http преобразует результат функции в JSON строку и кидает её в response.

Недостаток предложенного решения, который я вижу сразу - это использование только одного load_patterns в URL. Решить его можно, перенеся urlpatterns из easyurls в модуль views. Думаю, сделать это несложно, как дополнительное преимущество отпадёт необходимость в использовании load_patterns и будет достаточно стандартного include. Как недостаток - придётся выписывать urlpatterns = [] в каждом модуле views, который мы вяжем таким образом. Возможно и не придётся, если python может из одного модуля создавать глобальную переменную в другом и проверять есть ли она там уже.

Это не велосипед, кстати?

Спасибо тем, кто дочитал до этого места :-)



Вернуться в раздел: Programming / Python
© Copyright 1998-2012 Александр Томов. All rights reserved.