I want to pass a class to a function, and don't like to pass the name again.
class TableClass(Base):
__table__ = Table('t1', metadata, autoload=True)
def get_name(TableClass):
print TableClass.GetTableName() # print 't1'
get_name(TableClass)
So, I search it with google, and there is no answer.
According To:
How to discover table properties from SQLAlchemy mapped object
I can use this:
print TableClass.__table__.name
Independent on whether you use declarative extension or not, you can use the Runtime Inspection API:
def get_name(TableClass):
from sqlalchemy import inspect
mapper = inspect(TableClass)
print mapper.tables[0].name
Please note that a class can have multiple tables mapped to it, for example when using Inheritance.
print TableClass.__tablename__
works for me
In SQLAlchemy you can fetch table information with tableclass attributes.
In your example
print TableClass.__tablename__ # Prints 't1'
According to #Aylwyn Lake 's Finding
print TableClass.__table__.name
I just hit this issue myself, passing the object around and didn't want to pass the string of the tablename as well..
Turns out, it's just a property of the Table object, eg:
table = new Table("somename",meta)
...
print("My table is called: " + table.name)
None of the answers worked for me.
This did:
For Class Object:
TableClass.sa_class_manager.mapper.mapped_table.name
For Instance Object:
tableObj.sa_instance_state.mapper.mapped_table.name
Related
So I have a query...
qry = Query(models.UserList).filter(...)
models.UserList contains a mixin method that will return a count of a related table
So what I would like to do is something like ...
qry = qry.order_by(models.UserList.contactCount)
However this produces invalid sql of course.
So how can I do something like
qry.add_column((this.contactCount).label("contactCount"))
this.contactCount is just bad psuedocode, but hopefully you get the point.
I've been looking at how to do this for a while, but sqlalchemy doc isnt the easiest thing to find stuff in.
any help appreciated
You can use either a column_property or a hybrid_property for that. For example:
class UserList(Base):
...
contactCount = column_property(
select(
[func.count()],
contact_id == Contact.id,
).label('contactCount'),
deferred=True,
)
If I have an sqlalchemy-mapped instance. Can I get an underlying dynamic query object corresponding to an attribute of said instance?
For example:
e = Employee()
e.projects
#how do I get a query object loaded with the underlying sql of e.projects
I think you're describing the lazy="dynamic" property of relationship(). something like
class Employee(Base):
__table_name__ = "employees"
...
projects = relationship(..., lazy="dynamic")
which will cause Employee().project to return a sqlalchemy.orm.Query instance instead of a collection containing the related items. However, that means there's no (simple) way to access the collection directly. If you still need that (most likely you really do want it to be lazily loaded, set up two relationship()s instead.
class Employee(Base):
__table_name__ = "employees"
...
projects_query = relationship(..., lazy="dynamic")
projects = relationship(..., lazy="select")
edit: You said
I need somehow to get the dynamic query object of an already lazy relationship mapped property.
Supposing we have an instance i of class Foo related to a class Bar by the property bars. First, we need to get the property that handles the relationship.
from sqlalchemy.orm.attributes import manager_of_class
p = manager_of_class(Foo).mapper.get_property('bars')
We'd like an expression that and_s together all of the columns on i that relate it to bars. If you need to operate on Foo through an alias, substitute it in here.
e = sqlalchemy.and_(*[getattr(Foo, c.key) == getattr(i, c.key)
for c in p.local_side])
Now we can create a query that expresses this relationship. Substitute aliases for Foo and Bar here as needed.
q = session.query(Foo) \
.filter(e) \
.join(Foo.bars) \
.with_entities(Bar)
Not sure about the question in general, but you definitely can enable SQL logging by setting echo=True, which will log the SQL statement as soon as you try to get value of the attribute.
Depending on your relationship configuration, it might have been eagerly pre-loaded.
Is it possible to control which columns are queried in the query method of SQLAlchemy, while still returning instances of the object you are querying (albeit partially populated)?
Or is it necessary for SQLAlchemy to perform a SELECT * to map to an object?
(I do know that querying individual columns is available, but it does not map the result to an object, only to a component of a named tuple).
For example, if the User object has the attributes userid, name, password, and bio, but you want the query to only fill in userid and name for the objects it returns:
# hypothetical syntax, of course:
for u in session.query(User.columns[userid, name]).all():
print u
would print:
<User(1, 'bob', None, None)>
<User(2, 'joe', None, None)>
...
Is this possible; if so, how?
A simple solution that worked for me was:
users = session.query(User.userid, User.name)
for user in users:
print user
would print:
<User(1, 'bob')>
<User(2, 'joe')>
...
you can query for individual columns, which returns named tuples that do in fact act pretty much like your mapped object if you're just passing off to a template or something:
http://www.sqlalchemy.org/docs/orm/tutorial.html#querying
or you can establish various columns on the mapped class as "deferred", either configurationally or using options:
http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#deferred-column-loading
there's an old ticket in trac for something called "defer_everything_but()", if someone felt like providing tests and such there's no reason that couldn't be a feature add, here's a quick version:
from sqlalchemy.orm import class_mapper, defer
def defer_everything_but(entity, cols):
m = class_mapper(entity)
return [defer(k) for k in
set(p.key for p
in m.iterate_properties
if hasattr(p, 'columns')).difference(cols)]
s = Session()
print s.query(A).options(*defer_everything_but(A, ["q", "p"]))
defer() should really accept multiples, added ticket #2250 for that (edit: as noted in the comment this is in 0.9 as load_only())
Latest doc for load_only is here
http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#load-only-cols
If you're looking at a way to control that at model definition level, use deferred
http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#deferred
I'm trying to prepopulate lists of objects associateds. So for a specific mapped class, I list all tables with :
ExampleClass is my mapped python class, for example.
name = ExampleClass.__name__
tables = [x for x in ExampleClass.metadata.tables.keys() if x != name ]
So, I got the tables name but how can I get the class associated with that tables?
Is it possible?
I'm using the declarative way to map the table and class.
Thanks in advance.
I found this way passing the table name param found in list tables
def __find_class(self, table):
for x in mapperlib._mapper_registry.items():
if x[0].mapped_table.name == table:
return x[0].class_
All the docs for SQLAlchemy give INSERT and UPDATE examples using the local table instance (e.g. tablename.update()... )
Doing this seems difficult with the declarative syntax, I need to reference Base.metadata.tables["tablename"] to get the table reference.
Am I supposed to do this another way? Is there a different syntax for INSERT and UPDATE recommended when using the declarative syntax? Should I just switch to the old way?
well it works for me:
class Users(Base):
__tablename__ = 'users'
__table_args__ = {'autoload':True}
users = Users()
print users.__table__.select()
...SELECT users.......
via the __table__ attribute on your declarative class
There may be some confusion between table (the object) and tablename (the name of the table, a string). Using the table class attribute works fine for me.