#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 [email protected].
To post to this group, send email to [email protected].
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