2016-07-06 122 views
1

在我的数据库中有房间,这些房间有多个布尔值,如has_tvPython烧瓶SQLalchemy通过布尔值过滤查询过滤忽略假

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

现在有一个过滤器函数可以过滤当前的结果集,例如房间,例如有电视。为此用户检查一个复选框的值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() 

这是可以检查所有的值(也有很多,所以硬编码的所有possibilites是不可能的):

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") 

当然以后如果可以说其中两个被检查,它应该显示所有两个检查值是真实的房间,其他所有的都不重要!

下面是该网站的截图在需要的功能: enter image description here

编辑:

我似乎找到了解决方案,已经测试了几次,似乎是为了工作但它不觉得这是最佳实践:

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() 

回答

4

首先,如果你想避免硬编码,你需要一些方法来以编程方式获得哪些属性你想用来过滤和调用窗体中相应的字段。我想你可以扫描Zimmer类,并得到所有布尔属性的名称,但现在我只是asume与属性的名称的字符串列表,其中形式的名称是一样的:

filter_list = ["haustiere_erlaubt", ...] 

然后,只有表单为真时,您才需要将过滤器添加到查询。所以:

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() 

我想你也可以建立适当的过滤器的字典和使用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() 

在你的代码重新定义all_rooms_in_the_city在for循环的每个项目,所以只有最后的过滤器实际上会应用

+0

谢谢,我会试试你的代码。这实际上正是我在编辑帖子中所做的,但你的看起来更好。 – Roman

+0

在你发布的代码中有一个重要的区别:对于每个“过滤器”,你都要做'all_rooms_in_city = Zimmer.query.filter(item).all()'这意味着只有一个单独的过滤器将是“活动的”。如果您将其更改为'query = Zimmer。查询;对于filter_resuolt中的项目:query = query.filter(item)'你可以使用所有的过滤器。 – syntonym