简体   繁体   English

django ORM 在外键上加入两个 model

[英]django ORM join two model on a foreign key

The title might be misleading, I'm not sure on how to express my problem标题可能具有误导性,我不确定如何表达我的问题

I have two models declared this way:我有两个这样声明的模型:

class Record(models.Model):
    # autogen id as primary key
    name = models.ForeignKey(Product, on_delete=models.DO_NOTHING)
    value = models.FloatField()
    date = models.DateTimeField()


class Integration(models.Model):
    # autogen id as primary key
    action = models.FloatField()
    on_record = models.ForeignKey(Record, on_delete=models.DO_NOTHING)

I have one Record per hour per day on an entire year, thus 24*365.我一整年每天每小时都有一条Record ,因此是 24*365。
For each Record , there are exactely ten (10) Integration s, each having their distinct action .对于每个Record ,恰好有十 (10) 个Integration ,每个都有其不同的action

What I need is a QuerySet on Record that has an "extra column" with the average of the related 10 Integration's action s.我需要的是一个 QuerySet on Record ,它有一个“额外列”,其中包含相关 10 个 Integration 的action的平均值。 So所以

Record记录

id ID name姓名 value价值 date日期
1 1 A一个 120.00 120.00 2020-01-01 00:00 2020-01-01 00:00
2 2 B 85.00 85.00 2020-01-01 01:00 2020-01-01 01:00

Integration一体化

id ID action行动 on_record on_record
0x1 0x1 7.00 7.00 1 1
0x2 0x2 2.00 2.00 1 1
0x3 0x3 9.00 9.00 1 1
... ... ... ... ... ...
0x10 0x10 8.41 8.41 1 1
0x11 0x11 8.99 8.99 2 <-- next Record 2 <-- 下Record

What I need我需要的

id ID name姓名 value价值 date日期 integration_avg_action integration_avg_action
1 1 A一个 120.00 120.00 2020-01-01 00:00 2020-01-01 00:00 8.17 8.17
2 2 B 85.00 85.00 2020-01-01 00:00 2020-01-01 00:00 7.58 7.58

I was able to generate the average of the Integration s this way我能够以这种方式生成Integration的平均值

Integration.objects
    .values('on_record')
    .annotate(avg=Avg('action'))

but this is as far as I've come to.但这就是我所知道的。 I've tried itertools.chain and many select_related() but I'm more confused now than before.我试过itertools.chain和许多select_related()但我现在比以前更困惑。 It looks to me as a simple JOIN but I can't find a way to get it via ORM.在我看来它是一个简单的JOIN ,但我找不到通过 ORM 获得它的方法。

Since you want a QuerySet of Record you should annotate on that instead of on Integration .由于您想要一个 QuerySet of Record ,因此您应该对其进行注释,而不是在Integration上进行注释。 See the section Following relationships backwards in the documentation for aggregation.请参阅聚合文档中的向后关系部分。

Record.objects.annotate(integration_avg_action=Avg('integration__action'))

If at all changing your models is not costly then you can add related name to your FK field:如果完全更改模型并不昂贵,那么您可以在 FK 字段中添加相关名称:

class Record(models.Model):
    # autogen id as primary key
    name = models.ForeignKey(Product, on_delete=models.DO_NOTHING)
    value = models.FloatField()
    date = models.DateTimeField()


class Integration(models.Model):
    # autogen id as primary key
    action = models.FloatField()
    on_record = models.ForeignKey(Record, on_delete=models.DO_NOTHING, related_name='integration')

Then you can execute the following query:然后您可以执行以下查询:

Record.objects.all().annotate(integration_avg_action=Avg('integration__action')).values('name', 'value', 'date', 'integration_avg_action')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM