Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

ОБНОВЛЯТЬ:собственный Джанго общие представления теперь основаны на классах.

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

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

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

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)

Теперь я могу как создавать экземпляры классов представления, так и использовать экземпляры в качестве функций представления, ИЛИ я могу просто указать URL-адрес моего класса, и метакласс создаст (и вызовет) экземпляр класса представления для меня.Это работает путем проверки первого аргумента __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?Они созданы для того, чтобы вы могли легко отображать данные из модели без необходимости писать собственное представление и прочее, связанное с сопоставлением параметров URL-адресов с представлениями, получением данных, обработкой крайних случаев, рендерингом вывода и т. д.

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

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

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

-Дэн

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top