#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.

Reply via email to