[英]How can I join multiple models in Django into a virtual table?
如果我有 3 個模型,例如:
class Cow(models.Model):
name =
number_of_eyes =
number_of_feet =
color =
class Pig(models.Model):
name =
number_of_eyes =
number_of_feet =
intelligence =
class Horse(models.Model):
name =
number_of_eyes =
number_of_hooves =
weight_capacity =
speed =
而且我有興趣在我的模板中創建一個包含所有 3 個實例的Livestock
表,但我只對所有 3 個模型都具有的這些列感興趣:
我們可以忽略所有其他列。
如何將它們加入單個查詢集?
最終目標是獲得一個虛擬表(查詢集),我可以對它執行一些其他操作(filter、order_by、slice),然后僅在這些列中返回數據。
這在 Django ORM 中是否可行?
顯然,這也可以使用Union
來完成,正如 Nick ODell 所建議的:
from django.db.models import F
Cow.objects.filter(...).union(
Pig.objects.filter(...),
Horse.objects.filter(...).annotate(number_of_feet=F("number_of_hooves"))
).values('name', 'number_of_eyes', 'number_of_feet').order_by('name')[:3]
不幸的是,您無法在聯合之后過濾生成的查詢集,因此您需要在聯合之前過濾每個查詢集,但除此之外,在我的快速測試中似乎一切正常。
據我了解,這里與 MojixCoder 建議使用ContentType
的區別在於,您不需要在 Django 模型模塊中維護此虛擬表的單獨定義。 在某些情況下,這可能是一個優勢,因為當您獲得要包含在查詢中的新模型時,您不需要保持模塊更新,但在其他情況下,這可能是一個劣勢,因為我的方式有每次你想使用這個查詢時都要輸入很多,而在 MojixCoder 的例子中,你定義一次,你的查詢會更短。
我認為你有兩個選擇:
使用itertools.chain
:
from itertools import chain cows = Cow.objects.all() pigs = Pig.objects.all() horses = Horse.objects.all() livestock_list = sorted( chain(cows, pigs, horses), key=lambda livestock: livestock.created_at, reverse=True) )
使用contenttypes
:
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey class Livestock(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') created = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['-created']
現在您可以像 Django 中的任何其他 model 一樣查詢Livestock
Django
,但是您可以有一個可以引用 n 個模型的外鍵。 這就是內容contenttypes
所做的。
Livestock.content_object
為您提供您想要的東西,它可以是Cow
、 Pig
或Horse
。
只要記住在創建馬等實例后將對象添加到Livestock
model 即可。 您實際上需要將它們添加到 2 個模型中。 你可以用信號來做。
我認為第二種解決方案更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.