Zyg*_*lis 14 python rest json flask flask-restful
我有一个关于烧瓶宁静延伸的问题.我刚开始使用它并面临一个问题.我有flask-sqlalchemy
连接多对一关系的实体,我希望restful端点返回父实体及其所有子节点json
使用marshaller.在我的情况下,Set包含许多参数.我查看了烧瓶文件,但没有任何解释如何解决这个案例.
似乎我错过了一些明显的东西,但无法找出任何解决方案.这是我的代码:
# entities
class Set(db.Model):
id = db.Column("id", db.Integer, db.Sequence("set_id_seq"), primary_key=True)
title = db.Column("title", db.String(256))
parameters = db.relationship("Parameters", backref="set", cascade="all")
class Parameters(db.Model):
id = db.Column("id", db.Integer, db.Sequence("parameter_id_seq"), primary_key=True)
flag = db.Column("flag", db.String(256))
value = db.Column("value", db.String(256))
set_id = db.Column("set_id", db.Integer, db.ForeignKey("set.id"))
# marshallers
from flask.ext.restful import fields
parameter_marshaller = {
"flag": fields.String,
"value": fields.String
}
set_marshaller = {
'id': fields.String,
'title': fields.String,
'parameters': fields.List(fields.Nested(parameter_marshaller))
}
# endpoint
class SetApi(Resource):
@marshal_with(marshallers.set_marshaller)
def get(self, set_id):
entity = Set.query.get(set_id)
return entity
restful_api = Api(app)
restful_api.add_resource(SetApi, "/api/set/<int:set_id>")
Run Code Online (Sandbox Code Playgroud)
现在,当我打电话给/api/set/1
我得到服务器错误:
TypeError: 'Set' object is unsubscriptable
所以我需要一种方法来正确定义set_marshaller,该端点返回此json:
{
"id": : "1",
"title": "any-title",
"parameters": [
{"flag": "any-flag", "value": "any-value" },
{"flag": "any-flag", "value": "any-value" },
.....
]
}
Run Code Online (Sandbox Code Playgroud)
我感谢任何帮助.
Zyg*_*lis 22
我自己找到了解决这个问题的方法.
在玩完之后flask-restful
我发现我犯了一些错误:
首先set_marshaller
应该是这样的:
blob_marshaller = {
'id': fields.String,
'title': fields.String,
'parameters': fields.Nested(parameter_marshaller)
}
Run Code Online (Sandbox Code Playgroud)
如果参数列表和编组列表,不安分的编组可以处理大小写json
.
另一个问题是在API Set参数中有延迟加载,所以当我尝试编组我得到的时候KeyError: 'parameters'
,所以我需要显式加载这样的参数:
class SetApi(Resource):
@marshal_with(marshallers.set_marshaller)
def get(self, set_id):
entity = Set.query.get(set_id)
entity.parameters # loads parameters from db
return entity
Run Code Online (Sandbox Code Playgroud)
或者另一种选择是改变模型关系:
parameters = db.relationship("Parameters", backref="set", cascade="all" lazy="joined")
Run Code Online (Sandbox Code Playgroud)
这是一个除了Zygimantas的答案:
我正在使用Flask-RESTful,这是加载嵌套属性的解决方案.
你可以将一个callable传递给marshal装饰器:
class OrgsController(Resource):
@marshal_with(Organization.__json__())
def get(self):
return g.user.member.orgs
Run Code Online (Sandbox Code Playgroud)
然后更新模型以返回其自己的实体的资源字段.因此,嵌套实体将相对返回其实体的资源字段.
class Organization(db.Model):
id = db.Column(db.Integer, primary_key=True)
...
@staticmethod
def __json__(group=None):
_json = {
'id': fields.String,
'login': fields.String,
'description': fields.String,
'avatar_url': fields.String,
'paid': fields.Boolean,
}
if group == 'flat':
return _json
from app.models import Repository
_json['repos'] = fields.Nested(Repository.__json__('flat'))
return _json
class Repository(db.Model):
id = db.Column(db.Integer, primary_key=True)
owner_id = db.Column(db.Integer, db.ForeignKey('organization.id'))
owner = db.relationship('Organization', lazy='select', backref=db.backref('repos', lazy='select'), foreign_keys=[owner_id])
...
@staticmethod
def __json__(group=None):
_json = {
'id': fields.String,
'name': fields.String,
'updated_at': fields.DateTime(dt_format='iso8601'),
}
if group == 'flat':
return _json
from app.models import Organization
_json['owner'] = fields.Nested(Organization.__json__('flat'))
return _json
Run Code Online (Sandbox Code Playgroud)
这给出了我正在寻找的表示,并尊重延迟加载:
[
{
"avatar_url": "https://avatars.githubusercontent.com/u/18945?v=3",
"description": "lorem ipsum.",
"id": "1805",
"login": "foobar",
"paid": false,
"repos":
[
{
"id": "9813",
"name": "barbaz",
"updated_at": "2014-01-23T13:51:30"
},
{
"id": "12860",
"name": "bazbar",
"updated_at": "2015-04-17T11:06:36"
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
我喜欢
1)这种方法如何允许我为每个实体定义我的资源字段,并且它可用于整个应用程序的所有资源路径.
2)组参数如何允许我根据自己的需要自定义表示.我这里只有'平',但任何逻辑都可以编写并传递给更深层的嵌套对象.
3)实体仅在必要时加载.
归档时间: |
|
查看次数: |
11106 次 |
最近记录: |