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

Flask SQLAlchemy Integration - Documentation Suggestion #143

Open
williamjulianvicary opened this issue Jul 29, 2019 · 4 comments
Open

Flask SQLAlchemy Integration - Documentation Suggestion #143

williamjulianvicary opened this issue Jul 29, 2019 · 4 comments

Comments

@williamjulianvicary
Copy link

Firstly, thank you for the great extension!!

I've ran into an error that I'm sure others will have ran into, it may be worth updating the docs with a warning about it.

Our structure was as follows:

  • Each model has it's own module
  • Each model module also contains a Schema and Manager for example UserModel, UserSchema, UserManager all defined within /models/user.py

Some background - with SQLAlchemy, with separate models, you need to import them all at runtime, before the DB is initialised to avoid circular dependancies within relationships.

When the UserSchema(ma.ModelSchema) is hit during import from app.models import * (in bootstrap) this initialises the models and attempts to execute the relationships. At this stage, we may not have a relationship requirement (which SQLAlchemy avoids using string based relationships) however as the ma.ModelSchema initialises the models it creates errors such as this:

sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class User->users, expression ‘Team’ failed to locate a name (“name ‘Team’ is not defined”). If this is a class name, consider adding this relationship() to the <class ‘app.models.user.User’> class after both dependent classes have been defined.

and, on subsequent loads:

sqlalchemy.exc.InvalidRequestError: Table ‘users_teams’ is already defined for this MetaData instance. Specify ‘extend_existing=True’ to redefine options and columns on an existing Table object.

The solution to this is to simply build the UserSchemas in a different import namespace, we've now got:

/schemas/user_schema.py
/models/user.py

And no more circular issues - hopefully this helps someone else, went around in circles (pun intended) for a few hours before I realised it was the ModelSchema causing it.

Could the docs be updated to make a point of explaining that the ModelSchema initialises the model, and therefore it's a good idea for them to be in separate import destinations?

@sloria
Copy link
Member

sloria commented Jul 30, 2019

Thank you for the suggestion and the thorough report. I agree that this needs to be documented better. It might be appropriate to document this in marshmallow-sqlalchemy then link to those docs in flask-marshmallow.

Would you be up for sending a PR?

@antgel
Copy link

antgel commented Jul 31, 2019

Slightly-related: marshmallow-code/marshmallow-sqlalchemy#192

@tarponjargon
Copy link

Thanks @williamjulianvicary your post helped me alot

@zhengshubin
Copy link

I have tried to declare models in app.init.py,and it works.
like this: app. init.py
db = SQLAlchemy()
ma=Marshmallow()

from app.resources.models import Resource,BluePrint
#from app.dsawots.models import Dsawot
from app.roles.models import Role

from app.groups.models import Group
from app.users.models import User
from app.permissions.models import Permission

from app.film.models import FilmAoiRecord

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

No branches or pull requests

5 participants