Thanks, Mike! I have some studying to do...
On Wednesday, February 3, 2021 at 6:42:17 PM UTC-5 Mike Bayer wrote:
>
>
> On Wed, Feb 3, 2021, at 6:23 PM, Christian Henning wrote:
>
> Hi Mike,
>
> thanks for your advice! I'll make the changes.
>
> But let me ask you one thing. My classmethod create() is but more complex
> than I have posted. It's meant to catch IntegrityError so that unique
> constraints are enforced. Image a User table has a "unique" constraint on
> the name. When I try to create a user with the same name the create() would
> catch the exception and return the original user. I believe this only
> possible when all objects are committed to the database.
>
> class ModelBase:
>
> @classmethod
> def create(cls, session, **kwargs):
> obj = cls(**kwargs)
> try:
> obj.save(session)
> except IntegrityError:
> # print('HOLA - Integrity Error')
>
> session.rollback()
> obj = cls.find(session, **kwargs)
>
> return obj
>
> def save(self, session):
> session.add(self)
> session.commit()
>
> How would you solve the problem? Is there anything in the documentation?
>
>
> yes, use a SAVEPOINT for that, so you can roll back to the savepoint and
> still have the transaction continue:
>
>
> https://docs.sqlalchemy.org/en/13/faq/sessions.html#but-why-does-flush-insist-on-issuing-a-rollback
>
> so you can place in your method:
>
> session.begin_nested():
> session.add(obj)
> try:
> session.flush()
> except IntegrityError:
> session.rollback()
> else:
> session.commit()
>
>
>
>
> Thanks,
> Christian
>
>
>
>
>
> On Wednesday, February 3, 2021 at 5:12:30 PM UTC-5 Mike Bayer wrote:
>
>
> the session.commit() method expires all attributes by default:
>
> https://docs.sqlalchemy.org/en/13/orm/session_basics.html#committing
>
> your code is organized in an unusual way such that transactions are being
> committed inside of attribute assignment operations:
>
> jack.addresses.append(Address.create(session))
>
> We can expand this out as follows:
>
> addr = jack.addresses
> address = Address()
> session.add(address)
> session.commit() # <--- expires all attributes on "jack", "address",
> invalidates "addr"
> attr.append(address) # <--- this is invalid, transaction was already
> commited
>
> I would strongly advise keeping session scope manage external to the set
> of operations you are performing. See
> https://docs.sqlalchemy.org/en/13/orm/session_basics.html#when-do-i-construct-a-session-when-do-i-commit-it-and-when-do-i-close-it
>
> for guidelines.
>
>
> On Wed, Feb 3, 2021, at 2:27 PM, Christian Henning wrote:
>
> I don't understand why SQLAlchemy gives me the following warning:
>
> SAWarning: This collection has been invalidated.
> util.warn("This collection has been invalidated.")
>
> Here is a minimal code example:
>
> -----------------
> -----------------
>
> import sqlalchemy
> print(sqlalchemy.__version__)
>
> from sqlalchemy import create_engine
> from sqlalchemy import Column, Integer, ForeignKey
>
> from sqlalchemy.exc import IntegrityError
> from sqlalchemy.ext.declarative import declarative_base
>
> from sqlalchemy.orm import relationship
> from sqlalchemy.orm import sessionmaker
>
> Base = declarative_base()
>
> class ModelBase:
>
> @classmethod
> def create(cls, session, **kwargs):
> obj = cls(**kwargs)
> session.add(obj)
> session.commit()
>
> return obj
>
>
> class User(ModelBase, Base):
> __tablename__ = 'users'
>
> id = Column(Integer, primary_key=True)
>
> addresses = relationship("Address", order_by="Address.id",
> back_populates="user")
>
> class Address(ModelBase, Base):
> __tablename__ = 'addresses'
>
> id = Column(Integer, primary_key=True)
>
> user_id = Column(Integer, ForeignKey('users.id'))
>
> user = relationship("User", back_populates="addresses")
>
>
> engine = create_engine('sqlite:///:memory:', echo=False)
> Base.metadata.create_all(engine)
>
> Session = sessionmaker(bind=engine)
> session = Session()
>
> jack = User.create(session)
> jack.addresses.append(Address.create(session))
>
> -----------------
> -----------------
> I have tested the code with SQLAlchemy for 1.3.18 and 1.4.0b1. I'm using
> python 3.9.1
>
> When I rewrite the last few lines a bit the warning disappears. For
> instance:
>
> jack = User.create(session)
> a = Address.create(session)
> jack.addresses.append(a)
>
>
> Any insight is appreciated. I'm still learning.
>
> Thanks,
> Christian
>
>
>
> --
> 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 [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sqlalchemy/7a369ff7-659c-4ee4-a8d0-a786ec3579aen%40googlegroups.com
>
> <https://groups.google.com/d/msgid/sqlalchemy/7a369ff7-659c-4ee4-a8d0-a786ec3579aen%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
>
>
> --
> 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 [email protected].
>
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sqlalchemy/ba9d2326-976f-4418-bb92-f5e120fd3f52n%40googlegroups.com
>
> <https://groups.google.com/d/msgid/sqlalchemy/ba9d2326-976f-4418-bb92-f5e120fd3f52n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
>
>
--
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/sqlalchemy/32220880-7f26-4cb4-9068-d57104d2faabn%40googlegroups.com.