Billy Fung

SQLAlchemy and Flask-admin

Billy Fung / 2016-08-08


Using SQLAlchemy and Flask-admin

In my project, we have a data driven application, with a heavy focus on the database portion. The application is such that the data required comes from the government, so the database is populated with information from the government and needs to be routinely updated. Apart from just cron jobs to populate the database, there is also functionality to insert into certain tables from a Flask application. The architecture of the application consists of a PostgreSQL database and a Python program consisted of parsing scripts that handle the ingestion of the data from the government. This forms the backend, which has python workflows that create scheduled reports from the database.

Flask admin comes into play here for certain tables because we have customer information also within the same database, which sometimes needs to be updated. Using the SQLAlchemy automap feature, we are able to create models of certain tables from the database, and then we can use Flask-admin to create a web interface that allows the admin to update customers. Automap base handles the creation of a Python object that properly does the foreign key relationships of every table. This means that I can create an object that has a foreign key linkage, and when I commit that object into the PostgreSQL database, the ORM inserts into all the required tables for you.

    from sqlalchemy import create_engine, MetaData
    from sqlalchemy.ext.automap import automap_base
    from app import app
    
    DBNAME_engine = create_engine(app.config['DB_URI'], echo=True)
    
    metadata = MetaData()
    CHOSEN_TABLES = [
                'customer',
                'customer_meter_detail',
                'registry',
                'address',
                'contact',
                'customer_bank_detail',
    ]
    metadata.reflect(DBNAME_engine, only=CHOSEN_TABLES)
    
    Base = automap_base(metadata=metadata)
    Base.prepare()
    
    Customer = Base.classes.customer
    Registry = Base.classes.registry
    CustomerMeter = Base.classes.customer_meter_detail
    Address = Base.classes.address
    Contact = Base.classes.contact
    CustomerBankDetail = Base.classes.customer_bank_detail

This differs from the usual usage of a web application where the database is only ever handled as a single entity, so there is no need to hide some of the tables from the rest of the domain. Since SQLAlchemy already has an object created for each of the required tables, we can use these objects in Flask- admin by extending the ModelView class.

    from flask.ext.admin.contrib.sqla import ModelView
    from flask.ext.admin import Admin
    
    admin = Admin(app, name='Editing Customer Info')
    admin.add_view(CustomerAdminView(Customer, session))
    admin.add_view(ContactAdminView(Contact, session))
    admin.add_view(AddressAdminView(Address, session))

Doing so, you now have an easy admin access for those selected tables.