Django - Подсказки, чтобы не повторять код в представлениях

Я перемещаюсь происхождения PHP в разработку Django с помощью Python, главным образом ради занятия MVC (или MVT), что я чувствую, имеет большую часть смысла, хотя в этом шаблоне я начал замечать много повторного кода в моих представлениях.

Например, при входе в систему у меня есть информация относительно пользователя, что я хотел бы появиться на каждой странице, хотя при использовании render_to_response и в каждом представлении это требуется, я должен захватить информацию и передать ее функции render_to_response.

Я задаюсь вопросом, что было бы самым эффективным способом сократить дублирующий код, который будет в сущности требоваться во всех представлениях в конкретном приложении.

Заранее спасибо.

5
задан neopickaze 20 March 2010 в 09:41
поделиться

4 ответа

Лично я большой поклонник декораторов, которые представляют собой функцию 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. Удачи.

4
ответ дан 18 December 2019 в 09:48
поделиться

Есть два основных способа абстрагирования общего содержания .

Контекстные процессоры лучше всего подходят для передачи битов данных, которые, как вы знаете, вам понадобятся в каждом отдельном представлении.

Теги шаблона - особенно теги включения - полезны для визуализации отдельных областей страницы, которые будут одинаковыми в нескольких шаблонах.

5
ответ дан 18 December 2019 в 09:48
поделиться

Также не забывайте о общих представлениях ! В 90% случаев вы можете обернуть object_list или object_detail и сэкономить немного кода.

3
ответ дан 18 December 2019 в 09:48
поделиться

Инкапсулируйте общий код в функции и вызывайте ее из разных представлений. Звучит банально, но это решение для 99% таких потребностей.

Для более конкретного ответа вам нужно будет показать более конкретный пример кода, который вы хотите запустить.

5
ответ дан 18 December 2019 в 09:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: