mirror of
https://github.com/Hopiu/django-fobi.git
synced 2026-05-12 14:53:08 +00:00
514 lines
15 KiB
Python
514 lines
15 KiB
Python
import socket
|
|
|
|
from six.moves.urllib.parse import urlparse
|
|
|
|
from django import forms
|
|
from django.forms.models import modelformset_factory
|
|
from django.utils.translation import ugettext, ugettext_lazy as _
|
|
|
|
from nonefield.fields import NoneField
|
|
|
|
from .base import (
|
|
get_registered_form_element_plugins,
|
|
get_registered_form_handler_plugins,
|
|
get_registered_form_wizard_handler_plugins,
|
|
get_theme
|
|
)
|
|
from .constants import ACTION_CHOICES
|
|
from .exceptions import ImproperlyConfigured
|
|
from .models import (
|
|
# Form plugins
|
|
FormElement,
|
|
FormHandler,
|
|
FormWizardHandler,
|
|
|
|
# Form entries
|
|
FormEntry,
|
|
FormFieldsetEntry,
|
|
FormElementEntry,
|
|
FormHandlerEntry,
|
|
|
|
# Form wizard entries
|
|
FormWizardEntry,
|
|
FormWizardHandlerEntry,
|
|
FormWizardFormEntry
|
|
)
|
|
from .validators import url_exists
|
|
|
|
__title__ = 'fobi.forms'
|
|
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
|
__copyright__ = '2014-2016 Artur Barseghyan'
|
|
__license__ = 'GPL 2.0/LGPL 2.1'
|
|
__all__ = (
|
|
'BulkChangeFormElementPluginsForm',
|
|
'BulkChangeFormHandlerPluginsForm',
|
|
'BulkChangeFormWizardHandlerPluginsForm',
|
|
'FormElementEntryFormSet',
|
|
'FormEntryForm',
|
|
'FormFieldsetEntryForm',
|
|
'FormHandlerEntryForm',
|
|
'FormHandlerForm',
|
|
'FormWizardEntryForm',
|
|
'FormWizardFormEntryForm',
|
|
'FormWizardFormEntryFormSet',
|
|
'FormWizardHandlerEntryForm',
|
|
'ImportFormEntryForm',
|
|
)
|
|
|
|
# *****************************************************************************
|
|
# *****************************************************************************
|
|
# ******************************* Entry forms *********************************
|
|
# *****************************************************************************
|
|
# *****************************************************************************
|
|
|
|
|
|
class FormEntryForm(forms.ModelForm):
|
|
"""Form for ``fobi.models.FormEntry`` model."""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormEntry
|
|
fields = ('name', 'is_public', 'success_page_title',
|
|
'success_page_message', 'action',) # 'is_cloneable',
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
"""Constructor."""
|
|
self.request = kwargs.pop('request', None)
|
|
if self.request is None:
|
|
raise ImproperlyConfigured(
|
|
ugettext("The {0} form requires a "
|
|
"request argument.".format(self.__class__.__name__))
|
|
)
|
|
|
|
super(FormEntryForm, self).__init__(*args, **kwargs)
|
|
theme = get_theme(request=None, as_instance=True)
|
|
|
|
self.fields['name'].widget = forms.widgets.TextInput(
|
|
attrs={'class': theme.form_element_html_class}
|
|
)
|
|
|
|
self.fields['success_page_title'].widget = forms.widgets.TextInput(
|
|
attrs={'class': theme.form_element_html_class}
|
|
)
|
|
|
|
self.fields['success_page_message'].widget = forms.widgets.Textarea(
|
|
attrs={'class': theme.form_element_html_class}
|
|
)
|
|
|
|
self.fields['action'].widget = forms.widgets.TextInput(
|
|
attrs={'class': theme.form_element_html_class}
|
|
)
|
|
|
|
# At the moment this is done for Foundation 5 theme. Remove this once
|
|
# it's possible for a theme to override this form. Alternatively, add
|
|
# the attrs to the theme API.
|
|
self.fields['is_public'].widget = forms.widgets.CheckboxInput(
|
|
attrs={'data-customforms': 'disabled'}
|
|
)
|
|
# self.fields['is_cloneable'].widget = forms.widgets.CheckboxInput(
|
|
# attrs={'data-customforms': 'disabled'}
|
|
# )
|
|
|
|
def clean_action(self):
|
|
"""Validate the action (URL).
|
|
|
|
Checks if URL exists.
|
|
"""
|
|
url = self.cleaned_data['action']
|
|
if url:
|
|
full_url = url
|
|
|
|
if not (url.startswith('http://') or url.startswith('https://')):
|
|
full_url = self.request.build_absolute_uri(url)
|
|
|
|
parsed_url = urlparse(full_url)
|
|
|
|
local = False
|
|
|
|
try:
|
|
localhost = socket.gethostbyname('localhost')
|
|
except Exception as err:
|
|
localhost = '127.0.0.1'
|
|
|
|
try:
|
|
host = socket.gethostbyname(parsed_url.hostname)
|
|
|
|
local = (localhost == host)
|
|
except socket.gaierror as err:
|
|
pass
|
|
|
|
if local:
|
|
full_url = parsed_url.path
|
|
|
|
if not url_exists(full_url, local=local):
|
|
raise forms.ValidationError(
|
|
ugettext("Invalid action URL {0}.").format(full_url)
|
|
)
|
|
|
|
return url
|
|
|
|
|
|
class FormFieldsetEntryForm(forms.ModelForm):
|
|
"""Form for ``fobi.models.FormFieldsetEntry`` model."""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormFieldsetEntry
|
|
fields = ('name',)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
"""Constructor."""
|
|
super(FormFieldsetEntryForm, self).__init__(*args, **kwargs)
|
|
theme = get_theme(request=None, as_instance=True)
|
|
self.fields['name'].widget = forms.widgets.TextInput(
|
|
attrs={'class': theme.form_element_html_class}
|
|
)
|
|
|
|
|
|
class FormElementForm(forms.ModelForm):
|
|
"""FormElement form."""
|
|
|
|
# plugin_uid = forms.ChoiceField(
|
|
# choices=get_registered_form_element_plugins()
|
|
# )
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormElement
|
|
fields = ('users', 'groups')
|
|
|
|
|
|
class FormElementEntryForm(forms.ModelForm):
|
|
"""FormElementEntry form."""
|
|
|
|
plugin_uid = forms.ChoiceField(
|
|
choices=get_registered_form_element_plugins()
|
|
)
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormElementEntry
|
|
fields = ('form_entry', 'plugin_data', 'plugin_uid', 'position')
|
|
|
|
|
|
class _FormElementEntryForm(forms.ModelForm):
|
|
"""FormElementEntry form.
|
|
|
|
To be used with `FormElementEntryFormSet` only.
|
|
"""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormElementEntry
|
|
fields = ('position',)
|
|
|
|
|
|
FormElementEntryFormSet = modelformset_factory(
|
|
FormElementEntry,
|
|
fields=('position',),
|
|
extra=0,
|
|
form=_FormElementEntryForm
|
|
)
|
|
|
|
|
|
class FormHandlerForm(forms.ModelForm):
|
|
"""FormHandler form."""
|
|
|
|
# plugin_uid = forms.ChoiceField(
|
|
# choices=get_registered_form_handler_plugins()
|
|
# )
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormHandler
|
|
fields = ('users', 'groups')
|
|
|
|
|
|
class FormHandlerEntryForm(forms.ModelForm):
|
|
"""FormHandlerEntry form."""
|
|
|
|
plugin_uid = forms.ChoiceField(
|
|
choices=get_registered_form_handler_plugins()
|
|
)
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormHandlerEntry
|
|
fields = ('form_entry', 'plugin_data', 'plugin_uid')
|
|
|
|
|
|
# *****************************************************************************
|
|
# *****************************************************************************
|
|
# ****************************** Wizard forms *********************************
|
|
# *****************************************************************************
|
|
# *****************************************************************************
|
|
|
|
class FormWizardFormEntryForm(forms.ModelForm):
|
|
"""FormWizardFormEntryForm form.
|
|
|
|
|
|
"""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormWizardFormEntry
|
|
fields = ('form_wizard_entry', 'form_entry',)
|
|
|
|
|
|
class _FormWizardFormEntryForm(forms.ModelForm):
|
|
"""FormWizardFormEntryForm for formset.
|
|
|
|
.. note::
|
|
We have only two fields in the form: `form_entry` and `position`. The
|
|
`form_entry` field is a `nonefield.NoneField`, thus - read only. The
|
|
only changeable field is `position`.
|
|
|
|
.. warning::
|
|
|
|
To be used in `FormWizardFormEntryFormSet` only. If you need model
|
|
form for `FormWizardFormEntry` model, make another one and leave this
|
|
intact.
|
|
"""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormWizardFormEntry
|
|
fields = ('position',)
|
|
|
|
# def __init__(self, *args, **kwargs):
|
|
# """Constructor."""
|
|
# super(_FormWizardFormEntryForm, self).__init__(*args, **kwargs)
|
|
#
|
|
# self.fields['position'].widget = forms.widgets.HiddenInput(
|
|
# attrs={'class': 'form-element-position'}
|
|
# )
|
|
# # self.fields['form_entry'] = NoneField(
|
|
# # required=False,
|
|
# # label=self.fields['form_entry'].label,
|
|
# # initial=self.fields['form_entry'].initial,
|
|
# # help_text=self.fields['form_entry'].help_text
|
|
# # )
|
|
|
|
|
|
FormWizardFormEntryFormSet = modelformset_factory(
|
|
FormWizardFormEntry,
|
|
fields=('position',),
|
|
extra=0,
|
|
form=_FormWizardFormEntryForm
|
|
)
|
|
|
|
|
|
class FormWizardEntryForm(forms.ModelForm):
|
|
"""Form for ``fobi.models.FormWizardEntry`` model."""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormWizardEntry
|
|
fields = ('name', 'is_public', 'success_page_title',
|
|
'success_page_message',)
|
|
# 'wizard_type'
|
|
# 'action',
|
|
# 'is_cloneable',
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
"""Constructor."""
|
|
self.request = kwargs.pop('request', None)
|
|
if self.request is None:
|
|
raise ImproperlyConfigured(
|
|
ugettext("The {0} form requires a "
|
|
"request argument.".format(self.__class__.__name__))
|
|
)
|
|
|
|
super(FormWizardEntryForm, self).__init__(*args, **kwargs)
|
|
theme = get_theme(request=None, as_instance=True)
|
|
|
|
self.fields['name'].widget = forms.widgets.TextInput(
|
|
attrs={'class': theme.form_element_html_class}
|
|
)
|
|
|
|
self.fields['success_page_title'].widget = forms.widgets.TextInput(
|
|
attrs={'class': theme.form_element_html_class}
|
|
)
|
|
|
|
self.fields['success_page_message'].widget = forms.widgets.Textarea(
|
|
attrs={'class': theme.form_element_html_class}
|
|
)
|
|
|
|
# self.fields['action'].widget = forms.widgets.TextInput(
|
|
# attrs={'class': theme.form_element_html_class}
|
|
# )
|
|
|
|
# self.fields['wizard_type'].widget.attrs = {
|
|
# 'class': theme.form_element_html_class
|
|
# }
|
|
|
|
# At the moment this is done for Foundation 5 theme. Remove this once
|
|
# it's possible for a theme to override this form. Alternatively, add
|
|
# the attrs to the theme API.
|
|
self.fields['is_public'].widget = forms.widgets.CheckboxInput(
|
|
attrs={'data-customforms': 'disabled'}
|
|
)
|
|
# self.fields['is_cloneable'].widget = forms.widgets.CheckboxInput(
|
|
# attrs={'data-customforms': 'disabled'}
|
|
# )
|
|
|
|
# def clean_action(self):
|
|
# """Validate the action (URL).
|
|
#
|
|
# Checks if URL exists.
|
|
# """
|
|
# url = self.cleaned_data['action']
|
|
# if url:
|
|
# full_url = url
|
|
#
|
|
# if not (url.startswith('http://') or url.startswith('https://')):
|
|
# full_url = self.request.build_absolute_uri(url)
|
|
#
|
|
# parsed_url = urlparse(full_url)
|
|
#
|
|
# local = False
|
|
#
|
|
# try:
|
|
# localhost = socket.gethostbyname('localhost')
|
|
# except Exception as err:
|
|
# localhost = '127.0.0.1'
|
|
#
|
|
# try:
|
|
# host = socket.gethostbyname(parsed_url.hostname)
|
|
#
|
|
# local = (localhost == host)
|
|
# except socket.gaierror as err:
|
|
# pass
|
|
#
|
|
# if local:
|
|
# full_url = parsed_url.path
|
|
#
|
|
# if not url_exists(full_url, local=local):
|
|
# raise forms.ValidationError(
|
|
# ugettext("Invalid action URL {0}.").format(full_url)
|
|
# )
|
|
#
|
|
# return url
|
|
|
|
|
|
class FormWizardHandlerEntryForm(forms.ModelForm):
|
|
"""FormWizardHandlerEntry form."""
|
|
|
|
plugin_uid = forms.ChoiceField(
|
|
choices=get_registered_form_handler_plugins()
|
|
)
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormWizardHandlerEntry
|
|
fields = ('form_wizard_entry', 'plugin_data', 'plugin_uid')
|
|
|
|
# *****************************************************************************
|
|
# *****************************************************************************
|
|
# *********************************** Base ************************************
|
|
# *****************************************************************************
|
|
# *****************************************************************************
|
|
|
|
|
|
class BaseBulkChangePluginsForm(forms.ModelForm):
|
|
"""Bulk change plugins form.
|
|
|
|
- `selected_plugins` (str): List of comma separated values to be
|
|
changed.
|
|
- `users_action` (int): For indicating wheither the users shall be appended
|
|
to the dashbard plugins or replaced.
|
|
- `groups_action` (int): For indicating wheither the groups shall be
|
|
appended to the dashboard plugins or replaced.
|
|
"""
|
|
|
|
selected_plugins = forms.CharField(
|
|
required=True,
|
|
label=_("Selected plugins"),
|
|
widget=forms.widgets.HiddenInput
|
|
)
|
|
users_action = forms.ChoiceField(
|
|
required=False,
|
|
label=_("Users action"),
|
|
choices=ACTION_CHOICES,
|
|
help_text=_("If set to ``replace``, the groups are replaced; "
|
|
"otherwise - appended.")
|
|
)
|
|
groups_action = forms.ChoiceField(
|
|
required=False,
|
|
label=_("Groups action"),
|
|
choices=ACTION_CHOICES,
|
|
help_text=_("If set to ``replace``, the groups are replaced; "
|
|
"otherwise - appended.")
|
|
)
|
|
|
|
class Media:
|
|
"""Media class."""
|
|
|
|
css = {
|
|
'all': ('css/admin_custom.css',)
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
"""Constructor."""
|
|
super(BaseBulkChangePluginsForm, self).__init__(*args, **kwargs)
|
|
self.fields['users'].required = False
|
|
self.fields['groups'].required = False
|
|
|
|
|
|
class BulkChangeFormElementPluginsForm(BaseBulkChangePluginsForm):
|
|
"""Bulk change form element plugins form."""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormElement
|
|
fields = ['groups', 'groups_action', 'users', 'users_action']
|
|
|
|
|
|
class BulkChangeFormHandlerPluginsForm(BaseBulkChangePluginsForm):
|
|
"""Bulk change form handler plugins form."""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormHandler
|
|
fields = ['groups', 'groups_action', 'users', 'users_action']
|
|
|
|
|
|
class BulkChangeFormWizardHandlerPluginsForm(BaseBulkChangePluginsForm):
|
|
"""Bulk change form wizard handler plugins form."""
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = FormWizardHandler
|
|
fields = ['groups', 'groups_action', 'users', 'users_action']
|
|
|
|
# *****************************************************************************
|
|
# *****************************************************************************
|
|
# **************************** Import form entry ******************************
|
|
# *****************************************************************************
|
|
# *****************************************************************************
|
|
|
|
|
|
class ImportFormEntryForm(forms.Form):
|
|
"""Import form entry form."""
|
|
|
|
file = forms.FileField(required=True, label=_("File"))
|
|
# ignore_broken_form_element_entries = forms.BooleanField(
|
|
# required=False,
|
|
# label=_("Ignore broken form element entries"))
|
|
# ignore_broken_form_handler_entries = forms.BooleanField(
|
|
# required=False,
|
|
# label=_("Ignore broken form handler entries"))
|