Представления классов в Django

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

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

Один из способов - указать представления на методы класса, а затем расширить этот класс. Кто-нибудь пробовал этот подход или есть другая идея?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
54
0
14 390
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Мне кажется, вы пытаетесь сочетать то, что не следует сочетать. Если вам нужно выполнить различную обработку в вашем представлении в зависимости от того, является ли вы объектом User или Group, который вы пытаетесь просмотреть, вам следует использовать две разные функции просмотра.

С другой стороны, могут быть общие идиомы, которые вы хотите извлечь из представлений типа object_detail ... возможно, вы могли бы использовать декоратор или просто вспомогательные функции?

-Дэн

Если вы просто отображаете данные из моделей, почему бы не использовать Общие представления Django? Они предназначены для того, чтобы вы могли легко отображать данные из модели без необходимости писать собственное представление и прочее о сопоставлении параметров URL-адресов с представлениями, извлечении данных, обработке крайних случаев, рендеринге вывода и т. д.

Если вы не хотите делать что-то немного сложное, используйте общие представления. Они намного мощнее, чем следует из их названия, и если вы просто отображаете данные модели, общие представления сделают свою работу.

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

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

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

Attila O. 17.09.2010 15:48

Вы всегда можете создать класс, переопределить функцию __call__ и затем указать URL-файл на экземпляр класса. Вы можете взглянуть на класс FormWizard, чтобы увидеть, как это делается.

Процессор разметки съел ваши __. Используйте \ _, чтобы скрыть разметку. Вызывается метод класса __call__. Проблема заключается в том, чтобы убедиться, что urls.py имеет доступный экземпляр класса. Это несколько усложняет ваш urls.py.

S.Lott 17.09.2008 06:07
Ответ принят как подходящий

Я создал и использовал свои собственные общие классы представления, определяя __call__, поэтому экземпляр класса можно вызывать. Мне это и вправду нравится; в то время как общие представления Django допускают некоторую настройку с помощью аргументов ключевых слов, общие представления OO (если их поведение разделено на несколько отдельных методов) могут иметь гораздо более тонкую настройку с помощью подклассов, что позволяет мне намного реже повторяться. (Я устал переписывать одну и ту же логику создания / обновления в любое время, когда мне нужно настроить что-то, что общие представления Django не позволяют).

Я разместил код на djangosnippets.org.

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

ОБНОВИТЬ: собственные общие представления Django теперь основаны на классах.

ОБНОВИТЬ: FWIW, я изменил свое мнение о представлениях на основе классов с тех пор, как был написан этот ответ. После того, как я широко использовал их в нескольких проектах, я чувствую, что они, как правило, приводят к коду, который достаточно СУХОЙ для написания, но его очень трудно читать и поддерживать позже, потому что функциональность распределена по очень многим разным местам, а подклассы настолько зависимы. на каждой детали реализации суперклассов и миксинов. Теперь я считаю, что TemplateResponse и декораторы представления - лучший ответ для декомпозиции кода представления.

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

StefanNch 23.12.2012 16:06

Общие представления обычно подходят, но в конечном итоге вы можете обрабатывать URL-адреса, как хотите. FormWizard работает на основе классов, как и некоторые приложения для RESTful API.

По сути, с URL-адресом вам предоставляется набор переменных и место для предоставления вызываемого объекта. Какой вызываемый объект вы предоставляете, полностью зависит от вас - стандартный способ - предоставить функцию, - но в конечном итоге Django не накладывает никаких ограничений на то, что вы делаете.

Я согласен с тем, что было бы неплохо привести еще несколько примеров того, как это сделать, хотя FormWizard, вероятно, является местом для начала.

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

class CallableViewClass(type):
    def __call__(cls, *args, **kwargs):
        if args and isinstance(args[0], HttpRequest):
            instance = super(CallableViewClass, cls).__call__()
            return instance.__call__(*args, **kwargs)
        else:
            instance = super(CallableViewClass, cls).__call__(*args, **kwargs)
            return instance


class View(object):
    __metaclass__ = CallableViewClass

    def __call__(self, request, *args, **kwargs):
        if hasattr(self, request.method):
            handler = getattr(self, request.method)
            if hasattr(handler, '__call__'):
                return handler(request, *args, **kwargs)
        return HttpResponseBadRequest('Method Not Allowed', status=405)

Теперь я могу создавать экземпляры классов представления и использовать экземпляры в качестве функций представления, ИЛИ я могу просто указать свой URLconf на мой класс, и метакласс создаст (и вызовет) класс представления для меня. Это работает путем проверки первого аргумента __call__ - если это HttpRequest, это должен быть фактический HTTP-запрос, потому что было бы бессмысленно пытаться создать экземпляр класса представления с экземпляром HttpRequest.

class MyView(View):
    def __init__(self, arg=None):
        self.arg = arg
    def GET(request):
        return HttpResponse(self.arg or 'no args provided')

@login_required
class MyOtherView(View):
    def POST(request):
        pass

# And all the following work as expected.
urlpatterns = patterns(''
    url(r'^myview1$', 'myapp.views.MyView', name='myview1'),
    url(r'^myview2$', myapp.views.MyView, name='myview2'),
    url(r'^myview3$', myapp.views.MyView('foobar'), name='myview3'),
    url(r'^myotherview$', 'myapp.views.MyOtherView', name='otherview'),
)

(Я опубликовал отрывок об этом на http://djangosnippets.org/snippets/2041/)

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

Другие вопросы по теме