Code


Version 4 (modified by brantley (deadwisdom@…, 9 years ago) (diff)

--

Shortcut syntax ideas

The Django view system is completely flexible and decoupled from the template system, but that flexibility leads to repetitive code when all you want to do is use Django templates. Let's add a "shortcut" syntax to make it super quick for people to write views that use the Django templates.

This page collects ideas on how shortcut syntax would work.

Example

Each example on this page does the equivalent of this:

from django.core.template import Context
from django.core import template_loader
from django.utils.httpwrappers import HttpResponse

def prime_index(request):
    t = template_loader.get_template('primes/index')
    c = Context({
        'title': 'Page Title',
        'primes': [2, 3, 5, 7],
        'header': 'The first 4 primes',
    })
    return HttpResponse(t.render(c))

Idea 1: Decorator

from django.views.decorators.shortcuts import page

@page('primes/index', title='Page Title')      # @page(template_name, **default_context)
def prime_index(request):
    yield {"primes": [2, 3, 5, 7]}
    yield {"header": 'The first 4 primes'}

I think this is brilliant, but with a couple of hangups. Firstly, I think returning a single dictionary would make more sense (in most cases) than yielding - although I have no preblem with yield being supported as an alternative. Secondly, why yield single key dictionaries instead of tuple pairs? - SimonWillison

Idea 2: Class

from django.views.templated import TemplatedPage

class PrimeIndex(TemplatedPage):
    def get_context(self, request):
        return {'title': 'Page Title', 'primes': [2, 3, 5, 7], 'header': 'The first 4 primes:'}
prime_index = PrimeIndex('primes/index')

Idea 3: Function

from django.utils import render

def index(self, request):
     return render('index', 'title': 'Page Title', 'primes': [2, 3, 5, 7], 'header': 'The first 4 primes:')

Implementations

Idea 1

This goes in django.views.decorators.shortcuts:

class PageException(Exception):
    def __init__(self, arg):
        self.arg = arg
    
    def __call__(self):
        pass

class HttpResponseRedirect(PageException):    
    def __call__(self):
        return httpwrappers.HttpResponseRedirect(self.arg)

def page(template, **decorator_args):
    def _wrapper(fn):
        def _innerWrapper(request, **args):
            if (template):
                tmplt = template_loader.get_template(template)
                context_dict = decorator_args.copy()
            try:
                for i in fn(request, **args):
                    context_dict.update(i)
                context = Context(request, context_dict)
                return httpwrappers.HttpResponse(tmplt.render(context))
            except PageException, e:
                return e()
            
        return _innerWrapper
    return _wrapper

Idea 2

Implementation

This goes in django.views.templated:

class TemplatedPage:
    def __init__(self, template_name):
        self.template_name = template_name

    def __call__(self, *args, **kwargs):
        t = template_loader.get_template(self.template_name)
        c = Context(self.get_context(*args, **kwargs))
        return HttpResponse(t.render(c))

Idea 3

Implementation

This goes in django.utils:

def render(template, dictionary):
    t = template_loader.get_template(template)
    c = Context(dictionary)
    return HttpResponse(t.render(c))