如何在django中使用一个查询检索没有FK的相关实例
假设有三个模型,分别命名为电影、演员和参与如何在django中使用一个查询检索没有FK的相关实例,django,django-models,django-orm,Django,Django Models,Django Orm,假设有三个模型,分别命名为电影、演员和参与 class Movie(models.Model): identifier = models.CharField() class Actor(models.Model): name = models.CharField() class Participation(models.Model): movie_identifier = models.CharField() actor = models.ForgeinK
class Movie(models.Model):
identifier = models.CharField()
class Actor(models.Model):
name = models.CharField()
class Participation(models.Model):
movie_identifier = models.CharField()
actor = models.ForgeinKey(Actor, on_delete=models.CASCADE)
让我们假设我不能在参与模式中使用ForgeinKey
如何仅通过一个查询检索电影的所有参与记录
如果参与表中有电影的外键,下面是解决方案:
qs = Movie.objects.filter(identifier="an_identiier").prefetch_related("participations_set")
在参与模型中没有电影外键的情况下,如何执行此操作
谢谢 在设计数据库(因此在设计模型时)时,最重要的事情之一是 您谈论的
参与
与多个模型相关,如电影
,系列
,插曲
,等等。这意味着电影
,系列
,插曲
都可以说有一些共同的东西,或者它们可以说是另一个实体的专业化,让我们说可参与性
,因为没有更好的词,或者我们可以说可参与性
是电影
的一种推广,系列
,插曲
等
我们如何对这些进行建模?我们将有一个额外的模型,我们的其他模型将有一个OneToOneField
:
class Participatable(models.Model):
# Any common fields here
MOVIE = 'M'
SERIES = 'S'
TYPE_CHOICES = [
(MOVIE, 'Movie'),
(SERIES, 'Series'),
]
subject = models.CharField(max_length=1, choices=TYPE_CHOICES)
class Movie(models.Model):
# uncommon fields
participatable = models.OneToOneField(
Participatable,
on_delete=models.CASCADE,
related_name='movie',
)
class Series(models.Model):
# uncommon fields
participatable = models.OneToOneField(
Participatable,
on_delete=models.CASCADE,
related_name='series',
)
class Participation(models.Model):
participatable = models.ForgeinKey(Participatable, on_delete=models.CASCADE)
actor = models.ForgeinKey(Actor, on_delete=models.CASCADE)
除此之外,我发现这个解决方案对于此类建模来说是最好的,您可以使用,它将基本上完成您当前所做的工作。也就是说,它将使用一个存储相关id的字段和一个外键,该外键指向表中的一个条目,该条目将简单地描述该id用于哪个表。为什么不能使用外键?你能解释一下原因吗?另外,do note
prefetch\u related
进行多个查询,只是它收集需要获取的对象并进行查询以将它们全部聚集在一起,所以至少进行了2次查询。如果表不维护关系,您希望如何返回表的记录。我想那是不可能的。有很多像电影这样的模型,比如连续剧,插曲。参与应该与所有人都有关系,我不想有多个FK。关于预回迁,它只有一个对数据库的调用,对吗?因此,您不会多次为网络延迟付费。@Moein您可以自己尝试并模拟预回迁:获取与任何电影相关的所有参与对象(Participation.objects.filter(Movie\u identifier\u in=qs.values('identifier'))
),然后循环所有结果并附加到每部电影的列表中。“我不想有多个FK”可能不是让事情变得如此复杂的一个很好的理由:)@iain shelvington使用这种方式只向数据库发送一个请求?qs的所有元素都将被提取?例如,list(qs[:50])
不会发送请求吗?