Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing constraint naming conventions in Flask-SQLAlchemy

I would like to change the standard naming conventions of constraints that are set in Flask-SQLAlchemy, to ease migrations with Alembic.

As Flask-SQLAlchemy creates the declarative base (where you can supply naming conventions) by itself I'm not sure what the best way is going about doing this. Can I change naming conventions after the declarative base is created (i.e. when I've created the Flask-SQLAlchemy object) or do I have to subclass the SQLAlchemy class? Is there a completely different way?

like image 323
haeger Avatar asked Mar 19 '15 20:03

haeger


People also ask

What is difference between Flask-SQLAlchemy and SQLAlchemy?

One of which is that Flask-SQLAlchemy has its own API. This adds complexity by having its different methods for ORM queries and models separate from the SQLAlchemy API. Another disadvantage is that Flask-SQLAlchemy makes using the database outside of a Flask context difficult.

What is SQLAlchemy track modifications?

If set to True , Flask-SQLAlchemy will track modifications of objects and emit signals. The default is None , which enables tracking but issues a warning that it will be disabled by default in the future. This requires extra memory and should be disabled if not needed.

How do I make a column unique in SQLAlchemy?

Unique constraints can be created anonymously on a single column using the unique keyword on Column . Explicitly named unique constraints and/or those with multiple columns are created via the UniqueConstraint table-level construct.

What is DB Create_all ()?

create_all() function to create the tables that are associated with your models. In this case you only have one model, which means that the function call will only create one table in your database: from app import db, Student.


2 Answers

As of Flask-SQLAlchemy 2.1 you can do the following:

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData

metadata = MetaData(
  naming_convention={
    'pk': 'pk_%(table_name)s',
    'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s',
    'ix': 'ix_%(table_name)s_%(column_0_name)s',
    'uq': 'uq_%(table_name)s_%(column_0_name)s',
    'ck': 'ck_%(table_name)s_%(constraint_name)s',
    }
)
db = SQLAlchemy(metadata=metadata)
like image 74
poindexter Avatar answered Sep 24 '22 17:09

poindexter


Version 2.1 introduced the metadata argument to the extension. If all you want to customize about the base model is the metadata, you can pass a custom MetaData instance to it.

db = SQLAlchemy(metadata=MetaData(naming_convention={
    'pk': 'pk_%(table_name)s',
    'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s',
    'ix': 'ix_%(table_name)s_%(column_0_name)s',
    'uq': 'uq_%(table_name)s_%(column_0_name)s',
    'ck': 'ck_%(table_name)s_%(constraint_name)s',
}))

Previously, you would subclass the SQLAlchemy class and override make_declarative_base. This still works, and is useful if you need to further customize the base model.

from flask_sqlalchemy import SQLAlchemy as BaseSQLAlchemy, Model, _BoundDeclarativeMeta, _QueryProperty
from sqlalchemy import MetaData

class SQLAlchemy(BaseSQLAlchemy):
    def make_declarative_base(self):
        metadata = MetaData(naming_convention={
            'pk': 'pk_%(table_name)s',
            'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s',
            'ix': 'ix_%(table_name)s_%(column_0_name)s',
            'uq': 'uq_%(table_name)s_%(column_0_name)s',
            'ck': 'ck_%(table_name)s_%(constraint_name)s',
        })
        base = declarative_base(metadata=metadata, cls=Model, name='Model', metaclass=_BoundDeclarativeMeta)
        base.query = _QueryProperty(self)
        return base
like image 40
davidism Avatar answered Sep 21 '22 17:09

davidism