kopia lustrzana https://github.com/wagtail/wagtail
add ability for form builder to split choices by newline
- fixes #3001 - keep support for comma separated lists if suppliedpull/8192/head^2
rodzic
54e9d09421
commit
134bd19bef
|
@ -46,6 +46,7 @@ Changelog
|
|||
* Fully remove the legacy sidebar, with slim sidebar replacing it for all users (Thibaud Colas)
|
||||
* Add support for adding custom attributes for link menu items in the slim sidebar (Thibaud Colas)
|
||||
* Implement new slim page editor header with breadcrumb (Steven Steinwand, Karl Hobley)
|
||||
* Add the ability for choices to be separated by new lines instead of just commas within the form builder, commas will still be supported if used (Abdulmajeed Isa)
|
||||
* Fix: When using `simple_translations` ensure that the user is redirected to the page edit view when submitting for a single locale (Mitchel Cabuloy)
|
||||
* Fix: When previewing unsaved changes to `Form` pages, ensure that all added fields are correctly shown in the preview (Joshua Munn)
|
||||
* Fix: When Documents (e.g. PDFs) have been configured to be served inline via `WAGTAILDOCS_CONTENT_TYPES` & `WAGTAILDOCS_INLINE_CONTENT_TYPES` ensure that the filename is correctly set in the `Content-Disposition` header so that saving the files will use the correct filename (John-Scott Atlakson)
|
||||
|
|
|
@ -75,6 +75,7 @@ class LandingPage(Page):
|
|||
* Validate to and from email addresses within form builder pages when using `AbstractEmailForm` (Jake Howard)
|
||||
* Add [`WAGTAILIMAGES_RENDITION_STORAGE`](wagtailimages_rendition_storage) setting to allow an alternative image rendition storage (Heather White)
|
||||
* Add [`wagtail_update_image_renditions` management command](wagtail_update_image_renditions) to regenerate image renditions or purge all existing renditions (Hitansh Shah, Onno Timmerman, Damian Moore)
|
||||
* Add the ability for choices to be separated by new lines instead of just commas within the form builder, commas will still be supported if used (Abdulmajeed Isa)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
@ -214,3 +215,4 @@ After setting the keyword argument, make sure to generate and run the migrations
|
|||
### Removed support for Jinja2 2.x
|
||||
|
||||
Jinja2 2.x is no longer supported as of this release; if you are using Jinja2 templating on your project, please upgrade to Jinja2 3.0 or above.
|
||||
|
||||
|
|
|
@ -47,26 +47,20 @@ class FormBuilder:
|
|||
return django.forms.DecimalField(**options)
|
||||
|
||||
def create_dropdown_field(self, field, options):
|
||||
options["choices"] = map(
|
||||
lambda x: (x.strip(), x.strip()), field.choices.split(",")
|
||||
)
|
||||
options["choices"] = self.get_formatted_field_choices(field)
|
||||
return django.forms.ChoiceField(**options)
|
||||
|
||||
def create_multiselect_field(self, field, options):
|
||||
options["choices"] = map(
|
||||
lambda x: (x.strip(), x.strip()), field.choices.split(",")
|
||||
)
|
||||
options["choices"] = self.get_formatted_field_choices(field)
|
||||
return django.forms.MultipleChoiceField(**options)
|
||||
|
||||
def create_radio_field(self, field, options):
|
||||
options["choices"] = map(
|
||||
lambda x: (x.strip(), x.strip()), field.choices.split(",")
|
||||
)
|
||||
options["choices"] = self.get_formatted_field_choices(field)
|
||||
return django.forms.ChoiceField(widget=django.forms.RadioSelect, **options)
|
||||
|
||||
def create_checkboxes_field(self, field, options):
|
||||
options["choices"] = [(x.strip(), x.strip()) for x in field.choices.split(",")]
|
||||
options["initial"] = [x.strip() for x in field.default_value.split(",")]
|
||||
options["choices"] = self.get_formatted_field_choices(field)
|
||||
options["initial"] = self.get_formatted_field_initial(field)
|
||||
return django.forms.MultipleChoiceField(
|
||||
widget=django.forms.CheckboxSelectMultiple, **options
|
||||
)
|
||||
|
@ -101,6 +95,42 @@ class FormBuilder:
|
|||
"Must be one of: " + ", ".join(method_list),
|
||||
)
|
||||
|
||||
def get_formatted_field_choices(self, field):
|
||||
"""
|
||||
Returns a list of choices [(string, string),] for the field.
|
||||
Split the provided choices into a list, separated by new lines.
|
||||
If no new lines in the provided choices, split by commas.
|
||||
"""
|
||||
|
||||
if "\n" in field.choices:
|
||||
choices = map(
|
||||
lambda x: (
|
||||
x.strip().rstrip(",").strip(),
|
||||
x.strip().rstrip(",").strip(),
|
||||
),
|
||||
field.choices.split("\r\n"),
|
||||
)
|
||||
else:
|
||||
choices = map(lambda x: (x.strip(), x.strip()), field.choices.split(","))
|
||||
|
||||
return choices
|
||||
|
||||
def get_formatted_field_initial(self, field):
|
||||
"""
|
||||
Returns a list of initial values [string,] for the field.
|
||||
Split the supplied default values into a list, separated by new lines.
|
||||
If no new lines in the provided default values, split by commas.
|
||||
"""
|
||||
|
||||
if "\n" in field.default_value:
|
||||
values = [
|
||||
x.strip().rstrip(",").strip() for x in field.default_value.split("\r\n")
|
||||
]
|
||||
else:
|
||||
values = [x.strip() for x in field.default_value.split(",")]
|
||||
|
||||
return values
|
||||
|
||||
@property
|
||||
def formfields(self):
|
||||
formfields = OrderedDict()
|
||||
|
|
|
@ -102,14 +102,15 @@ class AbstractFormField(Orderable):
|
|||
verbose_name=_("choices"),
|
||||
blank=True,
|
||||
help_text=_(
|
||||
"Comma separated list of choices. Only applicable in checkboxes, radio and dropdown."
|
||||
"Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown."
|
||||
),
|
||||
)
|
||||
default_value = models.CharField(
|
||||
default_value = models.TextField(
|
||||
verbose_name=_("default value"),
|
||||
max_length=255,
|
||||
blank=True,
|
||||
help_text=_("Default value. Comma separated values supported for checkboxes."),
|
||||
help_text=_(
|
||||
"Default value. Comma or new line separated values supported for checkboxes."
|
||||
),
|
||||
)
|
||||
help_text = models.CharField(
|
||||
verbose_name=_("help text"), max_length=255, blank=True
|
||||
|
|
|
@ -222,6 +222,89 @@ class TestFormBuilder(TestCase):
|
|||
self.assertIn(get_field_clean_name(unsaved_field_1.label), fb.formfields)
|
||||
self.assertIn(get_field_clean_name(unsaved_field_2.label), fb.formfields)
|
||||
|
||||
def test_newline_value_separation_in_choices_and_default_value_fields(self):
|
||||
"""Ensure that the new line present between input choices or values gets formatted into choices or value list
|
||||
respectively as an alternative to commas.
|
||||
"""
|
||||
multiselect_field = FormField.objects.create(
|
||||
page=self.form_page,
|
||||
sort_order=2,
|
||||
label="Your favorite colors",
|
||||
field_type="multiselect",
|
||||
required=True,
|
||||
choices="red\r\nblue\r\ngreen",
|
||||
)
|
||||
self.form_page.form_fields.add(multiselect_field)
|
||||
|
||||
dropdown_field = FormField.objects.create(
|
||||
page=self.form_page,
|
||||
sort_order=2,
|
||||
label="Pick your next destination",
|
||||
field_type="dropdown",
|
||||
required=True,
|
||||
choices="hawaii\r\nparis\r\nabuja",
|
||||
)
|
||||
self.form_page.form_fields.add(dropdown_field)
|
||||
|
||||
checkboxes_field = FormField.objects.create(
|
||||
page=self.form_page,
|
||||
sort_order=3,
|
||||
label="Do you possess these attributes",
|
||||
field_type="checkboxes",
|
||||
required=False,
|
||||
choices="good, kind and gentle.\r\nstrong, bold and brave.",
|
||||
)
|
||||
self.form_page.form_fields.add(checkboxes_field)
|
||||
|
||||
radio_field = FormField.objects.create(
|
||||
page=self.form_page,
|
||||
sort_order=2,
|
||||
label="Your favorite animal",
|
||||
help_text="Choose one",
|
||||
field_type="radio",
|
||||
required=True,
|
||||
choices="cat\r\ndog\r\nbird",
|
||||
)
|
||||
self.form_page.form_fields.add(radio_field)
|
||||
|
||||
checkboxes_field_with_default_value = FormField.objects.create(
|
||||
page=self.form_page,
|
||||
sort_order=3,
|
||||
label="Choose the correct answer",
|
||||
field_type="checkboxes",
|
||||
required=False,
|
||||
choices="a\r\nb\r\nc",
|
||||
default_value="a\r\nc",
|
||||
)
|
||||
self.form_page.form_fields.add(checkboxes_field_with_default_value)
|
||||
|
||||
fb = FormBuilder(self.form_page.get_form_fields())
|
||||
form_class = fb.get_form_class()
|
||||
|
||||
self.assertEqual(
|
||||
[("red", "red"), ("blue", "blue"), ("green", "green")],
|
||||
form_class.base_fields["your_favorite_colors"].choices,
|
||||
)
|
||||
self.assertEqual(
|
||||
[("cat", "cat"), ("dog", "dog"), ("bird", "bird")],
|
||||
form_class.base_fields["your_favorite_animal"].choices,
|
||||
)
|
||||
self.assertEqual(
|
||||
[
|
||||
("good, kind and gentle.", "good, kind and gentle."),
|
||||
("strong, bold and brave.", "strong, bold and brave."),
|
||||
],
|
||||
form_class.base_fields["do_you_possess_these_attributes"].choices,
|
||||
)
|
||||
self.assertEqual(
|
||||
[("hawaii", "hawaii"), ("paris", "paris"), ("abuja", "abuja")],
|
||||
form_class.base_fields["pick_your_next_destination"].choices,
|
||||
)
|
||||
self.assertEqual(
|
||||
["a", "c"],
|
||||
form_class.base_fields["choose_the_correct_answer"].initial,
|
||||
)
|
||||
|
||||
|
||||
class TestCustomFormBuilder(TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
# Generated by Django 4.0.3 on 2022-03-22 13:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("tests", "0064_alter_formpage_from_address_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="extendedformfield",
|
||||
name="choices",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
|
||||
verbose_name="choices",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="extendedformfield",
|
||||
name="default_value",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Default value. Comma or new line separated values supported for checkboxes.",
|
||||
verbose_name="default value",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="formfield",
|
||||
name="choices",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
|
||||
verbose_name="choices",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="formfield",
|
||||
name="default_value",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Default value. Comma or new line separated values supported for checkboxes.",
|
||||
verbose_name="default value",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="formfieldforcustomlistviewpage",
|
||||
name="choices",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
|
||||
verbose_name="choices",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="formfieldforcustomlistviewpage",
|
||||
name="default_value",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Default value. Comma or new line separated values supported for checkboxes.",
|
||||
verbose_name="default value",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="formfieldwithcustomsubmission",
|
||||
name="choices",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
|
||||
verbose_name="choices",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="formfieldwithcustomsubmission",
|
||||
name="default_value",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Default value. Comma or new line separated values supported for checkboxes.",
|
||||
verbose_name="default value",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="jadeformfield",
|
||||
name="choices",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
|
||||
verbose_name="choices",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="jadeformfield",
|
||||
name="default_value",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Default value. Comma or new line separated values supported for checkboxes.",
|
||||
verbose_name="default value",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="redirectformfield",
|
||||
name="choices",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.",
|
||||
verbose_name="choices",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="redirectformfield",
|
||||
name="default_value",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Default value. Comma or new line separated values supported for checkboxes.",
|
||||
verbose_name="default value",
|
||||
),
|
||||
),
|
||||
]
|
Ładowanie…
Reference in New Issue