Migrations
Let’s learn to perform migrations in databases.
We'll cover the following...
- Alembic
- Perform migrations using Alembic
- Set environment variable requirement
- Configure Alembic
- Autogenerate database versions
- Apply migrations
- Connect to the database
- Check the Alembic version
- Select the room table
- Retrieve data from the room table
- Data insertion and retrieval in the room table
- Test the updated code
We need a way to create tables that correspond to the objects defined in rentomatic/repository/postgres_objects.py
.
Alembic
The best strategy when we use an ORM like SQLAlchemy is to create and run migrations. For this, we can use Alembic.
Perform migrations using Alembic
First of all, let’s initialize Alembic. In the project’s main directory (where manage.py
is stored), let’s run the command below:
$ alembic init migrations
The command above creates a directory called migrations
that contains Alembic’s configuration files and the migrations that will be created in migrations/versions
. It also creates the alembic.ini
file, which contains the configuration values. The name migrations
is completely arbitrary, so we can also choose to use a different one if we prefer.
Set environment variable requirement
The specific file we need to adjust to make Alembic aware of our models and our database is migrations/env.py
.
import osfrom logging.config import fileConfigfrom sqlalchemy import engine_from_configfrom sqlalchemy import poolfrom alembic import context# this is the Alembic Config object, which provides# access to the values within the .ini file in use.config = context.configsection = config.config_ini_sectionconfig.set_section_option(section, "POSTGRES_USER", os.environ.get("POSTGRES_USER"))config.set_section_option(section, "POSTGRES_PASSWORD", os.environ.get("POSTGRES_PASSWORD"))config.set_section_option(section, "POSTGRES_HOSTNAME", os.environ.get("POSTGRES_HOSTNAME"))config.set_section_option(section, "APPLICATION_DB", os.environ.get("APPLICATION_DB"))# Interpret the config file for Python logging.# This line sets up loggers basically.fileConfig(config.config_file_name)# add your model's MetaData object here# for 'autogenerate' support# from myapp import mymodel# target_metadata = mymodel.Base.metadata# target_metadata = Nonefrom rentomatic.repository.postgres_objects import Basetarget_metadata = Base.metadata# other values from the config, defined by the needs of env.py,# can be acquired:# my_important_option = config.get_main_option("my_important_option")# ... etc.
Through config.set_section_option
, we add relevant configuration values to the main Alembic INI file section, config.config_ini_section
, extracting them from the environment variables. We also import the file that contains the SQLAlchemy objects.
Configure Alembic
We can find documentation on configuring Alembic at https://alembic.sqlalchemy.org/en/latest/api/config.html.
Once Alembic is configured, we need to change the alembic.ini
file to use the new variables as follows:
# the output encoding used when revision files# are written from script.py.mako# output_encoding = utf-8sqlalchemy.url = postgresql://%(POSTGRES_USER)s:%(POSTGRES_PASSWORD)s@%(POSTGRES_HOSTNAME)s/%(APPLICATION_DB)s[post_write_hooks]# post_write_hooks defines scripts or Python functions that are run# on newly generated revision scripts. See the documentation for further# detail and examples
The %(VARNAME)s
syntax is the basic variable interpolation used by ConfigParser
(see the ...