Ecco quello che ho usato per un caso simile (un insieme di variabili fieldsets, ognuno contenente un insieme variabile di campi).
ho usato la funzione type()
per costruire la mia classe di form, e BetterBaseForm
classe da django-form-utils.
def makeFurnitureForm():
"""makeFurnitureForm() function will generate a form with
QuantityFurnitureFields."""
furnitures = Furniture.objects.all()
fieldsets = {}
fields = {}
for obj in furnitures:
# I used a custom Form Field, but you can use whatever you want.
field = QuantityFurnitureField(name = obj.name)
fields[obj.name] = field
if not obj.room in fieldsets.keys():
fieldsets[obj.room] = [field,]
else:
fieldsets[obj.room].append(field)
# Here I use a double list comprehension to define my fieldsets
# and the fields within.
# First item of each tuple is the fieldset name.
# Second item of each tuple is a dictionnary containing :
# -The names of the fields. (I used a list comprehension for this)
# -The legend of the fieldset.
# You also can add other meta attributes, like "description" or "classes",
# see the documentation for further informations.
# I added an example of output to show what the dic variable
# I create may look like.
dic = [(name, {"fields": [field.name for field in fieldsets[name]], "legend" : name})
for name in fieldsets.keys()]
print(dic)
# Here I return a class object that is my form class.
# It inherits from both forms.BaseForm and forms_utils.forms.BetterBaseForm.
return (type("FurnitureForm",
(forms.BaseForm, form_utils.forms.BetterBaseForm,),
{"_fieldsets" : dic, "base_fields" : fields,
"_fieldset_collection" : None, '_row_attrs' : {}}))
Ecco un esempio di come dic
possono apparire come:
[('fieldset name 1',
{'legend': 'fieldset legend 2',
'fields' ['field name 1-1']}),
('fieldset name 2',
{'legend': 'fieldset legend 2',
'fields' : ['field 1-1', 'field 1-2']})]
ho usato BetterBaseForm
piuttosto che BetterForm
per lo stesso motivo this article suggerisce di utilizzare BaseForm
piuttosto che Form
.
Questo articolo è interessante anche se è vecchio e spiega come eseguire i moduli dinamici (con set di campi variabile). Fornisce anche altri modi per ottenere forme dinamiche.
Non spiega come farlo con i fieldset, ma mi ha ispirato a scoprire come farlo, e il principio rimane lo stesso.
Usandolo in una vista è piuttosto semplice:
return (render(request,'main/form-template.html', {"form" : (makeFurnitureForm())()}))
e in un modello:
<form method="POST" name="myform" action=".">
{% csrf_token %}
<div>
{% for fieldset in form.fieldsets %}
<fieldset>
<legend>{{ fieldset.legend }}</legend>
{% for field in fieldset %}
<div>
{% include "main/furniturefieldtemplate.html" with field=field %}
</div>
{% endfor %}
</fieldset>
{% endfor %}
</div>
<input type="submit" value="Submit"/>
</form>
Non sarebbe meglio usare [formsets] (http: //docs.djangoproject .com/it/dev/topics/forms/formsets /) al posto dei set di campi? Una classe Form personalizzata per una domanda (con un attributo 'prompt'), quindi si caricano i dati della domanda usando [argomento parola chiave' 'initial'] (http://docs.djangoproject.com/en/dev/topics/forms/formsets/# utilizzando-iniziale-dati-con-un-formset)? Le forme –
non fanno il trucco. almeno non il dato formset_factory. Devo essere in grado di fornire alcuni parametri ai costruttori di campo effettivi per ogni modulo nel formset - l'etichetta/prompt per il campo del valore e l'elenco di unità per il campo di scelta. –