Python 抽象出Alchemy调用,以在try/except块中允许不同的选项
我试图抽象我的sqlalchemy查询调用,完整的未修改调用如下所示:Python 抽象出Alchemy调用,以在try/except块中允许不同的选项,python,sqlalchemy,abstraction,method-chaining,Python,Sqlalchemy,Abstraction,Method Chaining,我试图抽象我的sqlalchemy查询调用,完整的未修改调用如下所示: Session.query(User).options(FromCache('redis1')).filter(User.id == user_id).all() # Abstracts the final chained method def q(obj, action): return getattr(obj, action)() # Removes a lot of boiler plate code #
Session.query(User).options(FromCache('redis1')).filter(User.id == user_id).all()
# Abstracts the final chained method
def q(obj, action):
return getattr(obj, action)()
# Removes a lot of boiler plate code
# but doesn't give me control over the cache argument
# which I need in the same method as the action above
def query(model):
return Session.query(model).options(FromCache('redis1'))
# Called like this
result = q(query(User).filter(User.id == user_id), 'all')
q = query(User).filter(User.id = user_id).limit(whatever)
results = q.using_redis().all()
我需要控制的动态部分是User、redis1和最后一次调用all()
我想调用类似于线上的东西,可以更改参数中上面粗体的内容
我的第一次尝试结果如下:
Session.query(User).options(FromCache('redis1')).filter(User.id == user_id).all()
# Abstracts the final chained method
def q(obj, action):
return getattr(obj, action)()
# Removes a lot of boiler plate code
# but doesn't give me control over the cache argument
# which I need in the same method as the action above
def query(model):
return Session.query(model).options(FromCache('redis1'))
# Called like this
result = q(query(User).filter(User.id == user_id), 'all')
q = query(User).filter(User.id = user_id).limit(whatever)
results = q.using_redis().all()
但我显然只想要一个函数,而不是两个,这样我就可以控制动作和模型。
原因是我想将.one()或.all()调用包装在一个try except块中,该块在查询失败时将通过FromCache选项中的不同缓存服务器。但每次我写查询时都这样做会很烦人
我正在寻找这样的东西(显然,代码不起作用):
有什么想法吗?或者我完全偏离了底线?还是有更聪明的方法来做到这一点?唯一有趣的部分是“all()”。剩下的部分似乎你会坚持直截了当的提问 所以这里是单向模式:
q = query(User).filter(User.id = user_id).limit(whatever)
results = from_redis(q, Query.all)
这是我们可以做到的一个方法:
def from_redis(query, meth):
for server in ['r1', 'r2']:
try:
return meth(q.options(FromCache(server)))
except Exception, e:
continue
else:
raise e
但这似乎有点站不住脚。由于您正在使用缓存配方和子类化查询
,因此您也可以将您的redis功能添加到其中,类似于:
class RedisQuery(CachingQuery):
redis_servers = False
@_generative(self):
def using_redis(self):
self.redis_servers = True
def __iter__(self):
if self.redis_servers:
for server in ['r1', 'r2']:
try:
return super(RedisQuery, self).options(FromCache(server)).__iter__()
except Exception, e:
continue
else:
raise e
else:
return super(RedisQuery, self).__iter__()
你这样称呼他:
Session.query(User).options(FromCache('redis1')).filter(User.id == user_id).all()
# Abstracts the final chained method
def q(obj, action):
return getattr(obj, action)()
# Removes a lot of boiler plate code
# but doesn't give me control over the cache argument
# which I need in the same method as the action above
def query(model):
return Session.query(model).options(FromCache('redis1'))
# Called like this
result = q(query(User).filter(User.id == user_id), 'all')
q = query(User).filter(User.id = user_id).limit(whatever)
results = q.using_redis().all()
只是一些想法。谢谢你的回复。我对您的第二个示例感兴趣,但根据您的dogpile示例,已经有一个子类query包含一个_; iter __;方法。下面是dogpile示例中的查询类:。您能告诉我如何将您的答案集成到该代码中吗?:)应该如上所述工作,只是CachingQuery的子类,所以这里的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu!我决定坚持使用更简单的解决方案,因为另一个由于各种错误而不起作用,我根本没有时间尝试解决它们。您的第一个解决方案有效,因此我将其标记为正确答案。:)不过,我有一个半相关的问题要问你们:你们如何使缓存失效?因为我不知道除了实际表之外,哪些查询会受到影响。是否有某种方法可以使一个表上的所有查询无效,或者可以得到更具体的结果?你有没有想过这个问题与这个例子有关?谢谢