Nested In-line Formsets

Hi Vitor,

I was trying to use nested-Inline formset in my applications. I want to initialize the parent as well as child model formset. I am not able to initialize the child formset which I have used in the nested property of Parent formset.

Please help.

Thank you.

Hi Rachana,
Can you explain the problem in more detail. If you show your code here it would be more easy to understand the problem .

In my app, based on facility type of ProjectFacility model instance, equipment should be pre-populated from the master table. For each equipment associated properties should be populated from the master table, in the form. Every equipment can have ‘n’ number of properties. User has to fill the values for those properties.

Models:
class ProjectFacility(models.Model):
facility_name = models.CharField(max_length=256,unique=True)
facility_type = models.ForeignKey(MasterFacilityPropertyValue,related_name=‘facilities’,on_delete=models.CASCADE)

class FacilityEquipment(models.Model):
facility = models.ForeignKey(ProjectFacility,on_delete=models.CASCADE)
equipment = models.ForeignKey(MasterFacilityEquipment,on_delete=models.CASCADE,null=True, blank=True)

def __str__(self):
    return self.equipment.equipment.name

class FacilityEquipmentWithProperty(models.Model):
equipments = models.ForeignKey(FacilityEquipment,on_delete=models.CASCADE,null=True, blank=True)
property = models.ForeignKey(MasterFacilityEquipmentProperty,on_delete=models.CASCADE,null=True, blank=True)
property_char_value = models.CharField(max_length=360)
Forms:
class BaseFacilityEquipmentFormSet(BaseFormSet):

def add_fields(self, form, index):
        super(BaseFacilityEquipmentFormSet, self).add_fields(form, index)
        print(index,'index')
        form.nested = PropertyFormset(
                        instance=form.instance,
                       # initial=[{'property': 'property','property_char_value':0} for property in #MasterEquipmentWithProperty.objects.filter(equipment__name = 'Deck Crane')],
                        data=form.data if form.is_bound else None,
                        files=form.files if form.is_bound else None,
                        prefix='property-%s-%s' % (
                            form.prefix,
                            PropertyFormset.get_default_prefix()),
                        )
        
def is_valid(self):
    result = super(BaseFacilityEquipmentFormSet, self).is_valid()

    if self.is_bound:
        for form in self.forms:
            if hasattr(form, 'nested'):
                result = result and form.nested.is_valid()

    return result

def save(self, commit=True):
    result = super(BaseFacilityEquipmentFormSet, self).save(commit=commit)
    for form in self.forms:
        if hasattr(form, 'nested'):
            if not self._should_delete_form(form):
                form.nested.save(commit=commit)

    return result

class EquipmentForm(ModelForm):

EquipmentFormset = inlineformset_factory(ProjectFacility,
FacilityEquipment,
fields = (‘equipment’,),
formset=BaseFacilityEquipmentFormSet,
extra=0,
can_delete=False)
PropertyFormset = inlineformset_factory(FacilityEquipment,
FacilityEquipmentWithProperty,
fields = (‘property’,‘property_char_value’),
extra=1,
can_delete=False)

View:
def equipment_property_create_view(request,pk):
project_facility = ProjectFacility.objects.get(pk=pk)
template_name = ‘estimation/equipment_property_create_form.html’
equipment_in_facility = MasterFacilityEquipment.objects.filter(facility_type = project_facility.facility)

if request.method == "GET":
    formset = EquipmentFormset(initial=[{'equipment': equipment,
                           } for equipment in equipment_in_facility])
    
    return render(request, 'estimation/equipment_property_create_form.html', {'formset':formset,'project_facility':project_facility})

elif request.method == "POST":
    formset = EquipmentFormset(request.POST)
    if formset.is_valid():
        for form in formset.cleaned_data:
            if form:
                equipment = form['equipment']
                FacilityEquipment.objects.create(facility=project_facility,equipment=equipment)
                
        return HttpResponse('done')
        
    else:
        print(formset.errors)

return render(request, template_name, {'formset': formset,'project_facility':project_facility})

Hi Rachana,
Sorry for late reply , i think you should use model formset factory . Easy to implement and you can achieve your requirement .