姜戈 view 指向一个函数,如果您只想更改一点功能,这可能会出现问题。是的,我可以在函数中拥有数百万个关键字参数,甚至更多的 if 语句,但我更多地考虑面向对象的方法。

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

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

有帮助吗?

解决方案

我创建并使用了自己的通用视图类,定义 __call__ 所以该类的实例是可调用的。我很喜欢;虽然 Django 的通用视图允许通过关键字参数进行一些定制,但 OO 通用视图(如果它们的行为被分成许多单独的方法)可以通过子类化进行更细粒度的定制,这让我可以更少地重复自己。(每当我需要调整 Django 的通用视图不太允许的东西时,我都厌倦了重写相同的创建/更新视图逻辑)。

我已经发布了一些代码 djangosnippets.org.

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

更新: :姜戈自己的 通用视图 现在是基于阶级的。

更新: :FWIW,自从写完这个答案以来,我改变了对基于阶级的观点的看法。在几个项目中广泛使用它们之后,我觉得它们往往会导致代码写起来令人满意,但以后很难阅读和维护,因为功能分布在许多不同的地方,并且子类是如此依赖关于超类和 mixins 的每个实现细节。我现在感觉 模板响应 视图装饰器是分解视图代码的更好答案。

其他提示

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

如果您只是显示模型中的数据,为什么不使用 Django 通用视图?它们旨在让您轻松显示模型中的数据,而无需编写自己的视图以及将 URL 参数映射到视图、获取数据、处理边缘情况、渲染输出等内容。

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

在我看来,你正在尝试将不应该组合的东西组合起来。如果您需要根据您要查看的对象是用户还是组对象在视图中进行不同的处理,那么您应该使用两种不同的视图函数。

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

-担

除非您想做一些复杂的事情,否则使用通用视图是最好的选择。它们比它们的名字所暗示的要强大得多,如果您只是显示模型数据,通用视图就可以完成这项工作。

通用视图通常是可行的方法,但最终您可以随意处理 URL。FormWizard 以基于类的方式执行操作,某些 RESTful API 应用程序也是如此。

基本上,通过 URL,您会获得一堆变量和提供可调用对象的位置,您提供的可调用对象完全取决于您 - 标准方法是提供函数 - 但最终 Django 对您所做的事情没有任何限制。

我确实同意,再提供一些示例来说明如何执行此操作会很好,但 FormWizard 可能是一个起点。

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

还, 模板可以从其他模板扩展. 。这允许您拥有一个基本模板来设置页面布局并在填充空白的其他模板之间共享该布局。您可以将模板嵌套到任意深度;允许您在一个地方指定不同组的相关页面的布局。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top