4 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
5 from django.conf import settings
10 class HandlerMetaClass(type):
12 Metaclass that keeps a registry of class -> handler
15 def __new__(cls, name, bases, attrs):
16 new_cls = type.__new__(cls, name, bases, attrs)
18 def already_registered(model, anon):
19 for k, (m, a) in typemapper.iteritems():
20 if model == m and anon == a:
23 if hasattr(new_cls, 'model'):
24 if already_registered(new_cls.model, new_cls.is_anonymous):
25 if not getattr(settings, 'PISTON_IGNORE_DUPE_MODELS', False):
26 warnings.warn("Handler already registered for model %s, "
27 "you may experience inconsistent results." % new_cls.model.__name__)
29 typemapper[new_cls] = (new_cls.model, new_cls.is_anonymous)
31 typemapper[new_cls] = (None, new_cls.is_anonymous)
33 if name not in ('BaseHandler', 'AnonymousBaseHandler'):
34 handler_tracker.append(new_cls)
38 class BaseHandler(object):
40 Basehandler that gives you CRUD for free.
41 You are supposed to subclass this for specific
44 All CRUD methods (`read`/`update`/`create`/`delete`)
45 receive a request as the first argument from the
46 resource. Use this for checking `request.user`, etc.
48 __metaclass__ = HandlerMetaClass
50 allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
51 anonymous = is_anonymous = False
55 def flatten_dict(self, dct):
56 return dict([ (str(k), dct.get(k)) for k in dct.keys() ])
59 return hasattr(self, 'model') or hasattr(self, 'queryset')
61 def queryset(self, request):
62 return self.model.objects.all()
64 def value_from_tuple(tu, name):
70 def exists(self, **kwargs):
71 if not self.has_model():
72 raise NotImplementedError
75 self.model.objects.get(**kwargs)
77 except self.model.DoesNotExist:
80 def read(self, request, *args, **kwargs):
81 if not self.has_model():
82 return rc.NOT_IMPLEMENTED
84 pkfield = self.model._meta.pk.name
88 return self.queryset(request).get(pk=kwargs.get(pkfield))
89 except ObjectDoesNotExist:
91 except MultipleObjectsReturned: # should never happen, since we're using a PK
94 return self.queryset(request).filter(*args, **kwargs)
96 def create(self, request, *args, **kwargs):
97 if not self.has_model():
98 return rc.NOT_IMPLEMENTED
100 attrs = self.flatten_dict(request.POST)
103 inst = self.queryset(request).get(**attrs)
104 return rc.DUPLICATE_ENTRY
105 except self.model.DoesNotExist:
106 inst = self.model(**attrs)
109 except self.model.MultipleObjectsReturned:
110 return rc.DUPLICATE_ENTRY
112 def update(self, request, *args, **kwargs):
113 if not self.has_model():
114 return rc.NOT_IMPLEMENTED
116 pkfield = self.model._meta.pk.name
118 if pkfield not in kwargs:
119 # No pk was specified
120 return rc.BAD_REQUEST
123 inst = self.queryset(request).get(pk=kwargs.get(pkfield))
124 except ObjectDoesNotExist:
126 except MultipleObjectsReturned: # should never happen, since we're using a PK
127 return rc.BAD_REQUEST
129 attrs = self.flatten_dict(request.POST)
130 for k,v in attrs.iteritems():
131 setattr( inst, k, v )
136 def delete(self, request, *args, **kwargs):
137 if not self.has_model():
138 raise NotImplementedError
141 inst = self.queryset(request).get(*args, **kwargs)
146 except self.model.MultipleObjectsReturned:
147 return rc.DUPLICATE_ENTRY
148 except self.model.DoesNotExist:
151 class AnonymousBaseHandler(BaseHandler):
156 allowed_methods = ('GET',)