render_to improved
[UPD от 12 ночи]
Чуть больше года назад, когда меня окончательно задолбало писать
render_to_response c кучей параметров, я себе написал маленький декоратор
render_to, который заметно уменьшал количество писанины.
Но вот не так давно обсуждали его в джаббер-конференции pythonua@c.j.r (кстати, официальная конференция python.com.ua), где появилась идея слегка его проапгрейдить до возможности задавать темплейт из view (когда одна вью может выдавать различные странички). В принципе, идея усложнения декоратора мне не особенно нравится (да и потом, кому надо — может переделать себе, благо несложно), но по размышлении я увидел, что особенного усложнения нету, плюс сохраняется обратная совместимость полностью (что важно, потому как мне есть и где использовать новую фичу, но не очень хочется ломать все вьюхи, использующие старую версию ;).
Однако первая версия, с дополнительным параметром (именем ключа из возвращаемого словаря), имеет явно менее питоновский привкус, чем вариант, предложенный в комментариях. Теперь можно возвращать дополнительно к словарю ещё и имя темплейта, в который он должен отрисовываться:
@render_to('some/thing_detail.html')
def thing_detail(request):
...
return {'obj': obj}, 'other/thing.html'
Есть один небольшой момент: если возвращается тупль, то первый аргумент не проверяется на свою словарность — для определения типа это не нужно, а программист пускай по своим граблям шагает смело. ;)
def render_to(template):
"""
Decorator for Django views that sends returned dict to render_to_response function
with given template and RequestContext as context instance.
If view doesn't return dict then decorator simply returns output.
Additionally view can return two-tuple, which must contain dict as first
element and string with template name as second. This string will
override template name, given as parameter
Parameters:
— template: template name to use
"""
def renderer(func):
def wrapper(request, *args, **kw):
output = func(request, *args, **kw)
if isinstance(output, (list, tuple)):
return render_to_response(output[1], output[0], RequestContext(request))
elif isinstance(output, dict):
return render_to_response(template, output, RequestContext(request))
return output
return wrapper
return renderer
P.S.Явно в этот раз я из всей работы только то и сделал, что в блог написал… Ну да это мелочи, главное — удобно получилось. :-)
Comments
Нет, ну вот скажите люди, разве не должен ли быть default_template изначально None?
нет, не должен, ибо тогда ему нечего будет рендерить?
дык если ты ему не задашь никаких параметров ему так и так нечего будет рендрить
Думаю должен. (надо у себя тоже исправить) в моем случае выглядит так:
т.е. если нет шаблона и даные являются строкой, то возврашаем HttpResponse(data)
Хе-хе, он несколько другой вариант развития имел в виду. :-)
теперь понял :) ступил однако
Не должен быть. А в текущем варианте ещё и не может. :-)
а у меня почти аналогично как у тебя :)
только ещё добавил response_jsonp полезная штука.
Ну, для JSON’а у меня тоже есть отдельный, в исходниках byteflow можно увидеть. :-)
вай нот return {‘bar’: bar}, template_name
ну и соотв: elif isinstance(data, (list, tuple)): # у нас есть имя шаблона
Хмм… Скорее по недосмотру. Мне нравится идея. :-)
Незнаю, на мой взгляд это саоочевидное решение. Тем более на фоне совсем грязного хака template_key_name.
Джанга и так чуть менее чем полностью состоит из хаков, напоминая больше что-то перловое, чем python.
Очевидное оно только тогда, когда отвлечёшься от словаря.
Да ну, всё несколько веселее на самом деле.
Ну для меня это не основной инструмент к счастью, но временами что-то мелкое по быстрому на нём изготавливать приходиться.
Как правило это самый noisy код, из вообще всего, что я пишу на питоне.
Хм. А можно пальцем на это указать, плз?
Да любой view. У меня даже скрейперы вразумительнее выглядят.
Хз, наверное я уже просто привык. :-)
Да, после сегодняшних копаний в потрохах sqlalchemy, склонен согласиться. Можно привыкнуть практически к чему егодно.
алсо, можно было-бы прикрутить какую-нить нотификацию “вам ответили”
Нужно было бы… Пока ещё нету. :(
ну я вместо
в своем аналоге под названием @page пользую
ну скажите мне, кто будет использовать переменную template для чего-нибудь, кроме имени шаблона? :)
Это было первым вариантом реализации, но оно не такое прикольное, имхо. :-)
Comment form for «render_to improved»