这个问题与前面的问题基本相似:
- Django access to subclasses items from abstract class
- How to query abstract-class-based objects in Django?
我将此作为一个新的单独问题发布,因为:
- 我还有一些在前面的问题中没有提到的其他次要考虑事项
- 前面的问题相对来说比较老,如果正确答案在最近发生了变化,我想知道这些问题是否还不够明显(考虑到它们已经接受了答案),无法引起那些可能知道这种潜在变化的人的注意。
考虑到这一点,我将从头开始,全面而具体地定义这个问题--我把它留给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-utils
、django-polymorphic
和其他一些基于QuerySet.filter()
的最佳方案在性能方面是否有显著差异(可能还有顶部的相关问题)- 这两个扩展是否暗示了任何其他值得注意的考虑因素(易用性、可扩展性、如何进行附加过滤等)
- 如果我需要解决的用例永远不会比我提供的具体代码示例更复杂,那么我的"最终替代解决方案"最终会在所有方面(性能、易用性、可扩展性)都更好吗
1条答案
按热度按时间fdbelqdn1#
到目前为止,我还没有关于数据库性能主题的见解,但我要说的是:
django-polymorphic
使用起来非常流畅。所需的代码调整最少,语法既简短又直观。让它与管理面板兼容的困难是一个烟幕,至少只要你做基本的、直接的子类化。对于任何遇到类似问题的人,请不要犹豫,尝试一下吧。你不能在抽象类上使用它,如前所述,但是除非你有特殊的需要,否则它看起来确实像是有一个具体的超类,并且使用这个库比我在问题中描述的手动解决方案要容易得多。