在不知道子类名称的情况下,如何访问 django 中对象的子类?

2025-02-21 08:48:00
admin
原创
20
摘要:问题描述:在 Django 中,当您有一个父类和多个从该类继承的子类时,您通常会通过 parentclass.childclass1_set 或 parentclass.childclass2_set 访问子类,但是如果我不知道我想要的特定子类的名称怎么办?有没有办法在不知道子类名的情况下获取父->子方...

问题描述:

在 Django 中,当您有一个父类和多个从该类继承的子类时,您通常会通过 parentclass.childclass1_set 或 parentclass.childclass2_set 访问子类,但是如果我不知道我想要的特定子类的名称怎么办?

有没有办法在不知道子类名的情况下获取父->子方向的相关对象?


解决方案 1:

更新:对于 Django 1.2 及更新版本,可以跨反向 OneToOneField 关系(从而沿着继承层次结构向下)跟踪 select_related 查询,有一种更好的技术可用,它不需要real_type在父模型上添加字段。它在django-model-utils项目中作为InheritanceManager提供。)

执行此操作的常用方法是将 ForeignKey 添加到 Parent 模型上的 ContentType,该模型存储了正确的“叶”类的内容类型。如果没有这个,您可能必须在子表上执行大量查询才能找到实例,具体取决于继承树的大小。以下是我在一个项目中执行此操作的方法:

from django.contrib.contenttypes.models import ContentType
from django.db import models

class InheritanceCastModel(models.Model):
    """
    An abstract base class that provides a ``real_type`` FK to ContentType.

    For use in trees of inherited models, to be able to downcast
    parent instances to their child types.

    """
    real_type = models.ForeignKey(ContentType, editable=False)

    def save(self, *args, **kwargs):
        if self._state.adding:
            self.real_type = self._get_real_type()
        super(InheritanceCastModel, self).save(*args, **kwargs)
    
    def _get_real_type(self):
        return ContentType.objects.get_for_model(type(self))
            
    def cast(self):
        return self.real_type.get_object_for_this_type(pk=self.pk)
    
    class Meta:
        abstract = True

它被实现为一个抽象基类以使其可重用;您也可以将这些方法和 FK 直接放到特定继承层次结构中的父类上。

如果您无法修改父模型,则此解决方案将不起作用。在这种情况下,您几乎只能手动检查所有子类。

解决方案 2:

在 Python 中,给定一个(“新式”)类 X,您可以使用 获取其(直接)子类X.__subclasses__(),这将返回类对象列表。(如果您想要“进一步的后代”,您还必须调用__subclasses__每个直接子类,等等——如果您需要有关如何在 Python 中有效地执行此操作的帮助,请询问!)。

一旦您以某种方式确定了感兴趣的子类(如果您想要所有子类的实例,则可能是所有子类),getattr(parentclass,'%s_set' % childclass.__name__)应该会有所帮助(如果子类的名称是'foo',这就像访问一样parentclass.foo_set——不多也不少)。再次强调,如果您需要说明或示例,请询问!

解决方案 3:

Carl 的解决方案很好,如果有多个相关的子类,可以手动执行此操作:

def get_children(self):
    rel_objs = self._meta.get_all_related_objects()
    return [getattr(self, x.get_accessor_name()) for x in rel_objs if x.model != type(self)]

它使用了 _meta 之外的函数,虽然不能保证随着 django 的发展而保持稳定,但是它可以起到作用,并且可以在需要时即时使用。

解决方案 4:

事实证明我真正需要的是这个:

使用内容类型和继承感知管理器对继承进行建模

这对我来说非常有效。不过,也感谢其他人。光是阅读你们的回答我就学到了很多东西!

解决方案 5:

您可以为此使用django-polymorphic 。

它允许自动将派生类转换回其实际类型。它还提供 Django 管理支持、更高效的 SQL 查询处理以及代理模型、内联和表单集支持。

基本原理似乎被重新发明了很多次(包括 Wagtail 的.specific,或本文中概述的示例)。然而,需要付出更多努力才能确保它不会导致 N 查询问题,或者与管理员、表单集/内联或第三方应用程序很好地集成。

解决方案 6:

这是我的解决方案,再次使用它,_meta所以不能保证其稳定性。

class Animal(models.model):
    name = models.CharField()
    number_legs = models.IntegerField()
    ...

    def get_child_animal(self):
        child_animal = None
        for r in self._meta.get_all_related_objects():
            if r.field.name == 'animal_ptr':
                child_animal = getattr(self, r.get_accessor_name())
        if not child_animal:
            raise Exception("No subclass, you shouldn't create Animals directly")
        return child_animal

class Dog(Animal):
    ...

for a in Animal.objects.all():
    a.get_child_animal() # returns the dog (or whatever) instance

解决方案 7:

您可以通过查找父类中所有属于 django.db.models.fields.related.RelatedManager 实例的字段来实现此目的。从您的示例来看,您谈论的子类似乎不是子类。对吗?

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1343  
  信创产业的蓬勃发展推动着各行业数字化转型加速,数据库迁移作为其中关键一环,面临诸多挑战。信创数据库迁移旨在将传统数据库平稳过渡到信创环境,以满足自主可控、安全可靠的需求。这一过程涉及技术、业务等多方面因素,稍有不慎就可能出现各种问题,影响业务的正常运行。深入探讨信创数据库迁移过程中的常见问题及解决方案,对于保障迁移工作...
2027年信创国产化   41  
  随着信息技术的飞速发展,信创国产化成为了国家战略的重要组成部分。国产化信创产品名录涵盖了众多领域,其在各个关键应用场景中发挥着重要作用。而信创国产化操作系统作为其中的核心环节,具备五大核心优势,为我国信息技术产业的自主可控发展提供了坚实支撑。关键应用场景之办公领域在办公领域,国产化信创产品有着广泛且深入的应用。如今,越...
国产信创系统   37  
  随着信息技术的飞速发展,信创国产化操作系统在政府部门的推广应用具有重要的战略意义。它不仅关乎国家信息安全,更是推动国内信息技术产业自主创新、实现科技自立自强的关键举措。在当前复杂的国际形势下,政府部门积极推广信创国产化操作系统,对于保障国家政务信息的安全稳定运行,提升信息技术的自主可控能力,具有不可替代的重要作用。推广...
信创产品有哪些   28  
  在企业数字化转型的进程中,信创数据库解决方案的选择至关重要。它不仅关乎企业数据的安全存储与管理,更影响着企业业务的稳定运行与未来发展。合适的信创数据库能够助力企业在复杂多变的市场环境中提升竞争力,保障数据主权与安全。然而,面对市场上众多的信创数据库产品和解决方案,企业往往感到困惑,不知如何做出正确的选择。接下来,我们将...
信创电脑   24  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用