这是一个前沿的功能,我目前正在解决这个问题并迅速流血.我想在现有的查询集上注释子查询聚合.在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中毒了什么.根据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) 考虑一个名为 的表DataTable。它有两个字段:A和B。
我想返回该表中的所有行,并注释一个名为 的字段,该字段是和字段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。
在为精确找到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) 我正在尝试使用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.我知道这种语法错了.感谢您的任何帮助.
请帮助我,我已经被困在这个问题上太久了:(
我有这两个模型:
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
我正在使用 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
我有一个名为'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,而我希望它迭代指向商店项目的所有报价项目并计算它们,如果它们与条件匹配(单独).
我该如何实现?
我有以下两种型号.
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)
我需要得到
stock_in_sum 作为 sum(quantity) where ttype='I' stock_out_sum 作为 sum(quantity) where ttype='O'blance_stock 如 product.opening_stock …我正在尝试查询和注释模型中的一些数据:
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)
但是随后我将字段添加removed到Piece模型中,只需要计算未删除的部分:
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
我的模型结构的简化示例是
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)