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