Porównaj commity
7 Commity
Autor | SHA1 | Data |
---|---|---|
mtyton | f8f3d35935 | |
mtyton | 6bc385e47d | |
mtyton | 345dbe3f46 | |
mtyton | a5e243c55c | |
mtyton | 1ab8537c64 | |
mtyton | d365a1ee98 | |
mtyton | 19078bd03f |
|
@ -139,8 +139,8 @@ GitHub.sublime-settings
|
|||
#postgres pass files
|
||||
*.my_pgpass
|
||||
*.sql
|
||||
artel/static/
|
||||
wagtail_store/static/
|
||||
|
||||
# media
|
||||
artel/media/*
|
||||
artel/store/data/*
|
||||
wagtail_store/media/*
|
||||
wagtail_store/store/data/*
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% load wagtailcore_tags wagtailimages_tags %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ page.title }}</h1>
|
||||
<p class="meta">{{ page.date }}</p>
|
||||
{% if form %}
|
||||
{{form.errors}}
|
||||
<div>{{ page.intro|richtext }}</div>
|
||||
<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>
|
||||
{% endfor %}
|
||||
<div class="text-end mt-3">
|
||||
<input class="btn btn-lg btn-success" type="submit" value='{% trans "Submit" %}'>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<div>You can fill in the from only one time.</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -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
|
|
@ -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},
|
||||
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
|
|
@ -0,0 +1,40 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% load wagtailcore_tags wagtailimages_tags %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ page.title }}</h1>
|
||||
<p class="meta">{{ page.date }}</p>
|
||||
{% if form %}
|
||||
{{form.errors}}
|
||||
<div>{{ page.intro|richtext }}</div>
|
||||
<form enctype="multipart/form-data" action="{% pageurl page %}" method="POST">
|
||||
{% csrf_token %}
|
||||
{% for field in form %}
|
||||
{% 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" %}'>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<div>You can fill in the from only one time.</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -104,7 +104,7 @@ class CustomEmailFormTestCase(WagtailPageTests):
|
|||
def test_generate_html_form_from_model(self):
|
||||
html_form = self.form.get_form()
|
||||
self.assertIsInstance(html_form, DynamicForm)
|
||||
self.assertEqual(len(html_form.fields), 13)
|
||||
self.assertEqual(len(html_form.fields), 14)
|
||||
self.assertEqual(html_form.fields["name"].label, "Name")
|
||||
self.assertEqual(html_form.fields["name"].required, True)
|
||||
self.assertEqual(html_form.fields["name"].widget.attrs["class"], "form-control")
|
||||
|
@ -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)
|
||||
|
||||
|
|
@ -3,7 +3,7 @@ import os
|
|||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "artel.settings.dev")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wagtail_store.settings.dev")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue