如何更改 Wagtail 表单生成器呈现的 <textarea> 中的行数

Dan*_*ain 3 wagtail

我使用 Wagtail 的表单生成器创建了一个表单,其中包含多行文本项。当<textarea>元素被渲染时,它会使用 进行渲染rows="10"。我需要减少行数,但在文档中没有看到有关如何执行此操作的任何内容。

LB *_*ton 5

快速解决方案

  • 创建一个扩展FormBuilder自的类wagtail.contrib.forms.forms
  • 在这个CustomFormBuilder类中重写方法create_multiline_field
  • 此方法应返回Django 表单字段
  • 默认情况下使用的小部件是Textarea默认的 htmlattrs是 cols: 40 & rows: 10
  • 在重写的方法中,输入您需要的任何自定义属性,例如attrs = {'cols': '20', 'rows': '20'}
  • 最后,确保您的班级FormPage有一套。form_builderCustomFormBuilder
  • 下面是完整的代码片段,这将使所有多行表单字段相同
from django.db import models
import django.forms

from modelcluster.fields import ParentalKey

from wagtail.contrib.forms.forms import FormBuilder
from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField
from wagtail.admin.edit_handlers import FieldPanel, FieldRowPanel, InlinePanel, MultiFieldPanel


class FormField(AbstractFormField):
    page = ParentalKey('FormPage', related_name='form_fields', on_delete=models.CASCADE)


class CustomFormBuilder(FormBuilder):

    def create_multiline_field(self, field, options):
        attrs = {'cols': '20', 'rows': '20'} # default attrs = {'cols': '40', 'rows': '10'}
        return django.forms.CharField(widget=django.forms.Textarea(attrs=attrs), **options)


class FormPage(AbstractEmailForm):

    form_builder = CustomFormBuilder # added - allows us to override the default FormBuilder

    content_panels = AbstractEmailForm.content_panels + [
      #... InlinePanel etc
    ]
Run Code Online (Sandbox Code Playgroud)

更通用的解决方案

  • 在上面的代码的基础上,我们必须选择,使小部件属性可按字段或按页面自定义,所有这些都有其优点和缺点,但让每个表单字段都可以自定义自己的属性。
  • 下面我们添加了一个新StreamField功能FormField,让我们可以添加任何可以用作 HTML 属性的任意键/值对。
  • 由于新的 2.7 StreamField 设计非常简约,因此表单页面编辑不会受到太大影响。
  • 然后,我们需要在重写的create_multiline_field方法中读取该字段的数据。
  • 注意:下面的示例仅将属性传递到多行字段,如果您想将属性传递到每个小部件中,则需要重写每个表单字段方法。
from django.db import models
import django.forms

from modelcluster.fields import ParentalKey

from wagtail.core import blocks
from wagtail.core.fields import StreamField
from wagtail.contrib.forms.forms import FormBuilder
from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField
from wagtail.admin.edit_handlers import FieldPanel, FieldRowPanel, InlinePanel, MultiFieldPanel, StreamFieldPanel


class FormField(AbstractFormField):
    attributes = StreamField([
        ('attributes', blocks.StructBlock([
            ('name', blocks.CharBlock()),
            ('value', blocks.CharBlock()),
        ])),
    ], blank=True)

    page = ParentalKey('FormPage', related_name='form_fields', on_delete=models.CASCADE)

    panels = AbstractFormField.panels + [
        StreamFieldPanel('attributes'),
    ]


class CustomFormBuilder(FormBuilder):

    def create_multiline_field(self, field, options):
        # note - to accept attrs - ALL form field methods will need to be updated

        attributes = field.attributes
        attributes_data = attributes.get_prep_value() # convert the streamfield value into a Python data structure
        # outputs [{'value': {'value': '5', 'name': 'rows'}, 'id': '6cb7d669-626c-47c0-bcac-5d982e5d9209', 'type': 'attributes'}]

        keys = [_.get('value').get('name') for _ in attributes_data]
        values = [_.get('value').get('value') for _ in attributes_data]
        attrs = dict(zip(keys, values))
        return django.forms.CharField(widget=django.forms.Textarea(attrs=attrs), **options)


class FormPage(AbstractEmailForm):

    form_builder = CustomFormBuilder # added - allows us to override the default FormBuilder

    content_panels = AbstractEmailForm.content_panels + [
      #... InlinePanel etc
    ]
Run Code Online (Sandbox Code Playgroud)