摘要可能会非常混乱,但我不知道如何更简洁地制定摘要。
我的模特:
class Movie(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(
imdb_data = db.relationship('IMDBData', uselist=False)
class IMDBData(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(255))
rating = db.Column(db.Float)
movie_id = db.Column(db.Integer, db.ForeignKey('movie.id'))
使用Flask-Restful字段我正在编组这样的响应:
imdb_data_fields = {
'id': fields.Integer,
'title': fields.String,
'rating': fields.Float
}
movie_fields = {
'id': fields.Integer,
'title': fields.String
}
class MovieListAPI(Resource):
def __init__(self):
self.parser = reqparse.RequestParser()
super(MovieListAPI, self).__init__()
def get(self):
self.parser.add_argument('imdb_data', type=str, location='args')
args = self.parser.parse_args()
m_fields = copy.copy(movie_fields)
# TODO: Return empty object if movie.imdb_data = None
if args['imdb_data']:
m_fields['imdb_data'] = fields.Nested(imdb_data_fields)
movies = Movie.query.all()
return {'movies': marshal(movies, m_fields)}
现在,如果电影没有相应的imdb_data
记录,即Movie.query.filter_by(id=123).first().imdb_data = None
该电影的对象被编组为:
{
"id": 1302,
"imdb_data": {
"id": 0,
"rating": null,
"title": null
},
"title": "F 63 9 Love Sickness"
}
相反,我希望响应看起来像这样:
{
"id": 1302,
"imdb_data": {},
"title": "F 63 9 Love Sickness"
}
我知道如何在返回一部电影(通过id)时破解这个:
if args['imdb_data']:
if movie.imdb_data:
m_fields['imdb_data'] = fields.Nested(imdb_data_fields)
else:
m_fields['imdb_data'] = fields.Nested({})
但是我如何为电影列表做到这一点?可能我自己可以通过阵列并手动更改它,但必须有一个更有效的方法。
答案 0 :(得分:3)
这可以通过创建自定义字段来实现,如下所示:
class NestedWithEmpty(Nested):
"""
Allows returning an empty dictionary if marshaled value is None
"""
def __init__(self, nested, allow_empty=False, **kwargs):
self.allow_empty = allow_empty
super(NestedWithEmpty, self).__init__(nested, **kwargs)
def output(self, key, obj):
value = get_value(key if self.attribute is None else self.attribute, obj)
if value is None:
if self.allow_null:
return None
elif self.allow_empty:
return {}
return marshal(value, self.nested)
然后用它来封送通过allow_empty=True
的对象:
m_fields['imdb_data'] = NestedWithEmpty(imdb_data_fields, allow_empty=True)
我甚至使用此功能创建了一个拉取请求:https://github.com/twilio/flask-restful/pull/328
答案 1 :(得分:1)
在阅读PR#328(感谢@Andriy)并关注它之后,我的修复是添加默认 arg
foo['bar'] = fields.Nested(nested_fields, default={})
在文档中并不明显。
答案 2 :(得分:0)
从0.11.0开始,可以使用选项skip_none=True
返回空对象而不是null。
@marshal_with
的示例:
from flask_restplus import Model, fields, marshal_with
model = Model('Model', {
'name': fields.String,
'address_1': fields.String,
'address_2': fields.String
})
@marshal_with(model, skip_none=True)
def get():
return {'name': 'John', 'address_1': None}
指定嵌套字段:
from flask_restplus import Model, fields
model = Model('Model', {
'name': fields.String,
'location': fields.Nested(location_model, skip_none=True)
})
来源:https://flask-restplus.readthedocs.io/en/0.11.0/marshalling.html#skip-fields-which-value-is-none