Re: [sqlalchemy] Objects inadvertently being added to session
Hi Mike, Thanks so much for the reply and the pointer. Since I never added anything to the session explicitly, I think I was missing that loading an object implicitly adds that object to the session - which does make sense. Is that right ? thanks again, terry On Monday, June 15, 2015 at 11:26:39 AM UTC-4, Michael Bayer wrote: On 6/15/15 11:12 AM, T Mark wrote: Hi there, I have been pulling my hair out on this one. I understood that objects make it into the session only due to an explicit call to add(). or if they are associated with a parent object that is added to the Session via add(), or if they are associated with an object that is already present in a Session via add(); this also will occur for backrefs, e.g. A is in the session, B.a is referred to A, B.a has a backref A.bs, therefore B is now added. This is configurable. But, I seem to be seeing objects being added without my explicitly doing so. Is this to be expected ? yes. please see: http://docs.sqlalchemy.org/en/rel_1_0/orm/cascades.html?highlight=cascades For instance, I want to establish a many-to-many relationship between two classes: say, for the purposes here, Person and Kid. test= create table persons (id SERIAL NOT NULL); test= CREATE TABLE person_to_kids (person_id INT NOT NULL, kid_id INT NOT NULL); test= create table kids (id SERIAL NOT NULL, name TEXT NOT NULL); test= insert into kids (name) VALUES ('Fred'); test= insert into kids (name) VALUES ('Barney'); person_to_kids = Table('person_to_kids', Base.metadata, Column('person_id', Integer, ForeignKey(' persons.id')), Column('kid_id', Integer, ForeignKey('kids.id'))) class Person(Base): __tablename__ = 'persons' id = Column('id', Integer, primary_key = True) def __init__(self, kids = []): kids = Kid.get_kids(kid_names = kids) print(__init__ before kids assignment) print(session.new) Assigning to self.kids here seems to add self to session ??? self.kids=kids print(After assignment to self.kids) print(session.new) class Kid(Base): __tablename__ = 'kids' id = Column(Integer, primary_key = True) name = Column(String) parents = relationship(Person, secondary = person_to_kids, backref=kids) def __init__(self, name = None): self.name = name @staticmethod def get_kids(kid_names = []): kids = [] for name in kid_names: # find first kid target_set = session.query(Kid).filter(Kid.name == name).first() kids.append(target_set) return kids What is puzzling me is that, if I have a collection of Kid objects, and I assign it to the kids collection in a Person, the Person object seems to be automatically added to the session and marked as pending, even if I have not added it. For instance, if the Persons table is empty: test= select * from persons; id (0 rows) and I run the following code: print(session.new) obj = Person(kids = ['Barney', 'Fred']) print(obj has been created) print(session.new) session.commit() The output shows that the Person object is added immediately after the assignment to obj.kids, without any call to session.add() anywhere in the code: IdentitySet([]) __init__ before kids assignment IdentitySet([]) After assignment to self.kids IdentitySet([__main__.Person object at 0x7fb6ce447b10]) obj has been created IdentitySet([__main__.Person object at 0x7fb6ce447b10]) And indeed, due to the commit() at the end, the person object makes it into the database: test= select * from persons; id 10 (1 row) But, I understood that objects (only) make it into a session by virtue of being explicitly added. So, is this the correct behavior, or am I misunderstanding something ? If I'm not misunderstanding this all, the complete code is at https://github.com/NuggyBuggy/sqlalchemy_question.git . Thanks for reading, terry -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com javascript:. To post to this group, send email to sqlal...@googlegroups.com javascript:. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com.
Re: [sqlalchemy] Objects inadvertently being added to session
On 6/15/15 11:12 AM, T Mark wrote: Hi there, I have been pulling my hair out on this one. I understood that objects make it into the session only due to an explicit call to add(). or if they are associated with a parent object that is added to the Session via add(), or if they are associated with an object that is already present in a Session via add(); this also will occur for backrefs, e.g. A is in the session, B.a is referred to A, B.a has a backref A.bs, therefore B is now added. This is configurable. But, I seem to be seeing objects being added without my explicitly doing so. Is this to be expected ? yes. please see: http://docs.sqlalchemy.org/en/rel_1_0/orm/cascades.html?highlight=cascades For instance, I want to establish a many-to-many relationship between two classes: say, for the purposes here, Person and Kid. | test= create table persons (id SERIAL NOT NULL); test= CREATE TABLE person_to_kids (person_id INT NOT NULL, kid_id INT NOT NULL); test= create table kids (id SERIAL NOT NULL, name TEXT NOT NULL); test= insert into kids (name) VALUES ('Fred'); test= insert into kids (name) VALUES ('Barney'); person_to_kids = Table('person_to_kids', Base.metadata, Column('person_id', Integer, ForeignKey('persons.id')), Column('kid_id', Integer, ForeignKey('kids.id'))) class Person(Base): __tablename__ = 'persons' id = Column('id', Integer, primary_key = True) def __init__(self, kids = []): kids = Kid.get_kids(kid_names = kids) print(__init__ before kids assignment) print(session.new) Assigning to self.kids here seems to add self to session ??? self.kids=kids print(After assignment to self.kids) print(session.new) class Kid(Base): __tablename__ = 'kids' id = Column(Integer, primary_key = True) name = Column(String) parents = relationship(Person, secondary = person_to_kids, backref=kids) def __init__(self, name = None): self.name = name @staticmethod def get_kids(kid_names = []): kids = [] for name in kid_names: # find first kid target_set = session.query(Kid).filter(Kid.name == name).first() kids.append(target_set) return kids | What is puzzling me is that, if I have a collection of Kid objects, and I assign it to the kids collection in a Person, the Person object seems to be automatically added to the session and marked as pending, even if I have not added it. For instance, if the Persons table is empty: | test= select * from persons; id (0 rows) | and I run the following code: | print(session.new) obj = Person(kids = ['Barney', 'Fred']) print(obj has been created) print(session.new) session.commit() | The output shows that the Person object is added immediately after the assignment to obj.kids, without any call to session.add() anywhere in the code: | IdentitySet([]) | __init__ before kids assignment IdentitySet([]) After assignment to self.kids IdentitySet([__main__.Person object at 0x7fb6ce447b10]) obj has been created IdentitySet([__main__.Person object at 0x7fb6ce447b10]) And indeed, due to the commit() at the end, the person object makes it into the database: | test= select * from persons; id 10 (1 row) | But, I understood that objects (only) make it into a session by virtue of being explicitly added. So, is this the correct behavior, or am I misunderstanding something ? If I'm not misunderstanding this all, the complete code is at https://github.com/NuggyBuggy/sqlalchemy_question.git . Thanks for reading, terry -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com mailto:sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com mailto:sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
[sqlalchemy] Objects inadvertently being added to session
Hi there, I have been pulling my hair out on this one. I understood that objects make it into the session only due to an explicit call to add(). But, I seem to be seeing objects being added without my explicitly doing so. Is this to be expected ? For instance, I want to establish a many-to-many relationship between two classes: say, for the purposes here, Person and Kid. test= create table persons (id SERIAL NOT NULL); test= CREATE TABLE person_to_kids (person_id INT NOT NULL, kid_id INT NOT NULL); test= create table kids (id SERIAL NOT NULL, name TEXT NOT NULL); test= insert into kids (name) VALUES ('Fred'); test= insert into kids (name) VALUES ('Barney'); person_to_kids = Table('person_to_kids', Base.metadata, Column('person_id', Integer, ForeignKey('persons.id')), Column('kid_id', Integer, ForeignKey('kids.id'))) class Person(Base): __tablename__ = 'persons' id = Column('id', Integer, primary_key = True) def __init__(self, kids = []): kids = Kid.get_kids(kid_names = kids) print(__init__ before kids assignment) print(session.new) Assigning to self.kids here seems to add self to session ??? self.kids=kids print(After assignment to self.kids) print(session.new) class Kid(Base): __tablename__ = 'kids' id = Column(Integer, primary_key = True) name = Column(String) parents = relationship(Person, secondary = person_to_kids, backref=kids) def __init__(self, name = None): self.name = name @staticmethod def get_kids(kid_names = []): kids = [] for name in kid_names: # find first kid target_set = session.query(Kid).filter(Kid.name == name).first() kids.append(target_set) return kids What is puzzling me is that, if I have a collection of Kid objects, and I assign it to the kids collection in a Person, the Person object seems to be automatically added to the session and marked as pending, even if I have not added it. For instance, if the Persons table is empty: test= select * from persons; id (0 rows) and I run the following code: print(session.new) obj = Person(kids = ['Barney', 'Fred']) print(obj has been created) print(session.new) session.commit() The output shows that the Person object is added immediately after the assignment to obj.kids, without any call to session.add() anywhere in the code: IdentitySet([]) __init__ before kids assignment IdentitySet([]) After assignment to self.kids IdentitySet([__main__.Person object at 0x7fb6ce447b10]) obj has been created IdentitySet([__main__.Person object at 0x7fb6ce447b10]) And indeed, due to the commit() at the end, the person object makes it into the database: test= select * from persons; id 10 (1 row) But, I understood that objects (only) make it into a session by virtue of being explicitly added. So, is this the correct behavior, or am I misunderstanding something ? If I'm not misunderstanding this all, the complete code is at https://github.com/NuggyBuggy/sqlalchemy_question.git . Thanks for reading, terry -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] Objects inadvertently being added to session
On 6/15/15 11:48 AM, T Mark wrote: Hi Mike, Thanks so much for the reply and the pointer. Since I never added anything to the session explicitly, I think I was missing that loading an object implicitly adds that object to the session - which does make sense. Is that right ? All the objects we deal with when using the ORM represent a row in the database, in terms of a transaction. So when we load rows, the objects which proxy those rows stay associated with the session. The ORM uses the lazy loader pattern so that when unloaded attributes are accessed, the associated Session is used as a source of transactional context. Objects that are used in this way are known as persistent objects. There are several states an object might have, including states that are unassociated with a Session as well. These states are discussed at http://docs.sqlalchemy.org/en/rel_1_0/orm/session_state_management.html. thanks again, terry On Monday, June 15, 2015 at 11:26:39 AM UTC-4, Michael Bayer wrote: On 6/15/15 11:12 AM, T Mark wrote: Hi there, I have been pulling my hair out on this one. I understood that objects make it into the session only due to an explicit call to add(). or if they are associated with a parent object that is added to the Session via add(), or if they are associated with an object that is already present in a Session via add(); this also will occur for backrefs, e.g. A is in the session, B.a is referred to A, B.a has a backref A.bs, therefore B is now added. This is configurable. But, I seem to be seeing objects being added without my explicitly doing so. Is this to be expected ? yes. please see: http://docs.sqlalchemy.org/en/rel_1_0/orm/cascades.html?highlight=cascades http://docs.sqlalchemy.org/en/rel_1_0/orm/cascades.html?highlight=cascades For instance, I want to establish a many-to-many relationship between two classes: say, for the purposes here, Person and Kid. | test= create table persons (id SERIAL NOT NULL); test= CREATE TABLE person_to_kids (person_id INT NOT NULL, kid_id INT NOT NULL); test= create table kids (id SERIAL NOT NULL, name TEXT NOT NULL); test= insert into kids (name) VALUES ('Fred'); test= insert into kids (name) VALUES ('Barney'); person_to_kids = Table('person_to_kids', Base.metadata, Column('person_id', Integer, ForeignKey('persons.id http://persons.id')), Column('kid_id', Integer, ForeignKey('kids.id http://kids.id'))) class Person(Base): __tablename__ = 'persons' id = Column('id', Integer, primary_key = True) def __init__(self, kids = []): kids = Kid.get_kids(kid_names = kids) print(__init__ before kids assignment) print(session.new) Assigning to self.kids here seems to add self to session ??? self.kids=kids print(After assignment to self.kids) print(session.new) class Kid(Base): __tablename__ = 'kids' id = Column(Integer, primary_key = True) name = Column(String) parents = relationship(Person, secondary = person_to_kids, backref=kids) def __init__(self, name = None): self.name http://self.name = name @staticmethod def get_kids(kid_names = []): kids = [] for name in kid_names: # find first kid target_set = session.query(Kid).filter(Kid.name == name).first() kids.append(target_set) return kids | What is puzzling me is that, if I have a collection of Kid objects, and I assign it to the kids collection in a Person, the Person object seems to be automatically added to the session and marked as pending, even if I have not added it. For instance, if the Persons table is empty: | test= select * from persons; id (0 rows) | and I run the following code: | print(session.new) obj = Person(kids = ['Barney', 'Fred']) print(obj has been created) print(session.new) session.commit() | The output shows that the Person object is added immediately after the assignment to obj.kids, without any call to session.add() anywhere in the code: | IdentitySet([]) | __init__ before kids assignment IdentitySet([]) After assignment to self.kids IdentitySet([__main__.Person object at 0x7fb6ce447b10]) obj has been created IdentitySet([__main__.Person object at 0x7fb6ce447b10]) And indeed, due to the commit() at the end, the person object makes it into the database: | test= select * from persons; id 10 (1 row) | But, I understood that objects (only) make it into a session by virtue of being explicitly added.