给出一个课程:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=20)
是否有可能,如果有的话,如何让QuerySet根据动态参数进行过滤?例如:
# Instead of:
Person.objects.filter(name__startswith='B')
# ... and:
Person.objects.filter(name__endswith='B')
# ... is there some way, given:
filter_by = '{0}__{1}'.format('name', 'startswith')
filter_value = 'B'
# ... that you can run the equivalent of this?
Person.objects.filter(filter_by=filter_value)
# ... which will throw an exception, since `filter_by` is not
# an attribute of `Person`.
答案 0 :(得分:270)
Python的参数扩展可用于解决此问题:
kwargs = {
'{0}__{1}'.format('name', 'startswith'): 'A',
'{0}__{1}'.format('name', 'endswith'): 'Z'
}
Person.objects.filter(**kwargs)
这是一种非常常见且有用的Python习语。
答案 1 :(得分:6)
简化示例:
在Django调查应用程序中,我想要一个显示注册用户的HTML选择列表。但是因为我们有5000个注册用户,所以我需要一种方法来根据查询条件过滤该列表(例如只完成某个研讨会的人)。为了使调查元素可以重复使用,我需要创建调查问题的人能够将这些标准附加到该问题(不想将查询硬编码到应用程序中)。
我提出的解决方案不是100%用户友好(需要技术人员的帮助来创建查询)但它确实解决了问题。在创建问题时,编辑者可以在自定义字段中输入字典,例如:
{'is_staff':True,'last_name__startswith':'A',}
该字符串存储在数据库中。在视图代码中,它以self.question.custom_query
的形式返回。它的值是看起来的字符串,就像字典一样。我们将其转换为带有eval()的真实字典,然后将其填入查询集中,并使用** kwargs:
kwargs = eval(self.question.custom_query)
user_list = User.objects.filter(**kwargs).order_by("last_name")
答案 2 :(得分:5)
Django.db.models.Q正是您想要的Django方式。
答案 3 :(得分:-1)
一个非常复杂的搜索表单通常表明一个更简单的模型试图挖掘它的出路。
您希望如何获得列名称和操作的值?
您在哪里获得'name'
和'startswith'
的价值?
filter_by = '%s__%s' % ('name', 'startswith')
“搜索”表单?你要去 - 什么? - 从名单中选择名字?从操作列表中选择操作?虽然是开放式的,但大多数人发现这种结果令人困惑且难以使用。
有多少列有这样的过滤器? 6? 12? 18?
特定过滤器按钮。等等......这就是Django管理员的工作方式。特定过滤器变为按钮。并且上述相同的分析适用。一些过滤器是有道理的。大量过滤器通常意味着一种首次正常形式违规。
许多类似的字段通常意味着应该有更多的行和更少的字段。