如何使用动态过滤器制作django查询集?

时间:2015-04-14 22:32:30

标签: django django-views

所以基本上我在Django有一个店面,店面,最终用户有三个过滤器可供使用。产品类型过滤器(裤子,鞋子,衬衫等),送货过滤器(是/否)和位置/流行度过滤器。

目前在我的views.py中我有这种方法。

if request.is_ajax():
    if request.GET.get('filter') == 'shirts':
        latest_entries = Entry.objects.filter(entrytype="shirts")
        context = {'latest_entries': latest_entries}
        return render(request, 'storefrontload.html', context)
    if request.GET.get('filter') == 'pants':
        latest_entries = Entry.objects.filter(entrytype="pants")
        context = {'latest_entries': latest_entries}
        return render(request, 'storefrontload.html', context)
    if request.GET.get('filter') == 'shoes':
        latest_entries = Entry.objects.filter(entrytype="shoes")
        context = {'latest_entries': latest_entries}
        return render(request, 'storefrontload.html', context)

如您所见,这会处理第一个过滤器。我遇到的问题是,如果我选择,让我们说'裤子',它按裤子过滤但忽略了在其他两个过滤器中选择的内容。另一个例子,假设我选择裤子,页面填充了该过滤器的结果。但是,如果我转到交付过滤器并选择“是”,页面将填充仅可交付的项目,但“裤子”过滤器将被遗忘。

我想弄清楚如何在我的视图中创建一个记住其他两个查询集的查询集(如果这样做有意义的话)。

我能想到的唯一方法是为每个过滤器中的每个值创建True / False标志,然后添加大约100行if / then语句来检查每个标志。必须有更好的方法。

更新:

这就是我从模板中传递过滤器值的方法。

function filter(type) {
  $.get("/storefront/?filter="+type, function(data) {
     var $data = data;
     $('.grid').children().remove();
     $('.grid').append( $data ).masonry( 'appended', $data, true ).masonry( 'layout' ); 
  });
}


  //Product Filter    
$("#shirts").unbind().click(function () { 
  filter("shirts");
  return false;
});


$("#pants").unbind().click(function () { 
  filter("pants");
  return false;
});

$("#shoes").unbind().click(function () { 
  filter("shoes");
  return false;
});



  //Delivery Filter
$("#deliveryyes").unbind().click(function () { 
  filter("deliveryyes");
  return false;
});

$("#deliveryno").unbind().click(function () { 
  filter("deliveryno");
  return false;
});

在我的views.py中,这不起作用:

 entry_types = request.GET.getlist('filter')
 latest_entries = Entry.objects.filter(entrytype__in=entry_types)

因为我需要按entrytype('裤子','衬衫',鞋子')和deliveryoption('deliveryyes','deliveryno')进行过滤。每个过滤器在我的模型中都有自己的列。

models.py

class Entry(models.Model):
    headline= models.CharField(max_length=200,)
    body_text = models.TextField()
    author=models.ForeignKey(settings.AUTH_USER_MODEL, related_name='entryauthors')
    pub_date=models.DateTimeField(auto_now_add=True)
    zipcode =models.IntegerField(null=True, max_length=10)
    !!! entrytype = models.CharField(null=True, max_length=10)
    !!! deliveryoption=models.CharField(null=True, max_length=5)

2 个答案:

答案 0 :(得分:1)

您可以传递逗号分隔的filter值列表:

/mylist/filter=shirts,pants

然后使用__in查找条目获取条目:

entry_types = request.GET.get('filter', '').split(',')
latest_entries = Entry.objects.filter(entrytype__in=entry_types)

或使用getlist()的{​​{1}}方法:

QueryDict

使用相同的ORM呼叫:

/mylist/filter=shirts&filter=pants

UPDATE :要将多个类型传递给视图,请将它们保存在数组中,然后使用entry_types = request.GET.getlist('filter') latest_entries = Entry.objects.filter(entrytype__in=entry_types) 方法获取逗号分隔的字符串:

join()

更新2 :如果您使用两个字段来过滤查询集,则必须在视图中创建两个单独的列表:

var types = []; // currently shown entry types

function filter(type) {
  // add or remove the items from the grid
  var index = types.indexOf(type);
  if (index > -1) {
    types.splice(index, 1); // remove the type from the list
  } else {
    types.push(type); // add the type to the filter
  }
  $.get("/storefront/?filter="+types.join(","), function(data) {
    ...
  }
}

JavaScript代码无需任何操作即可使用。

答案 1 :(得分:0)

参数在请求中多次显示是完全有效的。使用QueryDict.getlist()获取包含所有值的列表。

http://example.com/?foo=12&foo=34

...

print >>sys.stderr, request.GET.getlist('foo')