aschmid00
aschmid00

Reputation: 7158

NDB query filtering by property (string)

with ndb and the new query class to to use filter on a query you need to use the syntax like:

qry = MyModel.query(MyModel.title == 'title')

how can i query on a model without knowing in advance which properties i have to query on?

with the 'old' way i had a dictionary with keys and values to query on and looped over keys and values:

kwargs = {'title' : 'mytitle', 
          'age'   : 34 }

q = MyModel.all()

for kw, vals in kwargs.items():
    if not isinstance(vals, (list, tuple)):
        vals = (vals,)
    for v in vals:
        q.filter('%s =' % kw, v)

how could i achieve this with ndb?

Upvotes: 5

Views: 5185

Answers (2)

Guido van Rossum
Guido van Rossum

Reputation: 16890

If it's an Expando model, or if you don't care validating the property name, you can do this easily using GenericProperty:

kwargs = {'title' : 'mytitle', 
          'age'   : 34 }

q = MyModel.query()

for kw, vals in kwargs.items():
    if not isinstance(vals, (list, tuple)):
        vals = (vals,)
    for v in vals:
        q = q.filter(ndb.GenericProperty(kw) == v)

Alternatively, if you just want to find an existing property (defined in your Model subclass) by name, you could use the _properties class attribute, e.g.

        q = q.filter(MyModel._properties[kw] == v)

or even use getattr() to get it from the class:

        q = q.filter(getattr(MyModel, kw) == v)

The difference is that getattr() uses the "Python" name of the property while _properties is indexed by the "datastore" name of the property. These only differ when the property was declared with something like

class MyModel(ndb.Model):
  foo = StringProperty('bar')

Here the Python name is foo but the datastore name is bar.

Upvotes: 13

Nick Johnson
Nick Johnson

Reputation: 101149

You can still do this with a dictionary - the keys just need to be model properties instead of strings, like this:

kwargs = {MyModel.title : 'mytitle', 
          MyModel.age   : 34 }
q = MyModel.query()
for prop, value in kwargs.items():
  q = q.filter(prop == value)

Upvotes: 0

Related Questions