from django import http from django.conf import settings from django.core import urlresolvers from django.shortcuts import get_object_or_404, redirect from django.utils import simplejson from django.utils.encoding import force_unicode from yabl.authors.models import Author class RESTResource(object): """ Dispatches based on HTTP method. """ # Possible methods; subclasses could override this. methods = ['GET', 'POST', 'PUT', 'DELETE'] def __call__(self, request, *args, **kwargs): callback = getattr(self, request.method, None) if callback: return callback(request, *args, **kwargs) else: allowed_methods = [m for m in self.methods if hasattr(self, m)] return http.HttpResponseNotAllowed(allowed_methods) class AuthorResource(RESTResource): """ Base class for all Author resources providing conversion between Author objects and simple flat dicts. """ def format(self, author, full=False): """ Convert from an Author object to a dict. """ link = urlresolvers.reverse('api_author_detail', args=[author.pk]) info = { 'first_name': author.first_name, 'last_name': author.last_name, 'link': link, } if full: info['bio'] = author.bio return info def parse(self, d): """ Convert from a dict to an Author object. """ try: return Author( first_name = force_unicode(d['first_name']), last_name = force_unicode(d['last_name']), bio = force_unicode(d.get('bio', '')), ) except (ValueError, KeyError, TypeError): return None class AuthorList(AuthorResource): """ The list of authors (e.g. /api/authors/). """ def GET(self, request): return JSONResponse([self.format(a) for a in Author.objects.all()]) def POST(self, request): author = self.parse(simplejson.loads(request.raw_post_data)) if not author: return http.HttpResponseBadRequest() author.save() response = http.HttpResponse(status=201) # HTTP 201 Created response['Location'] = urlresolvers.reverse('api_author_detail', args=[author.pk]) return response class AuthorDetail(AuthorResource): """ Author detail view (e.g. /api/authors/{id}/). """ def GET(self, request, id): a = get_object_or_404(Author, pk=id) return JSONResponse(self.format(a, full=True)) def DELETE(self, request, id): try: Author.objects.get(pk=id).delete() except Author.DoesNotExist: pass return redirect('api_author_list') def PUT(self, request, id): author = self.parse(simplejson.loads(request.raw_post_data)) if not author: return http.HttpResponseBadRequest() author.id = id author.save() return JSONResponse(self.format(author, full=True)) class JSONResponse(http.HttpResponse): def __init__(self, data): indent = 2 if settings.DEBUG else None mime = ("text/javascript" if settings.DEBUG else "application/json") super(JSONResponse, self).__init__( content = simplejson.dumps(data, indent=indent), mimetype = mime, )