簡體   English   中英

如何將 Django 中的多個模型加入到虛擬表中?

[英]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 個模型都具有的這些列感興趣:

  • 姓名
  • number_of_eyes
  • number_of_feet (number_of_hooves 如果馬)

我們可以忽略所有其他列。

如何將它們加入單個查詢集?

最終目標是獲得一個虛擬表(查詢集),我可以對它執行一些其他操作(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 的例子中,你定義一次,你的查詢會更短。

我認為你有兩個選擇:

  1. 使用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) )
  2. 使用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為您提供您想要的東西,它可以是CowPigHorse

    只要記住在創建馬等實例后將對象添加到Livestock model 即可。 您實際上需要將它們添加到 2 個模型中。 你可以用信號來做。

我認為第二種解決方案更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM