Piston customize response representation
I am using piston and I would like to spit out a custom format for my response.
My model is something like this:
class Car(db.Model):
name = models.CharField(max_length=256)
color = models.CharField(max_length=256)
Now when I issue a GET request to something like /api/cars/1/ I want to get a response like this:
{'name' : 'BMW', 'color' : 'Blue',
'link' : {'self' : '/api/cars/1'}
}
However piston only outputs this:
{'name' : 'BMW', 'color' : 'Blue'}
In other words I want to customize the representation of a particular resource.
My piston Resource handler currently looks like this:
class CarHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
model = Car
fields = ('name', 'color',)
def rea开发者_运维知识库d(self, request, car_id):
return Car.get(pk=car_id)
So I don't really get where I have the chance to customize the data. Unless I have to overwrite the JSON emitter, but that seems like a stretch.
You can return custom format by returning a Python dictionary. Here is an example on one of my app. I hope it helps.
from models import *
from piston.handler import BaseHandler
from django.http import Http404
class ZipCodeHandler(BaseHandler):
methods_allowed = ('GET',)
def read(self, request, zip_code):
try:
points = DeliveryPoint.objects.filter(zip_code=zip_code).order_by("name")
dps = []
for p in points:
name = p.name if (len(p.name)<=16) else p.name[:16]+"..."
dps.append({'name': name, 'zone': p.zone, 'price': p.price})
return {'length':len(dps), 'dps':dps}
except Exception, e:
return {'length':0, "error":e}
Its been two years since this question was asked, so its obviously late for OP. But for others who, like me, had a similar dilemma there exists a Pistonic way to get this done.
Using the Django example of polls and choices -
You will notice that for the ChoiceHandler the JSON response is:
[
{
"votes": 0,
"poll": {
"pub_date": "2011-04-23",
"question": "Do you like Icecream?",
"polling_ended": false
},
"choice": "A lot!"
}
]
This includes the entire JSON for the associated poll whereas just the id
for it could have been just as good if not better.
Let's say that the desired response is:
[
{
"id": 2,
"votes": 0,
"poll": 5,
"choice": "A lot!"
}
]
Here's how you would edit the handler to achieve that:
from piston.handler import BaseHandler
from polls.models import Poll, Choice
class ChoiceHandler( BaseHandler ):
allowed_methods = ('GET',)
model = Choice
# edit the values in fields to change what is in the response JSON
fields = ('id', 'votes', 'poll', 'choice') # Add id to response fields
# if you do not add 'id' here, the desired response will not contain it
# even if you have defined the classmethod 'id' below
# customize the response JSON for the poll field to be the id
# instead of the complete JSON for the poll object
@classmethod
def poll(cls, model):
if model.poll:
return model.poll.id
else:
return None
# define what id is in the response
# this is just for descriptive purposes,
# Piston has built-in id support which is used when you add it to 'fields'
@classmethod
def id(cls, model):
return model.id
def read( self, request, id=None ):
if id:
try:
return Choice.objects.get(id=id)
except Choice.DoesNotExist, e:
return {}
else:
return Choice.objects.all()
Django comes with a serialization library. You'll also need a json library to get it into the format you want
http://docs.djangoproject.com/en/dev/topics/serialization/
from django.core import serializers
import simplejson
class CarHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
model = Car
fields = ('name', 'color',)
def read(self, request, car_id):
return simplejson.dumps( serializers.serialize("json", Car.get(pk=car_id) )
精彩评论