Я недавно «подсел» на Django и мне очень нравится этот фреймворк. Однако есть деталь, которая доставляет беспокойство. Это одновременное редактирование файла с моими views и файла
Здесь я предлагаю такое решение, конечно же, завязанное на декораторах.
Итак, что в конечном итоге мы хотим получить? Допустим, нам нужно нарисовать новый view. Хочется дописать к этой функции декоратор
чтобы он сам всё подвязал, а нам не пришлось лазать руками в
Для этой цели служит небольшой модуль
Что он делает? Декоратор
Используется это следующим образом. В файле
где
В модуль
и теперь новые view можно писать примерно таким образом:
Отступление: вообще, я активно пользуюсь декораторами для облегчения написания однотипного кода. Например, здесь декоратор
Недостаток предложенного решения, который я вижу сразу — это использование только одного
Это не велосипед, кстати?
Спасибо тем, кто дочитал до этого места :-)
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 может из одного модуля создавать глобальную переменную в другом и проверять есть ли она там уже.Это не велосипед, кстати?
Спасибо тем, кто дочитал до этого места :-)