Piston自定义响应表示
我正在使用piston框架,想要自定义我的响应格式。
我的数据模型大概是这样的:
class Car(db.Model):
name = models.CharField(max_length=256)
color = models.CharField(max_length=256)
现在,当我向类似于/api/cars/1/的地址发送GET请求时,我希望得到这样的响应:
{'name' : 'BMW', 'color' : 'Blue',
'link' : {'self' : '/api/cars/1'}
}
但是piston只输出了这个:
{'name' : 'BMW', 'color' : 'Blue'}
换句话说,我想要自定义某个特定资源的表现形式。
我现在的piston资源处理器看起来是这样的:
class CarHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
model = Car
fields = ('name', 'color',)
def read(self, request, car_id):
return Car.get(pk=car_id)
所以我不太明白在哪里可以自定义数据。除非我需要重写JSON发射器,但这听起来有点复杂。
3 个回答
-2
Django自带了一个序列化库。你还需要一个json库来把数据转换成你想要的格式。
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) )
1
这个问题已经被问了两年,所以对提问者来说已经有点晚了。不过对于其他和我有类似困扰的人来说,有一种Pistonic的方法可以解决这个问题。
以Django的投票和选项示例为例——
你会注意到,对于ChoiceHandler,返回的JSON数据是:
[
{
"votes": 0,
"poll": {
"pub_date": "2011-04-23",
"question": "Do you like Icecream?",
"polling_ended": false
},
"choice": "A lot!"
}
]
这个数据包含了与投票相关的所有JSON信息,而实际上只返回它的id
就足够了,甚至可能更好。
假设我们想要的返回结果是:
[
{
"id": 2,
"votes": 0,
"poll": 5,
"choice": "A lot!"
}
]
下面是你如何修改处理程序来实现这个目标:
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()
6
你可以通过返回一个Python字典来返回自定义格式的数据。下面是我在一个应用中的例子。希望这对你有帮助。
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}