Class views in Django

2019-01-13 17:23发布

Django view 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.

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?

9条回答
虎瘦雄心在
2楼-- · 2019-01-13 18:03

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.

查看更多
姐就是有狂的资本
3楼-- · 2019-01-13 18:06

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/)

查看更多
混吃等死
4楼-- · 2019-01-13 18:09

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

查看更多
登录 后发表回答