#28620: Loop on boundfields at init of inline sub-forms breaks the form set --------------------------------------+------------------------------- Reporter: jxrossel | Owner: nobody Type: Bug | Status: new Component: Forms | Version: 1.11 Severity: Normal | Keywords: inlineformset Triage Stage: Unreviewed | Has patch: 0 Needs documentation: 0 | Needs tests: 0 Patch needs improvement: 0 | Easy pickings: 0 UI/UX: 0 | --------------------------------------+------------------------------- When doing a loop (even a dummy one) on their boundfields at the init phase, the sub-forms of an inline form set are "broken", i.e. **the parent key field is rendered instead of being hidden and many additional SQL requests are generated**.
In this illustration case, I have 2 related models - Fig and Line - where each Fig can have many Line(s). **forms.py** {{{ class FigForm( ModelForm ): class Meta: model = Fig fields = '__all__' class LineForm( ModelForm ): class Meta: model = Line fields = '__all__' def __init__(self, *args, **kwargs): super( LineForm, self ).__init__(*args, **kwargs) for bf in self: # <- this screws everything pass # even with a dummy loop LineFormSet = inlineformset_factory( Fig, Line, form=LineForm, extra=1 ) }}} In real life, I use this loop in a custom model form class to add default CSS classes to the form widgets, but the additionnal SQL requests kill my server. ---- == Additional information **model.py** {{{ class Fig(models.Model): name = models.CharField(max_length=200,unique=True) xlabel = models.CharField(max_length=200,blank=True) ylabel = models.CharField(max_length=200,blank=True) descr = models.TextField(blank=True) pub_date = models.DateTimeField('date published',auto_now=True) def __str__(self): return self.name def get_absolute_url(self): return reverse('webplot:detail', kwargs={'pk':self.pk} ) class Line(models.Model): fig = models.ForeignKey(Fig, on_delete=models.CASCADE) x = models.CharField(max_length=200) y = models.CharField(max_length=200) label = models.CharField(max_length=20) def __str__(self): return self.label + ': y(x)=' + self.y + ' for x=' + self.x }}} **views.py** {{{ def detail(request,pk='new'): # Used for both CREATE and UPDATE # create a form instance and populate it with data from the request if any if pk == 'new': fig = Fig() # instanciate empty object else: fig = get_object_or_404( Fig, pk=pk ) form = FigForm( request.POST or None, instance=fig ) subform = LineFormSet( request.POST or None, instance=fig ) if request.method == 'POST': if form.is_valid() and subform.is_valid(): form.save() subform.save() return redirect(fig) ctx = {'form': form, 'subform': subform } return render(request, 'webplot/detail.html', ctx ) }}} **detail.html** {{{ <form method="post" class="w3-container">{% csrf_token %} <h4>Figure settings</h4> <table class="w3-table"> {{ form.as_table }} </table> <h4>Line settings</h4> {{ subform.management_form }} {{ subform.non_field_errors }} <table class="w3-table"> {% for thisform in subform.forms %} {% if forloop.first %} <thead> <tr class="w3-border-bottom"> {% for field in thisform.visible_fields %} <th>{{ field.label_tag }}</th> {% endfor %} </tr> </thead> <tbody> {% endif %} <tr> {{ thisform.non_field_errors }} {% for field in thisform.hidden_fields %} {{ field }} {% endfor %} {% for field in thisform.visible_fields %} <td>{{ field.errors }}{{ field }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> <input type="submit" value="Submit" class="w3-btn" /> </form> }}} -- Ticket URL: <https://code.djangoproject.com/ticket/28620> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/051.b452ccda06657e859f3da0079b85d9ef%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.