1

I'm working on a Django app. I have a table, and one of its columns can have one of four values, and depending on that value, it must have a one-to-one relationship with another table which has columns specific to that value.

Here is my models.py:

from django.db import models

class Item(models.Model):
    id = models.AutoField(primary_key=True)
    type_choices = (
     ('A', 'Type A'),
     ('B', 'Type B'),
     ('C', 'Type C'),
     ('D', 'Type D'),
    )
    type = models.CharField(max_length=1, choices=type_choices)


class TypeA(models.Model):
    item = models.OneToOneField(
        Item,
        primary_key=True,
    )
    # Type A specific fields


class TypeB(models.Model):
    item = models.OneToOneField(
        Item,
        primary_key=True,
    )
    # Type B specific fields


class TypeC(models.Model):
    item = models.OneToOneField(
        Item,
        primary_key=True,
    )
    # Type C specific fields


class TypeD(models.Model):
    item = models.OneToOneField(
        Item,
        primary_key=True,
    )
    # Type D specific fields

Since nothing is stopping me from creating, say, a row in TypeA and a row in TypeB, with links back to the same row in Item, (Which is not something I want) I am sure to screw something up at some point.

Is their anything I can do, in Django or something else, that will let me protect myself against this problem?

Or perhaps should my models be structured in a completely different way?

Cheers

99lives
  • 798
  • 1
  • 8
  • 17

1 Answers1

1

Disclaimer: this may not be a complete answer, but will provide some pointers to get there.


This might get more complicated than you think.

What you can do is

  • Create a base class - TypeBase for the types you have. Add foreign key of your item class
  • Create required sub-classes per type - class TypeA(TypeBase).
  • Use django's ContenType and add its foreingn key into the base. This is used to determine which type of instance that particular object is. ContentType creates a loose coupling between the classes.
  • Override save() method of TypeBase to set the type appropriately.
  • You may need to add few more methods like
    • get_type - to get type from ContentType.
    • get_type_object - to get object of particular type from the TypeBase object.
Rohan
  • 52,392
  • 12
  • 90
  • 87