Django - 左连接父表和子表?

问题描述 投票:0回答:1

我是 Django 新手。我正在尝试找出如何以最少的数据库查询次数进行左连接。

我搜索了 stackoverflow,并花了几天时间试图弄清楚这一点。我研究过使用 .select_lated,我尝试过原始查询并尝试看看是否可以用 Q 来完成,但我仍然无法弄清楚这一点。我想检索所有州和链接城市(如果有),

模型.py

class State(models.Model):
  name = models.CharField(max_length=25)
  abbreviation = models.CharField(max_length=2)

  def __str__(self):
    return str(self.id)


class City(models.Model):
  name = models.CharField(max_length=25)
  population = models.IntegerField()
  state = models.ForeignKey(State, related_name="cities", on_delete=models.CASCADE)

  def __str__(self):
    return str(self.id)

状态表

身份证 姓名 缩写
1 德克萨斯州 TX
2 加利福尼亚州 CA
3 伊利诺伊州 IL

城市表

身份证 姓名 人口 状态
1 洛杉矶 3769485 2
2 达拉斯 1259404 1
3 休斯顿 2264876 1

想要的结果

|-------------- 州 -------------|-------------------- 城市 - ------------------|

身份证 姓名 缩写 身份证 姓名 人口 状态
1 德克萨斯州 TX 2 达拉斯 1259404 1
1 德克萨斯州 TX 3 休斯顿 2264876 1
2 加利福尼亚州 CA 1 洛杉矶 3769485 2
3 伊利诺伊州 IL

问题1(使用.select_lated):

cities_states = City.objects.all().select_related('state').order_by('state_id')

使用 .select_lated 不会给我任何没有城市的州(例如伊利诺伊州)

问题2(使用RawQuery):

sql = '''
SELECT S.*, C.* 
FROM "state" S
LEFT JOIN "city" C
ON (S."id" = C."state_id") 
ORDER BY S."id" ASC
'''

cities_states = State.objects.raw(sql)

for obj in cities_states:
  print(obj)

RawQuery 返回我需要的数据,但我不知道如何从特定表中检索特定字段。 例如: print(obj.name) 将为我提供州名称,而 print(obj.id) 将为我提供州 ID。 如果州表和城市表都有“名称”和“id”字段,如何仅提取城市名称或城市 ID?

有没有更好的方法以最少的数据库调用次数来获取我需要的数据? 除了更好的方法之外,我还想知道在使用原始查询时如何区分表的同名列名(例如id、name)。

谢谢你。

python django orm left-join
1个回答
0
投票

您想要的结果通常不是最佳的。事实上,它每次都会在这里重复

State
的数据,使得数据库的结果更大,并且还可能会增加Django很多的内存使用量。

为了解决这个问题,Django 提供了

.prefetch_related(…)
 [Django-doc],它将进行两个查询,第一个查询为
State
的数据,然后获取相关的
City
和在 Django/Python 中进行 JOINing。

因此我们可以通过以下方式查询:

states = State.objects.prefetch_related('cities')
for state in states:
    print(f'for {state}')
    for city in state.cities.all():
        print(f' - {city}')
© www.soinside.com 2019 - 2024. All rights reserved.