Django:两个不同的子类指向同一个父类 [英] Django: Two different child classes point to same parent class

查看:138
本文介绍了Django:两个不同的子类指向同一个父类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模型 Person 存储有关人员的所有数据。我还有一个扩展Person的客户端模型。我有另一个扩展模型 OtherPerson ,它也扩展了 Person 模型。我想创建一个指向 Person 的客户端,并且还创建一个 OtherPerson 记录,指向。基本上,我想要一个 Person 对象被视为客户端 OtherPerson ,具体取决于当前视图。这是否可能与Django的ORM,或者我需要以某种方式编写一个Raw查询来创建此场景。我相当确定从数据库方面是可能的,因为这两个子类都只能使用person_ptr_id字段指向父Person类。

I have a model Person which stores all data about people. I also have a Client model which extends Person. I have another extending model OtherPerson which also extends the Person model. I want to create a Client pointing to a Person, and ALSO create an OtherPerson record which points to that Person. Basically, I want one Person object to be viewed as a Client and and an OtherPerson, depending on the current view. Is this possible with Django's ORM, or do I need to somehow write a Raw query to create this scenario. I am quite certain it is possible from the database side, because both child classes would just point to the parent Person class with their person_ptr_id field.

只要我创建一个客户端(因此一个 Person ),我还可以创建一个 OtherPerson 对象使用客户端中的基础 Person 。这样,我可以将它们视为客户端 OtherPerson ,并保存一个将影响个人各个字段

Simply put, if I create a Client (and thus a Person), can I also create an OtherPerson object using the base Person from the Client. That way I can view them as a Client OR as an OtherPerson, and saving one will affect the Person fields of each?

水平多态性?

是我的模型的缩减版本,以便澄清:

Here is a cut down version of my models in case that clarifies:

class Person(models.Model):
    """
        Any person in the system will have a standard set of details, fingerprint hit details, some clearances and items due, like TB Test.
    """
    first_name = models.CharField(db_index=True, max_length=64, null=True, blank=True, help_text="First Name.")
    middle_name = models.CharField(db_index=True, max_length=32, null=True, blank=True, help_text="Middle Name.")
    last_name = models.CharField(db_index=True, max_length=64, null=True, blank=True, help_text="Last Name.")
    alias = models.CharField(db_index=True, max_length=128, null=True, blank=True, help_text="Aliases.")
    .
    .
    <some person methods like getPrintName, getAge, etc.>

class Client(Person):
    date_of_first_contact = models.DateField(null=True, blank=True)
    .
    .
    <some client methods>


class OtherPerson(Person):
    active_date = models.DateField(null=True, blank=True)
    termination_date = models.DateField(null=True, blank=True)
    .
    .
    <some other person methods>


推荐答案

好的,我讨厌回答我自己的问题因为它是重复的( Django模型继承:创建现有实例的子实例(downcast)?

Okay, I hate to answer my own question, especially since it is sort of a repeat of (Django model inheritance: create sub-instance of existing instance (downcast)?

@Daniel Roseman再次让我脱口而出。

@Daniel Roseman got me out of a jam AGAIN. Gotta love that guy!

person = Person.objects.get(id=<my_person_id>)
client = Client(person_ptr_id=person.id)
client.__dict__.update(person.__dict__)
client.save()
other_person = OtherPerson(person_ptr_id=person.id)
other_person.__dict__.update(person.__dict__)
other_person.save()

如果我有一个现有的客户端并希望从他们中获得一个 OtherPerson ,这是我的确切用例,我只是这样做:

If I have an existing Client and want to make an OtherPerson from them, which is my exact use-case, I just do this:

client_id = <ID of Client/Person I want to create an OtherPerson with>
p = Person.objects.get(id=client_id)
o = OtherPerson(person_ptr_id=p.id) # Note Person.id and Client.id are the same.
o.__dict__.update(p.__dict__)
o.save()

现在该人在客户端屏幕上显示为客户端,在另一人屏幕上显示为OtherPerson。我可以获得具有所有OtherPerson详细信息和功能的Person的OtherPerson版本,或者我可以获得具有所有客户端详细信息和功能的该人员的客户端版本。

Now the person shows up as a Client on the clients screen and as an OtherPerson on the other person screen. I can get the OtherPerson version of the Person which has all the OtherPerson details and functions or I can get a Client version of that Person which has all the Client details and functions.

这篇关于Django:两个不同的子类指向同一个父类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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