需要一种方法从marshmallow加载函数而不是字典中获取python对象而不使用post_load装饰器

时间:2017-04-05 13:31:14

标签: python marshmallow

class ProfileSchema(Schema):

    id = fields.Integer()
    first_name = fields.String(required=True)
    last_name = fields.String()
    phone = fields.Str()
    email = fields.Email()
    gender = fields.String()
    city = fields.Str()
    state = fields.Str()
    country = fields.Str()
    age = fields.Int()
    id_proof = fields.Str()
    id_number = fields.Str()
    id_kyc_url = fields.Str()
    image_url = fields.Str()
    profile_type = fields.Str()
    country_code = fields.String()

    @validates('gender')
    def validate_gender(self, value):
        """
        validates gender
        :param value:
        :return:
        """
        if value not in genders:
            raise ValidationError('Incorrect gender value it should be either Male or Female')

    @post_load
    def make_profile(self, data):
        """
        make profile obj
        :param data:
        :return:
        """
        return Profile(**data)

在上面的模式中,我使用post_load将dict转换为对象。无论如何不使用post_load装饰器来获取它吗?

1 个答案:

答案 0 :(得分:1)

如果我对您的理解正确,那不是post_load装饰器,您有一个问题,那就是维护两个对象定义是多余的。在这种情况下,您可以使用namedtupledataclasses来实现所需的功能。您仍将在架构上定义post_load方法,但不再需要维护第二个类定义。

命名元组解决方案

from collections import namedtuple

def make_object(class_name, members):
    obj = namedtuple(class_name, ' '.join(members.keys()))
    for k, v in members.items():
        setattr(obj, k, v)
    return obj

数据类解决方案

from dataclasses import make_dataclass

def make_object(class_name, members):
    obj = make_dataclass(class_name, [(k, type(v)) for k,v in members.items()])
    for k, v in members.items():
        setattr(obj, k, v)
    return obj
class ProfileSchema(Schema):

    id = fields.Integer()
    first_name = fields.String(required=True)
    last_name = fields.String()
    phone = fields.Str()
    email = fields.Email()
    gender = fields.String()
    city = fields.Str()
    state = fields.Str()
    country = fields.Str()
    age = fields.Int()
    id_proof = fields.Str()
    id_number = fields.Str()
    id_kyc_url = fields.Str()
    image_url = fields.Str()
    profile_type = fields.Str()
    country_code = fields.String()

    @validates('gender')
    def validate_gender(self, value):
        """
        validates gender
        :param value:
        :return:
        """
        if value not in genders:
            raise ValidationError('Incorrect gender value it should be either Male or Female')

    @post_load
    def make_profile(self, data):
        """
        make profile obj
        :param data:
        :return:
        """
        return make_object(data)