Login

Ajax API class

Author:
kcarnold
Posted:
June 13, 2008
Language:
Python
Version:
.96
Tags:
ajax api instance-view
Score:
2 (after 2 ratings)

Whip up an AJAX API for your site in a jiffy:

class MySite(AJAXApi):
  @AJAXApi.export
  def hello(request):
      return {'content': self.get_content()}

  def get_content(self):
    return 'Hello, world!'

  urlpatterns += MySite().url_patterns()

(the example needs the JSON encoding middleware of snippet 803 to work.)

The secret is that bound instance methods are callable too, so work as views. (Most Django people only use functions, or sometimes classes with __call__, as view functions.)

You get implicit type dispatch off that self object. So you could subclass MySite, change get_content, and still use the same hello method.

See (django-webapp)[http://code.google.com/p/django-webapp/] for a REST-ish Resource class using this same idea.

You can clearly do better than my func_to_view, and also make a better decorator than exported (so you can actually say @exported('name') def function() etc.). This is more of a proof of concept that should work for most people.

Caveat: I've changed a few things since I last really tested this.

(psst, this also works for non-AJAX views too.)

 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
from django.conf.urls.defaults import url
from django.utils.decorators import wraps

def func_to_view(f):
    @wraps(f)
    def _dec(request, *a, **kw):
        kwargs = dict(kw)
        for k, v in request.REQUEST.items():
            kwargs[str(k)] = v
        return f(request, *a, **kwargs)
    return _dec

class AjaxAPI(object):
    def url_patterns(self, prefix=''):
        attrs = ((name, getattr(self, name)) for name in dir(self)
                 if not name.startswith('__'))
        methods = ((name, method) for (name, method) in attrs if callable(method))

        res = []
        for name, method in methods:
            exported = getattr(method, 'exported', False)
            if not exported: continue
            if isinstance(exported, basestring):
                export_name = exported
            else:
                export_name = name # Default to exporting by function name
            res.append(url('^%s%s/$' % (prefix, export_name),
                           func_to_view(method)))
        return res

    @staticmethod
    def export(f, name=True):
        f.exported = name
        return f

More like this

  1. Automatic Memoization Decorator by nikmolnar 2 years, 7 months ago
  2. View and StatefulView classes by Digitalxero 6 years, 10 months ago
  3. RFC: Shim to allow view classes rather than functions by peterbraden 6 years, 5 months ago
  4. Management command decorator by eternicode 4 years, 12 months ago
  5. Resource by zvoase 6 years, 11 months ago

Comments

Please login first before commenting.