Fix dependent_objects
when using single table inheritance
This commit is contained in:
@@ -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:
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user