Я перемещаюсь происхождения PHP в разработку Django с помощью Python, главным образом ради занятия MVC (или MVT), что я чувствую, имеет большую часть смысла, хотя в этом шаблоне я начал замечать много повторного кода в моих представлениях.
Например, при входе в систему у меня есть информация относительно пользователя, что я хотел бы появиться на каждой странице, хотя при использовании render_to_response и в каждом представлении это требуется, я должен захватить информацию и передать ее функции render_to_response.
Я задаюсь вопросом, что было бы самым эффективным способом сократить дублирующий код, который будет в сущности требоваться во всех представлениях в конкретном приложении.
Заранее спасибо.
Лично я большой поклонник декораторов, которые представляют собой функцию Python, которая не является специфической для Django. Декораторы - это идеальный синтаксический сахар поверх функций высшего порядка, и они особенно полезны для сокращения шаблонов в представлениях - вы можете быстро определить обобщенную функцию-оболочку, в которую вы можете поместить повторяющийся код для легкого повторного использования и удобного -Остановить рефакторинг.
Наверное, легче показать, чем объяснить, как они работают. Вот упрощенный пример представления:
def listpage(request):
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.filter(visible=True).order_by("-modifydate")
}))
def itemlist_tags(request, tags):
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
}))
... но затем скажите, что вы хотите, чтобы эти страницы требовали входа пользователя в систему. Вы можете добавить такой код входа:
def listpage(request):
if not request.user.is_authenticated():
return f(request, *args, **kwargs)
else:
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.filter(visible=True).order_by("-modifydate")
}))
def itemlist_tags(request, tags):
if not request.user.is_authenticated():
return f(request, *args, **kwargs)
else:
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
}))
... который начинает заметно увеличиваться и повторяющийся, даже для надуманного примера. Вы можете снова сделать свои функции тонкими с помощью декораторов, например:
from decorator import decorator
@decorator
def loginrequired(f, request, *args, **kwargs):
if request.user.is_authenticated():
return f(request, *args, **kwargs)
else:
return HttpResponseRedirect("/")
@loginrequired
def listpage(request):
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.filter(visible=True).order_by("-modifydate")
}))
@loginrequired
def itemlist_tags(request, tags):
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
}))
@loginrequired
def another_such_function(request):
(...)
@loginrequired
def and_again(request):
(...)
Что происходит, когда функция декоратора выполняется во время определения функции. Буква «f» в моем примере - это объект, представляющий функцию, к которой применяется декоратор, которой вы можете бесконечно манипулировать.
Для этого требуется библиотека декораторов , которая бесплатна для PyPI, как и многие другие полезные кусочки Python, которые вы найдете.
Вам не нужна эта библиотека для написания функций декоратора, но она полезна, особенно вначале. Они могут делать гораздо больше - любой вызываемый объект может быть декоратором; вы можете декорировать методы класса и перехватывать переменную self
; декораторы могут быть соединены в цепочку, например:
@second
@first
def originalfunction(*args):
(...)
Я оставлю вам исследование того, что вы можете сделать с помощью такого простого манипулирования функциями высшего порядка, если эта идея возбудит ваш аппетит. У меня есть еще много примеров для вас или других любопытных новых поклонников Python. Удачи.
Есть два основных способа абстрагирования общего содержания .
Контекстные процессоры лучше всего подходят для передачи битов данных, которые, как вы знаете, вам понадобятся в каждом отдельном представлении.
Теги шаблона - особенно теги включения - полезны для визуализации отдельных областей страницы, которые будут одинаковыми в нескольких шаблонах.
Также не забывайте о общих представлениях ! В 90% случаев вы можете обернуть object_list или object_detail и сэкономить немного кода.
Инкапсулируйте общий код в функции и вызывайте ее из разных представлений. Звучит банально, но это решение для 99% таких потребностей.
Для более конкретного ответа вам нужно будет показать более конкретный пример кода, который вы хотите запустить.