Python Flask SQLalchemy查询过滤器通过布尔值忽略False

Rom*_*man 1 python sqlalchemy filter flask python-2.7

在我的数据库中,我有房间,这些房间有多个布尔值,例如has_tv

用户可以在城市中搜索房间,他将被重定向到结果页面,在该页面中找到搜索到的城市中的所有房间。

现在有一个过滤功能,可以按房间(例如有电视)过滤当前结果集。为此,用户选中具有以下值的复选框has_tv

我设法使其工作,但它不会忽略False值。这意味着如果用户选中has_tv它,则为true,但所有其他布尔值都为false(因为未选中它们)。因此,这将仅向我显示has_tv为true且所有其他值为false的结果,我需要查看has_tv为true且其他结果无关的结果,其中一些可以为false和true。

那就是我使用的atm:

if form.validate_on_submit():
    all_rooms_in_city = Zimmer.query.filter(or_(Zimmer.haustiere_erlaubt.is_(form.haustiere_erlaubt.data), Zimmer.bettwaesche_wird_gestellt.is_(form.bettwaesche_wird_gestellt.data))).all()
else:
    all_rooms_in_city = Zimmer.query.order_by(desc("stadt")).all()
Run Code Online (Sandbox Code Playgroud)

这些都是可以检查的值(有很多,所以不可能对所有可能性进行硬编码):

class FilterZimmerForm(Form):
    haustiere_erlaubt = BooleanField("Haustiere")
    bettwaesche_wird_gestellt = BooleanField("Bettwaesche")
    grill_vorhanden = BooleanField("grill_vorhanden")
    safe_vorhanden = BooleanField("safe_vorhanden")
    kuehlschrank_vorhanden = BooleanField("kuehlschrank_vorhanden")
    rauchen_erlaubt = BooleanField("rauchen_erlaubt")
    parkplatz_vorhanden = BooleanField("parkplatz_vorhanden")
    kochmoeglichkeit_vorhanden = BooleanField("kochmoeglichkeit_vorhanden")
    restaurant_im_haus_vorhanden = BooleanField("restaurant_im_haus_vorhanden")
    handtuecher_werden_gestellt = BooleanField("handtuecher_werden_gestellt")
    tv_vorhanden = BooleanField("tv_vorhanden")
    waschmoeglichkeit_vorhanden = BooleanField("waschmoeglichkeit_vorhanden")
    wlan_vorhanden = BooleanField("wlan_vorhanden")
Run Code Online (Sandbox Code Playgroud)

当然,如果稍后再说两个,则应显示所有房间,其中两个检查值均为真,而其他所有值都不要紧!

这是需要该功能的网站的屏幕截图: 在此处输入图片说明

编辑:

看来我找到了一种解决方案,已经测试了几次,它似乎可以按预期工作,但它似乎不是最佳实践:

if form.validate_on_submit():

    filter_result = []

    if form.haustiere_erlaubt.data == True:
        filter_result.append(Zimmer.haustiere_erlaubt.is_(True))
    if form.bettwaesche_wird_gestellt.data == True:
        filter_result.append(Zimmer.bettwaesche_wird_gestellt.is_(True))
    if form.grill_vorhanden.data == True:
        filter_result.append(Zimmer.grill_vorhanden.is_(True))
    if form.safe_vorhanden.data == True:
        filter_result.append(Zimmer.safe_vorhanden.is_(True))
    if form.kuehlschrank_vorhanden.data == True:
        filter_result.append(Zimmer.kuehlschrank_vorhanden.is_(True))
    if form.rauchen_erlaubt.data == True:
        filter_result.append(Zimmer.rauchen_erlaubt.is_(True))
    if form.parkplatz_vorhanden.data == True:
        filter_result.append(Zimmer.parkplatz_vorhanden.is_(True))
    if form.kochmoeglichkeit_vorhanden.data == True:
        filter_result.append(Zimmer.kochmoeglichkeit_vorhanden.is_(True))           
    if form.restaurant_im_haus_vorhanden.data == True:
        filter_result.append(Zimmer.restaurant_im_haus_vorhanden.is_(True))
    if form.handtuecher_werden_gestellt.data == True:
        filter_result.append(Zimmer.handtuecher_werden_gestellt.is_(True))
    if form.tv_vorhanden.data == True:
        filter_result.append(Zimmer.tv_vorhanden.is_(True))
    if form.waschmoeglichkeit_vorhanden.data == True:
        filter_result.append(Zimmer.waschmoeglichkeit_vorhanden.is_(True))
    if form.wlan_vorhanden.data == True:
        filter_result.append(Zimmer.wlan_vorhanden.is_(True))

    for item in filter_result:
        all_rooms_in_city = Zimmer.query.filter(item).all()
else:
    all_rooms_in_city = Zimmer.query.order_by(desc("stadt")).all()  
Run Code Online (Sandbox Code Playgroud)

syn*_*nym 5

首先,如果要避免硬编码,则需要某种方式以编程方式获取要用于过滤的属性以及调用表单中适当字段的内容。我猜您可以扫描Zimmer该类并获取所有布尔属性的名称,但是现在我只假设一个字符串列表,其中包含该属性的名称,其中名称形式相同:

filter_list = ["haustiere_erlaubt", ...]
Run Code Online (Sandbox Code Playgroud)

然后,在表单为true时,需要将过滤器添加到查询中。所以:

if form.validate_on_submit():

    query = Zimmer.query

    for filter_name in filter_list:
        if getattr(form, filter_name).data:
            query = query.filter(getattr(Zimmer, filter_name).is_(True)))

    all_rooms_in_city = query.all()
Run Code Online (Sandbox Code Playgroud)

我猜你也可以建立一个适当过滤器的字典并使用filter_by

filter_dict = { filter_name: True for filter_name in filter_list if getattr(form, filter_name).data }

all_rooms_in_city = Zimmer.query.filter_by(**filter_dict).all()
Run Code Online (Sandbox Code Playgroud)

在您的代码中,您正在for循环中为每个项目重新定义all_rooms_in_the_city,因此只有最后一个过滤器才会实际应用。