stefanofontanelli / ColanderAlchemy

ColanderAlchemy helps you autogenerating Colander schemas based on SQLAlchemy mapped objects.
Other
63 stars 33 forks source link

non-inline-serialization #88

Closed dpwrussell closed 8 years ago

dpwrussell commented 8 years ago

Hi,

I am attempting to serialize an object that has a backref to a list (potentially zero, one or many).


class Person(Base):
    __tablename__ = 'person'

    id = Column(Integer, primary_key=True)
    name = Column(String(128))
    surname = Column(String(128))

class Score(Base):
    __tablename__ = 'score'

    id = Column(Integer, primary_key=True)
    person_id = Column(Integer, ForeignKey('person.id'))
    person = relationship('Person', backref='scores')
    value = Column(Integer)

This will serialize Person like so:

{'id': '1',
 'name': u'Jayne',
 'scores': [{'id': '1', 'person_id': '1', 'value': '1000'},
            {'id': '2', 'person_id': '1', 'value': '2000'}],
 'surname': u'Cobb'}

I've tried to find a way to change this serialization to something like this:

{'id': '1',
 'name': u'Jayne',
 'scores': ['1', '2'],
 'surname': u'Cobb'}

I don't seem to be able to. It doesn't seem to be possible to change the typ of a relationship with the info dictionary.

Obviously it is possible to add this:

    __colanderalchemy_config__ = {
        'excludes': ['person_id', 'person', 'value']
    }

to reduce the serialization of person to this:

{'id': '1',
 'name': u'Jayne',
 'scores': [{'id': '1'}, {'id': '2'}],
 'surname': u'Cobb'}

which is a bit better, but not great. However, when I then want to serialize score specifically, it does not include those excluded fields either.

I have create a working example in this gist: https://gist.github.com/dpwrussell/7a72fee067a40f4dca97

Is this impossible?

Cheers

tisdall commented 8 years ago

I think excluding everything but the id on Score is probably the best you can do. If you add the exclusion directly to the Score object, though, you have the issue you've described. You can, however, pass exclusion information to SQLAlchemySchemaNode() if you call it manually and then restrict the exclusion to just when you want the schema for Person. I'm not exactly sure how you exclude child elements, though (or even if it's possible). Perhaps it's possible with the overrides argument.

The other possibility is to just manually edit the schema afterwards. You can replace the scores node with a SequenceSchema and then get exactly what you'd like. The objectify() and dictify() methods in ColanderAlchemy won't work any more, though.

dpwrussell commented 8 years ago

Thanks, I think that answers this.

tisdall commented 8 years ago

Which solution did you use?

dpwrussell commented 8 years ago

@tisdall I actually switched to using MarshmallowSqlalchemy as (a couple of bugs aside that I've now fixed and contributed) that more closely met my requirements.

Thanks

tisdall commented 8 years ago

@dpwrussell - Marshmallow looks pretty good. Are you using it with deform or is this unrelated to html forms?

dpwrussell commented 8 years ago

@tisdall It is not related to deform at this time, but we may need that later. Right now I just want a way of validating data before submitting it to our database. This also is likely to output a reasonable targeted error message when the data is not valid, helping our data curator streamline his process.