Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backref uselist=False support #21

Open
mentat-enki opened this issue May 28, 2015 · 0 comments
Open

backref uselist=False support #21

mentat-enki opened this issue May 28, 2015 · 0 comments

Comments

@mentat-enki
Copy link

Presently, attempting to use ModelSchema to model a SQLAlchemy model that contains a relationship that employs a one-to-one relationship, that is, they take advantage of the backref()'s uselist=False argument, results in an TypeError when attempting to serialize the relationship.

e.g. given something like… (note, this is pseudocode-y)

class Child(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))

class Parent(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
        child_id = db.Column(db.Integer, db.ForeignKey('child.id'))

    only_child = db.relationship('Child', backref=db.backref('father', uselist=False))


class ChildSchema(ma.ModelSchema):
    class Meta:
        model = Child

class ParentSchema(ma.ModelSchema):
    class Meta:
        model = Parent

…performing a dump on a record is where the "fun starts"…

child = child.get_or_404(1)
child_schema = ChildSchema()
child_schema.dump(child).data

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-2a42b0948473> in <module>()
      1 # hagbard = registrants.get_or_404(2)
----> 2 registrant_schema.dump(hagbard).data

/env/lib/python2.7/site-packages/marshmallow/schema.pyc in dump(self, obj, many, update_fields, **kwargs)
    562             dict_class=self.dict_class,
    563             index_errors=self.opts.index_errors,
--> 564             **kwargs
    565         )
    566         result = self._postprocess(preresult, many, obj=obj)

/env/lib/python2.7/site-packages/marshmallow/marshalling.pyc in serialize(self, obj, fields_dict, many, strict, skip_missing, accessor, dict_class, index_errors, index)
    135                 field_name=key,
    136                 field_obj=field_obj,
--> 137                 index=(index if index_errors else None)
    138             )
    139             skip_conds = (

/env/lib/python2.7/site-packages/marshmallow/marshalling.pyc in call_and_store(self, getter_func, data, field_name, field_obj, index)
     54         """
     55         try:
---> 56             value = getter_func(data)
     57         except ValidationError as err:  # Store validation errors
     58             self.error_fields.append(field_obj)

/env/lib/python2.7/site-packages/marshmallow/marshalling.pyc in <lambda>(d)
    129         for attr_name, field_obj in iteritems(fields_dict):
    130             key = ''.join([self.prefix, attr_name])
--> 131             getter = lambda d: field_obj.serialize(attr_name, d, accessor=accessor)
    132             value = self.call_and_store(
    133                 getter_func=getter,

/env/lib/python2.7/site-packages/marshmallow/fields.py in serialize(self, attr, obj, accessor)
    219                 else:
    220                     return self.default
--> 221         return self._serialize(value, attr, obj)
    222 
    223     def deserialize(self, value):

/env/lib/python2.7/site-packages/marshmallow/fields.py in _serialize(self, value, attr, obj)
   1215         # else:
   1216         #     items = []
-> 1217         items = [self.keygetter(v) for v in value]
   1218 
   1219         if not items:

TypeError: 'NoneType' object is not iterable

However, changing the Parent model's relationship to be only_child = db.relationship('Child', backref='father') fixes the issue.

I suspect this is because with the uselist=False, "relationship-oriented" attributes are no longer lists (even empty ones) but are rather simply None values. I tried putting in some guards to prevent the issue if value were None (there on line 1217 where it's blowing up) but simply referencing the value variable seemed to raise the error, e.g. even a if value is not None: caused the same TypeError.

I'd be really nice if this were supported, as this is the canonical way to represent 1:1 relationships AFAIK. Many kudos to you for an already great library, and thanks for your hard work!

(Also, while I realize this issue is coming up in marshmallow "proper", and might not be your purview, it seems to be a SQLAlchemy related issue and figured it would belong best here than under the vanilla marshmallow project's issues. If this is in error, I'm happy to open this issue there or elsewhere!)

q.v.: http://docs.sqlalchemy.org/en/rel_1_0/orm/basic_relationships.html#one-to-one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant