Login

Alternative to Class Based Views

Author:
sleepycal
Posted:
September 12, 2012
Language:
Python
Version:
1.4
Score:
0 (after 0 ratings)

There is a lot of debate on whether there is a real future for the Django CBVs (class based views). Personally, I find them tedious, and just wanted a way to keep my views clean.

So, here is a really minimalistic way of having class based views, without the fuss.

This is a fork from: http://stackoverflow.com/questions/742/class-views-in-django http://djangosnippets.org/snippets/2041/

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
#################################################################
# Callable class metaclass magic - borrowed from stackoverflow.
#################################################################

from django.http import HttpResponse, HttpRequest, HttpResponseNotAllowed, HttpResponseBadRequest

class CallableClass(type):
    def __call__(cls, *args, **kwargs):
        if args and isinstance(args[0], HttpRequest):
            instance = super(CallableClass, cls).__call__()
            return instance.__call__(*args, **kwargs)
        else:
            instance = super(CallableClass, cls).__call__(*args, **kwargs)
            return instance

class View(object):
    __metaclass__ = CallableClass

    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)

#################################################################
# Our URLs file
#################################################################

from models import LoginView
from models import AccountView
from models import AdminView

urlpatterns = patterns('',

    # /login
    url(r'^login$', LoginView, name = "login"),

    # /account
    url(r'^account$', AccountView, name = "account"),

    # /admin
    url(r'^admin$', AdminView, name = "admin"),
)

#################################################################
# Our base class for all views, although I'm not sure if method decorators would still work
#################################################################

class BaseView(View):

    # Sets our default view parameters
    auth_required = True
    staff_required = False

    def __call__(self, request, *args, **kwargs):
        """This allows us to automatically check the security context
        for objects"""

        # check if we are logged in
        if self.auth_required and not request.user:
            if _partial:
                raise Exception, "You are not authenticated"

            logout(request)
            return redirect("login")

        if self.staff_required ans not request.is_staff():
            raise Exception, "User does not have staff permissions"

        cx = RequestContext(request, {
            'custom_field' : "custom_value",
        })

        return super(PortalView, self).__call__(request, cx, org, domain, *args, **kwargs)

class LoginView(BaseView):
    """Shows login page"""

    auth_required = False
    staff_required = False

    def GET(self, request, cx, *args, **kwargs):
        return render_to_response("login.html", context_instance = cx)


class AccountView(BaseView):
    """Shows account overview page"""

    auth_required = True
    staff_required = False

    def GET(self, request, cx, org, domain, *args, **kwargs):
        return render_to_response("account.html", context_instance = cx)

class AdminView(BaseView):
    """Shows account overview page"""

    auth_required = True
    staff_required = True

    def GET(self, request, cx, org, domain, *args, **kwargs):
        return render_to_response("admin.html", context_instance = cx)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 11 months ago
  5. Help text hyperlinks by sa2812 11 months, 3 weeks ago

Comments

sv1jsb (on September 13, 2012):

At line 75 shouldn't this be:

return super(BaseView, self).__call__(request, cx, org, domain, *args, **kwargs)

#

Please login first before commenting.