How do I create a non-persistent Elixir / SQLAlchemy object?

Due to stale data that is not available in the database, but some external files, I want to create a SQLAlchemy object that contains data read from external files, but not written to the database if I execute session.flush()

My code looks like this:

try:
  return session.query(Phone).populate_existing().filter(Phone.mac == ident).one()
except:
  return self.createMockPhoneFromLicenseFile(ident)

def createMockPhoneFromLicenseFile(self, ident):
  # Some code to read necessary data from file deleted....
  phone = Phone()
  phone.mac = foo
  phone.data = bar
  phone.state = "Read from legacy file"
  phone.purchaseOrderPosition = self.getLegacyOrder(ident)
  # SQLAlchemy magic doesn't seem to work here, probably because we don't insert the created
  # phone object into the database. So we set the id fields manually.
  phone.order_id = phone.purchaseOrderPosition.order_id
  phone.order_position_id = phone.purchaseOrderPosition.order_position_id
  return phone 

      

Everything works fine, except that on session.flush()

, executed later in the application, SQLAlchemy tries to write the created Phone object to the database (which fortunately failed as phone.state is longer than the data type allows) which destroys the function that issues flush.

Is there a way to prevent SQLAlchemy from trying to write an object like this?

Update

So far I haven't found anything on

using_mapper_options(save_on_init=False)

      

in the Elixir documentation (maybe you can provide a link?), I thought it was worth trying (I would prefer a way to prevent a single instance from being written instead of the whole entity).

At first, the statement seemed to have no effect and I suspected that my versions of SQLAlchemy / Elixir were too old, but then I found out that the connection to the PurchaseOrderPosition object (which I did not change) was made with

phone.purchaseOrderPosition = self.getLegacyOrder(ident) 

      

causes the phone object to be recorded again. If I delete the statement, everything is fine.

+2


a source to share


3 answers


You need to do

import elixir
elixir.options_defaults['mapper_options'] = { 'save_on_init': False }

      

to prevent the instances Entity

you create from being automatically added to the session. Ideally, this should be done as early as possible in your code. You can also do this on an entity basis, via using_mapper_options(save_on_init=False)

- see the Elixir documentation for more details.



Update:

See this post on the Elixir mailing list indicating this is a solution.

Also, as Ants Aasma points out, you can use cascade parameters in relation to Elixir to tune cascade parameters in SQLAlchemy. See this page for details .

+3


a source


Well sqlalchemy is not the default.

Consider the following stand-alone example code.



from sqlalchemy import Column, Integer, Unicode, create_engine
from sqlalchemy.orm import create_session
from sqlalchemy.ext.declarative import declarative_base

e = create_engine('sqlite://')
Base = declarative_base(bind=e)

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(50))

# create the empty table and a session
Base.metadata.create_all()
s = create_session(bind=e, autoflush=False, autocommit=False)

# assert the table is empty
assert s.query(User).all() == []

# create a new User instance but don't save it to database:
u = User()
u.name = 'siebert'
# I could run s.add(u) here but I won't

s.flush()
s.commit()

# assert the table is still empty
assert s.query(User).all() == []

      

So I'm not sure if the implication is adding your instances to the session. You usually have to manually invoke s.add(u)

to go to the session. I am not familiar with the elixir, so maybe this is some kind of elixir trick ... Maybe you can remove it from the session using session.expunge()

.

0


a source


Old post, but I faced a similar problem, in my case in sqlalchemy it was caused by a cascade on the backrefs:

http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#backref-cascade

Disable it on your backrefs so that you explicitly add things to the session

0


a source







All Articles