I'm pretty new in Python and SQLAlchemy, so basically I changed from:
session = Session()
session.query(SOMETHING_HERE).filter()
to
session = Session()
nested_session = session.begin_nested()
nested_session.query(SOMETHING_HERE).filter()
in order to use SAVEPOINTS. But I'm getting the error:
AttributeError: 'SessionTransaction' object has no attribute 'query'
I did a deep dive in the documentation, like these:
https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.SessionTransaction
https://docs.sqlalchemy.org/en/13/orm/session_transaction.html
But it did not help me.
Questions: Am I able to use begin_nested to run query with filter like that or I need to change the approach? Is this a version issue (sql alchemy for example)?
This was originally posted as a comment.
You don't need to reassign the result of session.begin_nested() to anything, you can just do: session.begin_nested() and then proceed with session.query(SOMETHING_HERE).filter()
Reference for this assertion: https://docs.sqlalchemy.org/en/13/orm/session_transaction.html#using-savepoint
Related
When using SQLAlchemy (version 1.4.44) to create, drop or otherwise modify tables, the updates don't appear to be committing. Attempting to solve this, I'm following the docs and using the commit() function. Here's a simple example
from sqlalchemy import create_engine, text
engine = create_engine("postgresql://user:password#connection_string:5432/database_name")
with engine.connect() as connection:
sql = "create table test as (select count(1) as result from userquery);"
result = connection.execute(text(sql))
connection.commit()
This produces the error:
AttributeError: 'Connection' object has no attribute 'commit'
What am I missing?
The comment on the question is correct you are looking at the 2.0 docs but all you need to do is set future=True when calling create_engine() to use the "commit as you go" functionality provided in 2.0.
SEE migration-core-connection-transaction
When using 2.0 style with the create_engine.future flag, “commit as
you go” style may also be used, as the Connection features autobegin
behavior, which takes place when a statement is first invoked in the
absence of an explicit call to Connection.begin():
The documentation is actually misleading (version 1.4). We can see using Connection.commit() method in documentation describing rows inserting, but the method doesn't exist.
I have managed to find a clarity explanation for using transations in the transactions section:
The block managed by each .begin() method has the behavior such that the transaction is committed when the block completes. If an exception is raised, the transaction is instead rolled back, and the exception propagated outwards.
Example from documentation below. There is no commit() method calling.
# runs a transaction
with engine.begin() as connection:
r1 = connection.execute(table1.select())
connection.execute(table1.insert(), {"col1": 7, "col2": "this is some data"})
Sorry if this seems like a really stupid question. I am building an app using Django, and at some point I am accessing the db using db.objects.get(var = val)
But my question is what type object does this method return? And hw can I access the data in it?
Like as a dict, list or sth else?
When I use this:
a = db.objects.get(var=val)
print(a["id"])
It returns:
'db' object is not subscriptable
When I use this:
a = db.objects.get(var=val)
print(a)
I get:
db object (1)
I cannot use the data in this form.
It will return a object. See the docs for details.
Use . operator to access values inside object.
print(a.field_name)
It would return the object of your model on which you are querying.
If nothing matches and no rows is returned, it would through a Model.DoesNotExists exception.
As I already know that using .query.__str__() , we can get sql equivalent query from Django ORM query.
e.g : Employees.objects.filter(id = int(id)).query.__str__()
Above code working well & I am able to get sql equivalent query
but when I am using same on below query I am getting error like below.
Employees.objects.filter(id = int(id)).first().query.__str__()
AttributeError: 'Employees' object has no attribute 'query'
Why now I am getting error, any suggestions ?
.first() [Django-doc] does not return a QuerySet, it returns a model object. The query is evaluated eagerly.
You can inspect the last query that Django made with:
from django.db import connection
print(connection.queries[-1:])
That being said, in essence a some_queryset.first() is often the same query as some_queryset, except that it will limit the queryset.
Note: Please do not use .__str__, you can use str(my_queryset.query), or just print(my_queryset.query).
Hi I am using Flask Peewee and trying to update merchant_details model but it is not working.
Following is the error I am getting:
AttributeError: 'SelectQuery' object has no attribute 'update'
mdetails = merchant_details.filter(merchant_details.merchant_id==session['userid']).update(
merchant_name=request.form['merchantname'],
first_name=request.form['firstname'],
last_name=request.form['lastname'],
)
Please Help!
First, it looks like you are using pre-2.0 syntax (the filter method is now deprecated). I'd recommend looking at the docs for info on the latest version.
Typically, you do not "update a query". The two main ways of accomplishing this is are...
1.) Use a query to retrieve an object, then use the save() method to update the object. For example...
mdetails = MerchantDetails.select().where(MerchantDetails.id == 42).get()
mdetails.name = 'new name'
mdetails.save() # Will do the SQL update query.
2.) Use a SQL update statement...
q = MerchantDetails.update(name='new name')
.where(MerchantDetails.id == 42)
q.execute() # Will do the SQL update query.
Both of these, in essence, accomplish the same thing. The first will make two queries o the database (one to SELECT the record, another to UPDATE the record), while the second will only use one SQL call (to UPDATE the record).
I got the solution
mdetails = merchant_details.update(
merchant_name=request.form['merchantname'],
first_name=request.form['firstname'],
last_name=request.form['lastname'],
street_1=request.form['street1'],
street_2=request.form['street2'],
state=request.form['state'],
city=request.form['city'],
phone=request.form['phone'],
zipcode=request.form['zip'],
).where(merchant_details.merchant_id==session['userid'])
mdetails.execute()
Anyways Thanks Mark
I searched for this solution too and thanks to #Mark and #Rohit I changed my code (peeweee with PostgreSQL) and is working.
To add a small improve it seems the update will be executed even if you will not use the variable. For me is simpler and a cleaner code:
merchant_details.update(
merchant_name=request.form['merchantname'],
first_name=request.form['firstname'],
last_name=request.form['lastname'],
street_1=request.form['street1'],
street_2=request.form['street2'],
state=request.form['state'],
city=request.form['city'],
phone=request.form['phone'],
zipcode=request.form['zip'],
).where(merchant_details.merchant_id==session['userid']).execute()
While trying to do the following operation:
for line in blines:
line.account = get_customer(line.AccountCode)
I am getting an error while trying to assign a value to line.account:
DetachedInstanceError: Parent instance <SunLedgerA at 0x16eda4d0> is not bound to a Session; lazy load operation of attribute 'account' cannot proceed
Am I doing something wrong??
"detached" means you're dealing with an ORM object that is not associated with a Session. The Session is the gateway to the relational database, so anytime you refer to attributes on the mapped object, the ORM will sometimes need to go back to the database to get the current value of that attribute. In general, you should only work with "attached" objects - "detached" is a temporary state used for caching and for moving objects between sessions.
See Quickie Intro to Object States, then probably read the rest of that document too ;).
I had the same problem with Celery. Adding lazy='subquery' to relationship solved my problem.
I encountered this type of DetachedInstanceError when I prematurely close the query session (that is, having code to deal with those SQLAlchemy model objects AFTER the session is closed). So that's one clue to double check no session closure until you absolutely don't need interact with model objects, I.E. some Lazy Loaded model attributes etc.
I had the same problem when unittesting.
The solution was to call everything within the "with" context:
with self.app.test_client() as c:
res = c.post('my_url/test', data=XYZ, content_type='application/json')
Then it worked.
Adding the lazy attribute didn't work for me.
To access the attribute connected to other table, you should call it within session.
#contextmanager
def get_db_session(engine):
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
db = SessionLocal()
try:
yield db
except Exception:
db.rollback()
raise
finally:
db.close()
with get_db_session(engine) as sess:
data = sess.query(Groups).all()
# `group_users` is connected to other table
print([x.group_users for x in data]) # sucess
print([x.group_users for x in data]) # fail