python Django 中的类视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:23:20  来源:igfitidea点击:

Class views in Django

pythondjangoviewsoop

提问by Seb

Djangoview points to a function, which can be a problem if you want to change only a bit of functionality. Yes, I could have million keyword arguments and even more if statements in the function, but I was thinking more of an object oriented approach.

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

For example, I have a page that displays a user. This page is very similar to page that displays a group, but it's still not so similar to just use another data model. Group also has members etc...

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

One way would be to point views to class methods and then extend that class. Has anyone tried this approach or has any other idea?

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

采纳答案by Carl Meyer

I've created and used my own generic view classes, defining __call__so an instance of the class is callable. I really like it; while Django's generic views allow some customization through keyword arguments, OO generic views (if their behavior is split into a number of separate methods) can have much more fine-grained customization via subclassing, which lets me repeat myself a lot less. (I get tired of rewriting the same create/update view logic anytime I need to tweak something Django's generic views don't quite allow).

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

I've posted some code at djangosnippets.org.

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

The only real downside I see is the proliferation of internal method calls, which may impact performance somewhat. I don't think this is much of a concern; it's rare that Python code execution would be your performance bottleneck in a web app.

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

UPDATE: Django's own generic viewsare now class-based.

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

UPDATE: FWIW, I've changed my opinion on class-based views since this answer was written. After having used them extensively on a couple of projects, I feel they tend to lead to code that is satisfyingly DRY to write, but very hard to read and maintain later, because functionality is spread across so many different places, and subclasses are so dependent on every implementation detail of the superclasses and mixins. I now feel that TemplateResponseand view decorators is a better answer for decomposing view code.

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

回答by Erik Allik

I needed to use class based views, but I wanted to be able to use the full name of the class in my URLconf without always having to instantiate the view class before using it. What helped me was a surprisingly simple metaclass:

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

I can now both instantiate view classes and use the instances as view functions, OR I can simply point my URLconf to my class and have the metaclass instantiate (and call) the view class for me. This works by checking the first argument to __call__– if it's a HttpRequest, it must be an actual HTTP request because it would be nonsense to attept to instantiate a view class with an HttpRequestinstance.

我现在可以实例化视图类并将实例用作视图函数,或者我可以简单地将我的 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'),
)

(I posted a snippet for this at http://djangosnippets.org/snippets/2041/)

(我在http://djangosnippets.org/snippets/2041/ 上为此发布了一个片段)

回答by rossp

If you're simply displaying data from models, why not use the Django Generic Views? They're designed to let you easy show data from a model without having to write your own view and stuff about mapping URL paramaters to views, fetching data, handling edge cases, rendering output, etc.

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

回答by dguaraglia

You can always create a class, override the __call__function and then point the URL file to an instance of the class. You can take a look at the FormWizardclass to see how this is done.

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

回答by Harley Holcombe

Unless you want to do something a little complex, using the generic views are the way to go. They are far more powerful than their name implies, and if you are just displaying model data generic views will do the job.

除非你想做一些有点复杂的事情,否则使用通用视图是可行的方法。它们比其名称所暗示的要强大得多,如果您只是显示模型数据,通用视图就可以完成这项工作。

回答by Harley Holcombe

Sounds to me like you're trying to combine things that shouldn't be combined. If you need to do different processing in your view depending on if it's a User or Group object you're trying to look at then you should use two different view functions.

在我看来,您正在尝试组合不应该组合的事物。如果您需要在视图中进行不同的处理,取决于它是您要查看的用户还是组对象,那么您应该使用两个不同的视图函数。

On the other hand there can be common idioms you'd want to extract out of your object_detail type views... perhaps you could use a decorator or just helper functions?

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

-Dan

-担

回答by Andrew Wilkinson

If you want to share common functionality between pages I suggest you look at custom tags. They're quite easy to create, and are very powerful.

如果您想在页面之间共享通用功能,我建议您查看自定义标签。它们很容易创建,而且非常强大。

Also, templates can extend from other templates. This allows you to have a base template to set up the layout of the page and to share this between other templates which fill in the blanks. You can nest templates to any depth; allowing you to specify the layout on separate groups of related pages in one place.

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

回答by Varun Chadha

You can use the Django Generic Views. You can easily achieve desired functionality thorough Django generic Views

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

回答by Andrew Ingram

Generic views will usually be the way to go, but ultimately you're free to handle URLs however you want. FormWizard does things in a class-based way, as do some apps for RESTful APIs.

通用视图通常是可行的方法,但最终您可以随意处理 URL。FormWizard 以基于类的方式做事,就像一些用于 RESTful API 的应用程序一样。

Basically with a URL you are given a bunch of variables and place to provide a callable, what callable you provide is completely up to you - the standard way is to provide a function - but ultimately Django puts no restrictions on what you do.

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

I do agree that a few more examples of how to do this would be good, FormWizard is probably the place to start though.

我确实同意再举几个如何做到这一点的例子会很好,但 FormWizard 可能是开始的地方。