Сведения о вопросе

Математик

16:03, 1st July, 2020

Теги

python   django   views   oop    

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

Просмотров: 580   Ответов: 9

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

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

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



  Сведения об ответе

SKY

18:03, 1st July, 2020

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

Я отправил код по адресу djangosnippets.org .

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

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

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


  Сведения об ответе

LAST

18:03, 1st July, 2020

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


  Сведения об ответе

qwerty101

18:03, 1st July, 2020

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


  Сведения об ответе

PHPH

18:03, 1st July, 2020

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


  Сведения об ответе

piter

18:03, 1st July, 2020

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

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

-Дан


  Сведения об ответе

JUST___

18:03, 1st July, 2020

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


  Сведения об ответе

prince

18:03, 1st July, 2020

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

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


  Сведения об ответе

DAAA

18:03, 1st July, 2020

Общие представления, как правило, будут идти по этому пути, но в конечном счете вы можете обращаться с URLs, как вам угодно. FormWizard делает все на основе класса, как и некоторые приложения для RESTful APIs.

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

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


  Сведения об ответе

ASSembler

18:03, 1st July, 2020

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться