在Peewee中组合可选的已通过查询过滤器

时间:2018-12-05 21:22:17

标签: python-3.x peewee

我正在尝试将烧瓶服务器链接到Peewee数据库。我有一个Rest GET请求,该请求传递

格式的数据
  

{'a':1,'b':2,'filter':{'name':'Foo','count':3}}

我想编写一个将过滤器转换为数据库查询并执行以返回其资源的方法:

import datetime
import peewee as pw
import uuid

DATABASE = "Resources.db"

database = pw.SqliteDatabase(DATABASE)


class BaseModel(pw.Model):
    class Meta:
        database = database


class Resource(BaseModel):
    name = pw.CharField(unique=True)
    current_count = pw.IntegerField(default=1)
    total_count = pw.IntegerField(default=1)
    flavor = pw.CharField(default="undefined")
    users = pw.TextField()
    metadata = pw.TextField(default="")
    is_avalible = pw.BooleanField(default=True)
    uuid = pw.UUIDField(primary_key=True, default=uuid.uuid4)
    max_reservation_time = pw.IntegerField(default=10)

    def __str__(self):
        return f"My name is {self.name} {vars(self)}"

这有点像我的资源。这就是我想要做的...(不是一个完整的示例)

def filter(filters):

    for i,j in filters.items():
        dq = Resource.select().where(getattr(Resource, i) == j)

    for resource in dq:
        print(resource)

if __name__ == "__main__":
    try:
        database.connect()
    except pw.OperationalError:
        print("Open Connection")
    try:
        create_tables()
    except pw.OperationalError:
        print("Resource table already exists!")

    with database.atomic():
        reso = Resource.create(name="Burns", current_count=4, total_count=5, users="Bar", blah=2)

    filter({'name':"Burns","total_count":5})

我希望在这里能回来:My name is Burns {'__data__': {'uuid': UUID('80808e3a-4b10-47a5-9d4f-ff9ff9ca6f5c'), 'name': 'Burns', 'current_count': 4, 'total_count': 5, 'flavor': 'undefined', 'users': 'Grant', 'metadata': '', 'is_avalible': True, 'max_reservation_time': 10}, '_dirty': set(), '__rel__': {}}我相信我可以创建个人的peewee.expressions并以某种方式加入他们,但我不确定如何。

2 个答案:

答案 0 :(得分:1)

由于peewee表达式可以使用内置的&|运算符任意组合,因此我们将使用reduce()函数使用给定的操作数来组合列表:

def filter(filters):
    expression_list = [getattr(Resource, field) == value
                       for field, value in filters.items()]
    # To combine all expressions with "AND":
    anded_expr = reduce(operator.and_, expression_list)

    # To combine all expressions with "OR":
    ored_expr = reduce(operator.or_, expression_list)

    # Then:
    return Resource.select().where(anded_expr)  # or, ored_expr

答案 1 :(得分:-1)

感谢@coleifer的提醒。这是我的解决方案:

OP_MAP = {
    "==": pw.OP.EQ,
    "!=": pw.OP.NE,
    ">": pw.OP.GT,
    "<": pw.OP.LT,
    ">=": pw.OP.GTE,
    "<=": pw.OP.LTE,
}

def _generate_expressions(model, query_filter):
    expressions = []
    for expression in query_filter:
        expressions.append(
            pw.Expression(
                getattr(model, expression["attr"]), OP_MAP[expression["op"]], expression["value"]
            )
        )
    return expressions

def generate_query(model, query_data):
    if query_data.get("filters") is None:
        database_query = model.select()
    else:
        database_query = model.select().where(
            *(_generate_expressions(model, query_data["filters"]))
        )
    return database_query

我在过滤器数据中传递要为其创建表达式和运算符的对象的类型。遍历过滤器,我可以构建表达式并将其组合。