我在这里阅读了文档和所有相关问题,但是我没有正确理解 select_related 在链式/多个外键上的表现。
假设我们有以下模型:
class RecordLabel(models.Model):
title = models.CharField(...)
class Band(models.Model):
band_name = models.CharField(...)
class Artist(models.Model):
record_label = models.ForeignKey(RecordLabel,...)
belongs_to_band = models.ForeignKey(Band, ...)
class Producer(models.Model):
customer = models.ForeignKey(Artist, ...)
A 。我们将如何在
中使用select_relatedProducer.objects.filter(...).select_related(?)
查询,以便一切都预先加载?会是这样:
Producer.objects.filter(...).select_related(
'customer__record_label', 'customer__belongs_to_band')
为什么?
B。。如果Band类具有“流派”作为外键,
class Genre(models.Model):
genre_name = models.CharField(...)
class Band(models.Model):
band_name = models.CharField(...)
music_genre = models.ForeignKey(Genres, ...)
然后,为了预先加载所有内容,我们将执行以下操作:
Producer.objects.filter(...).select_related(
'customer__record_label__music_genre', 'customer__record_label__band_name',
'customer__belongs_to_band__music_genre', 'customer__belongs_to_band__music_genre')
或类似的内容:
Producer.objects.filter(...).select_related(
'customer__record_label__music_genre', 'customer__record_label__band_name',
'customer__belongs_to_band', 'customer__belongs_to_band')
答案 0 :(得分:1)
关于问题B:
如果我正确理解了您的问题,则只需指定一次字段,无需重复。
注意:我会再次在此处显示您模型的最终版本,否则会感到困惑。
class RecordLabel(models.Model):
title = models.CharField(...)
class Genre(models.Model):
genre_name = models.CharField(...)
class Band(models.Model):
band_name = models.CharField(...)
music_genre = models.ForeignKey(Genre, ...)
class Artist(models.Model):
record_label = models.ForeignKey(RecordLabel, ...)
belongs_to_band = models.ForeignKey(Band, ...)
class Producer(models.Model):
customer = models.ForeignKey(Artist, ...)
要选择所有相关模型(进行一个大联接SQL查询):
qs = Producer.objects.filter(...).select_related(
'customer__record_label',
'customer__belongs_to_band__music_genre')
第一部分(customer
)预提取相关艺术家和相关唱片公司标签(__record_label
);第二部分不需要获取艺术家,因为它已经存在了,但是它继续预取了相关乐队(__belongs_to_band
)和相关流派(__music_genre
)。现在,您有了一个可以访问所有5个表(模型)的SQL查询。
提示:您可以使用qs.query
来查看查询将生成的SQL语句的基本概念;这应该使您对它构成的联接有所了解。
如果查询遇到问题,则应添加更多有关正在发生的情况和期望的信息。
答案 1 :(得分:0)
对于问题A: 将参数作为字符串传递
qs = Producer.objects.filter(...).select_related(
'customer__record_label', 'customer__belongs_to_band')
编辑:似乎缺少的引号只是提问者的错字,而不是真正的问题。