Django formset with nested single inline form of each formset object(form)

I'm trying to figure out the logic of building such structure:

class Order(models.Model):
    id = ...

class OrderItem(models.Model):
    order = FK(Order)
    quantity = CharField()
    category = CharField(choices=..)

class OrderItemSchema(models.Model):
    class Meta:
        abstract = True

    order_item = OneToOneField(OrderItem)
    brand = CharField()
    model = CharField()

class SomeProduct1Schema(OrderItemSchema):
    size = PositivieIntegerField()

class SomeProduct2Schema(OrderItemSchema):
    weight = CharField()
    type = CharField()

Let's assume some customer has created new Order which "Company" has to produce. There are different types of products (not much: 2-10) which may not have even single common parameter/field but still be placed withing one Order. The question is:

How to manage FormSet (or there is another way?) of OrderItem elements where each element may has different fields?

Example:

  1. OrderItem: [SomeProduct1Schema] \ category \ quantity \ brand \ model \ size
  2. OrderItem: [SomeProduct2Schema] \ category \ quantity \ brand \ model \ weight \ type

So far I've added OrderItem inline formset to Order and both SomeProduct1Schema \ SomeProduct2Schema inline formsets attached to OrderItemFormSet as nested form. But it's works well with single nested formset class and becoming mess when need to handle multiple dynamically.

Now I'm thinking to make SomeProduct1Schema classes to inherit from OrderItem directly using multi-table inheritance. Performance is not a problem in this case as scalability is prefered. Appreciate any advice.

I think for this case django BaseFormSet might do the trick for example as you can see Django BaseFormset can able to help you to do fill up mutliple model instances at single go, Read the django docs about more, you will get the idea of it.Below is just a

class SomeProduct1Form(OrderItemForm):
    size = forms.IntegerField()

class SomeProduct2Form(OrderItemForm):
    weight = forms.CharField()
    type = forms.CharField()

# Custom FormSet
class CustomOrderItemFormSet(BaseFormSet):
    def add_fields(self, form, index):
        super().add_fields(form, index)
        # add product-specific fields
        if form.instance.category == 'foo':
            form.fields['size'] = forms.IntegerField()
        elif form.instance.category == 'foo2':
            form.fields['weight'] = forms.CharField()
            form.fields['type'] = forms.CharField()

# Create a formset factory
OrderItemFormSet = formset_factory(OrderItemForm, formset=CustomOrderItemFormSet)

Back to Top