Need suggestions for building many models with the same fields approximately

Hi everyone,
I need your opinions about my models to build good and robust models by django.
I have the following models

# make a generic model 
class BasicData(models.Model):
    user = models.ForeignKey(
        "users.CustomUser",
        on_delete=models.CASCADE
    )

    active = models.BooleanField(default=False)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    is_deleted = models.BooleanField(default=False, verbose_name=_('Deleted'))
    deleted_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True


class CreateObject(BasicData):
    name = models.CharField(verbose_name="Name", max_length=100)
    type = models.CharField(verbose_name="Type", max_length=100, choices=OBJECT_TYPE)
    account_no = models.CharField(
                  verbose_name="Account No.", 
                  max_length=100, 
                  blank=True, null=True
     )
     updated_user = models.ForeignKey(
            "users.CustomUser", 
            related_name="user_make_create_object_changes", 
            on_delete=models.CASCADE
    )

    class Meta:
        verbose_name = _("create object")
        verbose_name_plural = _("Create Object")
        indexes = [
            models.Index(fields=["name"]),
            models.Index(fields=["type"]),
            models.Index(fields=["account_no"]),
            models.Index(fields=["active"]),
            models.Index(fields=["created_at"]),
            models.Index(fields=["updated_at"]),
            models.Index(fields=["is_deleted"]),
            models.Index(fields=["deleted_at"]),
        ]

    def __str__(self):
        return f"{self.name} - {self.type}"

I tended to use (CreateObject model) to build any model has the same fields(to reduce models coding), but I like to ask first in order to ensure that I have a robust models design.
- Here I have some questions (if I made the index for(active, create_at, updated_at, is_deleted and deleted_at)) in (BasicData) under class Meta:
- Will it apply in all models which inherit from (BasicData) and I don’t need to write it again and again in all models?


The next models have the same fields and I have others.

class UnitNames(BasicData):
    name = models.CharField(max_length=100)

    updated_user = models.ForeignKey(
        "users.CustomUser",
        related_name="user_make_unit_names_changes",
        on_delete=models.CASCADE,
    )

    class Meta:
        app_label = "configurations"
        verbose_name = "unit_names"
        verbose_name_plural = "UnitNames"
        indexes = [
            models.Index(fields=["name"]),
            models.Index(fields=["active"]),
            models.Index(fields=["created_at"]),
            models.Index(fields=["updated_at"]),
            models.Index(fields=["is_deleted"]),
            models.Index(fields=["deleted_at"]),
        ]

    def __str__(self):
        return "{}".format(self.name)  


class Branches(BasicData):
    name = models.CharField(max_length=100, unique=True)
    description = models.TextField(blank=True, null=True)

    updated_user = models.ForeignKey(
        "users.CustomUser",
        related_name="user_make_branches_changes",
        on_delete=models.CASCADE,
    )

    class Meta:
        app_label = "configurations"
        verbose_name = "branches"
        verbose_name_plural = "Branches"
        indexes = [
            models.Index(fields=["name"]),
            models.Index(fields=["active"]),
            models.Index(fields=["created_at"]),
            models.Index(fields=["updated_at"]),
            models.Index(fields=["is_deleted"]),
            models.Index(fields=["deleted_at"]),
        ]

    def __str__(self):
        return f"{self.name}"


class PosStation(BasicData):
    branch = models.ForeignKey(
        Branches,
        related_name="pos_branch",
        verbose_name=_("Branch"),
        on_delete=models.CASCADE,
    )
    name = models.CharField(max_length=100, unique=True, default="Text")
    description = models.TextField(blank=True, null=True, default="Text")

    updated_user = models.ForeignKey(
        "users.CustomUser",
        related_name="user_make_pos_station_changes",
        on_delete=models.CASCADE,
    )

    class Meta:
        app_label = "configurations"
        verbose_name = "pos_station"
        verbose_name_plural = "PosStations"
        ordering = ["-id"]
        indexes = [
            models.Index(fields=["name"]),
            models.Index(fields=["active"]),
            models.Index(fields=["created_at"]),
            models.Index(fields=["updated_at"]),
            models.Index(fields=["is_deleted"]),
            models.Index(fields=["deleted_at"]),
        ]

    def __str__(self):
        return f"{self.name}"


class Departments(BasicData):
    name = models.CharField(max_length=100)

    updated_user = models.ForeignKey(
        "users.CustomUser",
        related_name="user_make_departments_changes",
        on_delete=models.CASCADE,
    )

    class Meta:
        app_label = "configurations"
        verbose_name = "departments"
        verbose_name_plural = "Departments"
        indexes = [
            models.Index(fields=["name"]),
            models.Index(fields=["active"]),
            models.Index(fields=["created_at"]),
            models.Index(fields=["updated_at"]),
            models.Index(fields=["is_deleted"]),
            models.Index(fields=["deleted_at"]),
        ]

    def __str__(self):
        return f"{self.name}" 

Kindly if you have any suggestions to enhance my models, I will appreciate it
Thanks,

I think your design is OK. An abstract Models is a Python Class, so every model based in an abstract class will heritage all its methods and properties.

1 Like

See the docs for Abstract base classes for the implications of class inheritance with regards to the Meta class.

Side note: You may also want to consider whether you really need indexes on all those fields for all tables.

1 Like

Thanks for your replys (@Rigo-Villalta and @KenWhitesell)
**I mean that if I can do as the following: Is it possible to add the index in the class Meta in “BasicData”

class BasicData(models.Model):
    user = models.ForeignKey(
        "users.CustomUser",
        on_delete=models.CASCADE
    )

    active = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_deleted = models.BooleanField(default=False, verbose_name=_('Deleted'))
    deleted_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True
        indexes = [
            models.Index(fields=["active"]),
            models.Index(fields=["created_at"]),
            models.Index(fields=["updated_at"]),
            models.Index(fields=["is_deleted"]),
            models.Index(fields=["deleted_at"]),
        ]

**And the second inquiry is Can I use ONE model (CreateObject) instead of building (UnitNames, PosStation, Branches and Departments)

I will give an example:
Using of (UnitNames) model: is for adding measuring unit name like(kilogram, meter, liter and so on)
Using of (Branches) model: is for adding branch name like(New York branch and so on)

Using of (Department) model: is for adding department name like(IT department, Purchasing department and so on)

**Is it possible and Is it a good way to make (CreateObject) model to perform the mission of all these models by select only the type ?
(i.e I want to use “CreateObject” and choose the type (UNIT) from (choices=OBJECT_TYPE) to create the unit name instead of using “UnitNames” and choose type(BRANCH) from (choices=OBJECT_TYPE))

BANK = "bank"
UNIT = "unit"
BRANCH = "branch"
DEPARTMENT = "department"
CREDIT_CARD = "visa"
SAFE = "safe"

OBJECT_TYPE = (
    (BANK, "Bank"),
    (UNIT, "Unit"),
    (BRANCH, "Branch"),
    (DEPARTMENT, "Department"),
    (CREDIT_CARD, "Visa"),
    (SAFE, "Safe"),
)

Hope my inquiry is clear now.
Thanks

First a side note: Please do not bold large chunks of your text. It makes it very difficult to read.

That is answered by the docs referenced in my previous response.

Is it possble? Yes.

Is it a good way? Absolutely not.

As an abstract model, you shouldn’t be thinking of BasicData as if it were a model. You should be thinking of it as a template that you will use and extend in your “real” models.

You could also implement this BasicData as a mixin model as well, but I’m not sure it really provides any benefit in your case. (For an example of model mixins, see Model Extensions — django-extensions 3.2.3 documentation)

1 Like

That’s exactly what I want to hear (I prefer to make separated model for them)

Thanks it’s helpful .

As I get help here and found awesome people give advices and help, So I will open another inquiries to understand and learn

Thanks @KenWhitesell so much

Please @KenWhitesell how can I mark your answer as a solution to my issue. I didn’t found a (Solution button)
Thanks again (@KenWhitesell , @Rigo-Villalta )

I have asked the Admins about this - I’ll let you know what I find out.

1 Like

I have been told that this has now been made available. Please check and let me know.