【问题标题】:Reorder DELETE Field in Formset重新排序 Formset 中的 DELETE 字段
【发布时间】:2022-06-14 23:52:50
【问题描述】:

我有一个 Django 表单集,它显示为一个表格,每个表格一个表格。我想在表格的第一列中添加一个复选框,以便用户在他们想要删除行(表单)时进行检查。

我有javascript来管理formset行(表单)的删除并在前端修改管理表单,但是当我将DELETE字段添加到表单时出现问题。我使用了modify DELETE widget 中的解决方案参考,这样我就可以将“删除”类添加到我的所有删除字段中,以便在前端的 CSS 和 JS 中使用。添加 DELETE 字段时,它始终是表单中的最后一个字段。我希望它是第一个。

models.py

class ModelOne(models.Model):
    attr_one = models.CharField(max_length=16)
    attr_two = models.CharField(max_length=16)

forms.py

class BaseFormOneFormset(BaseModelFormSet):
    def add_fields(self, form, index) -> None:
        super().add_fields(form, index)
        form.fields[DELETION_FIELD_NAME].widget = forms.CheckboxInput(attrs={'class':"delete"})
        form.fields["id"].widget=forms.HiddenInput(attrs={'class':'pk'}) 

class FormOne(forms.ModelForm):
    class Meta:
        model = ModelOne

    attr_one = forms.CharField(max_length=16,
                               required=True,
                               label="attr_one",
                               widget=forms.TextInput(attrs={'size':5,'class':'required '}))
    attr_two = forms.CharField(max_length=16,
                               required=True,
                               label="attr_two",
                               widget=forms.TextInput(attrs={'size':5,'class':'required '}))

views.py

def view_one(request):
    formset_factory_one = modelformset_factory( ModelOne,
                                                FormOne,
                                                formset=BaseFormOneFormset,
                                                extra=0,
                                                can_delete=True)
    formset_one = formset_factory_one(query_set=FormOne.objects.all(),
                                      prefix="formone")
    return render(request, "app_one/template_one.html",{"formset_one":formset_one})

template_one.html

<table id="tbl-id">
    <thead id="tbl-head-id">
        <tr>
            {% for form in formset_one|slice:":1" %}
                {% for field in form.visible_fields %}
                    <th>{{field.label|safe}}</th>
                {% endfor %}
            {% endfor %}
        </tr> 
    </thead>
    <tbody id="tbl-body-id">
        {% for form in formset_one %}
            <tr id="row{{forloop.counter0}}-id" class="formset-row">
                {% for field in form.visible_fields %}
                    <td>
                        {{field}}
                    </td>
                {% endfor %}
                {% for field in form.hidden_fields %}
                    <td hidden >{{field}}</td>
                {% endfor %}
            </tr>
        {% endfor %}
    </tbody>
</table>

结果表

image of resulting html table

已尝试的解决方案

我已经尝试在FormOne 类声明中同时设置Form.field_order

class FormOne(forms.ModelForm):
    field_order = [ DELETION_FIELD_NAME, "attr_one", "attr_two"]

BaseFormset.add_fields 方法中

def add_fields(self, form, index) -> None:
    super().add_fields(form, index)
    form.fields[DELETION_FIELD_NAME].widget = forms.CheckboxInput(attrs={'class':"delete"})
    form.fields["id"].widget=forms.HiddenInput(attrs={'class':'pk'})
    form.field_order = [ DELETION_FIELD_NAME, "attr_one", "attr_two"]

这些都导致 DELETE 字段仍然排在最后。

【问题讨论】:

    标签: python django django-forms


    【解决方案1】:

    虽然有一些方法可以通过覆盖表单集的 add_fields() 函数来更改 DELETE 字段的顺序,但它相当乏味且有点复杂。

    但是,如果您的目标是简单地首先呈现 DELETE,或者在页面的完全不同的部分呈现,那么您很幸运。这在模板中很容易完成。

    delete 字段可以使用{{ form.DELETE }} 在模板中显式呈现,这相当于您在迭代form.fields 时得到的{{ field }} 的常规输出。

    此示例将首先呈现 DELETE 字段:

    {{ form.DELETE }} {# this renders the DELETE field #}
    {% for field in form.visible_fields %} {# now we render the rest of the fields #}
      {% if field.name != 'DELETE' %}  {# this check prevents DELETE being rendered twice #}
        {{ field }}
      {% endif %}
    {% endfor %}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 2018-08-23
      相关资源
      最近更新 更多