2022-07-07 20:49:50 +00:00
|
|
|
import logging
|
|
|
|
|
|
2022-07-06 23:38:37 +00:00
|
|
|
from django.contrib import messages
|
2022-07-07 23:36:48 +00:00
|
|
|
from django.core.exceptions import PermissionDenied
|
2022-07-06 23:38:37 +00:00
|
|
|
from django.db import IntegrityError
|
|
|
|
|
from django.shortcuts import redirect
|
|
|
|
|
from django.urls import reverse_lazy
|
2022-07-07 20:49:50 +00:00
|
|
|
from django.utils.datastructures import MultiValueDictKeyError
|
2022-07-06 23:38:37 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
from django.views import View
|
2022-07-07 20:49:50 +00:00
|
|
|
from django.views.generic import CreateView, UpdateView
|
2022-07-06 23:38:37 +00:00
|
|
|
|
|
|
|
|
from ..base import get_theme
|
2022-07-07 20:49:50 +00:00
|
|
|
from ..dynamic import assemble_form_class
|
|
|
|
|
from ..forms import (
|
|
|
|
|
FormElementEntryFormSet,
|
|
|
|
|
FormEntryForm,
|
|
|
|
|
FormWizardEntryForm,
|
|
|
|
|
FormWizardFormEntryFormSet,
|
|
|
|
|
ImportFormEntryForm,
|
|
|
|
|
ImportFormWizardEntryForm,
|
|
|
|
|
)
|
|
|
|
|
from ..models import (
|
|
|
|
|
FormElementEntry,
|
|
|
|
|
FormEntry,
|
|
|
|
|
FormHandlerEntry,
|
|
|
|
|
FormWizardEntry,
|
|
|
|
|
FormWizardFormEntry,
|
|
|
|
|
FormWizardHandlerEntry,
|
|
|
|
|
)
|
2022-07-07 23:40:12 +00:00
|
|
|
from ..permissions.default import (
|
|
|
|
|
CreateFormEntryPermission,
|
|
|
|
|
EditFormEntryPermission,
|
|
|
|
|
)
|
2022-07-07 20:49:50 +00:00
|
|
|
from ..settings import DEBUG, GET_PARAM_INITIAL_DATA, SORT_PLUGINS_BY_VALUE
|
|
|
|
|
from ..utils import (
|
|
|
|
|
append_edit_and_delete_links_to_field,
|
|
|
|
|
get_user_form_element_plugins_grouped,
|
|
|
|
|
get_user_form_field_plugin_uids,
|
|
|
|
|
get_user_form_handler_plugin_uids,
|
|
|
|
|
get_user_form_handler_plugins,
|
|
|
|
|
get_user_form_wizard_handler_plugin_uids,
|
|
|
|
|
get_user_form_wizard_handler_plugins,
|
|
|
|
|
get_wizard_files_upload_dir,
|
|
|
|
|
perform_form_entry_import,
|
|
|
|
|
prepare_form_entry_export_data,
|
|
|
|
|
)
|
2022-07-06 23:38:37 +00:00
|
|
|
|
2022-07-07 21:38:54 +00:00
|
|
|
__all__ = (
|
|
|
|
|
"CreateFormEntryView",
|
|
|
|
|
"EditFormEntryView",
|
|
|
|
|
)
|
2022-07-06 23:38:37 +00:00
|
|
|
|
2022-07-07 20:49:50 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
2022-07-06 23:38:37 +00:00
|
|
|
|
2022-07-07 23:36:48 +00:00
|
|
|
class PermissionMixin(View):
|
|
|
|
|
"""Mixin for permission-based views."""
|
|
|
|
|
|
|
|
|
|
permission_classes: tuple = ()
|
|
|
|
|
|
|
|
|
|
def permission_denied(self, request, message=None, code=None):
|
|
|
|
|
"""If request is not permitted, raise."""
|
|
|
|
|
raise PermissionDenied()
|
|
|
|
|
|
|
|
|
|
def get_permissions(self):
|
|
|
|
|
"""Return initialized list of permissions required by this view."""
|
|
|
|
|
return [permission() for permission in self.permission_classes]
|
|
|
|
|
|
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
|
"""Dispatch the request."""
|
|
|
|
|
self.check_permissions(request)
|
|
|
|
|
return super(PermissionMixin, self).dispatch(request, *args, **kwargs)
|
|
|
|
|
|
|
|
|
|
def check_permissions(self, request):
|
|
|
|
|
"""Check if the request should be permitted.
|
|
|
|
|
|
|
|
|
|
Raises an appropriate exception if the request is not permitted.
|
|
|
|
|
"""
|
|
|
|
|
for permission in self.get_permissions():
|
|
|
|
|
if not permission.has_permission(request, self):
|
|
|
|
|
self.permission_denied(
|
|
|
|
|
request,
|
|
|
|
|
message=getattr(permission, 'message', None),
|
|
|
|
|
code=getattr(permission, 'code', None)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CreateFormEntryView(PermissionMixin, CreateView):
|
2022-07-06 23:38:37 +00:00
|
|
|
"""Create form entry view."""
|
|
|
|
|
|
|
|
|
|
template_name = None
|
|
|
|
|
form_class = FormEntryForm
|
|
|
|
|
theme = None
|
2022-07-07 23:40:12 +00:00
|
|
|
permission_classes = (CreateFormEntryPermission,)
|
2022-07-06 23:38:37 +00:00
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
|
"""Get context data."""
|
2022-07-07 23:36:48 +00:00
|
|
|
context = super(CreateFormEntryView, self).get_context_data(**kwargs)
|
2022-07-06 23:38:37 +00:00
|
|
|
context["form"] = self.get_form()
|
2022-07-07 22:18:23 +00:00
|
|
|
if not self.theme:
|
|
|
|
|
theme = get_theme(request=self.request, as_instance=True)
|
|
|
|
|
else:
|
|
|
|
|
theme = self.theme
|
|
|
|
|
|
|
|
|
|
if theme:
|
|
|
|
|
context.update({"fobi_theme": theme})
|
2022-07-06 23:38:37 +00:00
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
def get_template_names(self):
|
|
|
|
|
"""Get template names."""
|
|
|
|
|
template_name = self.template_name
|
|
|
|
|
if not template_name:
|
|
|
|
|
if not self.theme:
|
|
|
|
|
theme = get_theme(request=self.request, as_instance=True)
|
2022-07-07 21:38:54 +00:00
|
|
|
else:
|
|
|
|
|
theme = self.theme
|
2022-07-06 23:38:37 +00:00
|
|
|
template_name = theme.create_form_entry_template
|
|
|
|
|
return [template_name]
|
|
|
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
2022-07-07 23:36:48 +00:00
|
|
|
kwargs = super(CreateFormEntryView, self).get_form_kwargs()
|
2022-07-06 23:38:37 +00:00
|
|
|
kwargs["request"] = self.request
|
|
|
|
|
return kwargs
|
|
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
|
"""Handle GET requests: instantiate a blank version of the form."""
|
|
|
|
|
self.object = None
|
|
|
|
|
return self.render_to_response(self.get_context_data())
|
|
|
|
|
|
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
|
"""
|
|
|
|
|
Handle POST requests: instantiate a form instance with the passed
|
|
|
|
|
POST variables and then check if it's valid.
|
|
|
|
|
"""
|
|
|
|
|
self.object = None
|
|
|
|
|
form = self.get_form()
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
form_entry = form.save(commit=False)
|
|
|
|
|
form_entry.user = request.user
|
|
|
|
|
try:
|
|
|
|
|
form_entry.save()
|
|
|
|
|
messages.info(
|
|
|
|
|
request,
|
|
|
|
|
_("Form {0} was created successfully.").format(
|
|
|
|
|
form_entry.name
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
return redirect(
|
|
|
|
|
"fobi.edit_form_entry", form_entry_id=form_entry.pk
|
|
|
|
|
)
|
|
|
|
|
except IntegrityError as err:
|
|
|
|
|
messages.info(
|
|
|
|
|
request,
|
|
|
|
|
_("Errors occurred while saving the form: {0}.").format(
|
|
|
|
|
str(err)
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return self.render_to_response(self.get_context_data())
|
|
|
|
|
|
2022-07-07 20:49:50 +00:00
|
|
|
def run_after_form_create(self, form_entry):
|
2022-07-06 23:38:37 +00:00
|
|
|
"""Post hook."""
|
2022-07-07 20:49:50 +00:00
|
|
|
|
|
|
|
|
|
2022-07-07 23:36:48 +00:00
|
|
|
class EditFormEntryView(PermissionMixin, UpdateView):
|
2022-07-07 20:49:50 +00:00
|
|
|
"""Edit form entry."""
|
|
|
|
|
|
|
|
|
|
template_name = None
|
|
|
|
|
form_class = FormEntryForm
|
|
|
|
|
theme = None
|
2022-07-07 21:38:54 +00:00
|
|
|
pk_url_kwarg = "form_entry_id"
|
2022-07-07 23:40:12 +00:00
|
|
|
permission_classes = (EditFormEntryPermission,)
|
2022-07-07 20:49:50 +00:00
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
|
"""Get context data."""
|
2022-07-07 23:36:48 +00:00
|
|
|
context = super(EditFormEntryView, self).get_context_data(**kwargs)
|
2022-07-07 20:49:50 +00:00
|
|
|
|
|
|
|
|
# In case of success, we don't need this (since redirect would happen).
|
|
|
|
|
# Thus, fetch only if needed.
|
|
|
|
|
form_elements = self.object.formelemententry_set.all()
|
|
|
|
|
form_handlers = self.object.formhandlerentry_set.all()[:]
|
|
|
|
|
used_form_handler_uids = [
|
|
|
|
|
form_handler.plugin_uid for form_handler in form_handlers
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# The code below (two lines below) is not really used at the moment,
|
|
|
|
|
# thus - comment out, but do not remove, as we might need it later on.
|
|
|
|
|
# all_form_entries = FormEntry._default_manager \
|
|
|
|
|
# .only('id', 'name', 'slug') \
|
|
|
|
|
# .filter(user__pk=request.user.pk)
|
|
|
|
|
|
|
|
|
|
# List of form element plugins allowed to user
|
|
|
|
|
user_form_element_plugins = get_user_form_element_plugins_grouped(
|
|
|
|
|
self.request.user, sort_by_value=SORT_PLUGINS_BY_VALUE
|
|
|
|
|
)
|
|
|
|
|
# List of form handler plugins allowed to user
|
|
|
|
|
user_form_handler_plugins = get_user_form_handler_plugins(
|
|
|
|
|
self.request.user,
|
|
|
|
|
exclude_used_singles=True,
|
|
|
|
|
used_form_handler_plugin_uids=used_form_handler_uids,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Assembling the form for preview
|
|
|
|
|
form_cls = assemble_form_class(
|
|
|
|
|
self.object,
|
|
|
|
|
origin="edit_form_entry",
|
|
|
|
|
origin_kwargs_update_func=append_edit_and_delete_links_to_field,
|
|
|
|
|
request=self.request,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assembled_form = form_cls()
|
|
|
|
|
|
|
|
|
|
# In debug mode, try to identify possible problems.
|
|
|
|
|
if DEBUG:
|
|
|
|
|
assembled_form.as_p()
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
assembled_form.as_p()
|
|
|
|
|
except Exception as err:
|
|
|
|
|
logger.error(err)
|
|
|
|
|
|
|
|
|
|
# If no theme provided, pick a default one.
|
|
|
|
|
if not self.theme:
|
2022-07-07 22:18:23 +00:00
|
|
|
theme = get_theme(request=self.request, as_instance=True)
|
|
|
|
|
else:
|
|
|
|
|
theme = self.theme
|
2022-07-07 20:49:50 +00:00
|
|
|
|
2022-07-07 22:18:23 +00:00
|
|
|
if theme:
|
|
|
|
|
context.update({"fobi_theme": theme})
|
2022-07-07 20:49:50 +00:00
|
|
|
|
2022-07-07 22:18:23 +00:00
|
|
|
theme.collect_plugin_media(form_elements)
|
2022-07-07 20:49:50 +00:00
|
|
|
|
|
|
|
|
context.update(
|
|
|
|
|
{
|
|
|
|
|
"form": self.get_form(),
|
|
|
|
|
"form_entry": self.object,
|
|
|
|
|
"form_elements": form_elements,
|
|
|
|
|
"form_handlers": form_handlers,
|
|
|
|
|
"user_form_element_plugins": user_form_element_plugins,
|
|
|
|
|
"user_form_handler_plugins": user_form_handler_plugins,
|
|
|
|
|
"assembled_form": assembled_form,
|
2022-07-07 22:18:23 +00:00
|
|
|
"fobi_theme": theme,
|
2022-07-07 20:49:50 +00:00
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
def get_template_names(self):
|
|
|
|
|
"""Get template names."""
|
|
|
|
|
template_name = self.template_name
|
|
|
|
|
if not template_name:
|
|
|
|
|
if not self.theme:
|
|
|
|
|
theme = get_theme(request=self.request, as_instance=True)
|
2022-07-07 21:38:54 +00:00
|
|
|
else:
|
|
|
|
|
theme = self.theme
|
2022-07-07 20:49:50 +00:00
|
|
|
template_name = theme.edit_form_entry_template
|
|
|
|
|
return [template_name]
|
|
|
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
2022-07-07 23:36:48 +00:00
|
|
|
kwargs = super(EditFormEntryView, self).get_form_kwargs()
|
2022-07-07 20:49:50 +00:00
|
|
|
kwargs["request"] = self.request
|
|
|
|
|
return kwargs
|
|
|
|
|
|
2022-07-07 21:38:54 +00:00
|
|
|
def _get_queryset(self, request):
|
|
|
|
|
"""Get queryset."""
|
|
|
|
|
return FormEntry._default_manager \
|
|
|
|
|
.select_related('user') \
|
|
|
|
|
.prefetch_related('formelemententry_set') \
|
|
|
|
|
.filter(user__pk=request.user.pk)
|
|
|
|
|
|
2022-07-07 20:49:50 +00:00
|
|
|
def get(self, request, *args, **kwargs):
|
2022-07-07 21:38:54 +00:00
|
|
|
self.object = self.get_object(queryset=self._get_queryset(request))
|
2022-07-07 20:49:50 +00:00
|
|
|
"""Handle GET requests: instantiate a blank version of the form."""
|
|
|
|
|
form_element_entry_formset = FormElementEntryFormSet(
|
|
|
|
|
queryset=self.object.formelemententry_set.all(),
|
|
|
|
|
# prefix='form_element'
|
|
|
|
|
)
|
|
|
|
|
return self.render_to_response(
|
|
|
|
|
self.get_context_data(
|
2022-07-07 22:18:23 +00:00
|
|
|
form_element_entry_formset=form_element_entry_formset,
|
2022-07-07 20:49:50 +00:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
|
"""
|
|
|
|
|
Handle POST requests: instantiate a form instance with the passed
|
|
|
|
|
POST variables and then check if it's valid.
|
|
|
|
|
"""
|
2022-07-07 21:38:54 +00:00
|
|
|
self.object = self.get_object(queryset=self._get_queryset(request))
|
2022-07-07 20:49:50 +00:00
|
|
|
form = self.get_form()
|
|
|
|
|
|
|
|
|
|
# This is where we save ordering if it has been changed.
|
|
|
|
|
# The `FormElementEntryFormSet` contain ids and positions only.
|
|
|
|
|
if "ordering" in request.POST:
|
|
|
|
|
form_element_entry_formset = FormElementEntryFormSet(
|
|
|
|
|
request.POST,
|
|
|
|
|
request.FILES,
|
|
|
|
|
queryset=self.object.formelemententry_set.all(),
|
|
|
|
|
# prefix = 'form_element'
|
|
|
|
|
)
|
|
|
|
|
# If form elements aren't properly made (developers's fault)
|
|
|
|
|
# there might be problems with saving the ordering - likely
|
|
|
|
|
# in case of hidden elements only. Thus, we want to avoid
|
|
|
|
|
# errors here.
|
|
|
|
|
try:
|
|
|
|
|
if form_element_entry_formset.is_valid():
|
|
|
|
|
form_element_entry_formset.save()
|
|
|
|
|
messages.info(
|
|
|
|
|
request, _("Elements ordering edited successfully.")
|
|
|
|
|
)
|
|
|
|
|
return redirect(
|
|
|
|
|
reverse_lazy(
|
|
|
|
|
"fobi.edit_form_entry",
|
|
|
|
|
kwargs={"form_entry_id": self.object.pk},
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
except MultiValueDictKeyError as err:
|
|
|
|
|
messages.error(
|
|
|
|
|
request,
|
|
|
|
|
_(
|
|
|
|
|
"Errors occurred while trying to change the "
|
|
|
|
|
"elements ordering!"
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
return redirect(
|
|
|
|
|
reverse_lazy(
|
|
|
|
|
"fobi.edit_form_entry",
|
|
|
|
|
kwargs={"form_entry_id": self.object.pk},
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
form_element_entry_formset = FormElementEntryFormSet(
|
|
|
|
|
queryset=self.object.formelemententry_set.all(),
|
|
|
|
|
# prefix='form_element'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
obj = form.save(commit=False)
|
|
|
|
|
obj.user = request.user
|
|
|
|
|
try:
|
|
|
|
|
obj.save()
|
|
|
|
|
messages.info(
|
|
|
|
|
request,
|
|
|
|
|
_("Form {0} was edited successfully.").format(obj.name),
|
|
|
|
|
)
|
|
|
|
|
return redirect(
|
|
|
|
|
reverse_lazy(
|
|
|
|
|
"fobi.edit_form_entry", kwargs={"form_entry_id": obj.pk}
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
except IntegrityError as err:
|
|
|
|
|
messages.info(
|
|
|
|
|
request,
|
|
|
|
|
_("Errors occurred while saving the form: {0}.").format(
|
|
|
|
|
str(err)
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return self.render_to_response(
|
|
|
|
|
self.get_context_data(
|
2022-07-07 22:18:23 +00:00
|
|
|
form_element_entry_formset=form_element_entry_formset,
|
2022-07-07 20:49:50 +00:00
|
|
|
)
|
|
|
|
|
)
|