01.23
First of all: Last time I used Django was well over a year ago so if this is already possible to do with the current latest code base then shame on me, anyway – after messing around a bit with Django I got annoyed by the simplicity of the views, they’re very simple minded. I wanted some way of calling different functions depending on the request method and an easier way to return different output types, this is what I came up with.
The idea is simple, use a class with __call__ implemented instead of a function, within __call__ you can put custom logic to direct the requests to the appropriate callbacks – here’s my new base view class and a helper decorator (since Python 2.6 you can decorate classes).
def view(cls):
return cls()
class ClassView(object):
fallback = "HTML"
http_accept = {
"application/xhtml\+xml": "HTML",
"text/html":"HTML",
"application/json": "JSON",
"text/javascript": "JSON",
"application/xml": "XML"
}
request_method = {
"GET": "READ",
"POST": "WRITE",
"PUT": "WRITE",
"DELETE": "WRITE"
}
def __call__(self, request):
accept = request.META["HTTP_ACCEPT"]
method = getattr(self, self.request_method[request.META["REQUEST_METHOD"]])
for regex, call in self.http_accept.items():
if regex and re.search(regex, accept):
return getattr(self, call)(request, method(request))
return getattr(self, self.fallback)(request, method(request))
def READ(self, request):
pass
def WRITE(self, request):
pass
def JSON(self, request, method_vars):
pass
def HTML(self, request, method_vars):
pass
def XML(self, request, method_vars):
pass
Now when I want to create a new view in django, instead of doing something like this:
def index(request):
# blah
I do this:
# for python < 2.6 remove/comment out this next line:
@view
class index(ClassView):
def READ(self, request):
return {"title": "Hello World!"}
def HTML(self, request, method_vars):
return render_to_response("frontend/index.html", method_vars)
def JSON(self, request, method_vars):
return HttpResponse('{"title":"%(title)s"}' % method_vars)
# for python < 2.6 uncomment the next line
# index = view(index)
The READ method will be called on all GET requests, while the WRITE method will be called on all POST, PUT and DELETE. After which the appropriate output method will be selected based on the HTTP Accept header. This allows me to group common functionality in READ for all GET requests to one URL and then still be allowed to do output specific (HTML, XML, JSON, etc.) logic and template rendering based on what content types the client accepts (for example I will probably need to load more objects for HTML output since it usually has a rather advanced layout compared to say JSON which probably only wants to return the object collection as JSON string)

Buy:Human Growth Hormone.Synthroid.Prevacid.Prednisolone.Arimidex.Actos.100% Pure Okinawan Coral Calcium.Lumigan.Petcam (Metacam) Oral Suspension.Accutane.Nexium.Retin-A.Zyban.Valtrex.Zovirax.Mega Hoodia….
Buy:Valtrex.Arimidex.Actos.Synthroid.Human Growth Hormone.Nexium.100% Pure Okinawan Coral Calcium.Prevacid.Prednisolone.Petcam (Metacam) Oral Suspension.Lumigan.Zovirax.Accutane.Mega Hoodia.Zyban.Retin-A….