python - 在 django 表单中多次重复单个字段

标签 python django forms django-forms

警告:我知道字段集,但仍然不相信如此简单的想法需要它们。

我有一个简单的表创建表单,允许用户从给定的数据集中提取某些列:

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)

然后在处理 View 时我会这样做:

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 列,该怎么办。

嗯,我看到的每个答案都表明了表单集。但对于这个用例,这意味着创建一个只有一个字段的表单 - 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 在返回多个字段时不引发投诉

最佳答案

是的,还有另一种方法可以做到这一点。

不要像这样在表单中声明所有字段 -

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 中的值的绑定(bind)完成后,您将填充所有动态字段并正确绑定(bind) -

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)

关于python - 在 django 表单中多次重复单个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31552816/

相关文章:

python - 在 Numpy 中执行 `A[tuple(B.T)]` 的更快方法

python - 神秘的 "cannot import name"异常

python - 在 Django REST Framework 中公开 MoneyFields?

php - 如何从 PHP 发送固定值到数据库

forms - 即使某些字段正确, Bootstrap 验证程序也会将整个表单标记为红色

python - 在 Altair 的 transform_calculate 中使用自定义函数

python - 为什么使用 read_csv() 创建的 DataFrame 与使用相同数据的 DataFrame() 创建的另一个 DataFrame 不同?

Python 扰码器程序

database - Django ORM 模型对象的主键中的空值

html - 无法设置提交按钮的样式