我如何将这些多个连接作为Django查询集来执行呢?

问题描述

我有一个将多个表联接在一起的查询:

select 
    p.player_id
    , d.player_data_1
    , l.year
    , l.league
    , s.stat_1
    , l.stat_1_league_average
from 
    stats s
inner join players p on p.player_id = s.player_id
left join player_data d on d.other_player_id = p.other_player_id
left join league_averages as l on l.year = s.year and l.league = s.year
where 
    p.player_id = 123

我的模型如下所示:

class Stats(models.Model):
    player_id = models.ForeignKey(Player)
    stat_1 = models.IntegerField()
    year = models.IntegerField()
    league = models.IntegerField()


class Player(models.Model):
    player_id = models.IntegerField(primary_key=True)
    other_player_id = models.ForeignKey(PlayerData)

class PlayerData(models.Model):
    other_player_id = models.IntegerField(primary_key=True)
    player_data_1 = models.TextField()

class LeagueAverages(models.Model):
    year = models.IntegerField()
    league = models.IntegerField()
    stat_1_league_average = models.DecimalField()

我可以这样做:

Stats.objects.filter(player_id=123).select_related('player')

执行第一个联接。对于第二个连接,我尝试:

Stats.objects.filter(player_id=123).select_related('player').select_related('player_data')

但我收到此错误:

django.core.exceptions.FieldError:SELECT_Related:‘Player_Data’中给出的字段名无效。选项包括:播放器

考虑到yearleague在任何表中都不是外键,我该如何进行第三个连接呢?谢谢!


解决方案

select_related(*fields)返回将"遵循"外键关系的QuerySet,[.]

根据Django文档select_related遵循外键关系。player_data与外键相邻,甚至也不是Stats的字段。如果您想要内部联接PlayerDataPlayer,可以跟随它的外键。在您的情况下,请使用 double-underscore转到PlayerData

Stats.objects.all()
    .select_related('player_id')
    .select_related('player_id__other_player_id')

至于联接LeagueAverages:没有合适的外键就无法联接模型,只能使用原始SQL。看一下相关的问题:Django JOIN query without foreign key。通过使用.raw(),您的LEFT JOIN(顺便说一句,如果不使用RAW:Django Custom Left Outer Join也不是那么容易),您的LEFT JOIN也可以得到处理。

有关您的型号的快速说明:

  1. 每个模型默认都有一个自动递增的主键,可以通过.id.pk访问。因此不需要添加例如player_id
  2. models.ForeignKey字段引用的是对象,而不是它的id。因此,例如将player_id重命名为player会更直观。如果您将字段命名为playerplayerDjango允许您通过player_id
  3. 自动访问其ID

相关文章