2014-04-21 2 views
2

동적 조건을 가진 쿼리가 있습니다.ponyORM : 쿼리에 문제가 발생했습니다.

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'))[:] 

하지만 난 함수의 실행 중에이 오류가 있습니다 :

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

그래서 나는이에 대한 코드를 작성

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의 최신 버전을 https://github.com/ponyorm/pony 저장소에서 가져 와서 아래 제공된 몇 가지 예를 시도해 볼 수 있습니다.

먼저 우리는 엔티티를 정의하고 객체의 몇 작성 :

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 

또 다른 옵션을 위해 람다를 사용하는 것입니다

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_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 

HTH, 톰

관련 문제