From 2ab84212b6270c8f2c5e8445b9a80b216469dd01 Mon Sep 17 00:00:00 2001 From: mtyton Date: Thu, 12 Oct 2023 22:59:04 +0200 Subject: [PATCH] Added class to abstract form generation --- artel/dynamic_forms/forms.py | 25 +++++ .../dynamic_forms/migrations/0001_initial.py | 16 ++- artel/dynamic_forms/models.py | 15 ++- .../templates/forms/email_form_page.html | 21 ++-- artel/dynamic_forms/tests.py | 102 +++++++++++++++++- 5 files changed, 162 insertions(+), 17 deletions(-) create mode 100644 artel/dynamic_forms/forms.py diff --git a/artel/dynamic_forms/forms.py b/artel/dynamic_forms/forms.py new file mode 100644 index 0000000..e4fd790 --- /dev/null +++ b/artel/dynamic_forms/forms.py @@ -0,0 +1,25 @@ +from collections.abc import Mapping +from typing import Any +from django import forms +from django.forms.utils import ErrorList + + +class DynamicForm(forms.Form): + + FIELD_TYPE_MAPPING = { + "singleline": forms.CharField(max_length=255, widget=forms.TextInput(attrs={"class": "form-control"})), + "multiline": forms.CharField(max_length=255, widget=forms.Textarea(attrs={"class": "form-control"})), + "email": forms.EmailField(max_length=255, widget=forms.EmailInput(attrs={"class": "form-control"})), + "number": forms.IntegerField(widget=forms.NumberInput(attrs={"class": "form-control"})), + "url": forms.URLField(max_length=255, widget=forms.URLInput(attrs={"class": "form-control"})), + "checkbox": forms.BooleanField(required=False, widget=forms.CheckboxInput(attrs={"class": "form-control"})), + "checkboxes": forms.MultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple(attrs={"class": "form-control"})), + "dropdown": forms.ChoiceField(widget=forms.Select(attrs={"class": "form-control"})), + } + + def __init__(self, field_list, *args, **kwargs) -> None: + self.page = kwargs.pop("page") + self.user = kwargs.pop("user") + super().__init__(*args, **kwargs) + for field in field_list: + self.fields[field.clean_name] = self.FIELD_TYPE_MAPPING[field.field_type] diff --git a/artel/dynamic_forms/migrations/0001_initial.py b/artel/dynamic_forms/migrations/0001_initial.py index a5442b7..e2f8902 100644 --- a/artel/dynamic_forms/migrations/0001_initial.py +++ b/artel/dynamic_forms/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.1.11 on 2023-10-10 20:22 +# Generated by Django 4.1.11 on 2023-10-12 17:23 import django.core.serializers.json from django.db import migrations, models @@ -19,7 +19,17 @@ class Migration(migrations.Migration): migrations.CreateModel( name="CustomEmailForm", fields=[ - ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ( + "page_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="wagtailcore.page", + ), + ), ("intro", wagtail.fields.RichTextField(blank=True)), ("thank_you_text", wagtail.fields.RichTextField(blank=True)), ("allow_attachments", models.BooleanField(default=False)), @@ -30,7 +40,7 @@ class Migration(migrations.Migration): options={ "abstract": False, }, - bases=(wagtail.contrib.forms.models.FormMixin, models.Model), + bases=(wagtail.contrib.forms.models.FormMixin, "wagtailcore.page"), ), migrations.CreateModel( name="EmailFormSubmission", diff --git a/artel/dynamic_forms/models.py b/artel/dynamic_forms/models.py index 894963b..805f647 100644 --- a/artel/dynamic_forms/models.py +++ b/artel/dynamic_forms/models.py @@ -5,7 +5,6 @@ from django.conf import settings from django.utils.formats import date_format from modelcluster.fields import ParentalKey -from modelcluster.models import ClusterableModel from wagtail.admin.panels import ( FieldPanel, FieldRowPanel, InlinePanel, MultiFieldPanel @@ -19,9 +18,10 @@ from wagtail.contrib.forms.models import ( ) from mailings.models import send_mail +from dynamic_forms.forms import DynamicForm -class Form(FormMixin, ClusterableModel): +class Form(FormMixin, Page): intro = RichTextField(blank=True) thank_you_text = RichTextField(blank=True) allow_attachments = models.BooleanField(default=False) @@ -39,6 +39,17 @@ class Form(FormMixin, ClusterableModel): ], "Email"), ] + def get_form_class(self): + return DynamicForm + + def get_form(self, *args, **kwargs): + form_class = self.get_form_class() + form_params = self.get_form_parameters() + form_params.update(kwargs) + print(form_params) + fields = self.get_form_fields() + return form_class(field_list=fields, *args, **form_params) + class Meta: abstract = True diff --git a/artel/dynamic_forms/templates/forms/email_form_page.html b/artel/dynamic_forms/templates/forms/email_form_page.html index 89d786b..ff16e25 100644 --- a/artel/dynamic_forms/templates/forms/email_form_page.html +++ b/artel/dynamic_forms/templates/forms/email_form_page.html @@ -5,14 +5,17 @@ {% block content %}

{{ page.title }}

{{ page.date }}

+ {% if form %} +
{{ page.intro|richtext }}
+
+ {% csrf_token %} + {% for field in form %} + {{field.label}} {{field}} -
{{ page.body|richtext }}
- - {% for item in page.gallery_images.all %} -
- {% image item.image fill-320x240 %} -

{{ item.caption }}

-
- {% endfor %} - + {% endfor %} + +
+ {% else %} +
You can fill in the from only one time.
+ {% endif %} {% endblock %} diff --git a/artel/dynamic_forms/tests.py b/artel/dynamic_forms/tests.py index df3eb26..c5311d7 100644 --- a/artel/dynamic_forms/tests.py +++ b/artel/dynamic_forms/tests.py @@ -1,5 +1,101 @@ from django.test import TestCase -# Create your tests here. -class ComfyEmailFormMixin(TestCase): - ... +from dynamic_forms.models import ( + CustomEmailForm, + EmailFormField +) + + +class CustomEmailFormTestCase(TestCase): + def setUp(self): + self.form = CustomEmailForm.objects.create( + from_address="comfy-test@egalitare.pl", + to_address="comfy-dest@egalitare.pl", + subject="Test Form", allow_attachments=False + ) + EmailFormField.objects.create( + label="Name", + field_type="singleline", + required=True, + form=self.form + ) + EmailFormField.objects.create( + label="Message", + field_type="multiline", + required=True, + form=self.form + ) + EmailFormField.objects.create( + label="Email", + field_type="email", + required=True, + form=self.form + ) + EmailFormField.objects.create( + label="Number", + field_type="number", + required=True, + form=self.form + ) + EmailFormField.objects.create( + label="URL", + field_type="url", + required=True, + form=self.form + ) + EmailFormField.objects.create( + label="Checkbox", + field_type="checkbox", + required=True, + form=self.form + ) + EmailFormField.objects.create( + label="Checkboxes", + field_type="checkboxes", + required=True, + choices="a,b,c", + form=self.form + ) + EmailFormField.objects.create( + label="Dropdown", + field_type="dropdown", + required=True, + choices="a,b,c", + form=self.form + ) + EmailFormField.objects.create( + label="MultiSelect", + field_type="multiselect", + required=True, + choices="a,b,c", + form=self.form + ) + EmailFormField.objects.create( + label="Radio", + field_type="radio", + required=True, + choices="a,b,c", + form=self.form + ) + EmailFormField.objects.create( + label="Date", + field_type="date", + required=True, + form=self.form + ) + EmailFormField.objects.create( + label="DateTime", + field_type="datetime", + required=True, + form=self.form + ) + EmailFormField.objects.create( + label="Hidden", + field_type="hidden", + required=True, + form=self.form + ) + + + def test_create_form_submission_without_files(self): + ...