Last active
August 29, 2015 14:19
-
-
Save aodag/ab3c3f0f9fff3eb0ef0f to your computer and use it in GitHub Desktop.
filter内で使いたいhybrid_methodをQueryオブジェクトのメソッドのようにして流すアイディアの検討
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sqlalchemy.sql import func | |
def query_maker(session, cls): | |
query = session.query(cls) | |
return Adapter(query, cls) | |
def faster_count_query(query): | |
count_q = query.statement.with_only_columns([func.count()]).order_by(None) | |
return query.session.execute(count_q).scalar() | |
class QueryFactory(object): | |
def __init__(self, session): | |
self.session = session | |
def __call__(self, cls): | |
return query_maker(self.session, cls) | |
class Adapter(object): | |
def __init__(self, query, cls): | |
self.query = query | |
self.cls = cls | |
def __getattr__(self, name): | |
attr = getattr(self.cls, name) | |
return QueryWrapper(self.query, | |
self.cls, | |
attr) | |
def __iter__(self): | |
return iter(self.query) | |
def __len__(self): | |
return faster_count_query(self.query) | |
class QueryWrapper(object): | |
def __init__(self, query, cls, attr): | |
self.query = query | |
self.cls = cls | |
self.attr = attr | |
def __call__(self, *args, **kwargs): | |
query = self.query.filter( | |
self.attr(*args, **kwargs)) | |
return Adapter(query, self.cls) | |
def __getattr__(self, name): | |
query = self.query.filter(self.attr) | |
attr = getattr(self.cls, name) | |
return QueryWrapper(query, | |
self.cls, | |
attr) | |
def __iter__(self): | |
query = self.query.filter(self.attr) | |
return iter(query) | |
def __len__(self): | |
query = self.query.filter(self.attr) | |
return faster_count_query(query) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sqlalchemy import ( | |
create_engine, | |
Column, | |
Integer, | |
) | |
from sqlalchemy.orm import ( | |
sessionmaker, | |
) | |
from sqlalchemy.ext.declarative import declarative_base | |
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method | |
Base = declarative_base() | |
Session = sessionmaker() | |
class X(Base): | |
__tablename__ = 'x' | |
id = Column(Integer, primary_key=True) | |
value = Column(Integer) | |
@hybrid_property | |
def zero(self): | |
return self.value == 0 | |
@hybrid_method | |
def greater_than(self, value): | |
return self.value > value | |
@hybrid_method | |
def less_than(self, value): | |
return self.value < value | |
engine = create_engine('sqlite:///', echo=True) | |
Session.configure(bind=engine) | |
Base.metadata.create_all(bind=engine) | |
session = Session() | |
for i in range(1000): | |
x = X(value=i) | |
session.add(x) | |
session.flush() | |
from adapter import query_maker | |
print(list( | |
query_maker(session, X).zero | |
# session.query(X).filter(X.zero) | |
)) | |
print(list( | |
query_maker(session, X).greater_than(100) | |
# session.query(X).filter(X.greater_than(100)) | |
)) | |
print(list( | |
query_maker(session, X) | |
.greater_than(100) | |
.less_than(200) | |
# session.query(X).filter(X.greater_than(100)).filter(X.less_than(200)) | |
)) | |
print(len( | |
query_maker(session, X).zero | |
)) | |
print(len( | |
query_maker(session, X).greater_than(100) | |
)) | |
print(len( | |
query_maker(session, X) | |
.greater_than(100) | |
.less_than(200) | |
)) | |
print( | |
session.query(X) | |
.filter(X.greater_than(100)) | |
.filter(X.less_than(200)).count() | |
# this provides couting to wrapped subquery | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment