python -Django中的类视图

Translate

Django的视图指向一个功能,如果您只想更改一些功能,则可能会出现问题。是的,函数中可以有数百万个关键字参数,如果有语句,甚至可以更多,但是我在想更多的面向对象方法。

例如,我有一个显示用户的页面。该页面与显示组的页面非常相似,但仍与仅使用另一个数据模型不太相似。小组也有成员等...

一种方法是将视图指向类方法,然后扩展该类。有没有人尝试过这种方法或有其他想法?

This question and all comments follow the "Attribution Required."

所有的回答

Translate

我创建并使用了自己的通用视图类,__call__因此该类的实例是可调用的。我很喜欢;虽然Django的通用视图允许通过关键字参数进行一些自定义,但是OO通用视图(如果将其行为拆分为多个单独的方法)可以通过子类进行更细粒度的自定义,这使我重复了很多。 (我厌倦了在需要调整Django通用视图所不允许的任何东西时重写相同的create / update视图逻辑)。

我在张贴了一些代码djangosnippets.org.

我看到的唯一真正的缺点是内部方法调用的激增,这可能会在一定程度上影响性能。我认为这不是什么大问题。很少有Python代码执行会成为Web应用程序中的性能瓶颈。

更新:Django自己的通用视图现在基于类。

更新:FWIW,自撰写此答案以来,我已经改变了对基于类的观点的看法。在几个项目中广泛使用它们之后,我觉得它们倾向于导致令人满意地DRY编写的代码,但是以后很难阅读和维护,因为功能分布在许多不同的地方,并且子类是如此依赖有关超类和混合的每个实现细节。我现在觉得TemplateResponse并且视图装饰器是分解视图代码的更好答案。

来源
Translate

我需要使用基于类的视图,但是我希望能够在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/)

来源
Translate

如果您只是显示模型中的数据,为什么不使用Django通用视图?它们的设计使您可以轻松显示模型中的数据,而无需编写自己的视图以及将URL参数映射到视图,获取数据,处理边缘情况,呈现输出等方面的知识。

来源
Translate

您可以随时创建一个类,覆盖__call__函数,然后将URL文件指向该类的实例。你可以看看表单向导上课,看看如何完成。

来源
Lynn Lee
Translate

在我看来,您正在尝试合并不应合并的内容。如果需要根据要查看的是用户对象还是组对象在视图中进行不同的处理,则应使用两个不同的视图函数。

另一方面,您可能想从object_detail类型视图中提取出一些常见的成语...也许您可以使用装饰器或仅使用辅助函数?

-担

来源
Translate

除非您想做一些复杂的事情,否则使用通用视图是可行的方法。它们的功能远不如其名称所暗示的那样强大,并且如果您仅显示模型数据,那么通用视图就可以完成这项工作。

来源
Translate

通用视图通常是可以使用的方法,但是最终您可以随意使用所需的URL。 FormWizard和基于RESTful API的某些应用程序一样,都是以基于类的方式进行操作。

基本上,使用URL会给您提供一堆变量并提供可调用对象,提供的可调用对象完全取决于您-标准方法是提供函数-但Django最终对您的操作没有任何限制。

我确实同意,还有一些更多的方法可以做到这一点,尽管FormWizard可能是开始的地方。

来源
Translate

如果要在页面之间共享通用功能,建议您查看自定义标签。他们相当容易创建,并且功能非常强大。

也,模板可以从其他模板扩展。这样,您就可以拥有一个基本模板来设置页面的布局,并在其他模板之间进行共享,以填补空白。您可以将模板嵌套到任何深度;允许您在一个地方指定一组独立的相关页面上的布局。

来源
Translate

您可以使用Django通用视图。您可以通过Django通用视图轻松实现所需的功能

来源