Improve coverage and add more docs
This commit is contained in:
@@ -43,18 +43,28 @@ def dependencies(obj, foreign_keys=None):
|
||||
The common use case is checking for all 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. This can be achieved
|
||||
as follows::
|
||||
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 dependencies.
|
||||
|
||||
::
|
||||
|
||||
|
||||
from sqlalchemy_utils import get_referencing_foreign_keys
|
||||
|
||||
|
||||
user = session.query(User).get(some_user_id)
|
||||
|
||||
|
||||
deps = list(
|
||||
dependencies(
|
||||
user,
|
||||
(
|
||||
fk for fk in get_referencing_foreign_keys(obj)
|
||||
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
|
||||
if fk.ondelete == 'RESTRICT' or fk.ondelete is None
|
||||
)
|
||||
).limit(5)
|
||||
)
|
||||
@@ -62,6 +72,8 @@ def dependencies(obj, foreign_keys=None):
|
||||
if deps:
|
||||
# Do something to inform the user
|
||||
pass
|
||||
else:
|
||||
session.delete(user)
|
||||
|
||||
|
||||
:param obj: SQLAlchemy declarative model object
|
||||
@@ -73,6 +85,8 @@ def dependencies(obj, foreign_keys=None):
|
||||
.. note::
|
||||
This function does not support exotic mappers that use multiple tables
|
||||
|
||||
.. seealso:: :func:`get_referencing_foreign_keys`
|
||||
|
||||
.. versionadded: 0.26.0
|
||||
"""
|
||||
if foreign_keys is None:
|
||||
@@ -142,6 +156,7 @@ def get_referencing_foreign_keys(mixed):
|
||||
# or textitem table.
|
||||
get_referencing_foreign_keys(Article)
|
||||
|
||||
.. seealso:: :func:`get_tables`
|
||||
"""
|
||||
if isinstance(mixed, sa.Table):
|
||||
tables = [mixed]
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy_utils.functions.orm import dependencies
|
||||
from sqlalchemy_utils import dependencies, get_referencing_foreign_keys
|
||||
from tests import TestCase
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@ class TestDependencies(TestCase):
|
||||
__tablename__ = 'article'
|
||||
id = sa.Column(sa.Integer, primary_key=True)
|
||||
author_id = sa.Column(sa.Integer, sa.ForeignKey('user.id'))
|
||||
owner_id = sa.Column(sa.Integer, sa.ForeignKey('user.id'))
|
||||
owner_id = sa.Column(
|
||||
sa.Integer, sa.ForeignKey('user.id', ondelete='SET NULL')
|
||||
)
|
||||
|
||||
author = sa.orm.relationship(User, foreign_keys=[author_id])
|
||||
owner = sa.orm.relationship(User, foreign_keys=[owner_id])
|
||||
@@ -23,15 +25,17 @@ class TestDependencies(TestCase):
|
||||
class BlogPost(self.Base):
|
||||
__tablename__ = 'blog_post'
|
||||
id = sa.Column(sa.Integer, primary_key=True)
|
||||
author_id = sa.Column(sa.Integer, sa.ForeignKey('user.id'))
|
||||
owner_id = sa.Column(
|
||||
sa.Integer, sa.ForeignKey('user.id', ondelete='CASCADE')
|
||||
)
|
||||
|
||||
author = sa.orm.relationship(User)
|
||||
owner = sa.orm.relationship(User)
|
||||
|
||||
self.User = User
|
||||
self.Article = Article
|
||||
self.BlogPost = BlogPost
|
||||
|
||||
def test_multiple_refs(self):
|
||||
def test_returns_all_dependent_objects(self):
|
||||
user = self.User(first_name=u'John')
|
||||
articles = [
|
||||
self.Article(author=user),
|
||||
@@ -48,6 +52,31 @@ class TestDependencies(TestCase):
|
||||
assert articles[2] in deps
|
||||
assert articles[3] in deps
|
||||
|
||||
def test_with_foreign_keys_parameter(self):
|
||||
user = self.User(first_name=u'John')
|
||||
objects = [
|
||||
self.Article(author=user),
|
||||
self.Article(),
|
||||
self.Article(owner=user),
|
||||
self.Article(author=user, owner=user),
|
||||
self.BlogPost(owner=user)
|
||||
]
|
||||
self.session.add_all(objects)
|
||||
self.session.commit()
|
||||
|
||||
deps = list(
|
||||
dependencies(
|
||||
user,
|
||||
(
|
||||
fk for fk in get_referencing_foreign_keys(self.User)
|
||||
if fk.ondelete == 'RESTRICT' or fk.ondelete is None
|
||||
)
|
||||
).limit(5)
|
||||
)
|
||||
assert len(deps) == 2
|
||||
assert objects[0] in deps
|
||||
assert objects[3] in deps
|
||||
|
||||
|
||||
class TestDependenciesWithCompositeKeys(TestCase):
|
||||
def create_models(self):
|
||||
|
Reference in New Issue
Block a user