CyberHuginn

Home

/

Notes

/

designing-a-gold-jewelry-ecommerce-database-with-django

Designing a Gold Jewelry E-Commerce Database with Django

Learn how to design a scalable Django database for a gold jewelry e-commerce platform by modeling products, attributes, and purchasable product variants using real-world domain-driven design principles.

Aug 4, 2026 · 5 min read

At first glance, building an online jewelry store looks no different from building any other e-commerce platform. You have products, customers, orders, and payments. Simple enough, right?

That was exactly what I thought when I accepted a project to develop a jewelry gallery and online store.

A few hours later, after defining the business rules and identifying the domain entities, I realized the real challenge wasn't writing code—it was designing the data model.

Start with Business Scenarios, Not Models

One of the biggest mistakes developers make is opening the IDE before understanding the business.

Before creating a single Django model, I always walk through the application's use cases.

Imagine a customer visiting the website:

  • They browse products.
  • They compare different items.
  • They inspect colors, materials, weight, and specifications.
  • They check the price.
  • They compare similar products.
  • They add one or more items to the shopping cart.
  • Finally, they place an order.

For a jewelry store, the scenario becomes more interesting.

Customers don't just care about the product itself. They also care about:

  • Gold weight
  • Karat (purity)
  • Making fee
  • Gemstones
  • Color
  • Size
  • Additional materials such as leather straps

These values directly affect the final price.

Once you analyze these scenarios, the domain entities naturally begin to appear.

Identifying the Core Entities

The first obvious entity is the customer.

User

The customer browses products.

Product

Every product has characteristics.

ProductAttribute

The customer eventually adds something to the shopping cart.

Order
OrderItem

So far everything looks like a standard e-commerce system.

But here's the important question.

What Is the Customer Actually Buying?

This is where many database designs fail.

If you've previously built stores for books, digital products, or simple inventory, it's tempting to reference Product directly from the order.

That works until your products become configurable.

Consider a single ring.

The same ring may exist in several variations:

  • Different weights
  • Different sizes
  • Different karats
  • Different gemstones
  • Different colors
  • Different stock quantities
  • Different prices

Although customers see one product page, they are actually purchasing one specific variation.

This means an order should never point directly to Product.

Instead, it should reference a purchasable variant.

The Product Model

The base product remains simple.

class Product(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField(blank=True)

A product simply represents the parent item.

Think of it as the catalog entry.

Categories and Tags

Customers often search by category.

For example:

  • Rings
  • Necklaces
  • Bracelets

Or they may search by tags.

Category
Tag

Depending on your application, categories and tags may overlap or serve completely different purposes.

Product Attributes

A reusable attribute model makes filtering much easier.

class ProductAttribute(BaseModel):
    ATTRIBUTE_CHOICES = (
        ("color", "Color"),
        ("size", "Size"),
        ("weight", "Weight"),
        ("karat", "Karat"),
        ("gem", "Gem"),
        ("strap", "Strap"),
        ("other", "Other"),
    )

    attribute_type = models.CharField(...)
    key = models.CharField(...)
    value = models.CharField(...)

Notice that these attributes are only raw pieces of information.

They don't define a sellable product.

They don't have:

  • Price
  • Inventory
  • SKU
  • Making fee
  • Profit margin

Those belong somewhere else.

Introducing Product Variants

This is the missing piece.

class ProductVariable(BaseModel):
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE,
        related_name="variables"
    )

    code = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=10, decimal_places=0)
    making_fee = models.DecimalField(max_digits=10, decimal_places=0)
    stock = models.IntegerField(default=0)

    attributes = models.ManyToManyField(
        ProductAttribute,
        blank=True
    )

Each ProductVariable represents an actual purchasable item.

A single product can have multiple variants, each with:

  • Different attributes
  • Different stock
  • Different price
  • Different making fee
  • Different SKU

This is the model that inventory, payments, invoices, and order calculations should reference.

Not the parent product.

Why This Design Matters

Imagine a ring available in four variations.

VariantWeightKaratPriceStock
A3.2g18K$4202
B3.5g18K$4555
C4.0g21K$6101
D4.2g21K$6400

The customer visits a single product page.

However, when they click Buy, they are purchasing Variant C—not the generic ring.

That distinction makes all the difference in your database design.

Real-World Scenarios

Real businesses introduce even more complexity.

For example:

  • An item may be out of stock.
  • Customers may place custom manufacturing orders.
  • Products may contain image galleries.
  • Products may include promotional videos.
  • Prices may change according to the daily gold rate.
  • Making fees may differ between variants.

The more scenarios you analyze before coding, the fewer architectural changes you'll need later.

A Typical System Design Workflow

Before writing code, I usually follow these steps:

  1. Gather business requirements.
  2. Write the primary use cases.
  3. Identify domain entities.
  4. Define relationships between entities.
  5. Draw a Class Diagram.
  6. Create the ER Diagram.
  7. Design the database schema.
  8. Review edge cases.
  9. Validate the design with stakeholders.
  10. Finally, start implementing the models and business logic.

Skipping these steps often leads to frequent database migrations, broken relationships, and unnecessary refactoring.

Final Thoughts

Designing a jewelry e-commerce platform taught me an important lesson:

Customers don't buy products—they buy product variants.

Once you model that concept correctly, everything else becomes much simpler.

Orders reference variants.

Inventory tracks variants.

Invoices are generated for variants.

Pricing is calculated from variants.

The parent Product simply becomes the container that groups all of those purchasable variations together.

In future articles, I'll dive deeper into each step of the architecture—from writing use cases and drawing class diagrams to implementing the complete Django models with real-world examples.

End of note.