首页 文章

在Django中,如何使用动态字段查找过滤QuerySet?

提问于
浏览
132

给出一个类:

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`.

4 回答

  • -1

    Python的参数扩展可用于解决此问题:

    kwargs = {
        '{0}__{1}'.format('name', 'startswith'): 'A',
        '{0}__{1}'.format('name', 'endswith'): 'Z'
    }
    
    Person.objects.filter(**kwargs)
    

    这是一个非常常见且有用的Python习语 .

  • 254

    一个简化的例子:

    在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")
    
  • 6

    Django.db.models.Q正是你想要的Django方式 .

  • 6

    一个非常复杂的搜索表单通常表明一个更简单的模型试图挖掘它的出路 .

    您希望如何获得列名称和操作的值?你在哪里得到 'name' 的 Value 'startswith'

    filter_by = '%s__%s' % ('name', 'startswith')
    
    • “搜索”表单?你要去 - 什么? - 从名单中选择名字?从操作列表中选择操作?虽然开放式,但大多数人发现这种混乱和难以使用 .

    有多少列有这样的过滤器? 6? 12? 18?

    • 一些?复杂的选择列表没有意义 . 一些字段和一些if语句是有意义的 .

    • 数量众多?你的模型听起来不对劲 . 听起来"field"实际上是另一个表中行的键,而不是列 .

    • 特定过滤器按钮 . 等等......这就是Django管理员的工作方式 . 特定过滤器变为按钮 . 并且上述相同的分析适用 . 一些过滤器是有道理的 . 大量过滤器通常意味着一种第一次正常形式违规 .

    许多类似的字段通常意味着应该有更多的行和更少的字段 .

相关问题