from django.template.loader import get_template from django.template import RequestContext from django import http class BaseView(object): """ BaseView provides a class that is instantiated and then called like a function. __init__ called without arguments. You must just override the __call__ method. """ def __new__(cls, *args, **kwargs): obj = super(BaseView, cls).__new__(cls) return obj(*args, **kwargs) def __call__(self, *args, **kwargs): pass class View(BaseView): """ View provides a basic django view _class_ It is instantiated for each request, and it is provided to the template's context as the 'view' varable. __call__ sets the following: self.request self.response self.context = {} view.update() is called first. It may do a redirect, additional checks, or setup information for the template renderer. If view.render() is defined, it will be run to generate the output. If its return value is a string (or unicode), self.response.content will be set to this value. Otherwise its return value will be returned directly, possibly allowing other Django processors to do their magic. If view.render() is not defined, we assume it will be rendered with a template, so we define a context dictionary, then call self.render_template. The context dictionary contains: 'view' : self, 'request' : self.request, 'response' : self.response, plus anything defined in self.context is merged into the dictionary, possibly overriding the above variables. Override render_template(template_name, context_dictionary) to use an alternate template rendering mechanism. """ template = None context = None def redirect(self, url): self.response = http.HttpResponseRedirect(url) def update(self): pass def __call__(self, request, *args, **kwargs): self.request = request self.response = http.HttpResponse() self.update() if self.response.status_code in (301, 302): return self.response if hasattr(self, "render"): res = self.render() if isinstance(res, basestring): self.response.content = res return self.response return res elif self.template: template = self.template context = { 'view' : self, 'request' : self.request, 'response' : self.response, } extra = getattr(self, 'context', None) if extra: context.extend(extra) r = self.response r.content = self.render_template(template, context) return r else: if not self.response.content: self.response.content = 'No Template nor Render Method' return self.response def render_template(self, template, context): """ Given a template (either a filename to lookup, or an object with a render() method), lookup the template if necessary, then wrap the context in a RequestContext and call template.render(context) """ if isinstance(template, basestring): template = get_template(template) return template.render(RequestContext(self.request, context)) ### example view class testview(View): template = "testview.html" def update(self): self.age = 29 self.context["nose"] = "normal sized" self.response["X-Crazy"] = "Maybe" if self.request.GET.get('next'): self.redirect(self.request.GET['next']) def name(self): return "Robert" class testview2(View): template = "testview.html" def render(self): return "No template will be used here automatically" ### testview.html: Hello {{ view.name }}! You are {{ view.age }} years old. You have a {{ nose }} nose.