Django Multi-table inheritance: specify custom one-to-one column name
Asked Answered
F

2

9

I'm trying to create a Django ORM mapping that's compatible with an existing data model, so I'm trying to work with an existing set of table and column names.

I've got a multi-table inheritance situation where a class InformationObject derives from class Object. I'd like to let Django handle this the usual way:

class Object(models.Model):
    class Meta:
        db_table = "object"          

class InformationObject(Object):
    class Meta:
        db_table = "information_object"

In this case Django would automatically create a one-to-one field on the inheriting model called object_ptr_id. However, on the schema I'm constrained to use, the reference to the Object is simply called "id". So:

Is there a way to somehow specify the name of the column Django auto-magically uses for multi-table inheritance?

The alternative, which I'll have to use otherwise, is to use an explicit one-to-one field, but then I won't be able to inherit non-database methods from the Object model:

class Object(models.Model):
    class Meta:
        db_table = "object"          

class InformationObject(models.Model):
    class Meta:
        db_table = "information_object"
    id = models.OneToOneField(Object, primary_key=True, db_column="id")  

Any ideas? Maybe I could create a common base class for both of them and put non-db methods there...?

Fawcette answered 1/9, 2011 at 10:55 Comment(1)
Your last idea is pretty solid: create a common base class for both of them, and use it as a mixin to provide the extra functionality you're looking for. I suggest trying it as an experiment. (It may not work; Django's database layer does some pretty out-there things with Python's metaclasses, but it's worth a try.)Tades
H
11

From the django docs (latest stable version):

As mentioned, Django will automatically create a OneToOneField linking your child class back any non-abstract parent models. If you want to control the name of the attribute linking back to the parent, you can create your own OneToOneField and set parent_link=True to indicate that your field is the link back to the parent class.

Housework answered 4/10, 2011 at 8:52 Comment(0)
A
1

As mentioned by @fusion quoting from the docs, you will have to create a OneToOneField if you want to specify the column, while using model inheritance. The inherited fields will be available in the child class in both self scope AND the one-to-one field.

class Object(models.Model):
    class Meta:
        db_table = "object"   
    column_1 = models.CharField()

class InformationObject(Object):
    class Meta:
        db_table = "information_object"
    # arbitrary property name (parent_link)
    parent_link = models.OneToOneField(Object, primary_key=True, db_column="id", parent_link=True) 

In this example:

>>> inf_obj = InformationObject.objects.get(pk=1)
>>> print inf_obj.column_1 == inf_obj.parent_link.column_1
True
Anthropophagite answered 20/2, 2013 at 6:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.