Skip to content

Convention Configuration

Overview

But there is also a better way to go, which is to make use of a feature new in SQLAlchemy 0.9.2 which makes use of the events behind the scenes known as naming_convention. Here, we can create a new MetaData object while passing a dictionary referring to a naming scheme:

convention = {
  "ix": "ix_%(column_0_label)s",
  "uq": "uq_%(table_name)s_%(column_0_name)s",
  "ck": "ck_%(table_name)s_%(constraint_name)s",
  "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
  "pk": "pk_%(table_name)s"
}

metadata = MetaData(naming_convention=convention)

If we define our models using a MetaData as above, the given naming convention dictionary will be used to provide names for all constraints and indexes.

References

See also Configuring Constraint Naming Conventions - SQLAlchemy overview of naming convention support https://alembic.sqlalchemy.org/en/latest/naming.html

ORM Config Metadata Convention

Overview

How to implement in ORM engine

Based on the design, the ORM class has various components thoughts

It also accepts a series of string-codes as alternative keys, "fk" for foreign key "pk" for primary key "ix" for index "ck" for check "uq" for unique constraint

Configuring a Naming Convention for a MetaData Collection MetaData.naming_convention refers to a dictionary which accepts the Index class or individual Constraint classes as keys, and Python string templates as values. It also accepts a series of string-codes as alternative keys, "fk", "pk", "ix", "ck", "uq" for foreign key, primary key, index, check, and unique constraint, respectively. The string templates in this dictionary are used whenever a constraint or index is associated with this MetaData object that does not have an existing name given (including one exception case where an existing name can be further embellished).

An example naming convention that suits basic cases is as follows:

convention = {
    "ix": "ix_%(column_0_label)s",
    "uq": "uq_%(table_name)s_%(column_0_name)s",
    "ck": "ck_%(table_name)s_%(constraint_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s",
}

metadata_obj = MetaData(naming_convention=convention)

and we can config the element based on the scripts, they call custom-token

import uuid


def fk_guid(constraint, table):
    str_tokens = (
        [
            table.name,
        ]
        + [element.parent.name for element in constraint.elements]
        + [element.target_fullname for element in constraint.elements]
    )
    guid = uuid.uuid5(uuid.NAMESPACE_OID, "_".join(str_tokens).encode("ascii"))
    return str(guid)


convention = {
    "fk_guid": fk_guid,
    "ix": "ix_%(column_0_label)s",
    "fk": "fk_%(fk_guid)s",
}

Naming CHECK Constraints The CheckConstraint object is configured against an arbitrary SQL expression, which can have any number of columns present, and additionally is often configured using a raw SQL string. Therefore a common convention to use with CheckConstraint is one where we expect the object to have a name already, and we then enhance it with other convention elements. A typical convention is "ck*%(table_name)s*%(constraint_name)s":

metadata*obj = MetaData( naming_convention={"ck": "ck*%(table*name)s*%(constraint_name)s"} )

Table( "foo", metadata_obj, Column("value", Integer), CheckConstraint("value > 5", name="value_gt_5"), )

Very well document at https://docs.sqlalchemy.org/en/20/core/constraints.html

For the list of conventions

https://docs.sqlalchemy.org/en/20/core/metadata.html#sqlalchemy.schema.MetaData.params.naming_convention

The built-in names are as follows, some of which may only be available for certain types of constraint:

%(table_name)s - the name of the Table object associated with the constraint.

%(referred_table_name)s - the name of the Table object associated with the referencing target of a ForeignKeyConstraint.

%(column_0_name)s - the name of the Column at index position "0" within the constraint.

%(column_0N_name)s - the name of all Column objects in order within the constraint, joined without a separator.

%(column_0_N_name)s - the name of all Column objects in order within the constraint, joined with an underscore as a separator.

%(column_0_label)s, %(column_0N_label)s, %(column_0_N_label)s - the label of either the zeroth Column or all Columns, separated with or without an underscore

%(column_0_key)s, %(column_0N_key)s, %(column_0_N_key)s - the key of either the zeroth Column or all Columns, separated with or without an underscore

%(referred_column_0_name)s, %(referred_column_0N_name)s %(referred_column_0_N_name)s, %(referred_column_0_key)s, %(referred_column_0N_key)s, … column tokens which render the names/keys/labels of columns that are referenced by a ForeignKeyConstraint.

%(constraint_name)s - a special key that refers to the existing name given to the constraint. When this key is present, the Constraint object’s existing name will be replaced with one that is composed from template string that uses this token. When this token is present, it is required that the Constraint is given an explicit name ahead of time.

user-defined: any additional token may be implemented by passing it along with a fn(constraint, table) callable to the naming_convention dictionary.

Reference