Model(s) pattern architect with many optional fields

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.

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:

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.

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

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)

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):

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?

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.)

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