mirror of
https://github.com/Hopiu/django-fobi.git
synced 2026-05-17 09:01:08 +00:00
Merge pull request #23 from mariuccio/master
select_multiple_with_max plugin
This commit is contained in:
commit
9cf0fc13f6
9 changed files with 357 additions and 0 deletions
|
|
@ -0,0 +1,79 @@
|
|||
=========================================================
|
||||
fobi.contrib.plugins.form_elements.fields.select_multiple_with_max
|
||||
=========================================================
|
||||
A ``Fobi`` Select Multiple form field plugin with max choices. Makes use of the
|
||||
``django.forms.widgets.SelectMultiple``.
|
||||
|
||||
Installation
|
||||
===============================================
|
||||
1. Add ``fobi.contrib.plugins.form_elements.fields.select_multiple_with_max`` to the
|
||||
``INSTALLED_APPS`` in your ``settings.py``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
INSTALLED_APPS = (
|
||||
# ...
|
||||
'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max',
|
||||
# ...
|
||||
)
|
||||
|
||||
2. In the terminal type:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
$ ./manage.py fobi_sync_plugins
|
||||
|
||||
3. Assign appropriate permissions to the target users/groups to be using
|
||||
the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True.
|
||||
|
||||
4. By default, the submitted form value of `select_multiple_with_max`
|
||||
elements is label (human readable representation of the value chosen).
|
||||
However, that part of the bahaviour has been made configurable. You can
|
||||
choose between the following options:
|
||||
|
||||
Consider the following list of (value, label) choices (the first element in
|
||||
the tuple is value, the second element is label):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
[
|
||||
('alpha', 'Alpha'),
|
||||
('beta', 'Beta'),
|
||||
('gamma', 'Gamma'),
|
||||
]
|
||||
|
||||
- "val": `value` (example: "alpha").
|
||||
- "repr" (default): `label` (example: "Alpha").
|
||||
- "mix": `value (label)` (examle: "Alpha (alpha)").
|
||||
|
||||
Simply set the
|
||||
``FOBI_FORM_ELEMENT_SELECT_MULTIPLE_WITH_MAX_SUBMIT_VALUE_AS`` assign one of the
|
||||
following values: "val", "repr" or "mix" to get the desired behaviour.
|
||||
|
||||
Usage
|
||||
===============================================
|
||||
You should be entering a single choice per line. Choice might
|
||||
consist of just a single value or value/label pair. If you enter an integer in
|
||||
the 'max_choices' field, the user can choose only <max_choices> or less choices.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
1
|
||||
2
|
||||
alpha, Alpha
|
||||
beta, Beta
|
||||
omega
|
||||
|
||||
The following HTML would be made of:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<select id="id_NAME_OF_THE_ELEMENT" name="NAME_OF_THE_ELEMENT">
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="alpha">Alpha</option>
|
||||
<option value="beta">Beta</option>
|
||||
<option value="omega">omega</option>
|
||||
</select>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
__title__ = 'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = 'Copyright (c) 2014 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('default_app_config', 'UID',)
|
||||
|
||||
default_app_config = 'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max.apps.Config'
|
||||
|
||||
UID = 'select_multiple_with_max'
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
__title__ = 'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max.apps'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = 'Copyright (c) 2014 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('Config',)
|
||||
|
||||
try:
|
||||
from django.apps import AppConfig
|
||||
|
||||
class Config(AppConfig):
|
||||
name = 'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max'
|
||||
label = 'fobi_contrib_plugins_form_elements_fields_select_multiple_with_max'
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
__title__ = 'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max.conf'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = 'Copyright (c) 2014-2015 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('get_setting',)
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from . import defaults
|
||||
|
||||
def get_setting(setting, override=None):
|
||||
"""
|
||||
Get a setting from
|
||||
`fobi.contrib.plugins.form_elements.fields.select_multiple_with_max` conf module,
|
||||
falling back to the default.
|
||||
|
||||
If override is not None, it will be used instead of the setting.
|
||||
|
||||
:param setting: String with setting name
|
||||
:param override: Value to use when no setting is available. Defaults
|
||||
to None.
|
||||
:return: Setting value.
|
||||
"""
|
||||
if override is not None:
|
||||
return override
|
||||
if hasattr(settings, 'FOBI_FORM_ELEMENT_SELECT_MULTIPLE_WITH_MAX_{0}'.format(setting)):
|
||||
return getattr(settings, 'FOBI_FORM_ELEMENT_SELECT_MULTIPLE_WITH_MAX_{0}'.format(setting))
|
||||
else:
|
||||
return getattr(defaults, setting)
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
__title__ = 'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max.defaults'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = 'Copyright (c) 2014-2015 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('SUBMIT_VALUE_AS',)
|
||||
|
||||
from fobi.constants import SUBMIT_VALUE_AS_REPR
|
||||
|
||||
SUBMIT_VALUE_AS = SUBMIT_VALUE_AS_REPR
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
from django.forms.fields import MultipleChoiceField
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
class MultipleChoiceWithMaxField(MultipleChoiceField):
|
||||
|
||||
def __init__(self, max_choices=None, choices=(), required=True, widget=None,
|
||||
label=None, initial=None, help_text='', *args, **kwargs):
|
||||
super(MultipleChoiceWithMaxField, self).__init__(
|
||||
choices=choices, required=required, widget=widget, label=label,
|
||||
initial=initial, help_text=help_text, *args, **kwargs
|
||||
)
|
||||
self.max_choices = max_choices
|
||||
|
||||
def validate(self, value):
|
||||
super(MultipleChoiceWithMaxField, self).validate(value)
|
||||
if self.max_choices:
|
||||
if len(value) > self.max_choices:
|
||||
raise ValidationError(_("You must choose no more than {0} "
|
||||
"values.".format(self.max_choices)))
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
__title__ = 'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max.fobi_form_elements'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = 'Copyright (c) 2014 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('SelectMultipleWithMaxInputPlugin',)
|
||||
|
||||
from django.forms.widgets import SelectMultiple
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from fobi.base import FormFieldPlugin, form_element_plugin_registry, get_theme
|
||||
from fobi.constants import (
|
||||
SUBMIT_VALUE_AS_VAL, SUBMIT_VALUE_AS_REPR
|
||||
)
|
||||
from fobi.helpers import get_select_field_choices, safe_text
|
||||
|
||||
from . import UID
|
||||
from .fields import MultipleChoiceWithMaxField
|
||||
from .forms import SelectMultipleWithMaxInputForm
|
||||
from .settings import SUBMIT_VALUE_AS
|
||||
|
||||
theme = get_theme(request=None, as_instance=True)
|
||||
|
||||
class SelectMultipleWithMaxInputPlugin(FormFieldPlugin):
|
||||
"""
|
||||
Select multiple field plugin with max.
|
||||
"""
|
||||
uid = UID
|
||||
name = _("Select multiple with max")
|
||||
group = _("Fields")
|
||||
form = SelectMultipleWithMaxInputForm
|
||||
|
||||
def get_form_field_instances(self, request=None):
|
||||
"""
|
||||
Get form field instances.
|
||||
"""
|
||||
choices = get_select_field_choices(self.data.choices)
|
||||
|
||||
kwargs = {
|
||||
'label': self.data.label,
|
||||
'help_text': self.data.help_text,
|
||||
'initial': self.data.initial,
|
||||
'required': self.data.required,
|
||||
'choices': choices,
|
||||
'widget': SelectMultiple(attrs={'class': theme.form_element_html_class}),
|
||||
}
|
||||
|
||||
if self.data.max_choices:
|
||||
kwargs['max_choices'] = self.data.max_choices
|
||||
|
||||
return [(self.data.name, MultipleChoiceWithMaxField, kwargs)]
|
||||
|
||||
def submit_plugin_form_data(self, form_entry, request, form):
|
||||
"""
|
||||
Submit plugin form data/process.
|
||||
|
||||
:param fobi.models.FormEntry form_entry: Instance of
|
||||
``fobi.models.FormEntry``.
|
||||
:param django.http.HttpRequest request:
|
||||
:param django.forms.Form form:
|
||||
"""
|
||||
# In case if we should submit value as is, we don't return anything.
|
||||
# In other cases, we proceed further.
|
||||
if SUBMIT_VALUE_AS != SUBMIT_VALUE_AS_VAL:
|
||||
# Get the object
|
||||
values = form.cleaned_data.get(self.data.name, None)
|
||||
|
||||
# Get choices
|
||||
choices = dict(get_select_field_choices(self.data.choices))
|
||||
|
||||
# Returned value
|
||||
ret_values = []
|
||||
|
||||
for value in values:
|
||||
# Handle the submitted form value
|
||||
|
||||
if value in choices:
|
||||
label = safe_text(choices.get(value))
|
||||
|
||||
# Should be returned as repr
|
||||
if SUBMIT_VALUE_AS == SUBMIT_VALUE_AS_REPR:
|
||||
value = label
|
||||
# Should be returned as mix
|
||||
else:
|
||||
value = "{0} ({1})".format(label, value)
|
||||
|
||||
ret_values.append(value)
|
||||
|
||||
# Overwrite ``cleaned_data`` of the ``form`` with object
|
||||
# qualifier.
|
||||
form.cleaned_data[self.data.name] = ret_values
|
||||
|
||||
# It's critically important to return the ``form`` with updated
|
||||
# ``cleaned_data``
|
||||
return form
|
||||
|
||||
|
||||
form_element_plugin_registry.register(SelectMultipleWithMaxInputPlugin)
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
__title__ = 'fobi.contrib.plugins.form_elements.fields.select_multiple.forms'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = '2014-2015 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('SelectMultipleInputForm',)
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from fobi.base import BaseFormFieldPluginForm, get_theme
|
||||
from fobi.helpers import validate_initial_for_multiple_choices
|
||||
|
||||
theme = get_theme(request=None, as_instance=True)
|
||||
|
||||
class SelectMultipleWithMaxInputForm(forms.Form, BaseFormFieldPluginForm):
|
||||
"""
|
||||
Form for ``SelectMultipleInputPlugin``.
|
||||
"""
|
||||
plugin_data_fields = [
|
||||
("label", ""),
|
||||
("name", ""),
|
||||
("choices", ""),
|
||||
("help_text", ""),
|
||||
("initial", ""),
|
||||
("required", False),
|
||||
("max_choices", "")
|
||||
]
|
||||
|
||||
label = forms.CharField(
|
||||
label = _("Label"),
|
||||
required = True,
|
||||
widget = forms.widgets.TextInput(attrs={'class': theme.form_element_html_class})
|
||||
)
|
||||
name = forms.CharField(
|
||||
label = _("Name"),
|
||||
required = True,
|
||||
widget = forms.widgets.TextInput(attrs={'class': theme.form_element_html_class})
|
||||
)
|
||||
choices = forms.CharField(
|
||||
label = _("Choices"),
|
||||
required = False,
|
||||
help_text = _("Enter single values/pairs per line. Example:<code><br/>"
|
||||
" 1<br/>"
|
||||
" 2<br/>"
|
||||
" alpha, Alpha<br/>"
|
||||
" beta, Beta<br/>"
|
||||
" omega"
|
||||
"</code><br/>"
|
||||
"It finally transforms into the following HTML code:<code><br/>"
|
||||
' <select id="id_NAME_OF_THE_ELEMENT" name="NAME_OF_THE_ELEMENT"><br/>'
|
||||
' <option value="1">1</option><br/>'
|
||||
' <option value="2">2</option><br/>'
|
||||
' <option value="alpha">Alpha</option><br/>'
|
||||
' <option value="beta">Beta</option><br/>'
|
||||
' <option value="omega">omega</option><br/>'
|
||||
' </select>'
|
||||
"</code>"),
|
||||
widget = forms.widgets.Textarea(attrs={'class': theme.form_element_html_class})
|
||||
)
|
||||
help_text = forms.CharField(
|
||||
label = _("Help text"),
|
||||
required = False,
|
||||
widget = forms.widgets.Textarea(attrs={'class': theme.form_element_html_class})
|
||||
)
|
||||
initial = forms.CharField(
|
||||
label = _("Initial"),
|
||||
required = False,
|
||||
widget = forms.widgets.TextInput(attrs={'class': theme.form_element_html_class})
|
||||
)
|
||||
required = forms.BooleanField(
|
||||
label = _("Required"),
|
||||
required = False,
|
||||
widget = forms.widgets.CheckboxInput(attrs={'class': theme.form_element_checkbox_html_class})
|
||||
)
|
||||
max_choices = forms.IntegerField(
|
||||
label = _("Max choices"),
|
||||
required = False,
|
||||
widget=forms.widgets.NumberInput(attrs={'class': theme.form_element_html_class})
|
||||
)
|
||||
|
||||
def clean_initial(self):
|
||||
"""
|
||||
Validating the initial value.
|
||||
"""
|
||||
return validate_initial_for_multiple_choices(self, 'choices', 'initial')
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
__title__ = 'fobi.contrib.plugins.form_elements.fields.select_multiple_with_max.settings'
|
||||
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
|
||||
__copyright__ = 'Copyright (c) 2014-2015 Artur Barseghyan'
|
||||
__license__ = 'GPL 2.0/LGPL 2.1'
|
||||
__all__ = ('SUBMIT_VALUE_AS',)
|
||||
|
||||
from fobi.helpers import validate_submit_value_as
|
||||
|
||||
from .conf import get_setting
|
||||
|
||||
SUBMIT_VALUE_AS = get_setting('SUBMIT_VALUE_AS')
|
||||
|
||||
validate_submit_value_as(SUBMIT_VALUE_AS)
|
||||
Loading…
Reference in a new issue