Jesper Nøhr avatar Jesper Nøhr committed 7e872e4

piston: typemapper (metaclass), follows fks/m2ms, basic userhandler, default cruds

Comments (0)

Files changed (3)

piston/emitters.py

 from django.core.serializers.json import DateTimeAwareJSONEncoder
 
 class Emitter(object):
-    def __init__(self, payload, fields=()):
+    def __init__(self, payload, typemapper):
+        self.typemapper = typemapper
+        
         if isinstance(payload, QuerySet):
             self.data = tuple([m for m in payload.all()])
         elif isinstance(payload, Model):
-            self.data = (payload,)
+            self.data = payload
         else:
             raise ValueError("Can't emit this.")
     
     def construct(self):
         
         def _any(thing):
+
             ret = None
             
             if isinstance(thing, (tuple, list)):
 
             return ret
 
+        def _fk(data, field):
+            related = getattr(data, field.name)
+            
+            if not related:
+                if field.rel.field_name == related._meta.pk.name:
+                    related = related._get_pk_val()
+                else:
+                    related = getattr(related, field.rel.field_name)
+
+            return _any(related)
+            
+        def _m2m(data, field):
+            return [ _model(m) for m in getattr(data, field.name).iterator() ]
+
         def _model(data):
             ret = { }
             
-            for f in data._meta.fields:
-                ret[f.attname] = _any(getattr(data, f.attname))
+            if type(data) in self.typemapper.keys():
+
+                v = lambda f: getattr(data, f.attname)
+                want_fields = self.typemapper.get(type(data)).fields
+                
+                for f in data._meta.local_fields:
+                    if f.serialize:
+                        if not f.rel:
+                            if f.attname in want_fields:
+                                ret[f.attname] = _any(v(f))
+                        else:
+                            if f.attname[:-3] in want_fields:
+                                ret[f.name] = _fk(data, f)
+
+                for mf in data._meta.many_to_many:
+                    if mf.serialize:
+                        if mf.attname in want_fields:
+                            ret[mf.name] = _m2m(data, mf)
+
+            else:
+
+                for f in data._meta.fields:
+                    ret[f.attname] = _any(getattr(data, f.attname))
+
+                fields = dir(data.__class__) + ret.keys()
+                add_ons = [k for k in dir(data) if k not in fields]
             
-            fields = dir(data.__class__) + ret.keys()
-            add_ons = [k for k in dir(data) if k not in fields]
-            
-            for k in add_ons:
-                ret[k] = _any(getattr(data, k))
+                for k in add_ons:
+                    ret[k] = _any(getattr(data, k))
                 
             return ret
             

piston/handler.py

+typemapper = { }
+
+class HandlerType(type):
+    def __init__(cls, name, bases, dct):
+        model = dct.get('model', None)
+        
+        if model:
+            typemapper[model] = cls
+        
+        return super(HandlerType, cls).__init__(name, bases, dct)
+
 class BaseHandler(object):
-    pass
+    __metaclass__ = HandlerType
+
+    def has_model(self):
+        return hasattr(self, 'model')
+
+    def read(self, request, *a, **kwa):
+        if not self.has_model():
+            return NotImplementedError
+
+        return self.model.objects.filter(*a, **kwa)

piston/resource.py

 """
 from django.http import HttpResponse, Http404
 from emitters import Emitter
+from handler import typemapper
 
 class Resource(object):
     callmap = { 'GET': 'read', 'POST': 'create', 
         if not meth:        
             raise Http404
 
-        result, fields = meth(request)
+        result = meth(request)
         emitter, ct = Emitter.get(format)
-        srl = emitter(result, fields)
+        srl = emitter(result, typemapper)
         
         return HttpResponse(srl.render(), mimetype=ct)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.