Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make my models follow DRY principles

I have a model in which I need to represent different jobs for a labor application, for example:

from django.db import models

class PostFirstJobAd(models.Model):
    fist_job_ad_title = models.CharField(max_length=225)
    first_job_ad_description = models.TextField()
    created_at = models.DateTimeField(auto_now=True)

class PostSecondJobAd(models.Model):
    second_job_ad_title = models.CharField(max_length=225)
    second_job_ad_description = models.TextField()
    created_at = models.DateTimeField(auto_now=True)

class PostThirdJobAd(models.Model):
    third_job_ad_title = models.CharField(max_length=225)
    third_job_ad_description = models.TextField()
    created_at = models.DateTimeField(auto_now=True)

Instantly you can see that I'm repeating title, description and created_at, I'm just changing field's name, it's not DRY and code is starting to smell. The reason for this is because I want to register every job separately inside django admin, so I will have clear situation inside site administration.

One way to make them DRY is to use Abstract base classes but I have a problem because from the docs:

This model will then not be used to create any database table. Instead, when it is used as a base class for other models, its fields will be added to those of the child class.

What will be the right approach in this case, can someone help me understand this.

like image 514
copser Avatar asked Dec 13 '25 02:12

copser


1 Answers

Using abstract base models:

class JobAd(models.Model):
    title = models.CharField(max_length=225)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class PostFirstJobAd(JobAd):
    pass

class PostSecondJobAd(JobAd):
    pass

class PostThirdJobAd(JobAd):
    pass

This would create 3 tables. The base class JobAd does not have a table in the db.

Since you appear to have 3 different models with the exact same code, you should question whether you really need 3 different models at all. Another option is to just store them all in one table, and add another field for the "other" thing.

class JobAd(models.Model):
    pos = models.CharField(max_length=100, choices=['first', 'second', 'third'])
    title = models.CharField(max_length=225)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now=True)

An integer field for pos is also possible.

like image 124
wim Avatar answered Dec 15 '25 15:12

wim



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!