diff --git a/.gitignore b/.gitignore index fe0ed176..1e169510 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ MIND_BUCKET.rst /deploy/ fobi/fobi.migrations.rst /examples/db/ +/src/fobi/contrib/plugins/form_elements/fields/hidden_model_object/ /examples/tmp/ /examples/logs/ diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9ad05579..53f6dbcf 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,11 +15,23 @@ are used for versioning (schema follows below): 0.3.4 to 0.4). - All backwards incompatible changes are mentioned in this document. +0.4.22 +------------------------------------- +2015-03-03 + +- Fix replace system-specific path separator by a slash on file urls. +- Fix empty options appearing in the Select-like (`radio`, `select` and + `select_multiple`) plugins and unified the processing of the raw choices + data. +- Validate the initial value for Select-like (`radio`, `select` and + `select_multiple`) plugins. + 0.4.21 ------------------------------------- 2015-02-28 -- The ``fobi.contrib.plugins.form_elements.fields.select_multiple_model_objects`` +- The + ``fobi.contrib.plugins.form_elements.fields.select_multiple_model_objects`` plugin added. 0.4.20 diff --git a/examples/requirements.txt b/examples/requirements.txt index daf1736f..de5719b5 100644 --- a/examples/requirements.txt +++ b/examples/requirements.txt @@ -4,9 +4,10 @@ MarkupSafe MySQL-python South Sphinx -django-admin-tools==0.5.2 -django-autoslug==1.7.1 -django-debug-toolbar==0.11.0 +django-admin-tools>=0.5.2 +django-autoslug>=1.7.1 +django-debug-toolbar>=0.11.0 +django-localeurl>=2.0.2 django-registration-redux>=1.1 #django-simple-captcha docutils @@ -18,7 +19,7 @@ selenium simple-timer>=0.2 tox -hg+https://bitbucket.org/barseghyanartur/django-localeurl +#hg+https://bitbucket.org/barseghyanartur/django-localeurl #Django>=1.5,<1.7 #FeinCMS>=1.9,<2.0 diff --git a/examples/requirements_django16.txt b/examples/requirements_django16.txt index 895d509f..39ca22d4 100644 --- a/examples/requirements_django16.txt +++ b/examples/requirements_django16.txt @@ -2,10 +2,10 @@ Django>=1.6,<1.7 Jinja2 MarkupSafe -MySQL-python +#MySQL-python Sphinx -django-autoslug==1.7.1 -django-debug-toolbar==0.11.0 +django-autoslug>=1.7.1 +django-debug-toolbar>=0.11.0 django-registration-redux>=1.1 docutils ipdb diff --git a/examples/simple/settings.py b/examples/simple/settings.py index 87daa0e3..836b0a27 100644 --- a/examples/simple/settings.py +++ b/examples/simple/settings.py @@ -213,6 +213,7 @@ INSTALLED_APPS = ( 'fobi.contrib.plugins.form_elements.fields.email', 'fobi.contrib.plugins.form_elements.fields.file', 'fobi.contrib.plugins.form_elements.fields.hidden', + #'fobi.contrib.plugins.form_elements.fields.hidden_model_object', 'fobi.contrib.plugins.form_elements.fields.input', 'fobi.contrib.plugins.form_elements.fields.integer', 'fobi.contrib.plugins.form_elements.fields.password', diff --git a/scripts/install_django16.bat b/scripts/install_django16.bat new file mode 100644 index 00000000..2068da3c --- /dev/null +++ b/scripts/install_django16.bat @@ -0,0 +1,15 @@ +#pip install -r examples/requirements.txt --allow-all-external --allow-unverified django-admin-tools +#cd .. +pip install -r examples\requirements_django16.txt +python setup.py install +mkdir examples\logs +mkdir examples\db +mkdir examples\media +mkdir examples\media\static +mkdir examples\media\fobi_plugins\content_image +mkdir examples\media\fobi_plugins\file +python examples\simple\manage.py collectstatic --noinput --traceback -v 3 +python examples\simple\manage.py syncdb --noinput --traceback -v 3 +python examples\simple\manage.py migrate --noinput --traceback -v 3 +python examples\simple\manage.py fobi_create_test_data --traceback -v 3 +#cd scripts \ No newline at end of file diff --git a/scripts/reinstall_django16.bat b/scripts/reinstall_django16.bat new file mode 100644 index 00000000..5c3546e2 --- /dev/null +++ b/scripts/reinstall_django16.bat @@ -0,0 +1,3 @@ +reset +.\scripts\uninstall.sh +.\scripts\install_django16.sh \ No newline at end of file diff --git a/scripts/uninstall.bat b/scripts/uninstall.bat new file mode 100644 index 00000000..353fb2f0 --- /dev/null +++ b/scripts/uninstall.bat @@ -0,0 +1,9 @@ +pip uninstall django-fobi -y +#cd .. +rmdir build /s +rmdir dist /s +rmdir src\django_fobi.egg-info /s +rmdir src\django-fobi.egg-info /s +rmdir builddocs.zip +rmdir builddocs /s +#cd scripts \ No newline at end of file diff --git a/setup.py b/setup.py index 47eb830a..2a54bbac 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ for static_dir in static_dirs: for locale_dir in locale_dirs: locale_files += [os.path.join(locale_dir, f) for f in os.listdir(locale_dir)] -version = '0.4.21' +version = '0.4.22' install_requires = [ 'Pillow>=2.0.0', diff --git a/src/fobi/__init__.py b/src/fobi/__init__.py index c8b9055c..f57ffdd9 100644 --- a/src/fobi/__init__.py +++ b/src/fobi/__init__.py @@ -1,6 +1,6 @@ __title__ = 'django-fobi' -__version__ = '0.4.21' -__build__ = 0x000024 +__version__ = '0.4.22' +__build__ = 0x000025 __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2015 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' diff --git a/src/fobi/contrib/plugins/form_elements/fields/radio/forms.py b/src/fobi/contrib/plugins/form_elements/fields/radio/forms.py index 6e813411..d41a3f37 100644 --- a/src/fobi/contrib/plugins/form_elements/fields/radio/forms.py +++ b/src/fobi/contrib/plugins/form_elements/fields/radio/forms.py @@ -1,6 +1,6 @@ __title__ = 'fobi.contrib.plugins.form_elements.fields.select.forms' __author__ = 'Artur Barseghyan ' -__copyright__ = 'Copyright (c) 2014 Artur Barseghyan' +__copyright__ = '2014-2015 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' __all__ = ('RadioInputForm',) @@ -8,6 +8,7 @@ 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_choices theme = get_theme(request=None, as_instance=True) @@ -70,3 +71,20 @@ class RadioInputForm(forms.Form, BaseFormFieldPluginForm): required = False, widget = forms.widgets.CheckboxInput(attrs={'class': theme.form_element_checkbox_html_class}) ) + + def clean_initial(self): + """ + Validating the initial value. + """ + return validate_initial_for_choices(self, 'choices', 'initial') +# +# availalble_choices = dict( +# get_select_field_choices(self.cleaned_data['choices']) +# ).values() +# +# if not self.cleaned_data['initial'] in availalble_choices: +# raise forms.ValidationError( +# _("Invalid value for initial! Should be any of the " +# "following: {0}".format(','.join(availalble_choices))) +# ) +# return self.cleaned_data['initial'] diff --git a/src/fobi/contrib/plugins/form_elements/fields/select/forms.py b/src/fobi/contrib/plugins/form_elements/fields/select/forms.py index ceeb7bfe..9d6bd3f4 100644 --- a/src/fobi/contrib/plugins/form_elements/fields/select/forms.py +++ b/src/fobi/contrib/plugins/form_elements/fields/select/forms.py @@ -1,6 +1,6 @@ __title__ = 'fobi.contrib.plugins.form_elements.fields.select.forms' __author__ = 'Artur Barseghyan ' -__copyright__ = 'Copyright (c) 2014 Artur Barseghyan' +__copyright__ = '2014-2015 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' __all__ = ('SelectInputForm',) @@ -8,6 +8,7 @@ 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_choices theme = get_theme(request=None, as_instance=True) @@ -70,3 +71,9 @@ class SelectInputForm(forms.Form, BaseFormFieldPluginForm): required = False, widget = forms.widgets.CheckboxInput(attrs={'class': theme.form_element_checkbox_html_class}) ) + + def clean_initial(self): + """ + Validating the initial value. + """ + return validate_initial_for_choices(self, 'choices', 'initial') diff --git a/src/fobi/contrib/plugins/form_elements/fields/select_multiple/forms.py b/src/fobi/contrib/plugins/form_elements/fields/select_multiple/forms.py index dbeb37cf..3b8bd249 100644 --- a/src/fobi/contrib/plugins/form_elements/fields/select_multiple/forms.py +++ b/src/fobi/contrib/plugins/form_elements/fields/select_multiple/forms.py @@ -1,6 +1,6 @@ __title__ = 'fobi.contrib.plugins.form_elements.fields.select_multiple.forms' __author__ = 'Artur Barseghyan ' -__copyright__ = 'Copyright (c) 2014 Artur Barseghyan' +__copyright__ = '2014-2015 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' __all__ = ('SelectMultipleInputForm',) @@ -8,6 +8,7 @@ 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) @@ -70,3 +71,9 @@ class SelectMultipleInputForm(forms.Form, BaseFormFieldPluginForm): required = False, widget = forms.widgets.CheckboxInput(attrs={'class': theme.form_element_checkbox_html_class}) ) + + def clean_initial(self): + """ + Validating the initial value. + """ + return validate_initial_for_multiple_choices(self, 'choices', 'initial') diff --git a/src/fobi/helpers.py b/src/fobi/helpers.py index df3c500c..98b8c38c 100644 --- a/src/fobi/helpers.py +++ b/src/fobi/helpers.py @@ -8,6 +8,7 @@ __all__ = ( 'handle_uploaded_file', 'delete_file', 'clone_file', 'get_registered_models', 'admin_change_url', 'uniquify_sequence', 'safe_text', 'combine_dicts', 'update_plugin_data', 'get_select_field_choices', + 'validate_initial_for_choices', 'validate_initial_for_multiple_choices', ) import os @@ -24,6 +25,8 @@ from django.core.files.base import File from django.contrib.contenttypes.models import ContentType from django.db.utils import DatabaseError from django.utils.encoding import force_text +from django import forms +from django.utils.translation import ugettext_lazy as _ from autoslug.settings import slugify @@ -300,20 +303,77 @@ def get_select_field_choices(raw_choices_data): :param str raw_choices_data: :return list: """ - choices = [] - keys = set([]) + choices = [] # Holds return value + keys = set([]) # For checking uniqueness of keys + values = set([]) # For checking uniqueness of values + + # Looping through the raw data for choice in raw_choices_data.split('\n'): choice = choice.strip() + + # If comma separated key, value if ',' in choice: key, value = choice.split(',', 1) key = key.strip() value = value.strip() - if not key in keys: + if key and not key in keys and not value in values: choices.append((key, value)) keys.add(key) + values.add(value) + + # If key is also the value else: choice = choice.strip() - if not choice in keys: + if choice and not choice in keys and not choice in values: choices.append((choice, choice)) keys.add(choice) + values.add(choice) + return choices + +def validate_initial_for_choices(plugin_form, field_name_choices='choices', \ + field_name_initial='initial'): + """ + Validates the initial value for the choices given. + + :param fobi.base.BaseFormFieldPluginForm plugin_form: + """ + availalble_choices = dict( + get_select_field_choices(plugin_form.cleaned_data[field_name_choices]) + ).values() + + if plugin_form.cleaned_data[field_name_initial] \ + and not plugin_form.cleaned_data[field_name_initial] \ + in availalble_choices: + raise forms.ValidationError( + _("Invalid value for initial: {0}. Should be any of the following" + ": {1}".format(plugin_form.cleaned_data[field_name_initial], \ + ','.join(availalble_choices))) + ) + + return plugin_form.cleaned_data[field_name_initial] + + +def validate_initial_for_multiple_choices(plugin_form, \ + field_name_choices='choices', \ + field_name_initial='initial'): + """ + Validates the initial value for the multiple choices given. + + :param fobi.base.BaseFormFieldPluginForm plugin_form: + """ + availalble_choices = dict( + get_select_field_choices(plugin_form.cleaned_data[field_name_choices]) + ).values() + + if plugin_form.cleaned_data[field_name_initial]: + for choice in plugin_form.cleaned_data[field_name_initial].split(','): + choice = choice.strip() + if not choice in availalble_choices: + raise forms.ValidationError( + _("Invalid value for initial: {0}. Should be any " + "of the following: {1}" + "".format(choice, ','.join(availalble_choices))) + ) + + return plugin_form.cleaned_data[field_name_initial]