Schnell pip install tastypie in die virtualenv eingegeben, ein bisschen konfigurieren und voila! es klappt.
Nur leider ist es doch ein bisschen mühsam für jede ORM-Klasse das Tastypie-Gegenstück (Resource-Klasse) zu schreiben, auch wenn die Klasse trivial aufgebaut ist.
Der Ansatz jede Resource-Klasse in der urls.py zu registrieren erscheint mir nicht sehr elegant, das fürht bei größeren Projekten mit mehreren "Apps" und Klassen zu einem riesen Import-Schlacht (korrigiert mich, falls ich da falsch lege).
Also habe ich mich kurzer Hand entschieden eine API-POOL zu schreiben, der sich drum kümmert triviale Resource-Klassen dynamisch zu erstellen und komplexe Klassen zu sammeln.
#Datei: TastyPiePool
#coding: utf-8
'''
Created on 03.08.2012
@author: trungphanan
@contact: info@level96.de
'''
from tastypie.api import Api
from tastypie.resources import ModelResource, ALL, ALL_WITH_RELATIONS
from tastypie.authentication import Authentication
from tastypie.authorization import DjangoAuthorization
import tastypie.fields
class TastyPiePool(object):
'''
'''
def __init__(self, api_name="v1"):
self.api = Api(api_name=api_name)
self.allowed_methods = ("get", "post", "put", "delete")
def register(self, orm_class, resource_name, foreign_keys={}, filtering={}, manager=None, excludes=None, fields=None, allowed_methods=None, authentication=None, authorization=None):
'''
Dynamicly creates Resource Class from Django-ORM-Model
'''
resource_attrs = {"Meta": type(
"Meta", (),
{
"queryset": orm_class.objects.all() if not manager else manager,
"resource_name": resource_name,
"excludes": excludes,
"fields": fields,
"allowed_methods": allowed_methods if allowed_methods else self.allowed_methods,
"authentication": Authentication() if not authentication else authentication,
"authorization": DjangoAuthorization() if not authorization else authorization,
"filtering": dict([ (f, ALL_WITH_RELATIONS if filtering[f]=="all" else filtering[f]) for f in filtering ])
}
)}
for fk in foreign_keys:
resource_attrs.update({
fk: tastypie.fields.ForeignKey(foreign_keys[fk],
getattr(foreign_keys[fk].Meta, "resource_name"))
})
cls = type(
"%sResource" % type(orm_class).__name__,
(ModelResource, object),
resource_attrs
)
self.register_resource(cls())
return cls
def register_resource(self, resource, canonical=True):
self.api.register(resource, canonical)
@property
def urls(self):
return self.api.urls
api_pool = TastyPiePool()
in der models.py importieren wir die API-POOL und registrieren die Klasse und den resource-name, letzteres wird als Slug für die API verwendet.
Die Funktion register generiert dynamisch eine Resource-Klasse mit dem Namen: orm-klasse-name Resource (tastypie namens-konvention) mit der entsprechenden Meta-Klasse.
Dabei kann ein abweichenden Object-Manager, excludes, fields oder allowed_methods angegeben werden (siehe tastypie doku)
Für den Fall das ihr komplexere Resource-Klassen benötigt und geschrieben habt, könnt ihr die Funktion "register_resource(CLASS)" benutzen.
from TastyPiePool import api_pool
class Poll(models.Model):
name = models.TextField()
api_pool.register(Poll, 'poll' ) # args: orm-class, resource_name
Nach dem die Klasse registiert wurde müssen wir die api_pool nur noch der urls.py registriert werden damit die urls erreichtbar sind.
from django.conf.urls.defaults import *
from TastyPiePool import api_pool
urlpatterns = patterns('',
(r'^api/', include(api_pool.urls)),
)
danach server neustarren und ihr erreicht die API unter:
http://host:port/api/v1/RESCOURCE-NAME/?format=json
viel spaß beim Testen und Erweitern des Scripts
für jQuery-API klickt ihr hier.
Keine Kommentare:
Kommentar veröffentlichen