Merge pull request 'form anty-spam, hiden field rendering, added help_text showing' (#21) from feature/form_improvements into main
ci/woodpecker/push/build Pipeline was successful Szczegóły

Reviewed-on: #21
feature/project_rename
mtyton 2023-11-12 09:08:56 +00:00
commit 1ab8537c64
4 zmienionych plików z 90 dodań i 15 usunięć

Wyświetl plik

@ -24,6 +24,23 @@ class MultipleFileField(forms.FileField):
return result
class HoneypotField(forms.BooleanField):
default_widget = forms.HiddenInput(
{'style': 'display:none !important;', 'tabindex': '-1', 'autocomplete': 'off'}
)
def __init__(self, *args, **kwargs):
kwargs.setdefault('widget', HoneypotField.default_widget)
kwargs['required'] = False
super().__init__(*args, **kwargs)
def clean(self, value):
if cleaned_value := super().clean(value):
raise forms.ValidationError('')
else:
return cleaned_value
class DynamicForm(forms.Form):
FIELD_TYPE_MAPPING = {
@ -54,6 +71,7 @@ class DynamicForm(forms.Form):
if hasattr(f, "choices"):
f.choices = [(v, v) for v in field.choices.split(",")]
f.required = field.required
f.help_text = field.help_text or ""
self.fields[field.clean_name] = f
if file_uploads:
self.fields["attachments"] = MultipleFileField(
@ -61,3 +79,21 @@ class DynamicForm(forms.Form):
attrs={"class": "form-control"}
)
)
# add honeypot field
self.fields["secret_honey"] = HoneypotField()
def clean(self):
cleaned_data = super().clean()
new_cleaned_data = {}
for key, value in cleaned_data.items():
if isinstance(value, list):
if isinstance(self.fields[key], MultipleFileField):
continue
cleaned_data[key] = ",".join(value)
if key=="secret_honey":
continue
new_cleaned_data[key] = value
return new_cleaned_data

Wyświetl plik

@ -60,6 +60,11 @@ class Form(FormMixin, Page):
class EmailFormSubmission(AbstractFormSubmission):
# TODO - make this optional, allow to set pattern in admin
def get_submission_id(self, form_slug):
case_number_daily = EmailFormSubmission.objects.filter(submit_time__date=datetime.date.today()).count()
return f"{form_slug}-{datetime.date.today()}-{case_number_daily}"
def send_mail(self, data):
# modify this, get proper template
to_addresses = data.pop("to_address").split(",")
@ -69,7 +74,8 @@ class EmailFormSubmission(AbstractFormSubmission):
)
for file in data.pop("attachments", [])
]
subject = data.get("subject")
subject = data.pop("subject")
form_slug = data.pop("form_slug")
from_address = data.pop("from_address", settings.DEFAULT_FROM_EMAIL)
for address in to_addresses:
OutgoingEmail.objects.send(
@ -77,7 +83,7 @@ class EmailFormSubmission(AbstractFormSubmission):
template_name="form_mail",
recipient=address,
sender=from_address,
context={"form_data": data, "submission_id": self.id},
context={"form_data": data, "submission_id": self.get_submission_id(form_slug)},
attachments=attachments
)
@ -112,7 +118,8 @@ class CustomEmailForm(Form):
"from_address": self.from_address,
"to_address": self.to_address,
"subject": self.subject,
"attachments": attachments
"attachments": attachments,
"form_slug": self.slug
})
submission.send_mail(data=mail_data)
return submission

Wyświetl plik

@ -12,18 +12,23 @@
<form enctype="multipart/form-data" action="{% pageurl page %}" method="POST">
{% csrf_token %}
{% for field in form %}
<div class="form-group mt-3">
<label for="{{field.id}}" class="form-label">
{% trans field.label %}
</label>
{{field}}
<small id="emailHelp" class="form-text text-muted">
{% trans field.help_text %}
</small>
{% if field.error %}
{{error}}
{% endif %}
</div>
{% if field.is_hidden %}
<!--Empty space for reason, we don't want to show anything on empty fields-->
{{field}}
{% else %}
<div class="form-group mt-3">
<label for="{{field.id}}" class="form-label">
{% trans field.label %}
</label>
{{field}}
<small id="emailHelp" class="form-text text-muted">
{% trans field.help_text %}
</small>
{% if field.error %}
{{error}}
{% endif %}
</div>
{% endif %}
{% endfor %}
<div class="text-end mt-3">
<input class="btn btn-lg btn-success" type="submit" value='{% trans "Submit" %}'>

Wyświetl plik

@ -275,3 +275,30 @@ class CustomEmailFormTestCase(WagtailPageTests):
self.assertEqual(form.errors["name"], ['This field is required.'])
self.assertEqual(form.errors["url"], ['This field is required.'])
self.assertEqual(form.errors["attachments"], ['This field is required.'])
def test_no_hidden_field_in_clean_data_success(self):
form_data = {
# generate data for this class self.form.get_form()
"name": "Test",
"message": "Test message",
"email": "test@test.com",
"number": 1,
"url": "http://example.com",
"checkbox": True,
"checkboxes": ["a", "b"],
"dropdown": "a",
"multiselect": ["a", "b"],
"radio": "a",
"date": "2020-01-01",
"datetime": "2020-01-01 00:00:00",
"hidden": "hidden",
}
form = self.form.get_form(form_data)
self.assertTrue(form.is_valid())
cleaned_data = form.cleaned_data
self.assertIn("hidden", cleaned_data)
self.assertNotIn("secret_honey", cleaned_data)
self.assertIn("hidden", form.fields)
self.assertIn("secret_honey", form.fields)