From: Federico Caselli Date: Wed, 12 May 2021 19:09:41 +0000 (+0200) Subject: Detect back_populates referring to non-relationship X-Git-Tag: rel_1_4_16~18^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e26487e234e4192db7e75cedf029df6de83f3415;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Detect back_populates referring to non-relationship Change-Id: Ic26d5d6d230d8d3209e6e42ff7752b59b8cb7b28 --- diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py index 2ed9d859ab..7e97962f4e 100644 --- a/lib/sqlalchemy/orm/relationships.py +++ b/lib/sqlalchemy/orm/relationships.py @@ -2051,6 +2051,13 @@ class RelationshipProperty(StrategizedProperty): def _add_reverse_property(self, key): other = self.mapper.get_property(key, _configure_mappers=False) + if not isinstance(other, RelationshipProperty): + raise sa_exc.InvalidRequestError( + "back_populates on relationship '%s' refers to attribute '%s' " + "that is not a relationship. The back_populates parameter " + "should refer to the name of a relationship on the target " + "class." % (self, other) + ) # viewonly and sync_backref cases # 1. self.viewonly==True and other.sync_backref==True -> error # 2. self.viewonly==True and other.viewonly==False and diff --git a/test/orm/test_relationships.py b/test/orm/test_relationships.py index 867994866c..77a218bebd 100644 --- a/test/orm/test_relationships.py +++ b/test/orm/test_relationships.py @@ -2304,6 +2304,39 @@ class ManualBackrefTest(_fixtures.FixtureTest): configure_mappers, ) + def test_back_propagates_not_relationship(self): + addr, Addr, users, User = ( + self.tables.addresses, + self.classes.Address, + self.tables.users, + self.classes.User, + ) + + mapper( + User, + users, + properties={ + "addresses": relationship(Addr, back_populates="user_id") + }, + ) + + mapper( + Addr, + addr, + properties={ + "users": relationship(User, back_populates="addresses") + }, + ) + + assert_raises_message( + sa.exc.InvalidRequestError, + "back_populates on relationship 'User.addresses' refers to " + "attribute 'Address.user_id' that is not a relationship. " + "The back_populates parameter should refer to the name of " + "a relationship on the target class.", + configure_mappers, + ) + class NoLoadBackPopulates(_fixtures.FixtureTest): @@ -3146,6 +3179,7 @@ class ViewOnlySyncBackref(fixtures.MappedTest): return str(self.__dict__) cases = { + # (B_a_view, B_a_sync, A_bs_view, A_bs_sync) (0, 0, 0, 0): Case(), (0, 0, 0, 1): Case(Abs_evt=1), (0, 0, 1, 0): Case(),