Package: cereal-box
# cereal-box## Descriptioncereal-box is a serialization library that exposes defined functions through a custom Django template tag and a JSON API.## InstallationIn your settings, add 'cereal' to INSTALLED_APPS.In your urls.py, addimport cerealurlpatterns += (patterns('', (r'^api/', include(cereal.urls)))## Settings### Managing RequestsWhen using the standard ceral api the ip addresses and the number of requestsfrom those ip addresses will be kept in the cache.  If the number of requestsfor a specific ip address exceeds the number or requests per the timeoutthen the user will receive a 503 error response, Service Unavailable.The available settings to change this behavior are:CEREAL_REQUESTS_TIMEOUT, default = 1 (seconds)CEREAL_REQUESTS_PER_TIMEOUT, default = 15 (number requests)It is highly recommended that you use something fast like Redis or Memcache if youuse the timeout view.  Otherwise you'll be using the Django cache which defaultsto your registered database.If using the cache and the ip address timeout is not desired, simply write yourown url:('^api/(?P<model>\w+)/(?P<function>\w+)', cereal.views.json_api)### Sorting KeysIf you want to have the keys output by the api to be sorted simply set thefollowing setting:CEREAL_SORT_KEYS = TrueThat will make your api calls human readable.  This is suggested onlyfor development as it adds overhead in production.## Registering a functionThere are a couple of different ways you can do this.import cerealcereal.register(MyModel, [myfunction1, myfunction2])cereal.register('my_arbitrary_scope', [myfunction3, myfunction4])cereal.register(MyModel, myfunction5)cereal.register('my_arbitrary_scope', myfunction6)Model names will be lower cased.  So, MyModel and 'mymodel' are equivalent first arguments.Or you can use the decorator:@cereal.register_for('my_scope') #You could also use a model name heredef my_function(....)...### Function detailsFunctions take the arguments (scope, **kwargs) where kwargs is all of the arguments passed to cereal.TODO: eventually we'd like the request (and other info?) to be passed in here somehow.Functions are expected to return a jsonize-able python object.  Typically you would use .values() togo from a queryset to a dictionary, although for a less efficient way of getting a similar thing for polymorphicrelations, you can use cereal.smart_values(queryset, *keys).### Custom serializerscereal.register takes a third argument, a custom serializer.  This is called by the default filter*()methods and also can be called manually on a queryset in your registered function with cerial.ize(queryset).Note that the serializer is tied to a *model* not to a function. TODO: change this behavior?## Calling a functionYou can do this in python, with a template tag, or via a JSON API call.### Pythonimport cerealcereal.call('my_scope', 'my_function', arg1=value1, arg2=value2)### Template Tag{% load cereal_tags %}{% cereal my_scope.my_function arg1=value1 arg2=value2 as cereals %}Now 'cereal' will contain whatever python value was returned.### JSON APIThis uses regular old request parameters.  POSTing also works.curl http://path.to.my.site/api/my_scope/my_function?arg1=value1&arg2=value2The result is a jsonified version of the returned python values.## Examples#### models.pyfrom django.db import modelsclass Cereal(models.Model): # Nevermind the naming snafuname        = models.CharField(max_length=20)sugar_level = models.PositiveIntegerField()def __unicode__(self): return self.nameimport cerealcereal.register(Cereal, [cereal.functions.filter()])#### Python>>> import cereal>>> cereal.call('cereal', 'filter', sugar_level=9)[{'sugar_level': 9, 'id': 1, 'name': u'Lucky Charms'}]#### Template tag{% load cereal_tags %}{% cereal cereal.filter sugar_level=9 as cereals %}<ul>{% for c in cereals %}<li>{{c.name}}</li>{% endfor %}</ul>#### Curlcurl http://127.0.0.1:8000/api/cereal/filter?sugar_level=9[{"sugar_level": 9, "id": 1, "name": "Lucky Charms"}]