我正在尝试在Python中实现类似Rails动态查找器的东西(for web应用/ GAE)。动态查找器的工作方式如下:
Person类有一个名为“find_by_name”的方法,它接收名称 并返回查询结果:
@classmethod
def find_by_name(cls, name):
return Person.gql("WHERE name = :1", name).get()
我不想为每个属性编写类似的方法,而是愿意 像Ruby的method_missing那样允许我这样做。
到目前为止,我已经看过这两篇博文:http://blog.iffy.us/?p=43和 http://www.whatspop.com/blog/2008/08/method-missing-in-python.cfm但我会 喜欢听到“最合适”的做法。
答案 0 :(得分:7)
这里真的没有必要使用GQL - 这只会使问题复杂化。这是一个简单的实现:
class FindableModel(db.Model):
def __getattr__(self, name):
if not name.startswith("find_by_"):
raise AttributeError(name)
field = name[len("find_by_"):]
return lambda value: self.all().filter(field, value)
请注意,它返回一个Query对象,您可以调用.get(),。find()等;这是多功能的,但如果你想要,你当然可以让它只返回一个实体。
答案 1 :(得分:1)
您可以使用'find_by'方法和关键字,例如Django:
class Person (object):
def find_by(self, *kw):
qspec = ' AND '.join('%s=%s' % kv for kv in kw.items())
return self.gql('WHERE ' + qspec)
person.find_by(name='Robot')
person.find_by(name='Robot', age='2')
沿着这条路走,您可能最终会设计自己的查询语法。看看Django做了什么......
答案 2 :(得分:0)
class Person(object):
def __getattr__(self, name):
if not name.startswith("find_by"): raise AttributeError(name)
field_name = name.split("find_by_",1)[1]
return lambda name: Person.gql("WHERE %s = :1" % field_name, name).get()
答案 3 :(得分:0)
class Person:
name = ""
age = 0
salary = 0
def __init__(self, name, age):
self.name = name
self.age = age
def find(clsobj,* args): 返回人(姓名=“杰克”,年龄= 20)
下面的for循环为所有类属性插入@classmethod。这使得“find_by_name”,“find_by_age”和“sinf_by_salary”绑定方法可用。
for attr in Person.__dict__.keys():
setattr(Person, 'find_by_'+attr, find)
setattr(Person, 'find_by_'+attr, classmethod(find))
print Person.find_by_name(“jack”)。age#将打印值20。
我不确定这是否是正确的做事方式。但是,如果您能够为所有属性实现统一的“查找”,则上述脚本可以正常工作。