【问题标题】:Construct crispy forms layouts iteratively?迭代地构建清晰的表单布局?
【发布时间】:2013-06-25 14:17:47
【问题描述】:

我目前正在尝试呈现一个允许我们的用户编辑产品的表单,目前该表单全部显示为一个长列。

有人要求我将其分成两列,但由于使用modelform_factory() 生成的ModelForm 出现问题

有什么方法可以生成一个 Crispy 布局对象,它可以每两个表单对象插入一个新的 div?

注意:事先不知道表格的长度。

查看代码:

def layout_from_form(form, columns=2):
    field_count = sum(1 for i in form)  # form specified it's iterable but is not len() friendly
    for field_number, _ in enumerate(form):

        if field_number % columns == 0:

            max_length_field = field_number + 2
            if field_number + 2 > field_count:
                max_length_field = field_count
            try:
                selected_forms = form.helper[field_number:max_length_field]
                selected_forms.wrap(Div, css_class="span6")
                selected_forms.wrap_together(Div, css_class="row-fluid")
            except:
                assert False, (field_count, field_number, max_length_field)


def edit_product(request, bought_in_control_panel_id, item_uuid):

    boughtin_model = get_model_for_bought_in_control_panel(bought_in_control_panel_id)
    item = boughtin_model.objects.get(pk=item_uuid)
    BoughtinForm = modelform_factory(boughtin_model, exclude=("uuid", "date_time_updated", "date_time_created",
                                                              "manufacturer"))
    if request.method == "POST":
        boughtin_form = BoughtinForm(request.POST, instance=item)
        if boughtin_form.is_valid():
            boughtin_form.save()
            return redirect(reverse('view_product', kwargs={'bought_in_control_panel_id': bought_in_control_panel_id,
                                                            'item_uuid': item_uuid}))
    else:
        boughtin_form = BoughtinForm(instance=item)

        boughtin_form.helper = FormHelper(boughtin_form)
        boughtin_form.helper.form_action = reverse('edit_product', kwargs={'bought_in_control_panel_id': bought_in_control_panel_id,
                                                                           'item_uuid': item_uuid})
        boughtin_form.helper.add_input(Submit('submit', 'Submit'))
        layout_from_form(boughtin_form)
    return render_to_response('suppliers/products/edit_product.html', {'item': item,
                                                                       'boughtin_form': boughtin_form,
                                                                       'bought_in_control_panel_id': bought_in_control_panel_id})

示例布局对象:

Layout(
    Div(
        Field('name'),
        Field('type'),
        css_class="row-fluid"
    ),
    Div(
        Field('uuid'),
        Field('dave'),
        css_class="row-fluid"
    ),
    .... Etc ad infinitum ....
)

【问题讨论】:

  • 在什么情况下表格的长度是事先不知道的?
  • 您是否从crispy-form 文档中看到“随时随地更新布局”?:django-crispy-forms.readthedocs.org/en/latest/… 特别是,wrap 操作可能正是您正在寻找的。感觉就像您可以确定视图中传入表单(可变长度)的长度并以这种方式创建动态布局。
  • 好吧,我不知道如何获取由 modelform_factory 生成的表单上的字段计数,而且我不能依赖每次都传递相同的模型。
  • 有一种方法可以确定使用 modelform_factory 生成的对象的长度。看看我刚刚创建的这个 pastebin:bpaste.net/show/UEtjVLkKCEV3MYQA8E0E
  • 也许你从一个空的表单类开始,在__init__ 中构造一个 FormHelper() 类,然后根据 Crispy 文档动态添加字段。当您遍历 form.base_fields.keys() 中的字段时,您的逻辑可以确定何时放入 Div、Field 等类。对我来说,这感觉像是脆皮表格的绝佳用例。想法?

标签: django django-crispy-forms


【解决方案1】:

在您的问题中:“注意:表格的长度事先不知道。”

我们确实可以预先找到表格的长度:

>>> import apps.students.models as models
>>> from django.forms.models import modelform_factory
>>> form = modelform_factory(models.StudentProfileBasics)
>>> len(form.base_fields.keys())
5

从那里开始,a) Crispy 通过抓取布局切片来modify layouts on the go 的能力,b) Crispy 提供的wrap 方法,以及 c) 由 forms.Form.base_fields.keys( ) 应该可以带你去你需要的地方!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-31
    • 2018-01-08
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-28
    • 2016-02-13
    相关资源
    最近更新 更多