Вот что я использовал для подобного случая (переменный набор fieldsets, каждый из которых содержащий переменный набор полей).
Я использовал функцию type()
, чтобы построить свой класс формы, и BetterBaseForm
класс от 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' : {}}))
Вот пример того, как dic
может выглядеть следующим образом:
[('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']})]
Я использовал BetterBaseForm
, а не BetterForm
по той же причине this article предлагает использовать BaseForm
, а не Form
.
Эта статья интересна, даже если она старая, и объясняет, как делать динамические формы (с переменным набором полей). Он также дает другие способы достижения динамических форм.
Это не объясняет, как это сделать с помощью полей, но это вдохновило меня найти, как это сделать, и принцип остается тем же.
С его помощью в представлении довольно просто:
return (render(request,'main/form-template.html', {"form" : (makeFurnitureForm())()}))
и в шаблоне:
<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>
не было бы лучше использовать [FormSets] (HTTP: //docs.djangoproject .com/en/dev/themes/forms/formsets /) вместо полей? Пользовательский класс формы для вопроса (с атрибутом 'prompt'), затем вы загружаете данные вопроса с помощью [' initial' ключевого слова] (http://docs.djangoproject.com/en/dev/topics/forms/formsets/# с использованием-начальных данных-с-formset)? –
формы не делают трюка. по крайней мере, не данные formet_factory. Я должен быть в состоянии предоставить некоторые параметры фактическим конструкторам полей для каждой формы в наборе форм - ярлык/приглашение для поля значения и список единиц для поля выбора. –