Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django:筛选以检查列表中是否有两个/多个字段_Python_Django_Django Queryset - Fatal编程技术网

Python Django:筛选以检查列表中是否有两个/多个字段

Python Django:筛选以检查列表中是否有两个/多个字段,python,django,django-queryset,Python,Django,Django Queryset,我在Django这里有一个模型名,带有字段a和字段b。 我有一个python中的列表,其元组形式为(a,b) 我想要得到Django模型的所有实例,其中两个字段都在Python列表中 如果只有一个字段,这将很简单: my_filter_list = [a1, a2, a3] ModelNameHere.objects.filter(field_a__in=my_filter_list) 但对于多个字段,这不起作用 my_filter_list = [(a1, b1), (a2, b2), (a

我在Django这里有一个模型名,带有字段a和字段b。 我有一个python中的列表,其元组形式为(a,b)

我想要得到Django模型的所有实例,其中两个字段都在Python列表中

如果只有一个字段,这将很简单:

my_filter_list = [a1, a2, a3]
ModelNameHere.objects.filter(field_a__in=my_filter_list)
但对于多个字段,这不起作用

my_filter_list = [(a1, b1), (a2, b2), (a3, b3)]
ModelNameHere.objects.filter( ? )
有没有办法同时检查两个字段

或者,是否有方法将我的\u filter\u列表转换为临时表,以便我可以在此处使用字段a和字段b作为联接键,将该表与modelname联接

编辑:


快速添加:我在字段A上设置了索引,但在字段b上没有设置索引。

如果您的
my\u filter\u list
变量预计不会太长(因为您可能会遇到性能问题),您可以这样构造查询:

from django.db.models import Q

multi_field_filter = None
for field_a_val, field_b_val in my_filter_list:
    # logical AND the two field values together
    q = Q(field_a=field_a_val, field_b=field_b_val)
    # logical OR the AND'd terms together
    multi_field_filter = q if multi_field_filter is None else (multi_field_filter | q)

results = ModelNameHere.objects.all()
if multi_field_filter is not None:
    results = ModelNameHere.objects.filter(multi_field_filter)
对于更长的列表,人们不希望生成大量的SQL来执行这些类型的查询。一个(可能是黑客的)解决方案还包括向模型中添加一个额外字段,该字段以可搜索的方式连接两个值,如下所示:

class ModelNameHere(models.Model):
    field_a = models.IntegerField()
    field_b = models.IntegerField()
    fields_concat = models.CharField(max_length=200, blank=True, db_index=True)

    def save(self, *args, **kwargs):
        # automatically update on save
        self.fields_concat = "%s.%s" % (self.field_a, self.field_b)
        # call parent save
        super(ModelNameHere, self).save(*args, **kwargs)
然后,当您要查找特定组合时,只需执行精确的文本搜索匹配:

# using set() automatically deduplicates any search combinations
concat_filters = set([
    ("%s.%s" % (field_a_val, field_b_val)) for field_a_val, field_b_val in my_filter_list
])
# do your lookup here
results = ModelNameHere.objects.filter(fields_concat__in=concat_filters)

如果您的
my\u filter\u list
变量预计不会太长(因为您可能会遇到性能问题),您可以构建如下查询:

from django.db.models import Q

multi_field_filter = None
for field_a_val, field_b_val in my_filter_list:
    # logical AND the two field values together
    q = Q(field_a=field_a_val, field_b=field_b_val)
    # logical OR the AND'd terms together
    multi_field_filter = q if multi_field_filter is None else (multi_field_filter | q)

results = ModelNameHere.objects.all()
if multi_field_filter is not None:
    results = ModelNameHere.objects.filter(multi_field_filter)
对于更长的列表,人们不希望生成大量的SQL来执行这些类型的查询。一个(可能是黑客的)解决方案还包括向模型中添加一个额外字段,该字段以可搜索的方式连接两个值,如下所示:

class ModelNameHere(models.Model):
    field_a = models.IntegerField()
    field_b = models.IntegerField()
    fields_concat = models.CharField(max_length=200, blank=True, db_index=True)

    def save(self, *args, **kwargs):
        # automatically update on save
        self.fields_concat = "%s.%s" % (self.field_a, self.field_b)
        # call parent save
        super(ModelNameHere, self).save(*args, **kwargs)
然后,当您要查找特定组合时,只需执行精确的文本搜索匹配:

# using set() automatically deduplicates any search combinations
concat_filters = set([
    ("%s.%s" % (field_a_val, field_b_val)) for field_a_val, field_b_val in my_filter_list
])
# do your lookup here
results = ModelNameHere.objects.filter(fields_concat__in=concat_filters)

您可以使用枚举,如下与Q的组合:

from django.db.models import Q
result_list = []
my_filter_list = [(a1, b1), (a2, b2), (a3, b3)]

for n,m in enumerate(my_filter_list):
    query_set = ModelNameHere.objects.filter(Q(field_a=n[0]) | Q(field_b=m[0]))
    if query_set.count() >0:
        result_list.append(query_set)

您可以使用枚举,如下与Q的组合:

from django.db.models import Q
result_list = []
my_filter_list = [(a1, b1), (a2, b2), (a3, b3)]

for n,m in enumerate(my_filter_list):
    query_set = ModelNameHere.objects.filter(Q(field_a=n[0]) | Q(field_b=m[0]))
    if query_set.count() >0:
        result_list.append(query_set)

您可以对查询kwargs使用字典理解,并对查询集使用管道操作符或操作

query_fields = ({ 'field_a': value_a, 'field_b': value_b } for value_a, value_b in my_filter_list)

queryset = ModelNameHere.objects.none()
for query_kwarg in query_fields:
    queryset |= ModelNameHere.objects.filter(**query_kwarg)
queryset = queryset.distinct()

您可以对查询kwargs使用字典理解,并对查询集使用管道操作符或操作

query_fields = ({ 'field_a': value_a, 'field_b': value_b } for value_a, value_b in my_filter_list)

queryset = ModelNameHere.objects.none()
for query_kwarg in query_fields:
    queryset |= ModelNameHere.objects.filter(**query_kwarg)
queryset = queryset.distinct()
:

好的是,它是一个简单的查询,很容易理解

糟糕的是,您不仅会得到(a1,b1)和(a2,b2),还会得到(a1b1,)和(,a1b1)。如果它对您至关重要,请使用更复杂的分隔符(“:”)。

:

好的是,它是一个简单的查询,很容易理解


糟糕的是,您不仅会得到(a1,b1)和(a2,b2),还会得到(a1b1,)和(,a1b1)。如果它对您很重要,请使用更复杂的分隔符(“:”)

您是否想过将所有这些逻辑放入自定义QuerySet类?您是否想过将所有这些逻辑放入自定义QuerySet类?这将导致len(my_filter_list)许多查询,不是吗?不,只有一次。在所有情况下,查询总数都是相同的。它将只查询列表中的每个项目一次。这是必要和充分的。@FlorianDietz这是一个优化的解决方案。请重新考虑迭代。但是它不会发送len(my_filter_list)许多单独的查询,而另一个解决方案只发送一个查询吗?运行时在O(n)中应该是相同的,但是将如此多的查询转换为SQL并要求数据库执行它们可能会有很大的开销。@FlorianDietz Yes。但这就是要求,您需要检查这两个字段的每个值,如果第一个条件为真,或者不检查第二个条件,则它不会总是计算整个查询。这将导致len(my_filter_list)许多查询,不是吗?不,只有一次。在所有情况下,查询总数都是相同的。它将只查询列表中的每个项目一次。这是必要和充分的。@FlorianDietz这是一个优化的解决方案。请重新考虑迭代。但是它不会发送len(my_filter_list)许多单独的查询,而另一个解决方案只发送一个查询吗?运行时在O(n)中应该是相同的,但是将如此多的查询转换为SQL并要求数据库执行它们可能会有很大的开销。@FlorianDietz Yes。但这就是要求,您需要检查这两个字段的每一个值,如果第一个条件为真,或者没有检查第二个条件,那么它不会总是计算整个查询。这看起来很有趣。您知道生成的SQL是什么样子吗?它是否会像两个表之间的连接那样进行优化,还是会创建len(my_filter_list)许多查询并将它们合并?Django QuerySet是惰性的,在对其求值之前不会执行它
filter()
方法只需将所有查询累积到一个查询中。当计算
queryset
时,将执行一个查询(即,当您在
queryset
上循环时)。对不起,我的措辞很糟糕:我知道只有一个查询,但该查询的形式是否为“(选择…)UNION(选择…)UNION…”?实际上,我认为我对数据库的功能了解不够,无法知道这是比任何替代解决方案更快还是更慢:-(不,不会有任何联合查询,但更像是一系列左侧外部联接查询,这取决于您提供的查询字段的条件。这看起来很有趣。您知道生成的SQL是什么样子的吗?它是否像两个表之间的联接那样进行优化,还是会创建len(我的筛选器列表)许多查询并将它们合并?Django queryset是惰性的,在对其求值之前不会执行。
filter()
方法仅将所有查询累积到一个查询中。当对
queryset
求值时(即,在
queryset
上循环时),将执行一个查询