From 8102f82565d4d03a3b74ae5b1b244c4b527eca1e Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Tue, 12 Dec 2017 20:59:08 +0100 Subject: [PATCH] prepare 0.12.6 --- CHANGELOG.rst | 4 +- docs/changelog.rst | 26 +++-- docs/index.rst | 157 ++++++++++++++++++++++++------- examples/simple/settings/base.py | 2 +- setup.py | 2 +- src/fobi/__init__.py | 4 +- src/fobi/models.py | 6 +- src/fobi/tests/test_core.py | 35 ++++++- 8 files changed, 185 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 69624810e..f4de17e9e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,11 +17,13 @@ are used for versioning (schema follows below): 0.12.6 ------ -2017-mm-dd (not yet released) +2017-12-12 - Clean up. - Minor documentation fixes. - Minor plugin clean-up/fixes (``captcha``, ``recaptcha``, ``content_text``). +- Minor Python 3 fixes. +- Minor fixes in FormWizard ``get_absolute_url`` method. 0.12.5 ------ diff --git a/docs/changelog.rst b/docs/changelog.rst index f62c9eb6d..f4de17e9e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -15,6 +15,16 @@ are used for versioning (schema follows below): 0.3.4 to 0.4). - All backwards incompatible changes are mentioned in this document. +0.12.6 +------ +2017-12-12 + +- Clean up. +- Minor documentation fixes. +- Minor plugin clean-up/fixes (``captcha``, ``recaptcha``, ``content_text``). +- Minor Python 3 fixes. +- Minor fixes in FormWizard ``get_absolute_url`` method. + 0.12.5 ------ 2017-09-27 @@ -79,7 +89,7 @@ are used for versioning (schema follows below): 2017-05-29 - Minor fixes in ``content_text`` ``drf_integration`` plugin. -- Added ``imageurl`` support to the ``mailchimp_impoter`` plugin. +- Added ``imageurl`` support to the ``mailchimp_importer`` plugin. 0.11.10 ------- @@ -387,7 +397,7 @@ custom form element plugins you should update your code! - The :method:`get_form_field_instances` and :method:`_get_form_field_instances` of the :class:`fobi.base.FormElementPlugin` both accept two new optional - arguments: `form_entry` and `form_element_entries` as well as **kwargs. + arguments: `form_entry` and `form_element_entries` as well as `**kwargs`. Make sure to update your custom plugins if you have written any. - Minor fixes in the form wizards: forms in intermediate steps do receive updates from the `submit_plugin_form_data` of the plugins. @@ -471,7 +481,7 @@ Release supported by `Lund University Cognitive Science `_. - Adding form-wizards functionality. Note, that at the moment only - `bootstrap3` theme was updated to filly support the form wizards. Although, + `bootstrap3` theme was updated to fully support the form wizards. Although, all other themes would by default support form-wizard functionality, they may not look as nice as they should be (to be fixed in 0.8.x releases shortly). @@ -482,7 +492,7 @@ Release supported by `Lund University Cognitive Science may need to update your custom CSS/JS/HTML accordingly. See the listing 0.8.a for the files affected. - An additional property `form_view_form_entry_option_class` has been added - to all the themes. Change your custom CSS/jS/HTML accordingly. See the + to all the themes. Change your custom CSS/JS/HTML accordingly. See the listing 0.8.b for the files affected. - Fixed drag-and-drop not working for ordering of form elements. #43 - Fixed issue with non-proper rendering of the form-importer templates. @@ -847,7 +857,7 @@ carefully. `fobi.contrib.apps.feincms_integration`, `fobi.contrib.apps.djangocms_integration`, `fobi.contrib.apps.mezzanine_integration`). Due to the change, you would - likely have to to rename a couple of database tables and update referencies + likely have to rename a couple of database tables and update references accordingly. No migrations to solve the issue are included at the moment. 0.4.36 @@ -895,7 +905,7 @@ carefully. 2015-03-23 - When path of the uploaded file (plugins) doesn't yet exist, create it, - instaid of failing. + instead of failing. 0.4.30 ------ @@ -1250,7 +1260,7 @@ command which makes the necessary changes in the database for safe upgrade). your project apps, make necessary path changes and update the package paths in ``INSTALLED_APPS`` settings module (settings.py) before upgrading to this version. Then, in Django admin management interface, replace all the - occurances of ``Birthday`` field with ``Date drop down`` field. + occurrences of ``Birthday`` field with ``Date drop down`` field. - Better error validation/handling of hidden fields. A new form snippet template added for displaying the non-field and hidden fields errors. The new template makes a part of a standard theme as an attribute @@ -1301,7 +1311,7 @@ Note, that this release contains minor backwards incompatible changes. The changes do not anyhow affect your existing forms or data. The only thing you need to do is update the app paths in the ``settings`` module of your project. -- Minor core improvements related to the themeing of the form handler plugins. +- Minor core improvements related to the theming of the form handler plugins. - Several presentational form element plugins have been renamed. The ``fobi.contrib.plugins.form_elements.content.image`` plugin has been renamed to ``fobi.contrib.plugins.form_elements.content.content_image``. diff --git a/docs/index.rst b/docs/index.rst index b478ad080..9969b9f61 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -37,12 +37,12 @@ Key concepts - Number of form elements is not limited. - Each form may contain handlers. Handler processes the form data (for example, saves it or mails it). Number of the handlers is not limited. -- Both form elements and form handlers are made with Django permission system +- Both form elements and form handlers are made with Django permission system in mind. -- As an addition to form handlers, form callbacks are implemented. Form +- As an addition to form handlers, form callbacks are implemented. Form callbacks are fired on various stages of pre- and post-processing the form data (on POST). Form callbacks do not make use of permission system (unless - you intentionally do so in the code of your callback) and are fired for all + you intentionally do so in the code of your callback) and are fired for all forms (unlike form handlers, that are executed only if assigned). - Each plugin (form element or form handler) or a callback - is a Django micro-app. @@ -76,7 +76,7 @@ Main features and highlights - Data handling in plugins (form handlers). Save the data, mail it to some address or re-post it to some other endpoint. See the `Bundled form handler plugins`_ for more information. -- Developer-friendly API, which allows to edit existing or build new form +- Developer-friendly API, which allows to edit existing or build new form fields and handlers without touching the core. - Support for custom user model. - `Theming`_. There are 4 ready to use `Bundled themes`_: "Bootstrap 3", @@ -398,7 +398,7 @@ Defining the Sample textarea plugin. name = "Sample Textarea" form = SampleTextareaForm group = "Samples" # Group to which the plugin belongs to - + def get_form_field_instances(self, request=None, form_entry=None, form_element_entries=None, **kwargs): kwargs = { @@ -435,18 +435,18 @@ widget in edit mode. In the view mode, the original widget that you assigned in your form element plugin would be used. There might be cases, when you need to do additional handling of the data upon -the successful form submission. In such cases, you will need to define a -``submit_plugin_form_data`` method in the plugin, which accepts the +the successful form submission. In such cases, you will need to define a +``submit_plugin_form_data`` method in the plugin, which accepts the following arguments: - `form_entry` (fobi.models.FormEntry): Form entry, which is being submitted. - `request` (django.http.HttpRequest): The Django HTTP request. -- `form` (django.forms.Form): Form object (a valid one, which contains +- `form` (django.forms.Form): Form object (a valid one, which contains the ``cleaned_data`` attribute). - `form_element_entries` (fobi.models.FormElementEntry): Form element entries for the `form_entry` given. - (**)kwargs : Additional arguments. - + Example (taken from fobi.contrib.plugins.form_elements.fields.file): .. code-block:: python @@ -511,7 +511,7 @@ Form for for ``SampleTextareaPlugin`` form element plugin. initial = forms.CharField(label="Initial", required=False) required = forms.BooleanField(label="Required", required=False) -Note that although it's not being checked in the code, but for form +Note that although it's not being checked in the code, but for form field plugins the following fields should be present in the plugin form (``BasePluginForm``) and the form plugin (``FormFieldPlugin``): @@ -754,8 +754,8 @@ Prioritise the execution order ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Some form handlers shall be executed prior others. A good example of such, is a combination of "mail" and "db_save" form handlers for the form. In case if -large files are posted, submission of form data would fail if "mail" plugin -would be executed after "db_save" has been executed. That's why it's possible +large files are posted, submission of form data would fail if "mail" plugin +would be executed after "db_save" has been executed. That's why it's possible to prioritise that ordering in a ``FOBI_FORM_HANDLER_PLUGINS_EXECUTION_ORDER`` setting variable. @@ -881,7 +881,7 @@ Defining the Sample importer plugin. """Sample importer plugin.""" uid = 'sample_importer' - name = _("Sample importer) + name = _("Sample importer") wizard = SampleImporterWizardView templates = [ 'sample_importer/0.html', @@ -1135,7 +1135,7 @@ Custom action for the form -------------------------- Sometimes, you would want to specify a different action for the form. Although it's possible to define a custom form action (``action`` field -in the "Form properties" tab), you're advised to use the ``http_repost`` +in the "Form properties" tab), you're advised to use the ``http_repost`` plugin instead, since then the form would be still validated locally and only then the valid data, as is, would be sent to the desired endpoint. @@ -1424,7 +1424,7 @@ Directory structure │ │ └── override-simple-theme.css │ └── js │ └── override-simple-theme.js - │ + │ ├── templates │ └── override_simple_theme │ ├── snippets @@ -1755,7 +1755,7 @@ There are several management commands available. occur when some plugin which did exist in the system, no longer exists. - `fobi_sync_plugins`. Should be ran each time a new plugin is being added to the `django-fobi`. -- `fobi_update_plugin_data`. A mechanism to update existing plugin data in +- `fobi_update_plugin_data`. A mechanism to update existing plugin data in case if it had become invalid after a change in a plugin. In order for it to work, each plugin should implement and ``update`` method, in which the data update happens. @@ -1765,7 +1765,7 @@ Tuning There are number of `django-fobi` settings you can override in the settings module of your Django project: -- `FOBI_RESTRICT_PLUGIN_ACCESS` (bool): If set to True, (Django) permission +- `FOBI_RESTRICT_PLUGIN_ACCESS` (bool): If set to True, (Django) permission system for dash plugins is enabled. Defaults to True. Setting this to False makes all plugins available for all users. - `FOBI_DEFAULT_THEME` (str): Active (default) theme UID. Defaults to @@ -2107,7 +2107,7 @@ Rendering forms using third-party libraries =========================================== You might want to render your forms using third-party libraries such as `django-crispy-forms `_, -`django-floppyforms `_ or +`django-floppyforms `_ or other alternatives. For that purpose you should override the "snippets/form_snippet.html" used @@ -2201,7 +2201,7 @@ If you have forms referring to form element- of form handler- plugins that are currently missing (not registered, removed, failed to load - thus there would be a risk that your form would't be rendered properly/fully and the necessary data handling wouldn't happen either) you will get an -appropriate exception. Although it's fine to get an instant error message about +appropriate exception. Although it's fine to get an instant error message about such failures in development, in production is wouldn't look appropriate. Thus, there are two settings related to the non-existing (not-found) form element- and form handler- plugins. @@ -4861,6 +4861,101 @@ Installation } +fobi.contrib.plugins.form_elements.content.content_richtext +----------------------------------------------------------- + +A ``Fobi`` Rich text form element plugin based on +`Summernote `_. + +Installation +~~~~~~~~~~~~ + +(1) Install ``django-summernote``. + + .. code-block:: sh + + pip install django-summernote + +(2) Add ``django_summernote`` to ``INSTALLED_APPS`` in ``settings.py``. + + .. code-block:: python + + INSTALLED_APPS = ( + ... + 'django_summernote', + ... + ) + +(3) Add ``django_summernote.urls`` to ``urls.py``. + + .. code-block:: python + + urlpatterns = [ + ... + url(r'^summernote/', include('django_summernote.urls')), + ... + ] + +(4) Add ``fobi.contrib.plugins.form_elements.content.content_richtext`` to + ``INSTALLED_APPS`` in ``settings.py``. + + .. code-block:: python + + INSTALLED_APPS = ( + ... + 'fobi.contrib.plugins.form_elements.content.content_richtext', + ... + ) + +(5) In the terminal type: + + .. code-block:: sh + + ./manage.py fobi_sync_plugins + +(6) Assign appropriate permissions to the target users/groups to be using + the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to ``True``. + +Controlling HTML tags and attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(1) Install ``bleach``. + + .. code-block:: sh + + pip install bleach + +(2) Specify ``FOBI_PLUGIN_CONTENT_RICHTEXT_ALLOWED_TAGS`` and + ``FOBI_PLUGIN_CONTENT_RICHTEXT_ALLOWED_ATTRIBUTES`` in + ``settings.py``. The default values are: + + .. code-block:: python + + FOBI_PLUGIN_CONTENT_RICHTEXT_ALLOWED_TAGS = [ + 'a', + 'abbr', + 'acronym', + 'b', + 'blockquote', + 'code', + 'em', + 'i', + 'li', + 'ol', + 'strong', + 'ul', + ] + + FOBI_PLUGIN_CONTENT_RICHTEXT_ALLOWED_ATTRIBUTES = { + 'a': ['href', 'title'], + 'abbr': ['title'], + 'acronym': ['title'], + } + +For frontend-only control one could alternatively use +a ``summernote`` plugin like ``summernote-cleaner``. + + fobi.contrib.plugins.form_elements.content.content_video -------------------------------------------------------- A ``Fobi`` Video form element plugin. @@ -6303,11 +6398,11 @@ fobi.contrib.plugins.form_elements.security.captcha --------------------------------------------------- A `CAPTCHA `_ form field plugin. Makes use of the `django-simple-captcha -`_. +`_. Prerequisites ~~~~~~~~~~~~~ -You will need ``libfreetype6``, otherwise ``django-captcha`` won't work. +You will need ``libfreetype6``, otherwise ``django-simple-captcha`` won't work. .. code-block:: sh @@ -6328,9 +6423,7 @@ Taken from django-simple-captcha `installation instructions (2) Add ``captcha`` to the ``INSTALLED_APPS`` in your ``settings.py``. -(3) Run ``python manage.py syncdb`` (or ``python manage.py migrate`` if you are - managing database migrations via South) to create the required database - tables. +(3) Run ``python manage.py migrate``. (4) Add an entry to your ``urls.py``: @@ -6370,9 +6463,7 @@ At the moment, you can't use both ``CAPTCHA`` (fobi.contrib.plugins.form_elements.security.captcha) and ``ReCAPTCHA`` (fobi.contrib.plugins.form_elements.security.recaptcha) plugins alongside due to app name collision of the ``django-simple-captcha`` and ``django-recaptcha`` -packages. That limitation is likely to be solved in future in the -``django-recaptcha`` package. Until then, you should choose either one or -another, but not both on the same time. +packages. Usage ~~~~~ @@ -6428,9 +6519,7 @@ Install `django-recaptcha` (2) Add ``captcha`` to the ``INSTALLED_APPS`` in your ``settings.py``. -(3) Run ``python manage.py syncdb`` (or ``python manage.py migrate`` if you are - managing database migrations via South) to create the required database - tables. +(3) Run ``python manage.py migrate``. Install `fobi` ReCAPTCHA plugin ############################### @@ -6454,7 +6543,7 @@ Install `fobi` ReCAPTCHA plugin (3) Assign appropriate permissions to the target users/groups to be using the plugin if ``FOBI_RESTRICT_PLUGIN_ACCESS`` is set to True. -(4) Specify the following ReCAPTCHA credentials in your settings. +(4) Specify the following ReCAPTCHA credentials in your settings: .. code-block:: text @@ -6469,13 +6558,11 @@ At the moment, you can't use both ``CAPTCHA`` (fobi.contrib.plugins.form_elements.security.captcha) and ``ReCAPTCHA`` (fobi.contrib.plugins.form_elements.security.recaptcha) plugins alongside due to app name collision of the ``django-simple-captcha`` and ``django-recaptcha`` -packages. That limitation is likely to be solved in future in the -``django-recaptcha`` package. Until then, you should choose either one or -another, but not both on the same time. +packages. If you happen to see errors like "Input error: k: Format of site key was invalid", make sure to have defined (and filled in properly) the -``RECAPTCHA_PUBLIC_KEY`` and ``RECAPTCHA_PRIVATE_KEY`` in your settnings.py. +``RECAPTCHA_PUBLIC_KEY`` and ``RECAPTCHA_PRIVATE_KEY`` in your settings.py. See the `following `_ thread for more information. diff --git a/examples/simple/settings/base.py b/examples/simple/settings/base.py index f7d437856..60a12b4bc 100644 --- a/examples/simple/settings/base.py +++ b/examples/simple/settings/base.py @@ -333,7 +333,7 @@ def gettext(s): 'fobi.contrib.plugins.form_elements.content.content_image', 'fobi.contrib.plugins.form_elements.content.content_image_url', 'fobi.contrib.plugins.form_elements.content.content_text', - 'fobi.contrib.plugins.form_elements.content.content_richtext', + # 'fobi.contrib.plugins.form_elements.content.content_richtext', 'fobi.contrib.plugins.form_elements.content.content_video', # *********************************************************************** diff --git a/setup.py b/setup.py index d85753b73..7e4123864 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from distutils.version import LooseVersion from setuptools import setup, find_packages -version = '0.12.5' +version = '0.12.6' # *************************************************************************** # ************************** Python version ********************************* diff --git a/src/fobi/__init__.py b/src/fobi/__init__.py index 597124662..b50289ca6 100644 --- a/src/fobi/__init__.py +++ b/src/fobi/__init__.py @@ -1,6 +1,6 @@ __title__ = 'django-fobi' -__version__ = '0.12.5' -__build__ = 0x00008e +__version__ = '0.12.6' +__build__ = 0x00008f __author__ = 'Artur Barseghyan ' __copyright__ = '2014-2017 Artur Barseghyan' __license__ = 'GPL 2.0/LGPL 2.1' diff --git a/src/fobi/models.py b/src/fobi/models.py index cdea0001c..1d5fb7d85 100644 --- a/src/fobi/models.py +++ b/src/fobi/models.py @@ -321,8 +321,10 @@ def get_absolute_url(self): :return string: """ - return reverse('fobi.view_form_wizard_entry', - kwargs={'slug': self.slug}) + return reverse( + 'fobi.view_form_wizard_entry', + kwargs={'form_wizard_entry_slug': self.slug} + ) @python_2_unicode_compatible diff --git a/src/fobi/tests/test_core.py b/src/fobi/tests/test_core.py index f7fb8d416..1e0af7aa9 100644 --- a/src/fobi/tests/test_core.py +++ b/src/fobi/tests/test_core.py @@ -8,7 +8,7 @@ get_registered_themes, get_registered_form_callbacks ) -from fobi.models import FormEntry +from fobi.models import FormEntry, FormWizardEntry from fobi.forms import FormEntryForm from .base import print_info @@ -117,6 +117,19 @@ def _create_form_entry(self): form_entry.save() return form_entry + def _create_form_wizard_entry(self): + """Create form wizard entry.""" + user = get_or_create_admin_user() + self.assertTrue(user is not None) + + form_wizard_entry = FormWizardEntry( + name=TEST_FORM_NAME, + slug=TEST_FORM_SLUG, + user=user + ) + form_wizard_entry.save() + return form_wizard_entry + @print_info def test_05_action_url(self): """Test `action` field of the URL.""" @@ -152,6 +165,26 @@ def test_05_action_url(self): ) self.assertTrue(not saved) + @print_info + def test_06_form_entry_get_absolute_url(self): + """Test ``get_absolute_url`` of the form entry.""" + form_entry = self._create_form_entry() + absolute_url = form_entry.get_absolute_url() + self.assertTrue( + absolute_url, + '/en/fobi/view/{}/'.format(TEST_FORM_SLUG) + ) + + @print_info + def test_07_form_wizard_entry_get_absolute_url(self): + """Test ``get_absolute_url`` of the form wizard entry.""" + form_wizard_entry = self._create_form_wizard_entry() + absolute_url = form_wizard_entry.get_absolute_url() + self.assertTrue( + absolute_url, + '/en/fobi/wizard-view/{}/'.format(TEST_FORM_SLUG) + ) + if __name__ == '__main__': unittest.main()