Modelformset_factory does not comply with optional parameter

Django: 1.4.1

Model:

class Hoja(models.Model): nombre = models.CharField(max_length=200) # requerido class Linea(models.Model): hoja = models.ForeignKey(Hoja) # requerido nombre = models.CharField(max_length=200) # requerido padre = models.ForeignKey('self', null=True, blank=True, related_name='hijo') 

View:

 lineas = Linea.objects.filter(hoja=alt).order_by('id') LineaHojaSet = modelformset_factory(Linea, can_delete=True, extra=1 if request.POST.has_key('siguiente') else 0) formset = LineaHojaSet(request.POST or None, queryset=lineas) if request.method=='POST': # process formset return render_to_response('template.html', {'formset':formset}, context_instance=RequestContext(request)) 

Template:

 <table> <thead> <tr><th>Nombre</th><th>Borrar</th></tr> </thead> <tbody> {% for fs in formset %} <tr> <td>{{ fs.nombre }}</td> <td>{{ fs.id }}</td> </tr> {% endfor %} </tbody> </table> <input type="submit" name="siguiente" value="Añadir siguiente" /> 

When I submit the "siguiente" button, I see that formet receives the correct optional field 1, but only the following lines are shown on the web page. Is this a mistake, or am I doing something wrong?

+4
source share
1 answer

Formset factory finds the number of forms in the max_num , extra or form-TOTAL_FORMS in request.POST (or data) from the control form.

In your case, request.POST['form-TOTAL_FORMS'] has a number that does not include an additional form. Therefore, when creating a set of forms, it does not add an additional form.

One solution would be to increase this number by one when your condition is met. eg.

 data = None if request.POST: data = request.POST.copy() #required as request.POST is immutable if request.POST.has_key('siguiente'): data['form-TOTAL_FORMS'] = int(data['form-TOTAL_FORMS']) + 1 #now use data instead of request.POST formset = LineaHojaSet(data, queryset=lineas) .... 

However, there are some drawbacks to manipulating a set of forms in this way. When you check a set of forms, an additional form will show errors if there are any required fields.

The best solution would be to create the form set again before submitting it with one additional form and set of queries. Most likely, when formet is valid, you will save any new objects that will be added to queryset. Thus, your page will display newly added objects and one additional form.

 lineas = Linea.objects.filter(hoja=alt).order_by('id') LineaHojaSet = modelformset_factory(Linea, can_delete=True,) formset = LineaHojaSet(request.POST or None, queryset=lineas) if request.method=='POST': # process formset if formset.is_valid: #saved and done with formset. if request.POST.has_key('siguiente'): LineaHojaSet = modelformset_factory(Linea, can_delete=True, extra=1) formset = LineaHojaSet(queryset=lineas) ... return render_to_response('template.html', {'formset':formset}, context_instance=RequestContext(request)) 
+2
source

Source: https://habr.com/ru/post/1440486/


All Articles