[sqlalchemy] backrefs
Is there a straightforward way to determine if a RelationshipProperty has a corresponding "reverse" (backref)? -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
Re: [sqlalchemy] Backrefs vs. defining the relationships "by hand"
It was a typo! :-) > They keep the two sides of a relationship in sync on the python side. I was suspecting using backrefs was better and that it would do some kind of synchronization like that, yeah... But I was hoping that someone would say "No, it's the same"... Because now I won't sleep soundly at night until I change all my code... But hey... This is what learning while coding has :-) I will have to "expunge" my old ideas from my brain and update my code... I hope I can quickly flush the changes, though Thank you! 2011/2/24 Michael Bayer : > > On Feb 24, 2011, at 1:20 PM, Hector Blanco wrote: > >> Hello everyone... >> >> I'd like to know what do you think it's better: Whether using backrefs >> or "manually" defining the relationships one by one. Are the backrefs >> useful to code less code or do they have other advantages? >> >> I.e.: Let's say I have a User and a UserGroup class with (initially) >> the relationships defined by hand: >> >> class User(declarativeBase): >> __tablename__ = "users" >> >> _id = Column("id", Integer, primary_key=True) >> _email = Column("email", String(60)) >> _userName = Column("user_name", String(50), unique=True, >> nullable=False) >> _password = Column("password", String(64), nullable=False) >> _userGroupId = Column("user_group_id", Integer, >> ForeignKey("user_groups.id")) >> >> _userGroup = relationship("UserGroup", uselist=False) >> >> class UserGroup(declarativeBase): >> __tablename__ = "user_groups" >> >> _id = Column("id", Integer, primary_key=True) >> _name = Column("name", String(50)) >> >> _users = relationship("User", order_by=lambda:User.userName, >> cascade="all, delete", collection_class=set) >> >> >> If, instead, I define that _users (in the UserGroup class) as a backref: >> >> >> class User(declarativeBase): >> __tablename__ = "users" >> >> _id = Column("id", Integer, primary_key=True) >> _email = Column("email", String(60)) >> _userName = Column("user_name", String(50), unique=True, >> nullable=False) >> _password = Column("password", String(64), nullable=False) >> _userGroupId = Column("user_group_id", Integer, >> ForeignKey("user_groups.id")) >> >> >> _userGroup = relationship("UserGroup", uselist=False, backref=backref( >> backref = backref("_users", >> order_by=lambda:User._userName, >> cascade="all, delete", >> collection_class=set >> ) >> )) > > is that correct that there is backref(backref=backref()) up there ? clearly > that's not how it was intended to be used. unless its a typo. > >> >> and, at a certain point I want to create a resetUsers() method in the >> UserGroup class (to empty the "_users" set) I have to add the users in >> that set to the session first and then reset it: >> >> class UserGroup(declarativeBase): >> # Yadda, yadda yadda >> >> def resetUsers(self): >> Database.Session().add_all(self._users) >> self._users = set() >> >> That doesn't happen with the UserGroup._users being a relationship on >> its own (not a backref). I can just do self._users = set() and it >> seems to work fine. The database looks consistent to me, and all that. >> >> I'd like to know if I'm missing something, or if using backrefs is >> better for some reason I don't know yet. >> >> Any advice will be deeply appreciated. Thank you in advance. > > backref means that there are two relationships() set up that have a > "back_populates" relationship to each other - you can also configure this as > two distinct relationships with back_populates: > > class A(...): > bar = relationship("B", back_populates="foo") > > class B(...): > foo = relationship("A", back_populates="bar") > > > This means appending to one results in an append, or set, on the other, and > vice versa, and similar for removes. They keep the two sides of a > relationship in sync on the python side. That said it is optional, but if > you were to mutate both sides, both mutations would have an effect during > flush. > > > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to sqlalchemy@googlegroups.com. > To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. > > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
Re: [sqlalchemy] Backrefs vs. defining the relationships "by hand"
On Feb 24, 2011, at 1:20 PM, Hector Blanco wrote: > Hello everyone... > > I'd like to know what do you think it's better: Whether using backrefs > or "manually" defining the relationships one by one. Are the backrefs > useful to code less code or do they have other advantages? > > I.e.: Let's say I have a User and a UserGroup class with (initially) > the relationships defined by hand: > > class User(declarativeBase): > __tablename__ = "users" > > _id = Column("id", Integer, primary_key=True) > _email = Column("email", String(60)) > _userName = Column("user_name", String(50), unique=True, nullable=False) > _password = Column("password", String(64), nullable=False) > _userGroupId = Column("user_group_id", Integer, > ForeignKey("user_groups.id")) > > _userGroup = relationship("UserGroup", uselist=False) > > class UserGroup(declarativeBase): > __tablename__ = "user_groups" > > _id = Column("id", Integer, primary_key=True) > _name = Column("name", String(50)) > > _users = relationship("User", order_by=lambda:User.userName, > cascade="all, delete", collection_class=set) > > > If, instead, I define that _users (in the UserGroup class) as a backref: > > > class User(declarativeBase): > __tablename__ = "users" > > _id = Column("id", Integer, primary_key=True) > _email = Column("email", String(60)) > _userName = Column("user_name", String(50), unique=True, nullable=False) > _password = Column("password", String(64), nullable=False) > _userGroupId = Column("user_group_id", Integer, > ForeignKey("user_groups.id")) > > > _userGroup = relationship("UserGroup", uselist=False, backref=backref( > backref = backref("_users", > order_by=lambda:User._userName, > cascade="all, delete", > collection_class=set > ) > )) is that correct that there is backref(backref=backref()) up there ? clearly that's not how it was intended to be used. unless its a typo. > > and, at a certain point I want to create a resetUsers() method in the > UserGroup class (to empty the "_users" set) I have to add the users in > that set to the session first and then reset it: > > class UserGroup(declarativeBase): > # Yadda, yadda yadda > > def resetUsers(self): > Database.Session().add_all(self._users) > self._users = set() > > That doesn't happen with the UserGroup._users being a relationship on > its own (not a backref). I can just do self._users = set() and it > seems to work fine. The database looks consistent to me, and all that. > > I'd like to know if I'm missing something, or if using backrefs is > better for some reason I don't know yet. > > Any advice will be deeply appreciated. Thank you in advance. backref means that there are two relationships() set up that have a "back_populates" relationship to each other - you can also configure this as two distinct relationships with back_populates: class A(...): bar = relationship("B", back_populates="foo") class B(...): foo = relationship("A", back_populates="bar") This means appending to one results in an append, or set, on the other, and vice versa, and similar for removes.They keep the two sides of a relationship in sync on the python side.That said it is optional, but if you were to mutate both sides, both mutations would have an effect during flush. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
[sqlalchemy] Backrefs vs. defining the relationships "by hand"
Hello everyone... I'd like to know what do you think it's better: Whether using backrefs or "manually" defining the relationships one by one. Are the backrefs useful to code less code or do they have other advantages? I.e.: Let's say I have a User and a UserGroup class with (initially) the relationships defined by hand: class User(declarativeBase): __tablename__ = "users" _id = Column("id", Integer, primary_key=True) _email = Column("email", String(60)) _userName = Column("user_name", String(50), unique=True, nullable=False) _password = Column("password", String(64), nullable=False) _userGroupId = Column("user_group_id", Integer, ForeignKey("user_groups.id")) _userGroup = relationship("UserGroup", uselist=False) class UserGroup(declarativeBase): __tablename__ = "user_groups" _id = Column("id", Integer, primary_key=True) _name = Column("name", String(50)) _users = relationship("User", order_by=lambda:User.userName, cascade="all, delete", collection_class=set) If, instead, I define that _users (in the UserGroup class) as a backref: class User(declarativeBase): __tablename__ = "users" _id = Column("id", Integer, primary_key=True) _email = Column("email", String(60)) _userName = Column("user_name", String(50), unique=True, nullable=False) _password = Column("password", String(64), nullable=False) _userGroupId = Column("user_group_id", Integer, ForeignKey("user_groups.id")) _userGroup = relationship("UserGroup", uselist=False, backref=backref( backref = backref("_users", order_by=lambda:User._userName, cascade="all, delete", collection_class=set ) )) and, at a certain point I want to create a resetUsers() method in the UserGroup class (to empty the "_users" set) I have to add the users in that set to the session first and then reset it: class UserGroup(declarativeBase): # Yadda, yadda yadda def resetUsers(self): Database.Session().add_all(self._users) self._users = set() That doesn't happen with the UserGroup._users being a relationship on its own (not a backref). I can just do self._users = set() and it seems to work fine. The database looks consistent to me, and all that. I'd like to know if I'm missing something, or if using backrefs is better for some reason I don't know yet. Any advice will be deeply appreciated. Thank you in advance. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
[sqlalchemy] Backrefs and the identity map
Hi, Does accessing a backref always have to issue SQL, even if the object to be loaded already exists in the identity map? For example, if I have a many-to-one lazy-loaded relationship from Master to Detail with a backref, the statement "master.details[0].master" will issue SQL for the '.master' backref, even though it already exists in the session. I know I can eagerload('details.master'), but I was just wondering if there was any way of getting the relation mechanism to check the identity map before issuing the SQL. Here is an example: import sqlalchemy as sa import sqlalchemy.orm as saorm from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() Base.metadata.bind = sa.create_engine('sqlite:///:memory') class Master(Base): __tablename__ = 'master' id = sa.Column(sa.Integer, primary_key=True) class Detail(Base): __tablename__ = 'detail' id = sa.Column(sa.Integer, primary_key=True) master_id = sa.Column(None, sa.ForeignKey(Master.id)) master = saorm.relation(Master, backref='details') def dbg(msg): print "\n %s " % msg def test(): dbg('SQLAlchemy version: %s' % sa.__version__) Base.metadata.create_all() Session = saorm.sessionmaker() sess = Session() m = Master() for i in range(10): m.details.append(Detail()) sess.add(m) sess.commit() sess.close() Base.metadata.bind.echo = True sess = Session() dbg("Getting Master") m = sess.query(Master).first() dbg("Getting details") details = m.details dbg("Getting master of first detail") m2 = details[0].master assert m2 is m dbg("Getting master again via query.get") m3 = sess.query(Master).get(m.id) assert m3 is m2 if __name__ == '__main__': test() And here is the output: SQLAlchemy version: 0.5.5 Getting Master 2009-08-03 13:17:12,445 INFO sqlalchemy.engine.base.Engine.0x...7ecL BEGIN 2009-08-03 13:17:12,447 INFO sqlalchemy.engine.base.Engine.0x...7ecL SELECT master.id AS master_id FROM master LIMIT 1 OFFSET 0 2009-08-03 13:17:12,447 INFO sqlalchemy.engine.base.Engine.0x...7ecL [] Getting details 2009-08-03 13:17:12,451 INFO sqlalchemy.engine.base.Engine.0x...7ecL SELECT detail.id AS detail_id, detail.master_id AS detail_master_id FROM detail WHERE ? = detail.master_id 2009-08-03 13:17:12,451 INFO sqlalchemy.engine.base.Engine.0x...7ecL [1] Getting master of first detail 2009-08-03 13:17:12,456 INFO sqlalchemy.engine.base.Engine.0x...7ecL SELECT master.id AS master_id FROM master WHERE master.id = ? 2009-08-03 13:17:12,457 INFO sqlalchemy.engine.base.Engine.0x...7ecL [1] Getting master again via query.get Finished So "query.get" doesn't issue a query, but "master.details[0].master" does. Is there any way of making the backref use query.get, and thereby use the identity map? Thanks a lot, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] backrefs
hi just an idea: is it possible to have half-baked backref-declarations? i want to use the SA's way of inventing backrefs from a name, and just provide some extra arguments to that invention. instead now i have a full backref(...) having more or less all of the relation(...) arguments, but with additional logic on picking/swapping of primaryjoin/secondaryjoin - something that SA does internaly in the PropertyLoader constructor. alternatively, i can patch the backref later, letting SA invent it properly and then fix some things - like post_update and remote_side. how bad is that? btw remote_side is not propagated by PropertyLoader constructor - but IMO is needed. ciao svilen --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---