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
Django 查询集';s'count'在'extra'之后是错误的`_Django - Fatal编程技术网

Django 查询集';s'count'在'extra'之后是错误的`

Django 查询集';s'count'在'extra'之后是错误的`,django,Django,当我在Django查询集(称之为qs)上以某种方式使用extra时,qs.count()的结果不同于len(qs.all())。复制: 创建一个空的Django项目和应用程序,然后添加一个普通模型: class Baz(models.Model): pass 现在制作几个对象: >>> Baz(id=1).save() >>> Baz(id=2).save() >>> Baz(id=3).save() >>> Ba

当我在Django查询集(称之为
qs
)上以某种方式使用
extra
时,
qs.count()
的结果不同于
len(qs.all())
。复制:

创建一个空的Django项目和应用程序,然后添加一个普通模型:

class Baz(models.Model):
    pass
现在制作几个对象:

>>> Baz(id=1).save()
>>> Baz(id=2).save()
>>> Baz(id=3).save()
>>> Baz(id=4).save()
使用
extra
方法仅选择其中的一些会产生预期的计数:

>>> Baz.objects.extra(where=['id > 2']).count()
2
>>> Baz.objects.extra(where=['-id < -2']).count()
2
我认为问题与
django.db.models.sql.query.BaseQuery.get\u count()
有关。它检查BaseQuery的
select
aggregate\u select
属性是否已设置;如果是,则使用子查询。但是
django.db.models.sql.query.BaseQuery.add\u extra
只添加到BaseQuery的
extra
属性,而不是
select
aggregate\u select

我怎样才能解决这个问题?我知道我可以只使用
len(qs.all())
,但如果能够将
额外的
'ed查询集传递给代码的其他部分就好了,这些部分可以调用
count()
,而不知道它已损坏。

重新定义
get\u count()
和monkeypatching似乎可以解决问题:

def get_count(self):
    """
    Performs a COUNT() query using the current filter constraints.
    """
    obj = self.clone()
    if len(self.select) > 1 or self.aggregate_select or self.extra:
        # If a select clause exists, then the query has already started to
        # specify the columns that are to be returned.
        # In this case, we need to use a subquery to evaluate the count.
        from django.db.models.sql.subqueries import AggregateQuery
        subquery = obj
        subquery.clear_ordering(True)
        subquery.clear_limits()

        obj = AggregateQuery(obj.model, obj.connection)
        obj.add_subquery(subquery)

    obj.add_count_column()
    number = obj.get_aggregation()[None]

    # Apply offset and limit constraints manually, since using LIMIT/OFFSET
    # in SQL (in variants that provide them) doesn't change the COUNT
    # output.
    number = max(0, number - self.low_mark)
    if self.high_mark is not None:
        number = min(number, self.high_mark - self.low_mark)

    return number

django.db.models.sql.query.BaseQuery.get_count = quuux.get_count
测试:

>>> Baz.objects.extra(select={'negid': '0 - id'}, where=['"negid" < -2']).count()
2

但是,我不确定此修复是否会产生其他意外后果。

验证了Django 1.2.1中仍然存在此问题。
>>> Baz.objects.extra(select={'negid': '0 - id'}, where=['"negid" < -2']).count()
2
def basequery_get_count(self, using):
    """
    Performs a COUNT() query using the current filter constraints.
    """
    obj = self.clone()
    if len(self.select) > 1 or self.aggregate_select or self.extra:
        # If a select clause exists, then the query has already started to
        # specify the columns that are to be returned.
        # In this case, we need to use a subquery to evaluate the count.
        from django.db.models.sql.subqueries import AggregateQuery
        subquery = obj
        subquery.clear_ordering(True)
        subquery.clear_limits()

        obj = AggregateQuery(obj.model)
        obj.add_subquery(subquery, using=using)

    obj.add_count_column()
    number = obj.get_aggregation(using=using)[None]

    # Apply offset and limit constraints manually, since using LIMIT/OFFSET
    # in SQL (in variants that provide them) doesn't change the COUNT
    # output.
    number = max(0, number - self.low_mark)
    if self.high_mark is not None:
        number = min(number, self.high_mark - self.low_mark)

    return number
models.sql.query.Query.get_count = basequery_get_count