5

摘要可能非常混乱,但我不知道如何更简洁地表述它。

我拥有的模型:

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({})

但是我如何为电影列表做到这一点?可能我可以自己遍历数组并手动更改它,但必须有更有效的方法。

4

3 回答 3

4

这可以通过创建自定义字段来实现,如下所示:

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

于 2014-11-13T06:35:26.760 回答
2

在阅读 PR #328(感谢@Andriy)并遵循它之后,我的修复是添加默认arg

foo['bar'] = fields.Nested(nested_fields, default={})

在文档中并不明显。

于 2018-04-05T09:59:21.927 回答
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

于 2020-03-16T18:08:24.030 回答