Merge pull request #83 from jpvanhal/fix-dependent-objects-with-single-table-inheritance

Fix `dependent_objects` when using single table inheritance
This commit is contained in:
Konsta Vesterinen
2014-08-21 15:10:14 +03:00
2 changed files with 74 additions and 7 deletions

View File

@@ -4,6 +4,7 @@ from itertools import groupby
import six import six
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.engine import reflection from sqlalchemy.engine import reflection
from sqlalchemy.exc import NoInspectionAvailable
from sqlalchemy.orm import object_session, mapperlib from sqlalchemy.orm import object_session, mapperlib
from sqlalchemy.schema import MetaData, Table, ForeignKeyConstraint from sqlalchemy.schema import MetaData, Table, ForeignKeyConstraint
@@ -195,9 +196,7 @@ def dependent_objects(obj, foreign_keys=None):
through all dependent objects for given SQLAlchemy object. through all dependent objects for given SQLAlchemy object.
Consider a User object is referenced in various articles and also in Consider a User object is referenced in various articles and also in
various orders. Getting all these dependent objects is as easy as: various orders. Getting all these dependent objects is as easy as::
::
from sqlalchemy_utils import dependent_objects from sqlalchemy_utils import dependent_objects
@@ -219,9 +218,7 @@ def dependent_objects(obj, foreign_keys=None):
it will lead to nasty IntegrityErrors being raised. it will lead to nasty IntegrityErrors being raised.
In the following example we delete given user if it doesn't have any In the following example we delete given user if it doesn't have any
foreign key restricted dependent objects. foreign key restricted dependent objects::
::
from sqlalchemy_utils import get_referencing_foreign_keys from sqlalchemy_utils import get_referencing_foreign_keys
@@ -272,8 +269,17 @@ def dependent_objects(obj, foreign_keys=None):
classes = obj.__class__._decl_class_registry classes = obj.__class__._decl_class_registry
for table, keys in group_foreign_keys(foreign_keys): for table, keys in group_foreign_keys(foreign_keys):
keys = list(keys)
for class_ in classes.values(): for class_ in classes.values():
if hasattr(class_, '__table__') and class_.__table__ == table: try:
mapper = sa.inspect(class_)
except NoInspectionAvailable:
continue
parent_mapper = mapper.inherits
if (
table in mapper.tables and
not (parent_mapper and table in parent_mapper.tables)
):
criteria = [] criteria = []
visited_constraints = [] visited_constraints = []
for key in keys: for key in keys:

View File

@@ -153,3 +153,64 @@ class TestDependentObjectsWithCompositeKeys(TestCase):
assert len(deps) == 2 assert len(deps) == 2
assert articles[0] in deps assert articles[0] in deps
assert articles[3] in deps assert articles[3] in deps
class TestDependentObjectsWithSingleTableInheritance(TestCase):
def create_models(self):
class Category(self.Base):
__tablename__ = 'category'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
class TextItem(self.Base):
__tablename__ = 'text_item'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
category_id = sa.Column(
sa.Integer,
sa.ForeignKey(Category.id)
)
category = sa.orm.relationship(
Category,
backref=sa.orm.backref(
'articles'
)
)
type = sa.Column(sa.Unicode(255))
__mapper_args__ = {
'polymorphic_on': type,
}
class Article(TextItem):
__mapper_args__ = {
'polymorphic_identity': u'article'
}
class BlogPost(TextItem):
__mapper_args__ = {
'polymorphic_identity': u'blog_post'
}
self.Category = Category
self.TextItem = TextItem
self.Article = Article
self.BlogPost = BlogPost
def test_returns_all_dependent_objects(self):
category1 = self.Category(name=u'Category #1')
category2 = self.Category(name=u'Category #2')
articles = [
self.Article(category=category1),
self.Article(category=category1),
self.Article(category=category2),
self.Article(category=category2),
]
self.session.add_all(articles)
self.session.commit()
deps = list(dependent_objects(category1))
assert len(deps) == 2
assert articles[0] in deps
assert articles[1] in deps