标签: django-annotate

Django 1.11注释子查询聚合

这是一个前沿的功能,我目前正在解决这个问题并迅速流血.我想在现有的查询集上注释子查询聚合.在1.11之前执行此操作要么意味着自定义SQL,要么锤击数据库.这是这方面的文档,以及它的示例:

from django.db.models import OuterRef, Subquery, Sum
comments = Comment.objects.filter(post=OuterRef('pk')).values('post')
total_comments = comments.annotate(total=Sum('length')).values('total')
Post.objects.filter(length__gt=Subquery(total_comments))
Run Code Online (Sandbox Code Playgroud)

他们在总体上注释,这对我来说似乎很奇怪,但无论如何.

我正在努力解决这个问题,所以我正在把它煮回来,回到我有数据的最简单的现实世界的例子.我有Carparks包含很多Spaces.使用,Book?Author如果这让你更快乐,但是 - 现在 - 我只想使用Subquery*来注释相关模型的计数.

spaces = Space.objects.filter(carpark=OuterRef('pk')).values('carpark')
count_spaces = spaces.annotate(c=Count('*')).values('c')
Carpark.objects.annotate(space_count=Subquery(count_spaces))
Run Code Online (Sandbox Code Playgroud)

这给了我一个可爱的ProgrammingError: more than one row returned by a subquery used as an expression,在我的脑海里,这个错误非常有意义.子查询返回带有注释总计的空格列表.

这个例子表明会发生某种魔法,我最终会得到一个我可以使用的数字.但这不是在这里发生的?如何对聚合子查询数据进行注释?

嗯,有些东西被添加到我的查询的SQL中......

我建造了一个新的停车场/太空模型,它起作用了.所以下一步是弄清楚我的SQL中毒了什么.根据Laurent的建议,我看了一下SQL并尝试使它更像是他们在答案中发布的版本.这就是我发现真正问题的地方:

SELECT "bookings_carpark".*, (SELECT COUNT(U0."id") AS "c"
FROM "bookings_space" U0
WHERE U0."carpark_id" = ("bookings_carpark"."id")
GROUP BY U0."carpark_id", U0."space"
)
AS "space_count" FROM "bookings_carpark"; …
Run Code Online (Sandbox Code Playgroud)

django django-aggregation django-annotate django-subquery

28
推荐指数
6
解决办法
2万
查看次数

如何连接 Django 查询集中的两个模型字段?

考虑一个名为 的表DataTable。它有两个字段:AB

我想返回该表中的所有行,并注释一个名为 的字段,该字段是和字段C的串联。AB

这是我尝试过的:

from django.db.models import CharField, Value
from .models import DataTable

def Test(request):
    query = DataTable.objects.all().annotate(C=Value('A' + '-' + 'B', 
          output_field=CharField()))
    # the rest of the function...
Run Code Online (Sandbox Code Playgroud)

这里的问题是,C实际上每个返回行的字符串文字“A - B”。

A我想连接和字段的值B

python django concatenation django-queryset django-annotate

22
推荐指数
2
解决办法
2万
查看次数

Django自定义复杂的Func(sql函数)

在为精确找到Django ORM顺序的解决方案的过程中,我创建了一个自定义的django Func:

from django.db.models import Func

class Position(Func):
    function = 'POSITION'
    template = "%(function)s(LOWER('%(substring)s') in LOWER(%(expressions)s))"
    template_sqlite = "instr(lower(%(expressions)s), lower('%(substring)s'))"

    def __init__(self, expression, substring):
        super(Position, self).__init__(expression, substring=substring)

    def as_sqlite(self, compiler, connection):
        return self.as_sql(compiler, connection, template=self.template_sqlite)
Run Code Online (Sandbox Code Playgroud)

其工作原理如下:

class A(models.Model):
    title = models.CharField(max_length=30)

data = ['Port 2', 'port 1', 'A port', 'Bport', 'Endport']
for title in data:
    A.objects.create(title=title)

search = 'port'
qs = A.objects.filter(
        title__icontains=search
    ).annotate(
        pos=Position('title', search)
    ).order_by('pos').values_list('title', flat=True)
# result is
# ['Port 2', 'port …
Run Code Online (Sandbox Code Playgroud)

python django django-queryset django-annotate

13
推荐指数
3
解决办法
4944
查看次数

Django queryset注释字段是列表/查询集

我正在尝试使用django注释来创建queryset字段,该字段是一些相关模型属性的值列表.

queryset = ...
qs = queryset.annotate(
    list_field=SomeAggregateFunction(
        Case(When(related_model__field="abc"), then="related_model__id")
    ),
    list_elements=Count(F('list_field'))
)
Run Code Online (Sandbox Code Playgroud)

我正在考虑将所有这些id与一些分隔符连接起来,但我不知道相应的函数.另一个解决方案是使list_field成为a queryset.我知道这种语法错了.感谢您的任何帮助.

python django django-queryset django-annotate

10
推荐指数
2
解决办法
6493
查看次数

使用子查询来注释计数

请帮助我,我已经被困在这个问题上太久了:(

我想做的事:

我有这两个模型:

class Specialization(models.Model):
    name = models.CharField("name", max_length=64)
class Doctor(models.Model):
    name = models.CharField("name", max_length=128)
    # ...
    specialization = models.ForeignKey(Specialization)
Run Code Online (Sandbox Code Playgroud)

我想用具有该专业的医生数量来注释查询集中的所有专业。

到目前为止我的解决方案:

我经历了一个循环并做了一个简单的: Doctor.objects.filter(specialization=spec).count()然而事实证明这太慢而且效率低下。我读得越多,就越意识到使用此处SubQuery来筛选专业化的医生是有意义的OuterRef。这就是我想出的:

doctors = Doctor.objects.all().filter(specialization=OuterRef("id")) \
    .values("specialization_id") \
    .order_by()
add_doctors_count = doctors.annotate(cnt=Count("specialization_id")).values("cnt")[:1]

spec_qs_with_counts = Specialization.objects.all().annotate(
    num_applicable_doctors=Subquery(add_doctors_count, output_field=IntegerField())
)
Run Code Online (Sandbox Code Playgroud)

对于每个专业,我得到的输出仅为 1。代码只是用它来注释每个医生对象specialization_id,然后注释该组内的计数,这意味着它将是 1。

不幸的是,这对我来说并不完全有意义。在我最初的尝试中,我使用了一个聚合来进行计数,虽然它可以单独工作,但它不能作为 a 工作SubQuery,但我收到此错误:

This queryset contains a reference to an outer query and may only be used in a subquery.

我之前发布过这个问题,有人建议这样做Specialization.objects.annotate(count=Count("doctor"))

然而,这不起作用,因为我需要计算特定的医生查询集。

我已关注这些链接

但是,我没有得到相同的结果:

python django django-aggregation django-annotate django-subquery

10
推荐指数
2
解决办法
2万
查看次数

从 Django 的 ArrayAgg 中排除空值

我正在使用 Django 的 postgres 特定ArrayAgg聚合器。它工作正常,但是当列表为空时,我得到[None]而不是[]. 有没有办法过滤掉这些空值?我试图将过滤器参数传递给,ArrayAgg但没有用。这是我的设置的简化示例:

class Image(models.Model):
    # ...

class Reporter(models.Model):
    # ...

class Article(models.Model):
    reporter = models.ForeignKey(Reporter, related_name='articles')
    featured_image = models.ForeignKey(Image, related_name='articles')
    # ...
Run Code Online (Sandbox Code Playgroud)

然后,如果我进行此查询:

reporter = Reporter.objects.annotate(
    article_images=ArrayAgg('articles__featured_image'),
    distinct=True
).first()
Run Code Online (Sandbox Code Playgroud)

结果集中的第一个记者没有任何相关文章,我得到:

> reporter.article_images
[None]
Run Code Online (Sandbox Code Playgroud)

我试图添加一个过滤器,但没有运气:

Reporter.objects.annotate(
    article_images=ArrayAgg(
        'articles__featured_image',
        filter=Q(articles__featured_image__isnull=False)
    )
)
Run Code Online (Sandbox Code Playgroud)

django postgresql django-aggregation django-postgresql django-annotate

8
推荐指数
1
解决办法
3273
查看次数

django annotate - 条件计数

我有一个名为'StoreItem'的模型和一个名为'QuoteItem'的模型.QuoteItem指向StoreItem.

我正在尝试注释一个计数器,该计数器指出商店项目上有多少引用项目,但是条件适用于报价项目.

我试过这样的事情:

items = items.annotate(
            quote_count=Count(
                Case(
                    When(quoteitem__lookup_date__in=this_week, then=1), 
                    output_field=IntegerField()
                )
            )
        )
Run Code Online (Sandbox Code Playgroud)

'items'是StoreItems的查询集.'this_week'是代表本周的日期列表(这是我尝试应用的过滤器).在我使日期工作之后,我想为这个条件计数添加更多过滤器,但让我们开始吧.

无论如何我得到的更像是一个布尔值 - 如果符合条件的引用项存在,无论我有多少,计数器将是1.否则,将为0.

它看起来是Count(Case())唯一检查是否存在任何项目,如果存在则返回1,而我希望它迭代指向商店项目的所有报价项目并计算它们,如果它们与条件匹配(单独).

我该如何实现?

python django django-models django-filter django-annotate

6
推荐指数
1
解决办法
2541
查看次数

django - annotate() - 在另一列上有过滤器的列的Sum()

我有以下两种型号.

class Product(models.Model):
    product_group=models.ForeignKey('productgroup.ProductGroup', null=False,blank=False)
    manufacturer=models.ForeignKey(Manufacturer, null=False,blank=False)
    opening_stock=models.PositiveIntegerField(default=0)

    class Meta:
        unique_together = ('product_group', 'manufacturer')
Run Code Online (Sandbox Code Playgroud)

TRANSACTION_TYPE=(('I','Stock In'),('O','Stock Out'))
class Stock(models.Model):
    product=models.ForeignKey('product.Product', blank=False,null=False)
    date=models.DateField(blank=False, null=False,)
    quantity=models.PositiveIntegerField(blank=False, null=False)
    ttype=models.CharField(max_length=1,verbose_name="Transaction type",choices=TRANSACTION_TYPE, blank=False)
Run Code Online (Sandbox Code Playgroud)

我需要列出所有产品stock_in_sum=Sum(of all stock ins),stock_out_sum=Sum(of all stock outs)blance_stock=opening_stock+stock_in_sum - stock_out_sum

这是我到目前为止所取得的成就.

class ProductList(ListView):
    model=Product

    def get_queryset(self):
        queryset = super(ProductList, self).get_queryset()
        queryset = queryset.prefetch_related('product_group','product_group__category','manufacturer')
        queryset = queryset.annotate(stock_in_sum = Sum('stock__quantity'))
        queryset = queryset.annotate(stock_out_sum = Sum('stock__quantity'))
Run Code Online (Sandbox Code Playgroud)

我需要得到

  1. stock_in_sum 作为 sum(quantity) where ttype='I'
  2. stock_out_sum 作为 sum(quantity) where ttype='O'
  3. blance_stockproduct.opening_stock …

django listview django-annotate

6
推荐指数
1
解决办法
3527
查看次数

Django-“ WhereNode”对象没有属性“ output_field”错误

我正在尝试查询和注释模型中的一些数据:

class Feed(models.Model):     # Feed of content
    user = models.ForeignKey(User, on_delete=models.CASCADE)

class Piece(models.Model):    # Piece of content (video or playlist)
    removed = models.BooleanField(default=False)
    feed    = models.ForeignKey(Feed, on_delete=models.CASCADE)
    user    = models.ForeignKey(User, on_delete=models.CASCADE)
Run Code Online (Sandbox Code Playgroud)

在以下查询中未使用其他字段,因此在此跳过了它们。

在我看来,我需要获取经过身份验证的用户的所有供稿的queryset。批注应包含所有未删除的数量。

最初,Piece模型不包含removed字段,并且一切都可以与queryset一起运行,如下所示:

Feed.objects.filter(user=self.request.user).annotate(Count('piece'))
Run Code Online (Sandbox Code Playgroud)

但是随后我将字段添加removedPiece模型中,只需要计算未删除的部分

Feed.objects.filter(user=self.request.user)
            .annotate(Count('piece'), filter=Q(piece__removed=False))
Run Code Online (Sandbox Code Playgroud)

它给了我以下错误:

'WhereNode' object has no attribute 'output_field'
Run Code Online (Sandbox Code Playgroud)

这只是django在错误页面上输出的内容的一小部分,因此,如果这还不够的话,请告诉我我需要在问题中包含的内容。

我试图在这里和那里包含output_field诸如models.IntegerField()models.FloatField()(正确导入)之类的选项,但是出现了一些我未在此处提供的错误,因为我认为这些操作没有意义。

我正在使用Django 2.0.3

django django-models django-aggregation django-annotate django-2.0

6
推荐指数
1
解决办法
1756
查看次数

Django条件子查询聚合

我的模型结构的简化示例是

class Corporation(models.Model):
    ...

class Division(models.Model):
    corporation = models.ForeignKey(Corporation)

class Department(models.Model):
    division = models.ForeignKey(Division)
    type = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)

现在我想显示一个表格,显示公司,其中列将包含某种类型的部门数量,例如type=10.目前,这是通过Corporation模型上的帮助程序实现的,例如,检索那些帮助程序

class Corporation(models.Model):
    ...
    def get_departments_type_10(self):
        return (
            Department.objects
            .filter(division__corporation=self, type=10)
            .count()
        )
Run Code Online (Sandbox Code Playgroud)

这里的问题是,由于N + 1问题,这绝对是谋杀性能.

我试图用接近这个问题select_related,prefetch_related,annotate,和subquery,但我没有带能够得到我需要的结果.

理想情况下,查询Corporation集中的每个应该使用一个整数进行注释,该整数type_10_count反映了该类型的部门数量.

我确信我可以用原始sql做一些事情.extra(),但是文档宣布它将被弃用(我在Django 1.11上)

编辑:原始sql解决方案的示例

corps = Corporation.objects.raw("""
SELECT
*,
(
    SELECT COUNT(*)
    FROM foo_division div ON div.corporation_id = c.id
    JOIN foo_department dept ON dept.division_id = div.id
    WHERE dept.type …
Run Code Online (Sandbox Code Playgroud)

django django-annotate django-subquery

6
推荐指数
1
解决办法
1832
查看次数