I am quite new to Flask and Postgres, so hopefully my explanation and code make sense.
I am trying to run a postgres docker container for the test with some test data loaded into it. I need to use Flask-Migrate and Flask-Fixtures in one function.
Flask-Migrate for upgrading the database with table names, schemas, relations and etc.
Flask-Fixtures for loading test data into the tables from yaml file.
When I use postgres db with pre-created tables (migrations, schemas etc) and try to load the data with flask_fixtures everything works properly, all the data is loaded into the tables (code below).
def _load_db_fixtures(self, input_db_fixture_path, db_migrations_directory):
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://test:test@postgres:5432/test"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
db.metadata.reflect(bind=db.engine)
def _reload_fixture(fixture_file):
"""Reload fixtures."""
import flask_fixtures
import yaml
from yaml import SafeLoader
meta = db.metadata
session = db.session
with session.begin(nested=True), open(fixture_file, mode='r') as fp:
flask_fixtures.load_fixtures(db, yaml.load(fp, SafeLoader))
return "Reloaded"
_reload_fixture(input_db_fixture_path)
However, my goal is to use empty postgres container so I need to use flask_migrate to upgrade migrations (migrations directory already exists in the application, with alembic file and etc). So the problem is that flask_fixtures stops working properly when I add flask_migrate commands. Giving an integrity error with null value insertion attempt (code below)****.
sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) null value in column "id" of relation "accounts" violates not-null
def _load_db_fixtures(self, input_db_fixture_path, db_migrations_directory):
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://test:test@postgres:5432/test"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
db.metadata.reflect(bind=db.engine)
migrate = Migrate(app, db)
with app.app_context():
flask_migrate.upgrade(directory = db_migrations_directory)
def _reload_fixture(fixture_file):
"""Reload fixtures."""
import flask_fixtures
import yaml
from yaml import SafeLoader
meta = db.metadata
session = db.session
with session.begin(nested=True), open(fixture_file, mode='r') as fp:
flask_fixtures.load_fixtures(db, yaml.load(fp, SafeLoader))
return "Reloaded"
_reload_fixture(input_db_fixture_path)
I have noticed that the load_fixture (loading data into the tables) works fine again if I run the code second time (after migration part is done and loading data raises an error) with flask_migrate part commented
# migrate = Migrate(app, db)
# with app.app_context():
# flask_migrate.upgrade(directory = db_migrations_directory)
So I guess the problem is with Migrate(app, db) part, somehow making db unavailable for the loading.
Please give me a shout if you see an obvious issue and if you have any suggestion how to make my code cleaner, cause I am pretty sure I am doing some extra stuff