带原始Dict的flask-restplus字段.Nested()(不是模型) - python

剧透警报:我发布了我的解决方案作为对此问题的解答

我正在使用flastk-resptlus创建API。我必须以特定的结构提供数据,但要解决这个问题,请参见下面的示例:

我需要得到的是这种结构:

{
    "metadata": {
        "files": [] 
    },
    "result" : {
        "data": [
                {
                 "user_id": 1,
                  "user_name": "user_1",
                  "user_role": "editor"
                },
                {
                  "user_id": 2
                  "user_name": "user_2",
                  "user_role": "editor"
                },
                {
                  "user_id": 3,
                  "user_name": "user_3",
                  "user_role": "curator"
                }
            ]
    }
}

但是问题来了,如果不使“数据”本身成为模型,就无法获得"result" : { "data": []}的结构。

到目前为止,我试图做的事情(没有成功)

# define metadata model
metadata_model = api.model('MetadataModel', {
          "files": fields.List(fields.String(required=False, description='')),
}
# define user model 
user_model = api.model('UserModel', {
          "user_id": fields.Integer(required=True, description=''),
          "user_name": fields.String(required=True, description=''),
          "user_role": fields.String(required=False, description='')
}

# here is where I have the problems
user_list_response =  api.model('ListUserResponse', {
            'metadata': fields.Nested(metadata_model),
            'result' :  {"data" : fields.List(fields.Nested(user_model))}
             })

无法从"data"获取“模式”的投诉(因为这不是已定义的模型),但是我不想成为新的api模型,只想添加一个名为“ data”的键。有什么建议?

我尝试并成功了,但这不是我想要的(因为我错过了“数据”):

user_list_response =  api.model('ListUserResponse', {
            'metadata': fields.Nested(metadata_model),
            'result' :  fields.List(fields.Nested(user_model))
            })

我不希望data成为模型,因为api的通用结构如下:

{
    "metadata": {
        "files": [] 
    },
    "result" : {
        "data": [
                <list of objects> # here must be listed the single model
            ]
    }
}

然后,<list of objects>可以是用户,地址,工作等。.因此,我想创建一个“通用结构”,然后在其中可以注入特定的模型(UserModel,AddressModel,JobModel等),而无需创建特殊的每个模型。

参考方案

我的解决方法可以解决我所有的问题:

我创建一个新的List字段类(主要是从fields.List复制),然后仅调整输出格式和架构,以获取“数据”作为键:

class ListData(fields.Raw):
    '''
    Field for marshalling lists of other fields.

    See :ref:`list-field` for more information.

    :param cls_or_instance: The field type the list will contain.

    This is a modified version of fields.List Class in order to get 'data' as key envelope
    '''
    def __init__(self, cls_or_instance, **kwargs):
        self.min_items = kwargs.pop('min_items', None)
        self.max_items = kwargs.pop('max_items', None)
        self.unique = kwargs.pop('unique', None)
        super(ListData, self).__init__(**kwargs)
        error_msg = 'The type of the list elements must be a subclass of fields.Raw'
        if isinstance(cls_or_instance, type):
            if not issubclass(cls_or_instance, fields.Raw):
                raise MarshallingError(error_msg)
            self.container = cls_or_instance()
        else:
            if not isinstance(cls_or_instance, fields.Raw):
                raise MarshallingError(error_msg)
            self.container = cls_or_instance
    def format(self, value):

        if isinstance(value, set):
            value = list(value)

        is_nested = isinstance(self.container, fields.Nested) or type(self.container) is fields.Raw

        def is_attr(val):
            return self.container.attribute and hasattr(val, self.container.attribute)

        # Put 'data' as key before the list, and return the dict
        return {'data': [
            self.container.output(idx,
                val if (isinstance(val, dict) or is_attr(val)) and not is_nested else value)
            for idx, val in enumerate(value)
        ]}

    def output(self, key, data, ordered=False, **kwargs):
        value = fields.get_value(key if self.attribute is None else self.attribute, data)
        if fields.is_indexable_but_not_string(value) and not isinstance(value, dict):
            return self.format(value)

        if value is None:
            return self._v('default')
        return [marshal(value, self.container.nested)]

    def schema(self):
        schema = super(ListData, self).schema()
        schema.update(minItems=self._v('min_items'),
                      maxItems=self._v('max_items'),
                      uniqueItems=self._v('unique'))

        # work around to get the documentation as I want
        schema['type'] = 'object'
        schema['properties'] = {}
        schema['properties']['data'] = {}
        schema['properties']['data']['type'] = 'array'
        schema['properties']['data']['items'] = self.container.__schema__

        return schema

在返回'Response'(Python)中传递多个参数 - python

我在Angular工作,正在使用Http请求和响应。是否可以在“响应”中发送多个参数。角度文件:this.http.get("api/agent/applicationaware").subscribe((data:any)... python文件:def get(request): ... return Response(seriali…

Python exchangelib在子文件夹中读取邮件 - python

我想从Outlook邮箱的子文件夹中读取邮件。Inbox ├──myfolder 我可以使用account.inbox.all()阅读收件箱,但我想阅读myfolder中的邮件我尝试了此页面folder部分中的内容,但无法正确完成https://pypi.python.org/pypi/exchangelib/ 参考方案 您需要首先掌握Folder的myfo…

R'relaimpo'软件包的Python端口 - python

我需要计算Lindeman-Merenda-Gold(LMG)分数,以进行回归分析。我发现R语言的relaimpo包下有该文件。不幸的是,我对R没有任何经验。我检查了互联网,但找不到。这个程序包有python端口吗?如果不存在,是否可以通过python使用该包? python参考方案 最近,我遇到了pingouin库。

如何用'-'解析字符串到节点js本地脚本? - python

我正在使用本地节点js脚本来处理字符串。我陷入了将'-'字符串解析为本地节点js脚本的问题。render.js:#! /usr/bin/env -S node -r esm let argv = require('yargs') .usage('$0 [string]') .argv; console.log(argv…

TypeError:'str'对象不支持项目分配,带有json文件的python - python

以下是我的代码import json with open('johns.json', 'r') as q: l = q.read() data = json.loads(l) data['john'] = '{}' data['john']['use…