Data Management ORM design help

Hello!

I am implementing some kind of “data management” process with two models (see below). The first model is the main data object (Product in this example) - it has some and mandatory attributes. The second model represents change request over the products model (needed to create new or change existing product). It has exactly the same meaningful fields and some status. The purpose of change request is to go through some workflow process and eventually create the Product record. During the workflow process different users fills in the attribute fields, so those fields have to be nullable.

class Product(models.Model):
    code = models.CharField("Code", max_length=18)
    description = models.CharField("Desc", max_length=50)
    attr1 = models.CharField("Attribute 1", max_length=50)
    attr2 = models.CharField("Attribute 2", max_length=50)
    attr3 = models.CharField("Attribute 3", max_length=50)


class ProductChangeRequest(models.Model):
    product = models.ForeignKey(Product, null=True)
    code = models.CharField("Code", max_length=18)
    description = models.CharField("Desc", max_length=50)
    attr1 = models.CharField("Attribute 1", max_length=50, null=True)
    attr2 = models.CharField("Attribute 2", max_length=50, null=True)
    attr3 = models.CharField("Attribute 3", max_length=50, null=True)
    status = models.CharField("Status", max_length=10)

I am looking for a best way to design this without repeating all the fields multiple times. I see these options:

  1. Keep products and product requests in the same table, as they can be considered the same up to the state. I don’t like it because i cant set not null constraints on the DB level, because of the request. Validating nulls at application code level doesn’t look good.

  2. Table inheritance. As from the docs, there is no easy way to override field properties. Also it creates OneToOneField relations which is not the case (There can be multiple change requests on single product)

  3. Inherit each model from a kind of ProductAttrubutes abstract model and override the properties as needed.

Maybe someone has a similar experience and can share how to do best, or maybe there are some libs/source code to analyze?

Thanks!

<opinion>
I wouldn’t worry about having the repeated fields.

Those two models really are two different entities with different properties and behaviors. I wouldn’t feel the need to try and make them fix a common model, when they really don’t appear to.

Note: There are some circumstances where my thoughts on this could change. But those would be the exceptional conditions.
</opinion>

Hi

class ProductPublic(models.Model):
    attr1 = models.CharField("Attribute 1", max_length=50)
    attr2 = models.CharField("Attribute 2", max_length=50)
    attr3 = models.CharField("Attribute 3", max_length=50)

    class Meta:
        abstract = True

class Product(ProductPublic):
    code = models.CharField("Code", max_length=18)
    description = models.CharField("Desc", max_length=50)


class ProductChangeRequest(ProductPublic):
    product = models.ForeignKey(Product, null=True)
    code = models.CharField("Code", max_length=18)
    description = models.CharField("Desc", max_length=50)
    status = models.CharField("Status", max_length=10)

Abstract base classes

Abstract base classes are useful when you want to put some common information into a number of other models. You write your base class and put abstract=True in the Meta class. 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.