- changed status to resolved
backref collision detection
Issue #832
resolved
from sqlalchemy import *
from sqlalchemy.orm import *
engine = create_engine('sqlite://')
meta = MetaData(engine)
a = Table('a', meta, Column('id', Integer, primary_key=True))
b = Table('b', meta, Column('id', Integer, primary_key=True), Column('a_id', Integer, ForeignKey('a.id')))
class A(object):pass
class B(object):pass
class C(object):pass
mapper(A, a, properties={
'b':relation(B, backref='a')
})
mapper(B, b, properties={
'a':relation(A, backref='b')
})
compile_mappers()
should raise an exception. properties.py should ideally have this patch:
--- lib/sqlalchemy/orm/properties.py (revision 3649)
+++ lib/sqlalchemy/orm/properties.py (working copy)
@@ -152,7 +152,7 @@
self.comparator = PropertyLoader.Comparator(self)
self.join_depth = join_depth
self.strategy_class = strategy_class
-
+
if cascade is not None:
self.cascade = mapperutil.CascadeOptions(cascade)
else:
@@ -676,7 +676,7 @@
# try to set a LazyLoader on our mapper referencing the parent mapper
mapper = prop.mapper.primary_mapper()
- if not mapper.get_property(self.key, raiseerr=False) is not None:
+ if mapper.get_property(self.key, raiseerr=False) is None:
pj = self.kwargs.pop('primaryjoin', None)
sj = self.kwargs.pop('secondaryjoin', None)
# the backref property is set on the primary mapper
@@ -684,29 +684,18 @@
self.kwargs.setdefault('viewonly', prop.viewonly)
self.kwargs.setdefault('post_update', prop.post_update)
relation = PropertyLoader(parent, prop.secondary, pj, sj,
- backref=prop.key, is_backref=True,
+ #backref=prop.key,
+ is_backref=True,
**self.kwargs)
mapper._compile_property(self.key, relation);
+ prop.reverse_property = mapper.get_property(self.key)
+ mapper.get_property(self.key).reverse_property = prop
elif not isinstance(mapper.get_property(self.key), PropertyLoader):
raise exceptions.ArgumentError(
"Can't create backref '%s' on mapper '%s'; an incompatible "
"property of that name already exists" % (self.key, str(mapper)))
else:
- # else set one of us as the "backreference"
- parent = prop.parent.primary_mapper()
- if parent.class_ is not mapper.get_property(self.key)._get_target_class():
- raise exceptions.ArgumentError(
- "Backrefs do not match: backref '%s' expects to connect to %s, "
- "but found a backref already connected to %s" %
- (self.key, str(parent.class_), str(mapper.get_property(self.key).mapper.class_)))
- if not mapper.get_property(self.key).is_backref:
- prop.is_backref=True
- if not prop.viewonly:
- prop._dependency_processor.is_backref=True
- # reverse_property used by dependencies.ManyToManyDP to check
- # association table operations
- prop.reverse_property = mapper.get_property(self.key)
- mapper.get_property(self.key).reverse_property = prop
+ raise exceptions.ArgumentError("Property '%s' already exists on mapper '%s'" % (self.key, mapper))
def get_extension(self):
"""Return an attribute extension to use with this backreference."""
some tests are failing though (the proper backref config isn't fully set up).
Comments (2)
-
reporter -
reporter - removed milestone
Removing milestone: 0.4.xx (automated comment)
- Log in to comment
763a70d531039406f7a45d6e02a7621efb53f44b