警告:我知道字段集,但仍然不相信这些简单的想法需要它们。
我有一个简单的表创建表单,从给定的数据集允许用户提取某些列:
class TableBuildingForm(forms.Form):
data_set = forms.ChoiceField(choices=DATASETS,required=True,label="Initial object")
col1 = forms.CharField(label='Column 1', max_length=100, required=False)
col2 = forms.CharField(label='Column 2', max_length=100, required=False)
col3 = forms.CharField(label='Column 3', max_length=100, required=False)
col4 = forms.CharField(label='Column 4', max_length=100, required=False)
col5 = forms.CharField(label='Column 5', max_length=100, required=False)
sort_by = forms.CharField(label='Sort by', max_length=100, required=False)
然后在处理视图时我做了:
def custom_table(request):
# if this is a POST request we need to process the form data
rows = []
columns = []
if request.method == 'POST':
form = forms.TableBuildingForm(request.POST)
if form.is_valid():
sort_by = form.cleaned_data['sort_by']
columns = [ col for col in [
form.cleaned_data['col1'],
form.cleaned_data['col2'],
... etc ...
]
忽略动态表单的前端方面(这并不难),如果用户希望超过 5列,比如6,或9或42,那么当前的问题就是如何。
好吧,我见过的每个答案都建议使用formsets。但对于这个用例,这意味着制作一个包含一个字段的表单 - col1
- 这看起来过于复杂。
我想要的是:
class TableBuildingForm(forms.Form):
data_set = forms.ChoiceField(choices=DATASETS,required=True,label="Initial object")
columns = forms.CharField(label='Column 1', max_length=100, required=False)
sort_by = forms.CharField(label='Sort by', max_length=100, required=False)
用相应的:
def custom_table(request):
# if this is a POST request we need to process the form data
rows = []
columns = []
if request.method == 'POST':
form = forms.TableBuildingForm(request.POST)
if form.is_valid():
sort_by = form.cleaned_data['sort_by']
columns = form.cleaned_data['columns']
是否有简单方式声明字段可能以django形式 * 重复,或者如果不是这种情况,那么有一种方法可以捕获所有返回数据预清洗/验证以获取所有列?
*我不期待django为我建造前端,我可以做到。我只是想找个方法让django在多个字段被退回时不投诉
答案 0 :(得分:2)
是的,还有另一种方法可以做到这一点。
而不是像这样声明所有字段 -
class TableBuildingForm(forms.Form):
data_set = forms.ChoiceField(choices=DATASETS,required=True,label="Initial object")
col1 = forms.CharField(label='Column 1', max_length=100, required=False)
col2 = forms.CharField(label='Column 2', max_length=100, required=False)
col3 = forms.CharField(label='Column 3', max_length=100, required=False)
col4 = forms.CharField(label='Column 4', max_length=100, required=False)
col5 = forms.CharField(label='Column 5', max_length=100, required=False)
sort_by = forms.CharField(label='Sort by', max_length=100, required=False)
在表单的__init__
方法中声明所有表单字段。因为在为GET和POST创建表单时调用__ini__
。因此,当HTTP post的值绑定完成后,您将填充所有动态字段并正确绑定 -
class TableBuildingForm(forms.Form):
data_set = forms.ChoiceField(choices=DATASETS,required=True,label="Initial object")
sort_by = forms.CharField(label='Sort by', max_length=100, required=False)
def __init__(self, data=None, files=None, instance=None, **kwargs):
super().__init__(data=data, files=files, instance=instance, **kwargs)
for x in xrange(10): # just a dummy for 10 values
self.fields['col' + str(x)] = forms.CharField(label='Column ' + str(x), max_length=100, required=False)
然后在clean方法中,您可以获得值 -
def clean(self):
value = self.cleaned_data['field_' + str(0)]
这就是我填充具有动态元字段的表单的方式。
编辑:如果用JS添加了一个字段
要处理此问题,请保留另一个字段名称count
class TableBuildingForm(forms.Form):
data_set = forms.ChoiceField(choices=DATASETS,required=True,label="Initial object")
sort_by = forms.CharField(label='Sort by', max_length=100, required=False)
count = forms.HiddenField(required=False)
然后更新它将使用JS计算值。比如说5;
然后更新您的init
以考虑此值 -
def __init__(self, data=None, files=None, instance=None, **kwargs):
super().__init__(data=data, files=files, instance=instance, **kwargs)
_count = int(self.cleaned_data['count'])
for x in xrange(_count ): # get values from count because it will be updated with js
self.fields['col' + str(x)] = forms.CharField(label='Column ' + str(x), max_length=100, required=False)