[英]When using Generics types, how can I call an Attribute of an inherited class on the Base class instance with Python / Django?
Let's say I have a base Generic class called person to group all other persons that extend it:假设我有一个名为 person 的基本通用 class 来对扩展它的所有其他人进行分组:
class Person(models.Model):
name = models.CharField(...)
And the class Worker, that extends the Person:以及扩展 Person 的 class Worker:
class Worker(Person):
card_id = models.CharField(...)
When I access all Person objects I also see the Workers, but lets say that from there I want to do this:当我访问所有 Person 对象时,我也看到了 Workers,但可以说从那里我想这样做:
worker = Worker(name='Example', card_id='1234')
person = Person.objects.all().first()
Let's say that for some reason I want to use the Person class and call an Attribute o Worker:假设由于某种原因我想使用 Person class 并调用 Attribute o Worker:
[in] person.card_id
# Somehow expecting this result:
[out] '1234
Is it possible, is it viable and how do I do it?是否可能,是否可行,我该怎么做?
I'm afraid this is not possible, even when you can guarantee that the Person
object you retrieved (ie. Person.objects.all().first()
) is also a Worker
.恐怕这是不可能的,即使您可以保证您检索到的
Person
object (即Person.objects.all().first()
)也是Worker
。
There three styles of inheritance possible in Django: Abstract Base classes , Proxy Models , and Multi-Table Inheritance Django 中可能有 inheritance 的三个 styles: 抽象基类、 代理模型和多表 ZE58BB489C13E702
In this case, you are using Multi-Table Inheritance .在这种情况下,您使用的是多表 Inheritance 。 As the name suggest, each model will receive its own table in the database and can therefore also be queried.
顾名思义,每个 model 都会在数据库中收到自己的表,因此也可以进行查询。
When querying for Person
objects, what you will end up with are Person
instances, not Worker
instances or any other child class instance.在查询
Person
对象时,您最终会得到Person
实例,而不是Worker
实例或任何其他子 class 实例。 Since the card_id
field is not defined in the Person
model, but rather in one of its child models, you will get an error when trying to retrieve the card_id
value of Person
instance, even though the instance is also a Worker
.由于
card_id
字段未在Person
model 中定义,而是在其子模型之一中定义,因此在尝试检索Person
实例的card_id
值时会出错,即使该实例也是Worker
。
However, if you know that your Person
instance is also a Worker
, you can retrieve it via:但是,如果您知道您的
Person
实例也是一个Worker
,您可以通过以下方式检索它:
person = Person.objects.all().first()
worker = person.worker
This works because the inheritance relationship creates a OneToOneField
between the child and each of its parents.这是因为 inheritance 关系在孩子和它的每个父母之间创建了一个
OneToOneField
。 However, note that this will give an error in case the person
instance is not actually a Worker
.但是,请注意,如果
person
实例实际上不是Worker
,这将给出错误。
One library that might help is the InheritanceManager from django-model-utils
.一个可能有帮助的库是
django-model-utils
的InheritanceManager 。
By attaching the InheritanceManager to your base class model such as:通过将 InheritanceManager 附加到您的基础 class model 例如:
from model_utils.managers import InheritanceManager
class Person(models.Model):
objects = InheritanceManager()
# ...
You can then use the .select_subclasses
filter to filter a queryset of the Parent model to only include the objects of a particular child class.然后,您可以使用
.select_subclasses
过滤器过滤父 model 的查询集,以仅包含特定子 class 的对象。 For example to only select the persons that are also workers, you can do the following query:例如,对于同时也是工人的人,您可以执行以下查询:
persons_worker = Person.objects.select_subclasses(Worker)
and you should never run into troubles when trying to do retrieve the card_id
for any of the instances in persons_worker
.并且在尝试为
persons_worker
中的任何实例检索card_id
时,您永远不应该遇到麻烦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.