首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Flask-restful,marshal_with +嵌套数据

Flask-restful,marshal_with +嵌套数据
EN

Stack Overflow用户
提问于 2015-06-05 06:16:21
回答 2查看 10.8K关注 0票数 4

我已经在这个问题上坚持了一段时间了。我的问题是,我需要能够对来自POST的嵌套字段使用marshal_with和验证。我的测试如下所示:

代码语言:javascript
复制
def test_user_can_apply_with_multiple_dogs(self):

    data = {
        # User data
        'registration_type': "guest",
        'first_name': 'Alex',
        'last_name': 'Daro',
        'phone_number': '805-910-9198',
        'street': '13950 NW Passage',
        'street2': '#208',
        'city': 'Marina del Rey',
        'state': 'CA',
        'zipcode': '90292',
        'photo': 'test_image.png',
        'how_did_you_hear': 0,
        #Dog data
        'pets': [
            {
                'dog_photo': "dog.png",
                'name': 'Genghis Khan',
                'breed': 'Shih Tzu',
                'age': 'Puppy',
                'size': 'Small',
            },
            {
                'dog_photo': "dog2.png",
                'name': 'Archibald',
                'breed': 'Great Dane',
                'age': 'Adult',
                'size': 'Extra Large',
            },
        ]
    }

    resp = self.client.post('/profile/registration', data=json.dumps(data))
    self.assertEqual(resp.status_code, 200)

我的端点类看起来像这样:

代码语言:javascript
复制
nested_fields = {
    'dog_photo': fields.String,
    'name': fields.String,
    'breed': fields.String,
    'age': fields.String, 
    'size': fields.String, 
}

profile_fields = {
    # 'user_email':fields.String,
    'token': fields.String,
    'registration_type': fields.String,
    'first_name': fields.String,
    'last_name': fields.String,
    'phone_number': fields.String,
    'street': fields.String,
    'street2': fields.String,
    'city': fields.String,
    'state': fields.String,
    'zipcode': fields.Integer,
    'photo': fields.String,
    'how_did_you_hear': fields.String,
    #Dog data
    'pets': fields.Nested(nested_fields)

}
class GuestProfile(Resource):
    @marshal_with(profile_fields)
    def post(self):
        # User data
        parser = reqparse.RequestParser()
        parser.add_argument('registration_type', type=str)
        parser.add_argument('first_name', type=str, required=True, help="First Name cannot be blank.")
        parser.add_argument('last_name', type=str, required=True, help="Last Name cannot be blank.")
        parser.add_argument('phone_number', type=str, required=True, help="Phone Number cannot be blank.")
        parser.add_argument('street', type=str, required=True, help="Street cannot be blank.")
        parser.add_argument('street2', type=str)
        parser.add_argument('city', type=str, required=True, help="City cannot be blank.")
        parser.add_argument('state', type=str, required=True, help="State cannot be blank.")
        parser.add_argument('zipcode', type=str, required=True, help="Zipcode cannot be blank.")
        parser.add_argument('photo', type=str, required=True, help="Please select a photo.")
        parser.add_argument('how_did_you_hear', type=str, required=True, help="How did you hear about us cannot be "
                                                                              "blank.")
        parser.add_argument('pets', type=str)
        kwargs = parser.parse_args()
        print kwargs, "KWWW" 

kwargs的“宠物”总是以None的形式出现。有谁有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-05 13:01:41

Here's an example in the docs of how to make a custom parser type.

基本上,您定义一个函数,该函数:

  • 获取从请求中拉出的参数的原始值

如果解析或验证失败,

  • 将引发ValueError如果验证成功,
  • 将返回参数如果验证成功,
  • 将返回参数

与您的问题相关的基本示例:

代码语言:javascript
复制
def pet_list_parser(pets):
    if type(pets) != list:
        raise ValueError('Expected a list!')

    # Do your validation of the pet objects here. For example:
    for pet in pets:
        if 'name' not in pet:
            raise ValueError('Pet name is required')

        # Also do any conversion of data types here
        pet['name'] = pet['name'].capitalize()

    return pets

parser = RequestParser()
parser.add_argument('pets', type=pet_list_parser)

正如你可能猜到的,这很快就会变得古怪和恼人。Flask-RESTful中的请求解析不是为处理嵌套数据而设计的。它可以很好地处理查询字符串参数、头文件、基本JSON等,并且可以配置为处理嵌套数据。但是,如果您要经常这样做,那么可以省去一些麻烦,而是去看看像Marshmallow这样的编组库。

票数 3
EN

Stack Overflow用户

发布于 2015-06-05 09:06:49

您缺少“Content-Type”标头,也缺少here所描述的宠物参数的action='append'

我测试了上面的代码,只需添加“Content-Type”和指定的操作,它在Python2.7和3中都可以工作。

现在的问题是,由于您将宠物参数指定为type=str,因此它将返回一个字符串列表。为了获得一个字典列表,你必须编写一个自定义的解析器类型(正如@Josh正确指出的那样)。如下例所示:

例如。

代码语言:javascript
复制
def pet_parser(pet):
    # You can do other things here too as suggested in @Josh's repsonse
    return pet

在资源中:

代码语言:javascript
复制
parser.add_argument('pets', type=pet_parser, action='append')

在你的测试函数中:

代码语言:javascript
复制
headers = [('Content-Type', 'application/json')]
self.client.post('url', data=data, headers=headers)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30655146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档