[GH-ISSUE #40] running multiple sandman2 apps under a single wsgi #25

Open
opened 2026-02-26 01:32:56 +03:00 by kerem · 4 comments
Owner

Originally created by @thatcher on GitHub (Aug 3, 2016).
Original GitHub issue: https://github.com/jeffknupp/sandman2/issues/40

Hi Jeff. We have many legacy databases we are trying to do some data extraction on. We initially set up our approach using a single db/wsgi.py which does something like:

import os
import sys

app_dir = os.path.abspath(os.path.dirname(__file__))
project_dir = os.path.abspath(os.path.join(app_dir, '..' ))

activate_this = "%s/_env/bin/activate_this.py" % app_dir
execfile(activate_this, dict(__file__=activate_this))
sys.path.insert(0, project_dir)

from werkzeug.wsgi import DispatcherMiddleware

from foo import app as foo_app
from foo.services.goop import app as goop _db
from foo.services.blah import app as blah_db

application = DispatcherMiddleware(foo_app, {
    '/goop ': goop_db,
    '/blah ': blah_db
})

in foo/services/goop.py and foo/services/blah.py we have

app = sandman2.get_app(
    driver_uri, #driver_uri unique to each file
    read_only=True
)

where the idea is we can hit paths like:

  • /foo/ -> general stuff for our project
  • /foo/goop/admin/ -> sandman2 admin for goop database
  • /foo/blah/admin/ -> sandman2 admin for blah database

The problem is we see the table for both databases in both admin panels! And we get a lot of errors like:
SAWarning: This declarative base already contains a class with the same class name and module name...

The gist appears to be that there can only be one call to sandman2.get_app per wsgi as there is some class level state being set/stored and thus duplicating the information across the admin pages.

Thoughts? Is there just a better way we are missing or does it boil down to a separate wsgi per database?

Thanks!
Thatcher

Originally created by @thatcher on GitHub (Aug 3, 2016). Original GitHub issue: https://github.com/jeffknupp/sandman2/issues/40 Hi Jeff. We have many legacy databases we are trying to do some data extraction on. We initially set up our approach using a single db/wsgi.py which does something like: ``` python import os import sys app_dir = os.path.abspath(os.path.dirname(__file__)) project_dir = os.path.abspath(os.path.join(app_dir, '..' )) activate_this = "%s/_env/bin/activate_this.py" % app_dir execfile(activate_this, dict(__file__=activate_this)) sys.path.insert(0, project_dir) from werkzeug.wsgi import DispatcherMiddleware from foo import app as foo_app from foo.services.goop import app as goop _db from foo.services.blah import app as blah_db application = DispatcherMiddleware(foo_app, { '/goop ': goop_db, '/blah ': blah_db }) ``` in `foo/services/goop.py` and `foo/services/blah.py` we have ``` python app = sandman2.get_app( driver_uri, #driver_uri unique to each file read_only=True ) ``` where the idea is we can hit paths like: - `/foo/` -> general stuff for our project - `/foo/goop/admin/` -> sandman2 admin for goop database - `/foo/blah/admin/` -> sandman2 admin for blah database The problem is we see the table for both databases in both admin panels! And we get a lot of errors like: `SAWarning: This declarative base already contains a class with the same class name and module name...` The gist appears to be that there can only be one call to sandman2.get_app per wsgi as there is some class level state being set/stored and thus duplicating the information across the admin pages. Thoughts? Is there just a better way we are missing or does it boil down to a separate wsgi per database? Thanks! Thatcher
Author
Owner

@jeffknupp commented on GitHub (Aug 3, 2016):

This can be done, but I need to see how much refactoring is necessary. In the meantime, you're free to use a separate wsgi server per database and all will work as expected (though I realize that's not ideal).

<!-- gh-comment-id:237344292 --> @jeffknupp commented on GitHub (Aug 3, 2016): This can be done, but I need to see how much refactoring is necessary. In the meantime, you're free to use a separate wsgi server per database and all will work as expected (though I realize that's not ideal).
Author
Owner

@thatcher commented on GitHub (Aug 5, 2016):

Thanks Jeff. Appreciated.

<!-- gh-comment-id:237872710 --> @thatcher commented on GitHub (Aug 5, 2016): Thanks Jeff. Appreciated.
Author
Owner

@ptrourke commented on GitHub (Aug 5, 2016):

Jeff, thanks a lot, really appreciate you looking at this! (A colleague of @thatcher )

<!-- gh-comment-id:237962842 --> @ptrourke commented on GitHub (Aug 5, 2016): Jeff, thanks a lot, really appreciate you looking at this! (A colleague of @thatcher )
Author
Owner

@Carelvd commented on GitHub (Nov 5, 2019):

The Flask-Admin instance retains some internal state when it is initiated, in some cases when running the unit tests and instantiating Flask-Admin outside of the application factory I have encountered an error claiming I have registered duplicate views. (I had a link somewhere to the Flask-Admin issue tracker that explained this but can't find it now.)

The Flask-SQLAlchemy instance use the "DATABASE_URL" value set upon the application. This is read whenever one invokes it directly SQLALchemy(app) or initiates an instance, data=SQLAlchemy(), later on database.init(app). My understanding is that flask supports multiple database connections through binds, but I have not used this personally. Perhaps setting this might allow you to map multiple databases in one instance but I think the Flask-Admin issue might still bite you.

<!-- gh-comment-id:550038135 --> @Carelvd commented on GitHub (Nov 5, 2019): The Flask-Admin instance retains some internal state when it is initiated, in some cases when running the unit tests and instantiating Flask-Admin outside of the application factory I have encountered an error claiming I have registered duplicate views. (I had a link somewhere to the Flask-Admin issue tracker that explained this but can't find it now.) The Flask-SQLAlchemy instance use the "DATABASE_URL" value set upon the application. This is read whenever one invokes it directly ``SQLALchemy(app)`` or initiates an instance, ``data=SQLAlchemy()``, later on ``database.init(app)``. My understanding is that flask supports multiple database connections through [binds](https://flask-sqlalchemy.palletsprojects.com/en/2.x/binds/), but I have not used this personally. Perhaps setting this might allow you to map multiple databases in one instance but I think the Flask-Admin issue might still bite you.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/sandman2-jeffknupp#25
No description provided.