I'm building an application where product variants are intended to be handled as physical products already prepared and listed manually. Instead of using a conventional approach with complex relations between Product, Option, OptionValue, and SKUValue tables, I'm trying to simplify the design.
+--------------+ +-----------------+
| Product | | ProductVariant |
+--------------+ +-----------------+
| id (PK) |<------>| id (PK) |
| name | | product_id (FK) |
| owner_id (FK)| | note |
| created_at | | stock |
| updated_at | | price |
+--------------+ +-----------------+
In the ProductVariant table, the note field is a simple text field where users can manually enter descriptions like "Size: XL, Color: Red".
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Product(models.Model):
name = models.CharField(max_length=255)
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='products')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class ProductVariant(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='variants')
note = models.TextField() # Example: "Size: XL, Color: Red"
stock = models.PositiveIntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return f"{self.product.name} - {self.note}"
Is this simplified design using manual notes for product variants acceptable in scenarios where variants are predefined and manually recorded? What are the potential pitfalls I should be aware of when using this design compared to a more "standard" relational model?
If the design fits your use-case, it is by definition not bad. Don't worry about best-practices if your current practice in actuality fulfills all your needs, doesn't expose you to any downsides, and is sufficiently performant.
Current design
For the note
field: consider using JSONField
(though note the database compatibility point) instead of TextField
.
Storing the notes as structured data will make frontend parsing easier and backend searching/filtering/etc considerably easier (in particular if you're using Postgres, see the PG notes in the linked documentation). It also enables you to store more than one value-point, as well as metadata and parsing instructions (such as font size, color, or whatever you like) about the attribute.
Example:
[
{
"1": {
"title": "Size",
"us_value": "XL",
"eu_value": 50,
"title_color": "red",
"value_color": "blue"
}
}
]
Potential pitfalls:
JSONField
. If you're using TextField
it will be very painful for practical reasons.Alternate design
The "overengineered" approach would probably be something like a set of EAV-models. I know you didn't ask specifically for this, but it's always wise to know the neighboring concepts.
django-eav2 provides a good overview of EAV and its use-cases, and you could either use a library in that vein if it feels right or roll your own using generic relations.