- Author:
- Digitalxero
- Posted:
- October 13, 2008
- Language:
- Python
- Version:
- 1.0
- Score:
- 0 (after 2 ratings)
This snippet provides two view classes. The two reason I wanted to write this are, 1) Not have to import all the boilerplate code for each view and 2) so I could have the same URL handle loading a persons profile, or handle an OpenID login request without having to write two separate views. (Yes I know it isnt to hard to write my view, check the header and pass it off to the proper handler view, but I think it looks better code wise to have the handler methods all in one class)
The first one is just for normal views conveniently called View. The 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.
The second class StatefulView 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 user 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.
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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | 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()
"""
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.