Re: [sqlalchemy] Cascade relationship from child to parent

2018-09-15 Thread Mike Bayer
On Fri, Sep 14, 2018 at 4:46 PM, Edans Sandes  wrote:
> Hello,
>
> I got stuck on a problem related to relatioships and cascades. In the docs,
> we have the following explanation:
>
> Cascades:
>
>
>
> Mappers support the concept of configurable cascade behavior on
> relationship() constructs. This refers to how operations performed on a
> “parent” object relative to a particular Session should be propagated to
> items referred to by that relationship (e.g. “child” objects), and is
> affected by the relationship.cascade option.
>
>
>
> It seems to me that the cascade attribute works only in the parent->child
> direction. Right now, I'm trying to figure out how to create one child with
> its parent_id, followed by an automatic refresh of its parent children list
> (i.e. without appending the child to the parent children list). Maybe it is
> not a good practice to use parent ids in ORM, but I'm wondering if it is
> possible to do it so. Sometimes we only want to create a child to a
> parent_id, without loading the parent object.
>
>
> Let me show the source code that reproduce my problem:
>
> from sqlalchemy import Table, Column, Integer, String, ForeignKey
> from sqlalchemy.orm import relationship, backref, sessionmaker
> from sqlalchemy.ext.declarative import declarative_base
> from sqlalchemy import create_engine
>
> Base = declarative_base()
>
> Base = declarative_base()
>
> class Parent(Base):
> __tablename__ = 'parent'
> parent_id = Column(Integer, primary_key=True)
> children = relationship("Child", back_populates="parent", cascade="all")
>
> class Child(Base):
> __tablename__ = 'child'
> child_id = Column(Integer, primary_key=True)
> name = Column(String)
> parent_id = Column(Integer, ForeignKey('parent.parent_id'))
> parent = relationship("Parent", back_populates="children",
> cascade="all")
>
> engine = create_engine('sqlite:///:memory:', echo=False)
> Session = sessionmaker(bind=engine)
> Session.configure(bind=engine)
> Base.metadata.create_all(engine)
>
> s = Session()
>
> p = Parent()
> c1 = Child(name="C1")
> p.children.append(c1)
>
> s.add(p)
> s.flush()
>
> print([x.name for x in p.children])  # ['C1']
>
> c2 = Child(parent_id=1, name="C2")
> s.add(c2)
> s.flush()
>
> print([x.name for x in p.children])  # ['C1']
>
> s.refresh(c2.parent) # This solves my problem, but I would like to know how
> to do it automatically without an explicit refresh
>
> print([x.name for x in p.children])  # ['C1','C2']
>
> s.close()
>
>
>
> In this code, when I create child "C2" pointing it to parent_id=1, the
> parent object (children relationship) is not refreshed automatically. So, it
> only prints the first child: C1. After the refresh, I see both children C1
> and C2.

This FAQ entry should cover everything, note there's an event-based
recipe at the bottom as well:

http://docs.sqlalchemy.org/en/latest/faq/sessions.html#i-set-the-foo-id-attribute-on-my-instance-to-7-but-the-foo-attribute-is-still-none-shouldn-t-it-have-loaded-foo-with-id-7




> Is there any option that refresh the parent authomatically? Is there
> anything that I'm missing?
>
>
> Thanks!
> Edans Sandes
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> 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 https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
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 https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] Cascade relationship from child to parent

2018-09-14 Thread Edans Sandes
Hello, 

I got stuck on a problem related to relatioships and cascades. In the docs 
, we have the 
following explanation:

Cascades:

 

*Mappers support the concept of configurable cascade behavior 
on relationship() 

 constructs. This 
refers to how operations performed on a “parent” object relative to a 
particular Session 

 should 
be propagated to items referred to by that relationship (e.g. “child” 
objects), and is affected by the relationship.cascade 

 option.*



It seems to me that the cascade attribute works only in the parent->child 
direction. Right now, I'm trying to figure out how to create one child with 
its parent_id, followed by an automatic refresh of its parent children list 
(i.e. without appending the child to the parent children list). Maybe it is 
not a good practice to use parent ids in ORM, but I'm wondering if it is 
possible to do it so. Sometimes we only want to create a child to a 
parent_id, without loading the parent object.


Let me show the source code that reproduce my problem:

from sqlalchemy import Table, Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, backref, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine

Base = declarative_base()

Base = declarative_base()

class Parent(Base):
__tablename__ = 'parent'
parent_id = Column(Integer, primary_key=True)
children = relationship("Child", back_populates="parent", cascade="all")

class Child(Base):
__tablename__ = 'child'
child_id = Column(Integer, primary_key=True)
name = Column(String)
parent_id = Column(Integer, ForeignKey('parent.parent_id'))
parent = relationship("Parent", back_populates="children", 
cascade="all")

engine = create_engine('sqlite:///:memory:', echo=False)
Session = sessionmaker(bind=engine)
Session.configure(bind=engine)
Base.metadata.create_all(engine)

s = Session()

p = Parent()
c1 = Child(name="C1")
p.children.append(c1)

s.add(p)
s.flush()

print([x.name for x in p.children])  # ['C1']

c2 = Child(parent_id=1, name="C2")
s.add(c2)
s.flush()

print([x.name for x in p.children])  # ['C1']

s.refresh(c2.parent) # This solves my problem, but I would like to know how 
to do it automatically without an explicit refresh

print([x.name for x in p.children])  # ['C1','C2']

s.close()



In this code, when I create child "C2" pointing it to parent_id=1, the 
parent object (children relationship) is not refreshed automatically. So, 
it only prints the first child: C1. After the refresh, I see both children 
C1 and C2.
Is there any option that refresh the parent authomatically? Is there 
anything that I'm missing?


Thanks!
Edans Sandes

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
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 https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.