I’m building an order system and facing the following challenge.
An Order can contain multiple products (represented as OrderItem). Some of these products can have subproducts that are part of the order but specifically relate to a particular main product.
A simple example would be a car order: You can order multiple cars (main products), and for one of these cars, you might want to add a set of premium tires (a subproduct) that belongs specifically to that car.
This is where the item field in OrderItem comes into play—if you order two cars and two different sets of tires, the system needs to track which set of tires belongs to which car.
Where it gets interesting is that each subproduct can, in turn, have its own subproducts. For example, the premium tires might have custom tire caps as an additional configuration option. This nesting continues indefinitely until the configuration rules are exhausted.
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
class OrderItem(models.Model):
item = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True)
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="items")
product = models.ForeignKey(Product, on_delete=models.CASCADE)
class Product(models.Model):
name = models.CharField(max_length=255)
I’ve implemented this using Django and HTMX. Each time a product is selected, I fetch its related products and render the corresponding form. If one of these subproducts is selected, I fetch and render its related products, and so on.
The key part is that for each subproduct form, I assign it a prefix based on its parent product. This results in form prefixes like configuration-1-5-2-17 where:
1 is the main product
5 is a subproduct
2 is a sub-subproduct
17 is a sub-sub-subproduct
Now, my main concern is whether this is the best approach . Initially, I tried using FormSets, but I realized that I’m dealing with multiple different forms rather than the same form repeated multiple times.
Also, I am solely concerned about the backend here (how to build the forms, leverage Django’s tools, etc.), but too much about the frontend.