Python中缺少动态查找器和方法

时间:2009-05-26 22:10:42

标签: python google-app-engine web-applications

我正在尝试在Python中实现类似Rails动态查找器的东西(for web应用/ GAE)。动态查找器的工作方式如下:

  • 您的人员有一些字段:姓名,年龄和电子邮件。
  • 假设您要查找名为“Robot”的所有用户。

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=43http://www.whatspop.com/blog/2008/08/method-missing-in-python.cfm但我会 喜欢听到“最合适”的做法。

4 个答案:

答案 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。

我不确定这是否是正确的做事方式。但是,如果您能够为所有属性实现统一的“查找”,则上述脚本可以正常工作。