Daniel
Daniel

Reputation: 534

Managing inheritance in Django

So, in our database we had a Car model, but there could be different kinds of cars, with different fields and different processes associated to them, so I made some model classes that inherit from that Car, it's something like this:

class Car(models.Model):
    field = models.CharField(max_length=300)


class CarA(Car):
    field_a = models.CharField(max_length=300)


class CarA1(CarA):
    field_a1 = models.CharField(max_length=300)


class CarA2(CarA):
    field_a2 = models.CharField(max_length=300)


class CarB(Car):
    field_b = models.CharField(max_length=300)

Also, there are trips, and each trip has a car associated to them:

class Trip(BaseModel):
    car = models.ForeignKey(Car)

If I have a CarA1 instance, car_a1, I can save it in a Trip with car_a1.car_ptr, but it would be saved as a Car, and from there I don't think there's a way to get the CarA1 instance again except searching by the Car id in all the subclasses.

So, if I want to know which kind of car the trip has, or get a specific subclass field, it would be really complicated.

What do you suggest to do? I can just keep only the Car class with the specific fields nullable (field_a, field_b, etc), and a field to specify the kind of car, but that doesn't seem right, I would have to check on the kind to validate the fields, etc. But right now it seems like the better solution.

I'm using Django 1.11 and Python 3.6 btw.

Sorry I didn't use real code, I thought it would be way more complicated, also sorry if I didn't explain it very well, I'm sleep deprived and stressed.

Thanks!

Upvotes: 2

Views: 65

Answers (2)

slider
slider

Reputation: 12990

First, you can get to the child model from the parent model (see model based inheritance).

If you want to stick with your inheritance based design, you could define a field in Car called car_type which would correspond to the type of the child table. For example:

class Car(models.Model):
    CAR_A = 'car_a'
    CAR_B = 'car_b'
    CAR_TYPE_CHOICES = (
        (CAR_A, 'Car_A'),
        (CAR_B, 'Car_b'),
    )
    field = models.CharField(max_length=300)
    car_type = models.CharField(max_length=20, choices=CAR_TYPE_CHOICES)

And then you could override the save method of the child models so that their car_type field is the one that corresponds to their model.

class CarA(Car):
    field_a = models.CharField(max_length=300)

    def save(self, *args, **kwargs):
        self.car_type = Car.CAR_A
        super(CarA, self).save(*args, **kwargs)

# ... similarly for CarB

Now you can get to the child model from Car based on its car_type.

if car.car_type === Car.CAR_A:
    print(car.cara.field_a) 

Note that this will start to get cumbersome if you have many levels of inheritance, so I would encourage you to reconsider your design.

Upvotes: 1

a_k_v
a_k_v

Reputation: 1608

The problem in your model is when a new type of car introduced say car c you need to create another table for that. It is not ideal and what you need is one table for store the car details(commonly used) and separate table say Properties to store other details and give a foreign-key relation to Car model.

Upvotes: 3

Related Questions