2014-04-21 70 views
2

我有查詢動態條件,ponyORM:疑問查詢

select (lambda obj:obj.A = 'a' and obj.B = 'b' and ...) 

所以我寫的代碼如下:

def search(self,**kwargs): 
     q = unicode('lambda obj:', 'utf-8') 
    for field,value in kwargs.iteritems(): 
      value = unicode(value, 'utf-8') 
      field = unicode(field, 'utf-8') 
      q+=u" obj.%s == '%s' and" % (field,value 

    q = q[0:q.rfind('and')] 
    res = select(q.encode('utf-8'))[:] 

但我的函數執行過程中有這樣的錯誤:

tasks.search(title='Задача 1',url='test.com') 
res = select(q.encode('utf-8'))[:] 
File "<string>", line 2, in select 
File ".../local/lib/python2.7/site-packages/pony/utils.py", line 96, in  cut_traceback 
return func(*args, **kwargs) 
    File ".../local/lib/python2.7/site-packages/pony/orm/core.py", line 3844, in select 
if not isinstance(tree, ast.GenExpr): throw(TypeError) 
    File "...local/lib/python2.7/site-packages/pony/utils.py", line 123, in throw 
    raise exc 
    TypeError 

回答

5

雖然有可能爲了申請條件,使用字符串對於查詢來說,由於存在SQL注入的風險,它可能是不安全的。將條件應用於查詢的更好方法是使用filter()方法。您可以從​​存儲庫中獲取最新版本的Pony ORM,並嘗試下面提供的幾個示例。

首先我們定義實體,並創建一個連接對象:

from decimal import Decimal 
from pony.orm import * 

db = Database('sqlite', ':memory:') 

class Product(db.Entity): 
    name = Required(unicode) 
    description = Required(unicode) 
    price = Required(Decimal) 
    quantity = Required(int, default=0) 

db.generate_mapping(create_tables=True) 

with db_session: 
    Product(name='iPad', description='Air, 16GB', price=Decimal('478.99'), quantity=10) 
    Product(name='iPad', description='Mini, 16GB', price=Decimal('284.95'), quantity=15) 
    Product(name='iPad', description='16GB', price=Decimal('299.00'), quantity=10) 

現在我們可以應用過濾條件將它們作爲關鍵字參數:

def find_by_kwargs(**kwargs): 
    q = select(p for p in Product) 
    q = q.filter(**kwargs) 
    return list(q) 

with db_session: 
    products = find_by_kwargs(name='iPad', quantity=10) 
    for p in products: 
     print p.name, p.description, p.price, p.quantity 

另一種選擇是使用lambda表達式,以指定條件:

def find_by_params(name=None, min_price=None, max_price=None): 
    q = select(p for p in Product) 
    if name is not None: 
     q = q.filter(lambda p: p.name.startswith(name)) 
    if min_price is not None: 
     q = q.filter(lambda p: p.price >= min_price) 
    if max_price is not None: 
     q = q.filter(lambda p: p.price <= max_price) 
    return list(q) 

with db_session: 
    products = find_by_params(name='iPad', max_price=400) 
    for p in products: 
     print p.name, p.description, p.price, p.quantity 

正如您所見,可以動態應用過濾器。您可以通過此鏈接查找有關使用過濾器的更多信息:http://doc.ponyorm.com/queries.html#Query.filter

0

如果您仍想使用字符串進行過濾,則必須爲每個鍵/值對應用新的過濾器。

事情是這樣的:

def search(self,**kwargs): 
    q = select(m for m in Product) 
    for field,value in kwargs.iteritems(): 
     value = unicode(value, 'utf-8') 
     field = unicode(field, 'utf-8') 
     flt = u"m.{0} == {1}".format(value, field) 
     q = q.filter(flt) 
    # return q # return Query which can be further modified (for ex. paging, ordering, etc.) 
    return q[:] # or return found products 

心連心,湯姆