From: Mike Bayer Date: Sat, 10 May 2008 00:26:28 +0000 (+0000) Subject: backref() function uses primaryjoin/secondaryjoin of the parent relation() if not... X-Git-Tag: rel_0_5beta1~118 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bd8514e80bef54a535f46c58aee5945460929691;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git backref() function uses primaryjoin/secondaryjoin of the parent relation() if not otherwise specified, removing the frequently annoying need to specify primaryjoin twice. --- diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index 9c23fd409c..2c28be7158 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -144,14 +144,6 @@ def relation(argument, secondary=None, **kwargs): \**kwargs follow: - association - Deprecated; as of version 0.3.0 the association keyword is synonymous - with applying the "all, delete-orphan" cascade to a "one-to-many" - relationship. SA can now automatically reconcile a "delete" and - "insert" operation of two objects with the same "identity" in a flush() - operation into a single "update" statement, which is the pattern that - "association" used to indicate. - backref indicates the name of a property to be placed on the related mapper's class that will handle this relationship in the other direction, @@ -178,10 +170,6 @@ def relation(argument, secondary=None, **kwargs): metadata. Use this argument when no ForeignKey's are present in the join condition, or to override the table-defined foreign keys. - foreignkey - deprecated. use the ``foreign_keys`` argument for foreign key - specification, or ``remote_side`` for "directional" logic. - join_depth=None when non-``None``, an integer value indicating how many levels deep eagerload joins should be constructed on a self-referring @@ -281,11 +269,6 @@ def relation(argument, secondary=None, **kwargs): value is computed based on the foreign key relationships of the parent and child tables (or association table). - private=False - deprecated. setting ``private=True`` is the equivalent of setting - ``cascade="all, delete-orphan"``, and indicates the lifecycle of child - objects should be contained within that of the parent. - remote_side used for self-referential relationships, indicates the column or list of columns that form the "remote side" of the relationship. @@ -313,7 +296,6 @@ def relation(argument, secondary=None, **kwargs): properly. If this is the case, use an alternative method. """ - return PropertyLoader(argument, secondary=secondary, **kwargs) def dynamic_loader(argument, secondary=None, primaryjoin=None, secondaryjoin=None, entity_name=None, @@ -329,8 +311,8 @@ def dynamic_loader(argument, secondary=None, primaryjoin=None, secondaryjoin=Non operations are available. A subset of arguments available to relation() are available here. - """ + """ from sqlalchemy.orm.dynamic import DynaLoader return PropertyLoader(argument, secondary=secondary, primaryjoin=primaryjoin, @@ -339,8 +321,6 @@ def dynamic_loader(argument, secondary=None, primaryjoin=None, secondaryjoin=Non passive_deletes=passive_deletes, order_by=order_by, strategy_class=DynaLoader) -#def _relation_loader(mapper, secondary=None, primaryjoin=None, secondaryjoin=None, lazy=True, **kwargs): - def column_property(*args, **kwargs): """Provide a column-level property for use with a Mapper. @@ -413,8 +393,8 @@ def composite(class_, *cols, **kwargs): An optional instance of [sqlalchemy.orm#PropComparator] which provides SQL expression generation functions for this composite type. - """ + """ return CompositeProperty(class_, *cols, **kwargs) @@ -424,8 +404,8 @@ def backref(name, **kwargs): Used with the `backref` keyword argument to ``relation()`` in place of a string argument. - """ + """ return BackRef(name, **kwargs) def deferred(*columns, **kwargs): @@ -434,8 +414,8 @@ def deferred(*columns, **kwargs): table column when first accessed. Used with the `properties` dictionary sent to ``mapper()``. - """ + """ return ColumnProperty(deferred=True, *columns, **kwargs) def mapper(class_, local_table=None, *args, **params): @@ -606,8 +586,8 @@ def mapper(class_, local_table=None, *args, **params): that no other thread or process has updated the instance during the lifetime of the entity, else a ``ConcurrentModificationError`` exception is thrown. - """ + """ return Mapper(class_, local_table, *args, **params) def synonym(name, map_column=False, descriptor=None, proxy=False): diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 7f0353d494..64f2f700d3 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -834,7 +834,7 @@ class BackRef(object): self.kwargs = kwargs self.prop = _prop self.extension = attributes.GenericBackrefExtension(self.key) - + def compile(self, prop): if self.prop: return @@ -843,9 +843,15 @@ class BackRef(object): mapper = prop.mapper.primary_mapper() if mapper._get_property(self.key, raiseerr=False) is None: - pj = self.kwargs.pop('primaryjoin', None) - sj = self.kwargs.pop('secondaryjoin', None) - + if prop.secondary: + pj = self.kwargs.pop('primaryjoin', prop.secondaryjoin) + sj = self.kwargs.pop('secondaryjoin', prop.primaryjoin) + else: + pj = self.kwargs.pop('primaryjoin', prop.primaryjoin) + sj = self.kwargs.pop('secondaryjoin', None) + if sj: + raise exceptions.InvalidRequestError("Can't assign 'secondaryjoin' on a backref against a non-secondary relation.") + parent = prop.parent.primary_mapper() self.kwargs.setdefault('viewonly', prop.viewonly) self.kwargs.setdefault('post_update', prop.post_update) diff --git a/test/orm/cycles.py b/test/orm/cycles.py index d43a9062c5..d21cd1974b 100644 --- a/test/orm/cycles.py +++ b/test/orm/cycles.py @@ -800,9 +800,8 @@ class SelfReferentialPostUpdateTest(_base.MappedTest): primaryjoin=node.c.id==node.c.parent_id, lazy=True, cascade="all", - backref=backref("parent", - primaryjoin=node.c.parent_id == node.c.id, - remote_side=node.c.id)), + backref=backref("parent", remote_side=node.c.id) + ), 'prev_sibling': relation( Node, primaryjoin=node.c.prev_sibling_id==node.c.id, diff --git a/test/orm/inheritance/poly_linked_list.py b/test/orm/inheritance/poly_linked_list.py index 96c4b19280..f4b85dc951 100644 --- a/test/orm/inheritance/poly_linked_list.py +++ b/test/orm/inheritance/poly_linked_list.py @@ -70,7 +70,7 @@ class PolymorphicCircularTest(ORMTest): polymorphic_identity='table1', properties={ 'next': relation(Table1, - backref=backref('prev', primaryjoin=join.c.id==join.c.related_id, foreignkey=join.c.id, uselist=False), + backref=backref('prev', foreignkey=join.c.id, uselist=False), uselist=False, primaryjoin=join.c.id==join.c.related_id), 'data':relation(mapper(Data, data)) }, @@ -92,7 +92,7 @@ class PolymorphicCircularTest(ORMTest): polymorphic_identity='table1', properties={ 'next': relation(Table1, - backref=backref('prev', primaryjoin=table1.c.id==table1.c.related_id, remote_side=table1.c.id, uselist=False), + backref=backref('prev', remote_side=table1.c.id, uselist=False), uselist=False, primaryjoin=table1.c.id==table1.c.related_id), 'data':relation(mapper(Data, data), lazy=False, order_by=data.c.id) }, diff --git a/test/orm/inheritance/productspec.py b/test/orm/inheritance/productspec.py index 54810c31fa..ba4828c69b 100644 --- a/test/orm/inheritance/productspec.py +++ b/test/orm/inheritance/productspec.py @@ -93,7 +93,7 @@ class InheritTest(ORMTest): master=relation(Assembly, foreign_keys=[specification_table.c.master_id], primaryjoin=specification_table.c.master_id==products_table.c.product_id, - lazy=True, backref=backref('specification', primaryjoin=specification_table.c.master_id==products_table.c.product_id), + lazy=True, backref=backref('specification'), uselist=False), slave=relation(Product, foreign_keys=[specification_table.c.slave_id], @@ -169,7 +169,7 @@ class InheritTest(ORMTest): master=relation(Assembly, lazy=False, uselist=False, foreign_keys=[specification_table.c.master_id], primaryjoin=specification_table.c.master_id==products_table.c.product_id, - backref=backref('specification', primaryjoin=specification_table.c.master_id==products_table.c.product_id, cascade="all, delete-orphan"), + backref=backref('specification', cascade="all, delete-orphan"), ), slave=relation(Product, lazy=False, uselist=False, foreign_keys=[specification_table.c.slave_id], @@ -261,7 +261,7 @@ class InheritTest(ORMTest): master=relation(Assembly, lazy=False, uselist=False, foreign_keys=[specification_table.c.master_id], primaryjoin=specification_table.c.master_id==products_table.c.product_id, - backref=backref('specification', primaryjoin=specification_table.c.master_id==products_table.c.product_id), + backref=backref('specification'), ), slave=relation(Product, lazy=False, uselist=False, foreign_keys=[specification_table.c.slave_id], diff --git a/test/orm/relationships.py b/test/orm/relationships.py index 01c1724d96..a002f7f8d9 100644 --- a/test/orm/relationships.py +++ b/test/orm/relationships.py @@ -311,11 +311,8 @@ class RelationTest3(_base.MappedTest): primaryjoin=sa.and_(pages.c.jobno==pageversions.c.jobno, pages.c.pagename==pageversions.c.pagename), order_by=pageversions.c.version, - backref=backref('page', - lazy=False, - primaryjoin=sa.and_( - pages.c.jobno==pageversions.c.jobno, - pages.c.pagename==pageversions.c.pagename)))}) + backref=backref('page',lazy=False) + )}) mapper(PageComment, pagecomments, properties={ 'page': relation( Page, @@ -323,9 +320,6 @@ class RelationTest3(_base.MappedTest): pages.c.pagename==pagecomments.c.pagename), backref=backref("comments", cascade="all, delete-orphan", - primaryjoin=sa.and_( - pages.c.jobno==pagecomments.c.jobno, - pages.c.pagename==pagecomments.c.pagename), order_by=pagecomments.c.comment_id))}) @testing.resolve_artifact_names