try: frozenset except NameError: # Import from the sets module for python 2.3 from sets import Set as set from sets import ImmutableSet as frozenset from datetime import datetime, timedelta from threading import Thread import time from django.shortcuts import render_to_response from django.http import ( Http404, HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect, HttpResponseGone, HttpResponseNotAllowed, HttpResponseForbidden, HttpResponseBadRequest, HttpResponseNotModified, HttpResponseServerError ) from django.template import RequestContext from django.core.urlresolvers import reverse from django.conf import settings class View(object): """ View class that lets you do at least 90% of what you can do in a normal view function, but without having to import all the normal boilerplate code first since this class wraps methods around most if not all the HttpResponse types """ context = {} template = None allowed_methods = frozenset(['GET', 'POST', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE', 'CONNECT']) build_response = False mimetype = None def __call__(self, request, *args, **kwargs): """ This is the meat of the class, it lets it act as a callable Thus allowing the url handler to call the correct view Whats happening is it first sets the class request attribute, so it can be accessed via the other class methods Second it checks to make sure the requests method (GET, POST, etc) is in the allowed types list, if it is not then retuns a not allowed page Next it check to see if you want to build your own response (False by default), thus setting self.response to an empty HttpResponse that you can use to manualy build up your response. If you just want the normal way of using render_to_response it sets self.response to self.http_response Finnaly it attempts to call render without sending it the request object Since render will have access to the request object via self.request this should be the normal way of sending it, BUT if you need to decorate render with somnething like @login_required, then it needs to pass the request object along with it so it can be used by the decorator """ self.request = request if self.request.method not in self.allowed_methods: return self.not_allowed(self.allowed_methods) if self.build_response: self.response = HttpResponse() else: self.response = self.http_response try: return self.render(*args, **kwargs) except TypeError: return self.render(request, *args, **kwargs) def render(self, *args, **kwargs): """ This is the method that gets called when your view gets called So this is the method you need to override in your subclass """ return HttpResponse("This View is not yet Implimented!") def http_response(self): """ Wrapper around the render_to_response shortcut. It uses the classes self.template, self.context, and self.mimetype and ensures that you get a normal request_context """ return render_to_response(self.template, self.context, context_instance=RequestContext(self.request), mimetype=self.mimetype) def raw_response(self, msg, **kwargs): """ Wrapper around the HttpResponse object so you can deal with a raw response instead of being forced to use the render_to_response """ return HttpResponse(msg, **kwargs) def redirect(self, url, reverse=True): """ Wrapper around the HttpResponseRedirect class. Takes a url, and assumes that you want to use reverse to find the actual url """ if reverse: url = reverse(url) return HttpResponseRedirect(url) def permanent_redirect(self, url, reverse=True): """ Wrapper around the HttpResponsePermanentRedirect class. Takes a url, and assumes that you want to use reverse to find the actual url """ if reverse: url = reverse(url) return HttpResponsePermanentRedirect(url) def gone(self): """ Wrapper around the HttpResponseGone class. """ return HttpResponseGone() def not_allowed(self, methods): """ Wrapper around the HttpResponseNotAllowed class. """ return HttpResponseNotAllowed(methods) def forbidden(self): """ Wrapper around the HttpResponseForbidden class. """ return HttpResponseForbidden() def server_error(self): """ Wrapper around the HttpResponseServerError class. """ return self.Http500() def not_found(self): """ Wrapper around the HttpResponseNotFound class. """ self.Http404() def bad(self): """ Wrapper around the HttpResponseBadRequest class. """ return HttpResponseBadRequest() def unmodified(self): """ Wrapper around the HttpResponseNotModified class. """ return HttpResponseNotModified() def Http404(self): """ Raises the 404 exception """ raise Http404 def Http500(self): """ Wrapper around the HttpResponseServerError class. """ return HttpResponseServerError() def is_ajax(self): """ Wrapper around the request.is_ajax method Should work on 0.96 as well if anyone is still using that """ try: return self.request.is_ajax() except: idx = self.request.META['HTTP_X_REQUESTED_WITH'].find('XMLHttpRequest') if idx > -1: return True return False def is_secure(self): """ Wrapper around the request.is_secure method """ return self.request.is_secure() class StatefulView(View): """ This is a StatefulView class that maintains its state across page loads This is especialy useful for ajax type calls where you wish to maintain some form of state while the use is doing something but do not wish to make DB calls and do not wish to polute the session with trivial things NOTE: On my system it maintains state across browsers and computers as it is not tied to the session, BUT for this to happen all requests must be handled by the same proccess. So requests going to a differing process with not have the state maintained. """ def __new__(cls, *args, **kwds): it = cls.__dict__.get("__it__") if it is not None: return it cls.__it__ = it = object.__new__(cls) it.init(*args, **kwds) return it def init(self, *args, **kwds): pass """ from apps.utils.views import View, StatefulView class Home(View): template = 'index.html' def render(self): return self.response() class Test(StatefulView): counter = 0 build_response = True def render(self): self.counter += 1 self.response.write("You have viewed this page %d times" % (self.counter,)) return self.response index = Home() test = Test() """