Виды классов в Django

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

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

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

9 ответов


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

я опубликовал код в djangosnippets.org.

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

обновление: собственные универсальный вид теперь на основе классов.

обновление: FWIW, я изменил свое мнение о классовых представлениях, так как этот ответ был написан. После того, как я широко использовал их в нескольких проектах, я чувствую, что они, как правило, приводят к коду, который удовлетворительно сухой для записи, но очень трудно читать и поддерживать позже, потому что функциональность распространяется по стольким разным местам, а подклассы так зависят от каждой детали реализации суперклассов и миксинов. Теперь я чувствую это. TemplateResponse и View decorators-лучший ответ для разложения кода представления.


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

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 на мой класс и создать экземпляр metaclass (и вызвать) класс представления для меня. Это работает путем проверки первого аргумент к __call__ – если это HttpRequest, Это должен быть фактический HTTP-запрос, потому что было бы глупо attept для создания экземпляра класса представления с 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? Они предназначены для того, чтобы вы могли легко отображать данные из модели без необходимости писать собственное представление и прочее о сопоставлении параметров URL-адресов с представлениями, извлечении данных, обработке краевых случаев, рендеринге и т. д.


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


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

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

-Дэн


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


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

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

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


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

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


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