You may want to try something like this:
form_view.html
<!-- simple form page -->
<form action="{{ request.path }}" method="post">
{{ form }}
</form>
views.py
# Some form controller
class DynamicFormView(FormView):
form_class = DynamicForm
template_name = "form_view.html"
def get_form_kwargs(self):
kwargs = super(DynamicFormView, self).get_form_kwargs()
# Decide on a number of dynamic fields
# to pass into the form
# i.e. form(num_products=5)
kwargs['num_products'] = 5
return kwargs
models.py
# A model
class Company(models.Model):
name = models.CharField(max_length=200)
# A model with a many to one relationship with another model
class Product(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
forms.py
class DynamicForm(forms.ModelForm):
product_label = 'Product name'
class Meta:
model = MyModel
fields = ['name']
def __init__(self, *args, **kwargs):
# get the number of dynamic fields to create
num_products = kwargs.pop('num_products')
# initialize the form before creating fields
super(DynamicForm, self).__init__(*args, **kwargs)
# create the dynamic fields
for row in range(num_products):
self.fields['product_'.format(row)] = forms.CharField(label=self.question_label)
def save(self, commit=True):
# create the default object
company = super(DynamicForm, self).save(commit)
# create child products from the dynamic fields
products = []
for key, value in self.cleaned_data.items():
if key.startswith('product_'):
product = Product()
product.name = value
product.company = company
products.append(product)
if commit is True:
Product.objects.filter(company=company).delete()
Product.objects.bulk_create(products)
return company
{% ifequal field.label 'asdf' %}matches, and then useforloop.counterto show 1, 2, 3, etc. I updated my answer below.