Ok, copied to https://bitbucket.org/zzzeek/sqlalchemy/issues/3941
W dniu piątek, 17 marca 2017 15:34:11 UTC+1 użytkownik Mike Bayer napisał: > > that's not a bad idea at all can you transfer this to a bug report at > https://bitbucket.org/zzzeek/sqlalchemy/issues?status=new&status=open ? > that would be helpful. > > > > On 03/17/2017 09:11 AM, bartwo...@gmail.com <javascript:> wrote: > > I've run into autoflush issue while using AssociationProxy with > > sqlalchemy-1.1.6. Appending to association list fails, because object is > > flushed before it is appended (and appending sets primary key value). I > > can avoid it with session.no_autoflush context manager, but I wonder if > > it's not worth slightly changing proxy behaviour to make it work with > > autoflush enabled. > > > > Minimal example of this issue below: > > > > | > > engine =engine_from_config(CONFIG) > > DBSession=scoped_session(sessionmaker()) > > DBSession.configure(bind=engine) > > Base=declarative_base() > > > > > > classUserAlias(Base): > > __tablename__ ='user_aliases' > > user_id =Column(Integer,ForeignKey('user.id'),primary_key=True) > > alias_id =Column(Integer,ForeignKey('aliases.id'),primary_key=True) > > valid =Column(Boolean) > > > > > alias=relationship('Alias',backref=backref('user_assocs',uselist=False)) > > user =relationship('User',backref=backref('alias_assocs')) > > > > def__init__(self,alias,valid=True): > > self.alias=alias > > self.valid =valid > > > > > > classAlias(Base): > > __tablename__ ='aliases' > > id =Column(Integer,primary_key=True) > > name =Column('name',String(64)) > > > > user =association_proxy('user_assocs','user') > > > > def__init__(self,name): > > self.name =name > > > > > > classUser(Base): > > __tablename__ ='user' > > id =Column(Integer,primary_key=True) > > name =Column(String(64)) > > > > aliases =association_proxy('alias_assocs','alias') > > > > def__init__(self,name): > > self.name =name > > > > > > deftest_assoc(): > > user =User(name='John') > > DBSession.add(user) > > DBSession.commit() > > > > johny =Alias(name='Johny') > > user.aliases.append(johny) > > DBSession.commit() > > > > jan =Alias(name='Jan') > > DBSession.add(jan) # in my real use case proxied object is already > > attached to session before appending, here I simulate it with > DBSession.add > > user.aliases.append(jan) # autoflush fails here > > > > DBSession.commit() > > returnuser > > | > > > > and stacktrace: > > > > | > > > /home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/sql/crud.py:692:SAWarning:Column'user_aliases.user_id'ismarked > > > > asa member of the primary key fortable 'user_aliases',but has > > noPython-side orserver-side defaultgenerator indicated,nor does it > > indicate 'autoincrement=True'or'nullable=True',andnoexplicitvalue > > ispassed. Primarykey columns typically may notstore NULL.Notethat asof > > SQLAlchemy1.1,'autoincrement=True'must be indicated explicitly > > forcomposite (e.g.multicolumn)primary keys > > ifAUTO_INCREMENT/SERIAL/IDENTITY behavior isexpected forone of the > > columns inthe primary key.CREATE TABLE statements are impacted > > bythischange aswell on most backends. > > util.warn(msg) > > Traceback(most recent call last): > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line > > > > 1182,in_execute_context > > context) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/default.py",line > > > > 470,indo_execute > > cursor.execute(statement,parameters) > > psycopg2.IntegrityError:nullvalue incolumn "user_id"violates > > not-nullconstraint > > DETAIL: Failingrow contains (null,50,t). > > > > > > Theabove exception was the direct cause of the following exception: > > > > Traceback(most recent call last): > > File"/home/bartek/dev/sqlalchemy-test/sqlalchemy_test/models.py",line > > 111,in<module> > > test_assoc() > > File"/home/bartek/dev/sqlalchemy-test/sqlalchemy_test/models.py",line > > 105,intest_assoc > > user.aliases.append(jan) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/ext/associationproxy.py",line > > > > 610,inappend > > self.col.append(item) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/ext/associationproxy.py",line > > > > 509,in<lambda> > > col =property(lambdaself:self.lazy_collection()) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/ext/associationproxy.py",line > > > > 467,in__call__ > > returngetattr(obj,self.target) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/attributes.py",line > > > > 237,in__get__ > > returnself.impl.get(instance_state(instance),dict_) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/attributes.py",line > > > > 584,inget > > value =self.callable_(state,passive) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/strategies.py",line > > > > 557,in_load_for_state > > returnself._emit_lazyload(session,state,ident_key,passive) > > File"<string>",line 1,in<lambda> > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/strategies.py",line > > > > 635,in_emit_lazyload > > result =q.all() > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/query.py",line > > > > 2679,inall > > returnlist(self) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/query.py",line > > > > 2830,in__iter__ > > self.session._autoflush() > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line > > > > 1375,in_autoflush > > util.raise_from_cause(e) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line > > > > 203,inraise_from_cause > > reraise(type(exception),exception,tb=exc_tb,cause=cause) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line > > > > 187,inreraise > > raisevalue > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line > > > > 1365,in_autoflush > > self.flush() > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line > > > > 2139,inflush > > self._flush(objects) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line > > > > 2259,in_flush > > transaction.rollback(_capture_exception=True) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/langhelpers.py",line > > > > 60,in__exit__ > > compat.reraise(exc_type,exc_value,exc_tb) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line > > > > 187,inreraise > > raisevalue > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/session.py",line > > > > 2223,in_flush > > flush_context.execute() > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/unitofwork.py",line > > > > 389,inexecute > > rec.execute(self) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/unitofwork.py",line > > > > 548,inexecute > > uow > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/persistence.py",line > > > > 181,insave_obj > > mapper,table,insert) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/orm/persistence.py",line > > > > 835,in_emit_insert_statements > > execute(statement,params) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line > > > > 945,inexecute > > returnmeth(self,multiparams,params) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/sql/elements.py",line > > > > 263,in_execute_on_connection > > returnconnection._execute_clauseelement(self,multiparams,params) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line > > > > 1053,in_execute_clauseelement > > compiled_sql,distilled_params > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line > > > > 1189,in_execute_context > > context) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line > > > > 1393,in_handle_dbapi_exception > > exc_info > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line > > > > 203,inraise_from_cause > > reraise(type(exception),exception,tb=exc_tb,cause=cause) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/util/compat.py",line > > > > 186,inreraise > > raisevalue.with_traceback(tb) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/base.py",line > > > > 1182,in_execute_context > > context) > > > > > File"/home/bartek/envs/sqlalchemy-test/lib/python3.5/site-packages/sqlalchemy/engine/default.py",line > > > > 470,indo_execute > > cursor.execute(statement,parameters) > > sqlalchemy.exc.IntegrityError:(raised asa result of Query-invoked > > autoflush;consider usinga session.no_autoflush block ifthisflush > > isoccurring prematurely)(psycopg2.IntegrityError)nullvalue incolumn > > "user_id"violates not-nullconstraint > > DETAIL: Failingrow contains (null,50,t). > > [SQL:'INSERT INTO user_aliases (alias_id, valid) VALUES (%(alias_id)s, > > %(valid)s)'][parameters:{'alias_id':50,'valid':True}] > > | > > > > Autoflush occurs in _AssociationList append method: > > > > | > > defappend(self,value): > > item =self._create(value) > > self.col.append(item) > > | > > > > If _create was called before self.col is evaluted created object would > > not be autoflushed prematurely. Maybe it is worth changing it if it does > > not break anything else. > > > > -- > > 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+...@googlegroups.com <javascript:> > > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:>>. > > To post to this group, send email to sqlal...@googlegroups.com > <javascript:> > > <mailto:sqlal...@googlegroups.com <javascript:>>. > > 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.