Django如何动态选择__gt和__range
我在我的一个Django模板里有一个HTML表单,用户可以选择一个对象的价格范围和它的实际价值范围,但这不是必选项。
<select name="minimum_price">
<option value="1">1</option>
<option value="2">2</option>
</select>
<select name="maximum_price">
<option value="1">1</option>
<option value="2">2</option>
</select>
<select name="min_real_value">
<option value="1">1</option>
<option value="2">2</option>
</select>
<select name="max_real_value">
<option value="1">1</option>
<option value="2">2</option>
</select>
为了这个问题,我看了大部分Django的文档,包括一篇很有启发性的文章:Q类。不过我还没弄明白如何根据用户从这四个选择框中选择的任意组合,动态构建一个查询。
真正的问题出现在,当Django的__range
需要被替换成__gt
或__lt
时,这种情况发生在每个“类别”的选择框中只选择了一个。
这是我到目前为止所做的:
myList = MyObjectsCost.objects.filter(price__range=(minimum_price, maximum_price),
real_value__range=(min_real_value, max_real_value),
**kwargs)
但是如果这四个变量中有一个缺失,这个方法就会失败……
提前谢谢你。
2 个回答
1
这里你可以用一些巧妙的方法来处理kwargs,但其实更简单的办法是直接理解range
其实就是gt
和lt
的组合。所以你可以动态地构建查询:
my_list = MyObjectsCost.objects.all()
if minimum_price:
my_list.filter(price__gt=minimum_price)
if maximum_price:
my_list.filter(price__lt=maximum_price)
if min_real_value:
my_list.filter(real_value__gt=min_real_value)
if max_real_value:
my_list.filter(real_value__lt=max_real_value)
1
丹尼尔·罗斯曼提到的“聪明”的方法,是通过字符串来构建过滤器,对吧?
大概是这样的:
method = MyObjectsCost.objects.filter
qs = method(**{'%s__%s' % (field_name, lookup_type): value})
根据你的具体情况提供合适的值,你可以构建出类似这样的东西:
field_name = 'real_value'
lookup_type = 'gt'
value = 'min_real_value'
这会生成一个像'real_value__gt=min_real_value
'这样的字符串,然后把它传递给过滤方法。这样你就可以根据字符串来创建过滤器。这种方法可能会很有用,但也可能导致代码变得很丑陋和复杂。所以要谨慎使用,不过这个概念可以帮助你构建过滤器。
如果你喜欢使用第三方应用,可以看看 https://github.com/alex/django-filter,它也能让你的过滤器更灵活。
但永远不要忘记保持简单。