Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

UPDATE: Django собственный общие представления теперь основаны на классах.

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

Ответ 2

Мне нужно было использовать представления на основе классов, но я хотел иметь возможность использовать полное имя класса в своем 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__ - если он a 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/)

Ответ 3

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

Ответ 4

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

Ответ 5

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

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

Дан

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

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

Ответ 9

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