cuducos/alchemydumps

Tables not directly mapped to a class don't get dumped.

baumatron opened this issue · 4 comments

If, for example, your database contains an association table for a many-to-many mapping as described here: http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html#many-to-many, the many-to-many association table doesn't get dumped by alchemy dumps. This seems to be because the base declarative class's subclasses are the only things enumerated when creating dumps, which will result in missing other data. Some other examples of usages that alchemydumps doesn't support can be found here: http://docs.sqlalchemy.org/en/latest/orm/nonstandard_mappings.html

Would it work to enumerate db.Model.metadata.tables and dump the contents that way instead?

This seems to be because the base declarative class's subclasses are the only things enumerated when creating dumps, which will result in missing other data.

That's completely true, @baumatron. You've found a huge bug.

Unfortunately, I cannot take a look on these issues this soon because things are kind of hectic here the following weeks.

However, feel free to send e PR if you want to give it a try.

Usually I follow a TDD (test-driven development) approach:

  1. Add the missing models at tests/app.py (e.g. many-to-many relationships this time)
  2. Write tests for the new models at tests/test_commands.py
  3. Fix the package ; )
  4. Add the novelties to theREADME.md

Thanks for your reply and feedback! I unfortunately am also pretty busy at the moment so I won't be able to look at this either for the time being.

For anyone who might be trying to a create many-to-many association table and need to save it with achemy dumps, I came up with a workaround for that specific case. I created a mapped class that would create a table with the same shape that I needed. That way alchemy dumps will pick it up since it will be enumerated as a subclass of db.Model.

For example:

user_to_project_table = db.Table(
    'user_to_project',
    Base.metadata,
    db.Column('user_id', db.ForeignKey('user.id'), primary_key=True),
    db.Column('project_id', db.ForeignKey('project.id'), primary_key=True)
)

Becomes something like:

class UserToProjectTable(db.Model):
    __tablename__ = 'user_to_project'
    user_id = db.Column('user_id', db.ForeignKey('user.id'), primary_key=True)
    project_id = db.Column('project_id', db.ForeignKey('project.id'), primary_key=True)

Then in your classes where you declare the relationship, the relationship's 'secondary' property can be assigned the string 'user_to_project' instead of user_to_project_table.

Many thanks again @baumatron!
I edited your last comment just to add Python color to the code bits, ok?

Perfect, thanks for making that more readable.