django 如何在ForeignKey上Annotate F()工作?

cnh2zyt3  于 2023-04-22  发布在  Go
关注(0)|答案(2)|浏览(157)

我有一个非常简单的测试项目,包含以下模型:

class Category(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name

class Pizza(models.Model):
    name = models.CharField(max_length=50)
    category = models.ForeignKey(Category, related_name='pizzas')

    def __str__(self):
        return self.name

为了测试的目的,我创建了4个“Pizza”示例,它们都具有相同的Category:

'Test Pizza'
'Test'
'Another One'
'Yoplahihou'

下面是一个简单的代码及其结果:

[print(p.id, p) for p in Pizza.objects.all()]

1 Test Pizza
2 Test
3 Another one
4 Yoplahihou

到目前为止,一切都很好。对这段代码进行简单的修改以添加注解,得到:

[print(p.id, p, "| test:", p.test) for p in Pizza.objects.annotate(test=F('category'))]

1 Test Pizza | test: 1
2 Test | test: 1
3 Another one | test: 1
4 Yoplahihou | test: 1

仍然很好,(它们都属于id为1的类别).但我完全失去它的地方是以下结果:

[print(p.id, p, "| test:", p.test) for p in Pizza.objects.annotate(test=F('category__pizzas'))]

1 Test Pizza | test: 1
1 Test Pizza | test: 2
1 Test Pizza | test: 3
1 Test Pizza | test: 4
2 Test | test: 1
2 Test | test: 2
2 Test | test: 3
2 Test | test: 4
3 Another one | test: 1
3 Another one | test: 2
3 Another one | test: 3
3 Another one | test: 4
4 Yoplahihou | test: 1
4 Yoplahihou | test: 2
4 Yoplahihou | test: 3
4 Yoplahihou | test: 4

有没有人能给我解释一下这是怎么回事?为什么我在查询中得到了这么多额外的结果,为什么每个结果的“test”值都不一样?
这是一个简单的例子,但我试图在另一个项目的一个更复杂的查询中重现这个结果,我绝对没有这个结果的乘法(但我试图获得它)。如果我能理解这里发生了什么,我可能会弄清楚在我的其他项目中应该做什么。

rhfm7lfc

rhfm7lfc1#

使用此查询:

[print(p.id, p, "| test:", p.test) for p in Pizza.objects.annotate(test=F('category'))]

您选择比萨饼并加入类别。
在第二个中:

[print(p.id, p, "| test:", p.test) for p in Pizza.objects.annotate(test=F('category__pizzas'))]

你选择披萨并加入类别(就像第一个),然后将类别加入到披萨关联中。类别1与披萨1,2,3,4关联。

Category 1 | Pizza 1
Category 1 | Pizza 2
Category 1 | Pizza 3
Category 1 | Pizza 4

回到第二个查询,第一行:
有4条线相连。
为您提供:
另一条来自桌上披萨的线也是一样。
PS:抱歉英语不好

5fjcxozz

5fjcxozz2#

下面是一个如何使用F()函数将两个字段相乘的示例:

from django.db.models import F

books = Book.objects.annotate(total_price=F('unit_price') * F('inventory'))

在本例中,我们使用annotate()函数创建一个名为total_price的新字段,它是unit_price和inventory字段的乘积。
如果要将本地字段与外键字段相乘,可以使用双下划线语法访问外键字段:

books = Book.objects.annotate(total_price=F('unit_price') * F('discount__value'))

在这个例子中,我们使用discount__value语法来访问discount外键的value字段。
请记住,您要相乘的字段必须是兼容的类型(即两个整数或两个小数),才能使乘法生效。如果您仍然有问题,请提供有关您试图相乘的字段的更多信息以及您收到的任何错误消息。

相关问题