SQLalchemy select using ORM the resulting row contains only memory location - python

I think I have misunderstood something critical and obvious, I am attempting to use the SqlAlchemy ORM to select a row from a table in a database and return the values. The first step is to get the row and access it, from there I think I'm good however, when I select the row and try and investigate the object that is returned, all I find is an address for the object in memory: <main.UserMap object at 0x000001F65A54B490>,
Attempting to use objprint to investigate the object gives no further information, I am confused as per my understanding the resulting row object should behave like a tuple so at least objprint should find a variety of entries within it even if it can't print them due to them being differen't data types.
The statement in question:
select(UserMap).where(UserMap.google_auth == '***********************')
a more basic select(UserMap) also seems to give a similar result.
The table contains some fields as strings, some as integers and some in date and time formats but obviously only one type per column.
I am using session.execute, I would like to avoid query as I understand that it's functionality is being deprecated in the 2.x API, if I have misunderstood this then I am happy to attempt that but would still like to understand what I am getting wrong about the result and row objects.
As I said, I think I have missed something important, but don't realise what, as far as I can see I am executing the statements in much the same way as shown in the ORM documentation e.g:
>>> stmt = select(User).where(User.name == 'spongebob')
>>> with Session(engine) as session:
... for row in session.execute(stmt):
... print(row)

<main.UserMap object at 0x000001F65A54B490> is the default string representation of an ORM object. You can retrieve the attributes (properties) of the object using the standard syntax:
me = UserMap(user_name="Gord")
print(me) # <main.UserMap object at 0x000001F65A54B490>
print(me.user_name) # Gord

Related

SQLAlchemy returns a result double - even when only one is expected

I'm writing a flask - sqlalchemy database.
I'dont understand nor do I find a solution. If I write a query, it returns the row double...
The database Class has indeed two rows, but they are different.
data = db.session.query(Class).filter_by(Class.id==1).first()
print(data)
<Class>
<Class>
Check if 'data' variable is not defined somewhere earlier in the code, resulting in two rows.
The query, as you have written it, should actually result in a TypeError (wrong use of filter_by method).
It should be either:
data = db.session.query(Class).filter_by(id=1).first()
or
data = db.session.query(Class).filter(Class.id==1).first()

How to filter on calculated column of a query and meanwhile preserve mapped entities

I have a query which selects an entity A and some calculated fields
q = session.query(Recipe,func.avg(Recipe.somefield).join(.....)
I then use what I select in a way which assumes I can subscript result with "Recipe" string:
for entry in q.all():
recipe=entry.Recipe # Access KeyedTuple by Recipe attribute
...
Now I need to wrap my query in an additional select, say to filter by calculated field AVG:
q=q.subquery();
q=session.query(q).filter(q.c.avg_1 > 1)
And now I cannot access entry.Recipe anymore!
Is there a way to make SQLAlchemy adapt a query to an enclosing one, like aliased(adapt_on_names=True) orselect_from_entity()`?
I tried using those but was given an error
As Michael Bayer mentioned in a relevant Google Group thread, such adaptation is already done via Query.from_self() method. My problem was that in this case I didn't know how to refer a column which I want to filter on
This is due to the fact, that it is calculated i.e. there is no table to refer to!
I might resort to using literals(.filter('avg_1>10')), but 'd prefer to stay in the more ORM-style
So, this is what I came up with - an explicit column expression
row_number_column = func.row_number().over(
partition_by=Recipe.id
).label('row_number')
query = query.add_column(
row_number_column
)
query = query.from_self().filter(row_number_column == 1)

SQLAlchemy func issue with date and .isocalendar()

I have a table that stores tasks submitted by users, with timestamps. I would like to write a query that returns certain rows based on when they were submitted (was it this day/week/month..).
To check if it was submitted on this week, I wanted to use date.isocalendar()[1] function. The problem is, that my timestamps are datetimes, so I would need to transform those to dates.
Using func:
filter(func.date(Task.timestamp) == datetime.date(datetime.utcnow()))
works properly.
But I need the date object's isocalendar() method, so I try
filter(func.date(Task.timestamp).isocalendar()[1]==datetime.date(datetime.utcnow()).isocalendar()[1])
and it's no good, I get AttributeError: Neither 'Function' object nor 'Comparator' object has an attribute 'isocalendar'
If I make a simple query and try datetime.date(task.timestamp).isocalendar()[1] it works properly.
How do I get it to work in the query's filter?
Rule of thumb when understanding and debugging sqlalchemy queries is to always think – "How will it look in SQL?"
isocalendar() is a python function, and sqlalchemy query filters get compiled to SQL. Moreover, isocalendar() returns a tuple – and while rendering tuple comparison as SQL is probably possible, it's more trouble then it's worth. You should compare scalars and find sql date functions that suit you.
It seems you're looking to compare week number, so something like this should do the trick:
filter(func.week(Task.timestamp)==datetime.utcnow().isocalendar()[1])
Can you try sqlalchemy.extract(func.date('year', Task.timestamp)) == ... ?
You cannot mix pure python functions with those which are executed on the SQL backend. From your code it looks like you are trying to filter on the iso week. One way to do it would be to load everything from the database into memory and perform the filtering there. Obviously, it most cases it is far from efficient.
An alternative would be to use respective SQL functions, which sqlalchemy will call for you. On MySQL it looks like the function you need is weekofyear, so your filter might look similar to below:
_utcnow = datetime.utcnow().date()
_isoweek = _utcnow.isocalendar()[1]
q = db.session.query(...)
# ...
q = q.filter(db.func.weekofyear(Task.timestamp) == _isoweek)

column names and types for insert operation in sqlalchemy

I am building a sqlite browser in Python/sqlalchemy.
Here is my requirement.
I want to do insert operation on the table.
I need to pass a table name to a function. It should return all columns along with the respective types.
Can anyone tell me how to do this in sqlalchemy ?
You can access all columns of a Table like this:
my_table.c
Which returns a type that behaves similar to a dictionary, i.e. it has values method and so on:
columns = [(item.name, item.type) for item in my_table.c.values()]
You can play around with that to see what you can get from that. Using the declarative extension you can access the table through the class' __table__ attribute. Furthermore, you might find the Runtime Inspection API helpful.

Any easy way to alter the data that comes from a mysql database?

so I'm using mysql to grab data from a database and feeding it into a python function. I import mysqldb, connect to the database and run a query like this:
conn.query('SELECT info FROM bag')
x = conn.store_result()
for row in x.fetch_row(100):
print row
but my problem is that my data comes out like this (1.234234,)(1.12342,)(3.123412,)
when I really want it to come out like this: 1.23424, 1.1341234, 5.1342314 (i.e. without parenthesis). I need it this way to feed it into a python function. Does anyone know how I can grab data from the database in a way that doesn't have parenthesis?
Rows are returned as tuples, even if there is only one column in the query. You can access the first and only item as row[0]
The first time around in the for loop, row does indeed refer to the first row. The second time around, it refers to the second row, and so on.
By the way, you say that you are using mySQLdb, but the methods that you are using are from the underlying _mysql library (low level, scarcely portable) ... why??
You could also simply use this as your for loop:
for (info, ) in x.fetch_row(100):
print info

Categories