Basic forms has been implemented
rodzic
2ab84212b6
commit
b149b85f53
|
@ -67,7 +67,7 @@
|
|||
<div class="col-md-11 mt-5 ml-2"></div>
|
||||
<div class="col-md-1 mt-5 ml-2">
|
||||
|
||||
{% if page %}
|
||||
{% if page and page.get_translations.live %}
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-outline-secondary btn-lg" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<img src="{% static 'images/icons/globe.svg' %}">
|
||||
|
|
|
@ -1,13 +1,28 @@
|
|||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
from django import forms
|
||||
from django.forms.utils import ErrorList
|
||||
|
||||
|
||||
class MultipleFileInput(forms.ClearableFileInput):
|
||||
allow_multiple_selected = True
|
||||
|
||||
|
||||
class MultipleFileField(forms.FileField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault("widget", MultipleFileInput())
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, data, initial=None):
|
||||
single_file_clean = super().clean
|
||||
if isinstance(data, (list, tuple)):
|
||||
result = [single_file_clean(d, initial) for d in data]
|
||||
else:
|
||||
result = single_file_clean(data, initial)
|
||||
return result
|
||||
|
||||
|
||||
class DynamicForm(forms.Form):
|
||||
|
||||
FIELD_TYPE_MAPPING = {
|
||||
"singleline": forms.CharField(max_length=255, widget=forms.TextInput(attrs={"class": "form-control"})),
|
||||
"singleline": forms.CharField(max_length=50, 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"})),
|
||||
|
@ -17,9 +32,17 @@ class DynamicForm(forms.Form):
|
|||
"dropdown": forms.ChoiceField(widget=forms.Select(attrs={"class": "form-control"})),
|
||||
}
|
||||
|
||||
def __init__(self, field_list, *args, **kwargs) -> None:
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
self.page = kwargs.pop("page")
|
||||
self.user = kwargs.pop("user")
|
||||
field_list = kwargs.pop("field_list")
|
||||
file_uploads = kwargs.pop("file_uploads", False)
|
||||
super().__init__(*args, **kwargs)
|
||||
for field in field_list:
|
||||
self.fields[field.clean_name] = self.FIELD_TYPE_MAPPING[field.field_type]
|
||||
if file_uploads:
|
||||
self.fields["attachments"] = MultipleFileField(
|
||||
required=True, widget=MultipleFileInput(
|
||||
attrs={"class": "form-control"}
|
||||
)
|
||||
)
|
||||
|
|
|
@ -37,6 +37,7 @@ class Form(FormMixin, Page):
|
|||
]),
|
||||
FieldPanel('subject'),
|
||||
], "Email"),
|
||||
FieldPanel("allow_attachments")
|
||||
]
|
||||
|
||||
def get_form_class(self):
|
||||
|
@ -46,9 +47,9 @@ class Form(FormMixin, Page):
|
|||
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)
|
||||
form_params["field_list"] = self.get_form_fields()
|
||||
form_params["file_uploads"] = self.allow_attachments
|
||||
return form_class(*args, **form_params)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
@ -67,18 +68,21 @@ class EmailFormSubmission(AbstractFormSubmission):
|
|||
elif isinstance(value, datetime.date):
|
||||
value = date_format(value, settings.SHORT_DATE_FORMAT)
|
||||
|
||||
content.append("{}: {}".format(field_name.label, value))
|
||||
content.append("{}: {}".format(field_name, value))
|
||||
|
||||
return "\n".join(content)
|
||||
|
||||
def send_mail(self, data):
|
||||
addresses = [x.strip() for x in data["to_address"].split(",")]
|
||||
to_addresses = data.pop("to_address").split(",")
|
||||
subject = data.pop("subject")
|
||||
from_address = data.pop("from_address", settings.DEFAULT_FROM_EMAIL)
|
||||
addresses = [x.strip() for x in to_addresses]
|
||||
send_mail(
|
||||
addresses,
|
||||
[],
|
||||
data.pop("subject"),
|
||||
subject,
|
||||
self.render_email(data),
|
||||
data.pop("from_address", settings.DEFAULT_FROM_EMAIL)
|
||||
from_address
|
||||
)
|
||||
|
||||
|
||||
|
@ -98,6 +102,22 @@ class CustomEmailForm(Form):
|
|||
|
||||
template = "forms/email_form_page.html"
|
||||
|
||||
def get_submission_class(self):
|
||||
return EmailFormSubmission
|
||||
|
||||
def process_form_submission(self, form):
|
||||
submission = self.get_submission_class().objects.create(
|
||||
form_data=form.cleaned_data,
|
||||
page=self,
|
||||
)
|
||||
mail_data = form.cleaned_data.copy()
|
||||
mail_data.update({
|
||||
"from_address": self.from_address,
|
||||
"to_address": self.to_address,
|
||||
"subject": self.subject
|
||||
})
|
||||
submission.send_mail(data=mail_data)
|
||||
return submission
|
||||
|
||||
class EmailFormField(AbstractFormField):
|
||||
form = ParentalKey(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% load wagtailcore_tags wagtailimages_tags %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ page.title }}</h1>
|
||||
|
@ -10,10 +11,20 @@
|
|||
<form action="{% pageurl page %}" method="POST">
|
||||
{% csrf_token %}
|
||||
{% for field in form %}
|
||||
{{field.label}} {{field}}
|
||||
<div class="form-group mt-3">
|
||||
<label for="{{field.id}}" class="form-label">
|
||||
{{field.label}}
|
||||
</label>
|
||||
{{field}}
|
||||
<small id="emailHelp" class="form-text text-muted">
|
||||
{{form.help_text}}
|
||||
</small>
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
<input type="submit">
|
||||
<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>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load wagtailcore_tags wagtailimages_tags %}
|
||||
|
||||
{% block content %}
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<div class="card col-9 bg-white shadow-md p-5">
|
||||
<div class="mb-4 text-center">
|
||||
<svg class="text-success" width="75" height="75"
|
||||
fill="currentColor" class="bi bi-check-circle" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z" />
|
||||
<path
|
||||
d="M10.97 4.97a.235.235 0 0 0-.02.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-1.071-1.05z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div>
|
||||
{{page.thank_you_text|richtext}}
|
||||
</div>
|
||||
<a class="btn btn-outline-primary mt-3" href="/">
|
||||
{% trans "Go to homepage" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -4,7 +4,7 @@
|
|||
<div class="d-flex justify-content-center align-items-center">
|
||||
<div class="card col-9 bg-white shadow-md p-5">
|
||||
<div class="mb-4 text-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="text-success" width="75" height="75"
|
||||
<svg class="text-success" width="75" height="75"
|
||||
fill="currentColor" class="bi bi-check-circle" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z" />
|
||||
<path
|
||||
|
|
Ładowanie…
Reference in New Issue