Bri*_*unt 148 python django django-models
给出一个类:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=20)
Run Code Online (Sandbox Code Playgroud)
是否有可能,如果有的话,如何使用基于动态参数进行过滤的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`.
Run Code Online (Sandbox Code Playgroud)
Dan*_*aab 288
Python的参数扩展可用于解决此问题:
kwargs = {
'{0}__{1}'.format('name', 'startswith'): 'A',
'{0}__{1}'.format('name', 'endswith'): 'Z'
}
Person.objects.filter(**kwargs)
Run Code Online (Sandbox Code Playgroud)
这是一个非常常见且有用的Python习语.
另外,为了扩展之前对更多代码元素提出一些请求的答案,我添加了一些在我的代码中使用 Q 的工作代码。假设我在我的请求中可以对以下字段进行过滤,也可以不进行过滤:
publisher_id
date_from
date_until
Run Code Online (Sandbox Code Playgroud)
这些字段可能会出现在查询中,但也可能会丢失。
这就是我基于聚合查询上的那些字段构建过滤器的方式,这些字段在初始查询集执行后无法进一步过滤:
# prepare filters to apply to queryset
filters = {}
if publisher_id:
filters['publisher_id'] = publisher_id
if date_from:
filters['metric_date__gte'] = date_from
if date_until:
filters['metric_date__lte'] = date_until
filter_q = Q(**filters)
queryset = Something.objects.filter(filter_q)...
Run Code Online (Sandbox Code Playgroud)
希望这会有所帮助,因为我花了相当长的时间来挖掘这个。
编辑:
作为额外的好处,您还可以使用列表。对于前面的示例,如果您有一个名为publisher_ids的列表而不是publisher_id,那么您可以使用这段代码:
if publisher_ids:
filters['publisher_id__in'] = publisher_ids
Run Code Online (Sandbox Code Playgroud)
一个简化的例子:
在Django调查应用程序中,我想要一个显示注册用户的HTML选择列表.但是因为我们有5000个注册用户,所以我需要一种方法来根据查询条件过滤该列表(例如只完成某个研讨会的人).为了使调查元素可以重复使用,我需要创建调查问题的人能够将这些标准附加到该问题(不想将查询硬编码到应用程序中).
我提出的解决方案不是100%用户友好(需要技术人员的帮助来创建查询)但它确实解决了问题.创建问题时,编辑器可以将字典输入自定义字段,例如:
{'is_staff':True,'last_name__startswith':'A',}
Run Code Online (Sandbox Code Playgroud)
该字符串存储在数据库中.在视图代码中,它以self.question.custom_query
.它的值是一个看起来像字典的字符串.我们用eval()把它变成一个真正的字典,然后用**kwargs将它填入查询集:
kwargs = eval(self.question.custom_query)
user_list = User.objects.filter(**kwargs).order_by("last_name")
Run Code Online (Sandbox Code Playgroud)
Django.db.models.Q正是你想要的Django方式.