Tiago Cogumbreiro

O Irrepupável

Back to top

Showing posts with label source code. Show all posts
Showing posts with label source code. Show all posts

Friday, May 30, 2008

Simple Django handlers

Or, an example about introspection targeting Python's functions.

I really like the way CherryPy maps GET parameters to the parameters of the handling function (usually, methods). I miss this mapping in Django, therefore I implemented it. I am "lazy" and I did not search Django's API for something related to this — I did this for pleasure.

Anyway, I have implemented a decorator, params_from_GET that adds this functionality to Django-handlers. You have to read the docstring to read the usage.

Code dump (licensed under public domain):

import inspect
def get_func_args(func):
    """
    Returns a generators of pairs (parameter name, default value)
    of the target function.
    """
    (args, varargs, varkw, defaults) = inspect.getargspec(func)
    if defaults is None:
        defaults = ()
    offset = len(args) - len(defaults)
    return args[:offset], dict(zip(args[offset:], defaults))

def params_from(func, method, default_value=''):
    """
    Returns a decorator, see params_from_GET.
    """
    # get the default params
    args, params = get_func_args(func)
    if args[0] != "request":
        raise TypeError("First parameters needs to be 'request'")
    for param in args[1:]:
        params[param] = default_value=''
    
    def wrapper(request, **orig_kwargs):
        # copy the parameters
        kwargs = params.copy()
        # get the map for the defined method, e.g GET
        method_dict = getattr(request, method)
        # set the request object
        kwargs['request'] = request
        for key in params:
            # fill with values that were sent by the user
            if key in method_dict:
                kwargs[key] = method_dict[key]
        kwargs.update(orig_kwargs)
        return func(**kwargs)
    return wrapper

def params_from_GET(func):
    """
    The decorator pics up a handler function and fetches the
    values from the GET map.

    For example:

    @params_from_GET
    handler(request, foo, bar):
       pass

    Is the same as:

    handler(request):
       foo = request.GET('foo', '')
       bar = request.GET('bar', '')
    """
    return params_from(func, 'GET')

Update: added support for the keyword arguments that may be passed to the dispatcher by urls.py.