Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(303): Allow querying viewonly relationships #304

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions sqlalchemy_continuum/relationship_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ def association_subquery(self, obj):

:param obj: SQLAlchemy declarative object
"""
self.set_association_version_table(build=False)

tx_column = option(obj, 'transaction_column_name')
join_column = self.property.primaryjoin.right.name
Expand Down Expand Up @@ -306,12 +307,18 @@ def association_subquery(self, obj):
).correlate(self.local_cls, self.remote_cls)
)

def build_association_version_tables(self):
def set_association_version_table(self, build=True):
"""
Builds many-to-many association version table for given property.
Set the many-to-many association version table for given property.
Association version tables are used for tracking change history of
many-to-many associations.

:param build:
Whether to build the version table if it is not found in the metadata
"""
if hasattr(self, 'association_version_table'):
return

column = list(self.property.remote_side)[0]

self.manager.association_tables.add(column.table)
Expand All @@ -327,7 +334,7 @@ def build_association_version_tables(self):
else:
table_name = builder.table_name

if table_name not in metadata.tables:
if table_name not in metadata.tables and build:
self.association_version_table = table = builder()
self.manager.association_version_tables.add(table)
else:
Expand All @@ -351,10 +358,12 @@ def __call__(self):
self.remote_cls = self.property.mapper.class_

if (self.property.secondary is not None and
not self.property.viewonly and
not self.manager.is_excluded_property(
self.model, self.property.key)):
self.build_association_version_tables()
if not self.property.viewonly:
# viewonly properties don't need set the association_version_table at this time
# and are set during query time (when all tables are added to metadata)
self.set_association_version_table(build=True)

# store remote cls to association table column pairs
self.remote_to_association_column_pairs = []
Expand Down
28 changes: 28 additions & 0 deletions tests/relationships/test_many_to_many_relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Article(self.Model):

id = sa.Column(sa.Integer, autoincrement=True, primary_key=True)
name = sa.Column(sa.Unicode(255))
is_sponsored = sa.Column(sa.Boolean(), default=False)

article_tag = sa.Table(
'article_tag',
Expand Down Expand Up @@ -48,6 +49,15 @@ class Tag(self.Model):
secondary=article_tag,
backref='tags'
)
Tag.sponsored_articles = sa.orm.relationship(
Article,
secondary=article_tag,
secondaryjoin=sa.and_(
article_tag.c.article_id == Article.id,
Article.is_sponsored == True,
),
viewonly=True,
)

self.Article = Article
self.Tag = Tag
Expand Down Expand Up @@ -217,6 +227,24 @@ def test_relations_with_varying_transactions(self):
assert tag1.versions[2] in article.versions[2].tags
assert tag2.versions[0] in article.versions[2].tags

def test_viewonly_relationships(self):
tag = self.Tag(name=u'some tag')
article1 = self.Article(
name=u'Sponsored Article',
is_sponsored=True,
tags=[tag],
)
article2 = self.Article(
name=u'Normal Article',
tags=[tag],
)
self.session.add(article1)
self.session.add(article2)
self.session.commit()

assert len(tag.versions[0].articles) == 2
assert len(tag.versions[0].sponsored_articles) == 1


create_test_cases(ManyToManyRelationshipsTestCase)

Expand Down