I realize that the 3 models that I use right now have a ton of shared fields. I was wondering what the best way to condense these models would be. I've read some articles on metaclasses and model inheritance but wanted to see what the "best" way to do this would be.
models.py
class Car(models.Model):
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.IntegerField(default=2021, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
seats = models.PositiveSmallIntegerField()
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Truck(models.Model):
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.IntegerField(default=datetime.now().year, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
seats = models.PositiveSmallIntegerField()
bed_length = models.CharField(max_length=100)
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Boat(models.Model):
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.PositiveSmallIntegerField(default=datetime.now().year, validators=[MaxValueValidator(datetime.now().year)])
length = models.CharField(max_length=100)
width = models.CharField(max_length=100)
HIN = models.CharField(max_length=14, validators=[MinLengthValidator(12)], blank=True)
current_hours = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
I can notice that some fields are similar but aren't the same, for example year
are not the same for all. Due to that I propose to you the following.
class TimeStampedModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Vehicule(TimeStampedModel):
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Meta:
abstract = True
class WheeledVehicle(Vehicule):
seats = models.PositiveSmallIntegerField()
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
class Meta:
abstract = True
class Car(WheeledVehicle):
year = models.IntegerField(default=2021, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
class Truck(WheeledVehicle):
year = models.IntegerField(default=datetime.now().year, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
bed_length = models.CharField(max_length=100)
class Boat(Vehicule):
year = models.PositiveSmallIntegerField(default=datetime.now().year, validators=[MaxValueValidator(datetime.now().year)])
length = models.CharField(max_length=100)
width = models.CharField(max_length=100)
HIN = models.CharField(max_length=14, validators=[MinLengthValidator(12)], blank=True)
current_hours = models.PositiveSmallIntegerField()
And if you want to go further, I suggest you to add created_by
and modified_by
fields to audit.
class TimeStampedModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class TimeStampedAuthModel(TimeStampedModel):
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL,
related_name="%(app_label)s_%(class)s_created_by")
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL,
related_name="%(app_label)s_%(class)s_modified_by")
class Meta:
abstract = True
class Vehicule(TimeStampedAuthModel):
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Meta:
abstract = True
class WheeledVehicle(Vehicule):
seats = models.PositiveSmallIntegerField()
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
class Meta:
abstract = True
class Car(WheeledVehicle):
year = models.IntegerField(default=2021, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
class Truck(WheeledVehicle):
year = models.IntegerField(default=datetime.now().year, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
bed_length = models.CharField(max_length=100)
class Boat(Vehicule):
year = models.PositiveSmallIntegerField(default=datetime.now().year, validators=[MaxValueValidator(datetime.now().year)])
length = models.CharField(max_length=100)
width = models.CharField(max_length=100)
HIN = models.CharField(max_length=14, validators=[MinLengthValidator(12)], blank=True)
current_hours = models.PositiveSmallIntegerField()