pythondjangodatabasebackendproduct-variations

Is It Reasonable to Simplify Product Variant Design Using Notes Instead of Complex Relations?


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.

đź’ˇ ERD 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".

🔍 Django Models Based on This Design:

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}"

🎯 Why I'm Doing This:

  1. The application is designed to handle product variants that are often predefined and don't change dynamically.
  2. Users will manually input variant descriptions based on the actual physical products they have.
  3. The goal is to avoid overengineering by eliminating unnecessary tables and relationships.

🤔 What I'm Concerned About:


âť“ Question:

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?


Solution

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

    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.