# Model(s) pattern architect with many optional fields

**URL:** <https://forum.djangoproject.com/t/model-s-pattern-architect-with-many-optional-fields/34086>\
**Category:** Using the ORM\
**Created:** [August 22, 2024, 1:58pm UTC](https://forum.djangoproject.com/t/model-s-pattern-architect-with-many-optional-fields/34086 "2024-08-22T13:58:32Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![DoOrQuit](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/doorquit/32/16890_2.png) [@DoOrQuit](https://forum.djangoproject.com/u/DoOrQuit)\
**Post date:** [August 22, 2024, 1:58pm UTC](https://forum.djangoproject.com/t/model-s-pattern-architect-with-many-optional-fields/34086/1 "2024-08-22T13:58:32Z")

</div>

Hi everyone!  
I have a question related not to Django only but to DB architecture as well.  
Let’s say I want to create model for `Computer` which may have completely different configuration / hardware.  
I want to control hardware remains on stock but also I have assembled computers to sell.  
Whenever “whole computer” being sold I like to decriment stock remains of hardware the “whole computer” consist of.  
First idea to create `model.HardwareItem` as abstract class. Then the key parts of computer such as GPU, CPU, Motherboard etc. will inherit `model.HardwareItem` with some individual fields as all of them basicaly may have common fields such a `maker`, `platform`, `category` etc.  
But from the other hand it leads to lot of models which have to be maintained.  
Another approach is to make one model like `models.HardwareItem` with lot of optional fields which may be used with particular instances. Both of approches feels not well (especially the second one).  
Is there a better approch considering scalability and maintenance?  
Thanks in advance and apologies for my english.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 22, 2024, 2:25pm UTC](https://forum.djangoproject.com/t/model-s-pattern-architect-with-many-optional-fields/34086/2 "2024-08-22T14:25:57Z")

</div>

There is no one generic answer for situations like this. This needs to be addressed in the context of the specific desired usage of the data and relationships involved among the data.

For example, you identify “maker” as a common field. Yes, you could make it a field in `HardwareItem`. Now, what sort of field should it be? Is there associated data for _that_ `maker` that needs to be tracked?

E.g., Do you want to track their website? Do you have a contact person at that company? Or, if the company is large enough with a wide product line, you might have different contacts for different products - are you still considering them the same `maker`? If the name of the `maker` changes, does that affect how you have the data stored for pre-existing purchases?

This is just the start of what you want to consider when trying to model situations like this. You need to _fully_ understand what your data usage requirements are going to be, and why, before settling on a model structure.

Having said that, it is _possible_ that these internal relationships really aren’t an issue, that your system is only a “point in time” record-keeping system, and that there’s no particular reason to maintain these attributes after being entered - or that their values are not used in combination with other entries. In that case, you might do just as well to store all those attributes in a JSON field.

Side note:

> [@DoOrQuit](#):
>
> But from the other hand it leads to lot of models which have to be maintained.

In the general sense, “more” is better than “fewer”. Relational databases exist for the purpose of managing relationships among tables. Trying to minimize the number of tables being used for the sole purpose of minimizing the number of tables in the database is a “false” or “incorrect” optimization.

Personally, I’d rather work on a system with 100 models that are properly normalized than a system with 10 models having the potential for invalid or internally inconsistent data.

> [@DoOrQuit](#):
>
> Thanks in advance and apologies for my english.

No apologies necessary at all. Your English is far superior to my knowledge of whatever your native language(s) may be.

---

<div class="post-metadata">

**Author:** ![DoOrQuit](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/doorquit/32/16890_2.png) [@DoOrQuit](https://forum.djangoproject.com/u/DoOrQuit)\
**Post date:** [August 22, 2024, 3:04pm UTC](https://forum.djangoproject.com/t/model-s-pattern-architect-with-many-optional-fields/34086/3 "2024-08-22T15:04:08Z")

</div>

Hi, @KenWhitesell! Thanks for a lighting fast reply as always.  
I know the details of info provided are not enough to consider some universal approach as I wanted to simplify the question (what actually made the question not clear).  
The main goal in my particular case is to make automatic writing off harware remains on stock when assembled computer being sold.  
For this purpose I have every single part of computer in a model:

_(Code simplifiied again but relations are actual or not considered as important)_

```auto
class Stock(models.Model):
    title = models.CharField()
    organization = models.ForeignKey(Organization)

class HardwareItem(models.Model):
    maker = models.CharField() # <- No relation
    type = models.ForeignKey(HardwareType)
    model = models.CharField() 
    stock = models.ForeignKey(Stock)
    quantity = models.PositiveIntegerField()

```

Above I’ve prescribed simple `HardwareItem` which is core model for writing off from a stock which may be a `CPU` as well as a `Cooling Fan`.  
For the key hardware I have another models (I will add few to avoid this answer being too long):

```auto
class Cpu(HardwareItem):
    socket = models.CharField()
    name = models.Charfield()
    frequency = models.IntegerField()

class Gpu(HardwareItem):
    name = models.Charfield()
    frequency = models.IntegerField() # <- This field duplicates CPU

class Motherboard(HardwareItem):
    chipset = models.ForeignKey(Chipset)
    memory_type = models.CharField(choices=MEMORY)

```

This is a basic example. Of course, looking on this 3 models I can’t find what is wrong but lets imagine in my real project there are ~ 8-12 models which often have a similar parameters.  
The goal is to finaly make some “container” like `models.Configuration` which finally enclose all this items with ForeignKeys.  
Is the models presented above may be considered as normalized / good practice models or there is another way to implement `Hardware` instance model?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 22, 2024, 4:23pm UTC](https://forum.djangoproject.com/t/model-s-pattern-architect-with-many-optional-fields/34086/4 "2024-08-22T16:23:55Z")

</div>

From the information available to me based upon your description, this looks fine. I certainly wouldn’t worry about the definition of duplicated fields between models, such as what you identified with “frequency”. It’s not like you’re going to be comparing or matching the frequency of a CPU with that of the GPU. (I’m not aware of any relationship between those two that justify concerns about them having identical names.)

I would make `HardwareItem` a real model (not abstract), allowing for each of the sub-types (Cpu, Gpu, etc) to use Multi-table inheritance.

What this allows is for you to define another model, perhaps call it “Computer”, with a single ManyToMany relationship with `HardwareItem`. That provides the flexibility to allow things like a system with multiple CPUs without having to code them up as special cases.

It may even be a situation where one of your items, such as the `Motherboard` model, defines the limits for the other `HardwareItem`, such as number of CPUs, GPUs and memory; and another `HardwareItem` such as a `Case`, defining the limits for number of hard drives. Or even that the `Cpu` identifies _which_ `CoolingFan` it can be paired with. (Again, I don’t fully understand your requirements, so I’m just tossing out ideas here.)

---

<div class="post-metadata">

**Author:** ![DoOrQuit](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/doorquit/32/16890_2.png) [@DoOrQuit](https://forum.djangoproject.com/u/DoOrQuit)\
**Post date:** [August 23, 2024, 9:53am UTC](https://forum.djangoproject.com/t/model-s-pattern-architect-with-many-optional-fields/34086/5 "2024-08-23T09:53:39Z")

</div>

You got my point right and I grateful for such a detail explanation of your point of view. It’s gave me some direction how job to be done.  
Thank you @KenWhitesell
