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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 | 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,
)
|
Comments