django 仅查询抽象超类的特定子类

jbose2ul  于 2023-01-10  发布在  Go
关注(0)|答案(1)|浏览(106)

这个问题与前面的问题基本相似:

我将此作为一个新的单独问题发布,因为:

  • 我还有一些在前面的问题中没有提到的其他次要考虑事项
  • 前面的问题相对来说比较老,如果正确答案在最近发生了变化,我想知道这些问题是否还不够明显(考虑到它们已经接受了答案),无法引起那些可能知道这种潜在变化的人的注意。

考虑到这一点,我将从头开始,全面而具体地定义这个问题--我把它留给Hive来确定一个近似的重复是否合适。

    • 背景**

假设我正在构建模型来表示建筑物的各个部分,我将建筑物拆分为逻辑类:

  • 第一个月
  • BuildingSpace(ABC)
  • Office(BuildingSpace)
  • CommonArea(BuildingSpace)
    • 目标**

Floor下,我希望方法能够检索所有buildingspaces-* 或 *,分别是它的两个子类之一:

from typing import Type
class Floor(models.Model):
    def getAllSpaces():
        # return all objects that satisfy Type[BuildingSpace]
    def getAllOffices():
        # return all objects that satisfy strictly and only Type[Office]
    def getAllCommonAreas():
        # return all objects that satisfy strictly and only Type[CommonArea]
    • 可能的解决办法**

django-model-utils看起来可以通过其InheritanceManager和.select_subclass()方法支持这种开箱即用的查询--但是,最重要的是requires BuildingSpace to be concrete,因此该解决方案不得不使用多表继承。据我所知,这会增加每个查询的数据库负载,因此我研究了创建子类代理以减轻这种负载。但是InheritanceManager doesn't support proxies。当所有的都说了和做了之后,django-model-utils在我看来不可避免地会在查询时给我带来多表继承的损失。
就我所知,django-polymorphic也支持这种开箱即用的方式,使用.instance_of(subclass)。纯粹从编码的Angular 来看,这种方法看起来非常干净和易于使用。但它也考虑come with database performance considerations,使admin-panel compliant看起来不是微不足道的。
从本质上看,django可以通过一些迂回的方式来实现这一点,但我看到有人声称,使用原生QuerySet.filter()方法实现上述相同的功能比上述两种扩展的性能更差。
我简要考虑过的最后一个替代解决方案,我认为它可以在不考虑创建数据库的情况下在本地工作(但确实需要稍微重新设计),是直接访问子类管理器,然后通过QuerySet.Union类型的方法实现getAllSpaces()的预期结果。

    • 几乎死亡**

天真的设置如何我想象能够使用代码:

class BuildingSpace(models.Model):
    floor  = models.ForeignKey('Floor', 
                                on_delete=models.CASCADE, 
                                related_name="interiors")
    class Meta:
        abstract = True

class Floor(models.Model):
    def _InteriorManager(self): # get the default manager of BuildingSpace
        return self.interiors
    def GetAllInteriors(self):
        return self._InteriorManager().all() # get the full Type[BuildingSpace] queryset, but this isn't supported in native django

    def GetOffices(self):
        return self._InteriorManager().instance_of(Office) # django-polymorphic
    def GetCommonAreas(self):
        return self._InteriorManager().select_subclasses(CommonAreas).all() # django-model-utils
    • 问题**

我希望得到的答案能够权衡以下因素:

  • django-model-utilsdjango-polymorphic和其他一些基于QuerySet.filter()的最佳方案在性能方面是否有显著差异(可能还有顶部的相关问题)
  • 这两个扩展是否暗示了任何其他值得注意的考虑因素(易用性、可扩展性、如何进行附加过滤等)
  • 如果我需要解决的用例永远不会比我提供的具体代码示例更复杂,那么我的"最终替代解决方案"最终会在所有方面(性能、易用性、可扩展性)都更好吗
fdbelqdn

fdbelqdn1#

到目前为止,我还没有关于数据库性能主题的见解,但我要说的是:
django-polymorphic使用起来非常流畅。所需的代码调整最少,语法既简短又直观。让它与管理面板兼容的困难是一个烟幕,至少只要你做基本的、直接的子类化。
对于任何遇到类似问题的人,请不要犹豫,尝试一下吧。你不能在抽象类上使用它,如前所述,但是除非你有特殊的需要,否则它看起来确实像是有一个具体的超类,并且使用这个库比我在问题中描述的手动解决方案要容易得多。

相关问题