我如何找到“具体类"?django 模型基类 [英] How do I find the "concrete class" of a django model baseclass

查看:14
本文介绍了我如何找到“具体类"?django 模型基类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在使用模型继承时找到 django-model 对象的实际类.

I'm trying to find the actual class of a django-model object, when using model-inheritance.

一些描述问题的代码:

class Base(models.model):
    def basemethod(self):
        ...

class Child_1(Base):
    pass

class Child_2(Base):
    pass

如果我创建两个子类的各种对象并创建一个包含它们的查询集:

If I create various objects of the two Child classes and the create a queryset containing them all:

Child_1().save()
Child_2().save()
(o1, o2) = Base.objects.all()

我想在 basemethod 中确定对象是 Child_1 还是 Child_2 类型,我可以通过 o1.child_1 和 o2.child_2 访问子对象,但这会重新获取有关基类中子类的知识.

I want to determine if the object is of type Child_1 or Child_2 in basemethod, I can get to the child object via o1.child_1 and o2.child_2 but that reconquers knowledge about the childclasses in the baseclass.

我想出了以下代码:

def concrete_instance(self):
    instance = None
    for subclass in self._meta.get_all_related_objects():
        acc_name = subclass.get_accessor_name()
        try:
            instance = self.__getattribute__(acc_name)
            return instance
        except Exception, e:
            pass

但感觉很脆弱,如果我继承更多级别,我不确定会发生什么.

But it feels brittle and I'm not sure of what happens when if I inherit in more levels.

推荐答案

Django 在父模型的表和子模型的表之间使用 OneToOneField 实现模型继承.当您执行 Base.object.all() 时,Django 只查询 Base 表,因此无法知道子表是什么.因此,不幸的是,如果没有额外的查询,就不可能直接进入子模型实例.

Django implements model inheritance with a OneToOneField between the parent model's table and the child model's table. When you do Base.object.all(), Django is querying just the Base table, and so has no way of knowing what the child table is. Therefore, unfortunately, it's not possible to go directly to the child model instance without additional queries.

这个 snippet 展示了向基础模型添加 ContentType 字段的常用方法:

This snippet shows a common method of adding a ContentType field to the base model:

from django.contrib.contenttypes.models import ContentType

class Base(models.Model):
    content_type = models.ForeignKey(ContentType,editable=False,null=True)

    def save(self):
        if(not self.content_type):
            self.content_type = ContentType.objects.get_for_model(self.__class__)
        self.save_base()

    def as_leaf_class(self):
        content_type = self.content_type
        model = content_type.model_class()
        if(model == Base):
            return self
        return model.objects.get(id=self.id)

然后你可以说if Base.content_type.model_class()来确定类型.

You can then say if Base.content_type.model_class() to determine the type.

这里是另一个将自定义管理器添加到组合中的代码段.

Here is another snippet that adds a custom manager into the mix.

如您所见,这两种解决方案都有可能非常昂贵.如果您有大量实例,则使用 as_leaf_class() 方法将需要对每个项目进行一次查询.

As you can see, both of these solutions have the potential to be extremely expensive. If you have a large number of instances, using the as_leaf_class() method will require one query on each item.

相反,如果您有一组已知的子模型,只需单独查询每个模型并将实例聚合到一个列表中.

Instead, if you have a known set of child models, simply query each model separately and aggregate the instances into one list.

这篇关于我如何找到“具体类"?django 模型基类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆