Django视图指向一个函数,如果您只想更改一点功能,这可能是个问题。是的,我可以在函数中有数百万个关键字参数甚至更多 if 语句,但我更多地考虑的是一种面向对象的方法。 例如,我有一个显示用户的页面。该页面与显示组的页面非常相似,但仍然不太相似,只是使用另一个数据模型。组也有成员等... 一种方法是将视图指向类方法,然后扩展该类。有没有人尝试过这种方法或有其他想法?


我已经创建并使用了我自己的通用视图类,定义了__call__该类的一个实例是可调用的。我很喜欢; 虽然 Django 的通用视图允许通过关键字参数进行一些自定义,但 OO 通用视图(如果它们的行为被拆分为多个单独的方法)可以通过子类化进行更细粒度的自定义,这让我重复了很多。(每当我需要调整 Django 的通用视图不太允许的东西时,我都厌倦了重写相同的创建/更新视图逻辑)。 我在djangosnippets.org上发布了一些代码。 我看到的唯一真正的缺点是内部方法调用的激增,这可能会在一定程度上影响性能。我认为这不是什么大问题;Python 代码执行很少会成为 Web 应用程序的性能瓶颈。 更新:Django 自己的通用视图现在是基于类的。 更新:FWIW,自撰写此答案以来,我已经改变了对基于类的视图的看法。在几个项目中广泛使用它们之后,我觉得它们往往会导致代码写起来令人满意,但以后很难阅读和维护,因为功能分布在很多不同的地方,而且子类非常依赖关于超类和混入的每个实现细节。我现在觉得TemplateResponse和视图装饰器是分解视图代码的更好答案。
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: 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 HttpRequest instance. 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/)
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.
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 FormWizard class to see how this is done.
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.
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? -Dan
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. 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. I do agree that a few more examples of how to do this would be good, FormWizard is probably the place to start though.
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.
You can use the Django Generic Views. You can easily achieve desired functionality thorough Django generic Views