Django: Two different child classes point to same parent class

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 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()

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()

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.


What you are doing is not possible as you do it, Django has specific rules for inheritance

The only possible schema is:

class Parent(models.Model):
    class Meta:
        abstract = True # MUST BE !!! This results in no relation generated in your DB

    field0 = models.CharField(...
    ...

    # here you're allowed to put some functions and some fields here


class Child(models.Model):
    field1 = models.CharField(...
    ...

    # Anything you want, this model will create a relation in your database with field0, field1, ...


class GrandChild(models.Model):
    class Meta:
        proxy = True # MUST BE !!! This results in no relation generated in your DB

    # here you're not allowed to put DB fields, but you can override __init__ to change attributes of the fields: choices, default,... You also can add model methods.

This is because there is no DB inheritance in most DBGS. Thus you need to make you parent class abstract !

Tags:

Django

Orm