Foreign key helpers

dependent_objects

sqlalchemy_utils.functions.dependent_objects(obj, foreign_keys=None)[source]

Return a QueryChain that iterates through all dependent objects for given SQLAlchemy object.

Consider a User object is referenced in various articles and also in various orders. Getting all these dependent objects is as easy as:

from sqlalchemy_utils import dependent_objects


dependent_objects(user)

If you expect an object to have lots of dependent_objects it might be good to limit the results:

dependent_objects(user).limit(5)

The common use case is checking for all restrict dependent objects before deleting parent object and inform the user if there are dependent objects with ondelete=’RESTRICT’ foreign keys. If this kind of checking is not used it will lead to nasty IntegrityErrors being raised.

In the following example we delete given user if it doesn’t have any foreign key restricted dependent objects:

from sqlalchemy_utils import get_referencing_foreign_keys


user = session.query(User).get(some_user_id)


deps = list(
    dependent_objects(
        user,
        (
            fk for fk in get_referencing_foreign_keys(User)
            # On most databases RESTRICT is the default mode hence we
            # check for None values also
            if fk.ondelete == 'RESTRICT' or fk.ondelete is None
        )
    ).limit(5)
)

if deps:
    # Do something to inform the user
    pass
else:
    session.delete(user)
Parameters:
  • obj – SQLAlchemy declarative model object
  • foreign_keys – A sequence of foreign keys to use for searching the dependent_objects for given object. By default this is None, indicating that all foreign keys referencing the object will be used.

Note

This function does not support exotic mappers that use multiple tables

get_referencing_foreign_keys

sqlalchemy_utils.functions.get_referencing_foreign_keys(mixed)[source]

Returns referencing foreign keys for given Table object or declarative class.

Parameters:mixed – SA Table object or SA declarative class
get_referencing_foreign_keys(User)  # set([ForeignKey('user.id')])

get_referencing_foreign_keys(User.__table__)

This function also understands inheritance. This means it returns all foreign keys that reference any table in the class inheritance tree.

Let’s say you have three classes which use joined table inheritance, namely TextItem, Article and BlogPost with Article and BlogPost inheriting TextItem.

# This will check all foreign keys that reference either article table
# or textitem table.
get_referencing_foreign_keys(Article)

See also

get_tables()

group_foreign_keys

sqlalchemy_utils.functions.group_foreign_keys(foreign_keys)[source]

Return a groupby iterator that groups given foreign keys by table.

Parameters:foreign_keys – a sequence of foreign keys
foreign_keys = get_referencing_foreign_keys(User)

for table, fks in group_foreign_keys(foreign_keys):
    # do something
    pass

is_indexed_foreign_key

merge_references

sqlalchemy_utils.functions.merge_references(from_, to, foreign_keys=None)[source]

Merge the references of an entity into another entity.

Consider the following models:

class User(self.Base):
    __tablename__ = 'user'
    id = sa.Column(sa.Integer, primary_key=True)
    name = sa.Column(sa.String(255))

    def __repr__(self):
        return 'User(name=%r)' % self.name

class BlogPost(self.Base):
    __tablename__ = 'blog_post'
    id = sa.Column(sa.Integer, primary_key=True)
    title = sa.Column(sa.String(255))
    author_id = sa.Column(sa.Integer, sa.ForeignKey('user.id'))

    author = sa.orm.relationship(User)

Now lets add some data:

john = self.User(name='John')
jack = self.User(name='Jack')
post = self.BlogPost(title='Some title', author=john)
post2 = self.BlogPost(title='Other title', author=jack)
self.session.add_all([
    john,
    jack,
    post,
    post2
])
self.session.commit()

If we wanted to merge all John’s references to Jack it would be as easy as

merge_references(john, jack)
self.session.commit()

post.author     # User(name='Jack')
post2.author    # User(name='Jack')
Parameters:
  • from – an entity to merge into another entity
  • to – an entity to merge another entity into
  • foreign_keys – A sequence of foreign keys. By default this is None indicating all referencing foreign keys should be used.

non_indexed_foreign_keys

sqlalchemy_utils.functions.non_indexed_foreign_keys(metadata, engine=None)[source]

Finds all non indexed foreign keys from all tables of given MetaData.

Very useful for optimizing postgresql database and finding out which foreign keys need indexes.

Parameters:metadata – MetaData object to inspect tables from