Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need a way to get python object from marshmallow load function instead of dictionary without using post_load decorator

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)

In the above schema I am using post_load to convert the dict to an object. Is there anyway to get this without using the post_load decorator?

like image 693
bhaskara indupriya Avatar asked Apr 05 '17 13:04

bhaskara indupriya


1 Answers

If I understand you correctly, it's not the post_load decorator you have an issue with it's the redundancy of maintaining two object definitions. If that's the case, you can use namedtuple or dataclasses to achieve what you want. You would still define a post_load method on your schema but would not longer have to maintain a second class definition.

namedtuple solution

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

dataclasses solution

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)
like image 90
infosmith Avatar answered Oct 16 '22 15:10

infosmith