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

2025-02-21 08:48:00
admin
原创
18
摘要:问题描述:在 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 实例的字段来实现此目的。从您的示例来看,您谈论的子类似乎不是子类。对吗?

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1325  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它涵盖了从产品概念产生到产品退市的整个生命周期,通过整合跨部门团队、优化流程等方式,显著提升产品开发的效率和质量,进而为项目的成功奠定坚实基础。深入探究IPD流程的五个阶段与项目成功之间...
IPD流程分为几个阶段   4  
  华为作为全球知名的科技企业,其成功背后的管理体系备受关注。IPD(集成产品开发)流程作为华为核心的产品开发管理模式,其中的创新管理与实践更是蕴含着丰富的经验和深刻的智慧,对众多企业具有重要的借鉴意义。IPD流程的核心架构IPD流程旨在打破部门墙,实现跨部门的高效协作,将产品开发视为一个整体的流程。它涵盖了从市场需求分析...
华为IPD是什么   3  
  IPD(Integrated Product Development)研发管理体系作为一种先进的产品开发模式,在众多企业的发展历程中发挥了至关重要的作用。它不仅仅是一套流程,更是一种理念,一种能够全方位提升企业竞争力,推动企业持续发展的有效工具。深入探究IPD研发管理体系如何助力企业持续发展,对于众多渴望在市场中立足并...
IPD管理流程   3  
  IPD(Integrated Product Development)流程管理旨在通过整合产品开发流程、团队和资源,实现产品的快速、高质量交付。在这一过程中,有效降低成本是企业提升竞争力的关键。通过优化IPD流程管理中的各个环节,可以在不牺牲产品质量和性能的前提下,实现成本的显著降低,为企业创造更大的价值。优化产品规划...
IPD流程分为几个阶段   4  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用