flush() communicates a series of operations to the database (insert, update, delete). The database maintains them as pending operations in a transaction.
As the documentation says, all() returns the result of the query as a list.
Return the first result of this Query or None if the result doesn't contain any row. first() applies a limit of one within the generated SQL, so that only one primary entity row is generated on the server side (note this may consist of multiple result rows if join-loaded collections are present).
_sa_instance_state is a non-database-persisted value used by SQLAlchemy internally (it refers to the InstanceState for the instance.
I've just run across the same problem, and after testing I have found that NONE of these answers are sufficient.
Currently, or as of sqlalchemy .6+, there is a very simple solution (I don't know if this exists in prior version, though I imagine it does):
session.refresh()
So, your code would look something like this:
f = Foo(bar=x)
session.add(f)
session.flush()
# At this point, the object f has been pushed to the DB,
# and has been automatically assigned a unique primary key id
f.id
# is None
session.refresh(f)
# refresh updates given object in the session with its state in the DB
# (and can also only refresh certain attributes - search for documentation)
f.id
# is the automatically assigned primary key ID given in the database.
That's how to do it.
Your sample code should have worked as it is. SQLAlchemy should be providing a value for f.id
, assuming its an autogenerating primary-key column. Primary-key attributes are populated immediately within the flush()
process as they are generated, and no call to commit()
should be required. So the answer here lies in one or more of the following:
Thanks for everybody. I solved my problem by modifying the column mapping. For me, autoincrement=True
is required.
origin:
id = Column('ID', Integer, primary_key=True, nullable=False)
after modified:
id = Column('ID', Integer, primary_key=True, autoincrement=True, nullable=True)
then
session.flush()
print(f.id)
is ok!
unlike the answer given by dpb, a refresh is not necessary. once you flush, you can access the id field, sqlalchemy automatically refreshes the id which is auto generated at the backend
I encountered this problem and figured the exact reason after some investigation, my model was created with id as integerfield and in my form the id was represented with hiddenfield( since i did not wanted to show the id in my form). The hidden field is by default represented as a text. once I changed the form to integerfield with widget=hiddenInput()) the problem was solved.
I once had a problem with having assigned 0
to id before calling session.add
method. The id was correctly assigned by the database but the correct id was not retrieved from the session after session.flush()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With