From 7f852e51eab1ec56a3efeea3b8a22436db51173c Mon Sep 17 00:00:00 2001 From: Artur Barseghyan Date: Sun, 11 Sep 2016 22:50:34 +0200 Subject: [PATCH] prepare 0.6.10; Moved field choices from model level to form level for --- CHANGELOG.rst | 12 +- README.rst | 12 +- examples/simple/settings.py | 2 +- src/fobi/admin.py | 84 ++++++++------ src/fobi/forms.py | 108 +++++++++++++----- .../migrations/0006_auto_20160911_1549.py | 25 ++++ src/fobi/models.py | 12 +- 7 files changed, 170 insertions(+), 85 deletions(-) create mode 100644 src/fobi/migrations/0006_auto_20160911_1549.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8891d72b..af01340d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,14 +15,20 @@ are used for versioning (schema follows below): 0.3.4 to 0.4). - All backwards incompatible changes are mentioned in this document. +0.6.10 +------ +2016-09-11 + +- Moved `plugin_uid` field choices from model level to form level for + `FormHandler` and `FormHandlerEntry` models. #37 0.6.9 ----- 2016-09-08 -- Fixed changing order of the `FormElement`, `FormElementEntry`, `FormHandler` - and `FormHandlerEntry` models. #37 -- Fixed element "name" field strips underscores issue. #33 +- Moved `plugin_uid` field choices from model level to form level for + `FormElement` and `FormElementEntry` models. #37 +- Fixed element "name" field stripping underscores issue. #33 0.6.8 ----- diff --git a/README.rst b/README.rst index a6de8353..13557ea7 100644 --- a/README.rst +++ b/README.rst @@ -10,15 +10,9 @@ handling the submitted form data). Prerequisites ============= -- Django 1.5, 1.6, 1.7, 1.8 +- Django 1.5, 1.6, 1.7, 1.8, 1.9 - Python >= 2.6.8, >= 2.7, >= 3.3 -Note, that Django 1.9 is not yet proclaimed to be flawlessly supported, however -it's in progress. The latest core and contrib packages (from master branch, -with no additional dependencies) have been tested against the latest stable -Django 1.9 release. All tests have successfully passed, although it's yet too -early to claim that Django 1.9 is fully supported. - Key concepts ============ - Each form consists of elements. Form elements are divided into two groups: @@ -586,7 +580,7 @@ example the ``db_store`` form handler isn't), while others are (``mail``, You should see a form handler as a Django micro app, which could have its' own models, admin interface, etc. -By default, it's possible to use a form handler plugin multiple time per form. +By default, it's possible to use a form handler plugin multiple times per form. If you wish to allow form handler plugin to be used only once in a form, set the ``allow_multiple`` property of the plugin to False. @@ -1491,7 +1485,7 @@ There are several management commands available. Tuning ====== -There are number of Dash settings you can override in the settings module of +There are number of `fobi` settings you can override in the settings module of your Django project: - `FOBI_RESTRICT_PLUGIN_ACCESS` (bool): If set to True, (Django) permission diff --git a/examples/simple/settings.py b/examples/simple/settings.py index 94db55d6..2da5e3d9 100644 --- a/examples/simple/settings.py +++ b/examples/simple/settings.py @@ -275,7 +275,7 @@ INSTALLED_APPS = [ # *********************************************************************** # *********************************************************************** 'fobi.contrib.plugins.form_handlers.db_store', - 'fobi.contrib.plugins.form_handlers.http_repost', + #'fobi.contrib.plugins.form_handlers.http_repost', 'fobi.contrib.plugins.form_handlers.mail', # *********************************************************************** diff --git a/src/fobi/admin.py b/src/fobi/admin.py index 3188e5c9..b0870905 100644 --- a/src/fobi/admin.py +++ b/src/fobi/admin.py @@ -1,8 +1,3 @@ -__title__ = 'fobi.admin' -__author__ = 'Artur Barseghyan ' -__copyright__ = 'Copyright (c) 2014 Artur Barseghyan' -__license__ = 'GPL 2.0/LGPL 2.1' - from django.contrib import admin from django.contrib.admin import helpers from django.utils.translation import ugettext_lazy as _ @@ -21,10 +16,17 @@ from fobi.models import ( #FormWizardEntry, FormFieldsetEntry, ) from fobi.forms import ( - BulkChangeFormElementPluginsForm, BulkChangeFormHandlerPluginsForm + BulkChangeFormElementPluginsForm, BulkChangeFormHandlerPluginsForm, + FormElementEntryForm, FormHandlerEntryForm ) from fobi.constants import ACTION_CHOICE_REPLACE +__title__ = 'fobi.admin' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' + + staff_member_required_m = method_decorator(staff_member_required) # ***************************************************************************** @@ -33,11 +35,11 @@ staff_member_required_m = method_decorator(staff_member_required) # ***************************************************************************** # ***************************************************************************** + def base_bulk_change_plugins(PluginForm, named_url, modeladmin, request, \ queryset): - """ - Bulk change of plugins action additional view. - """ + """Bulk change of plugins action additional view.""" + opts = modeladmin.model._meta app_label = opts.app_label @@ -67,7 +69,9 @@ def base_bulk_change_plugins(PluginForm, named_url, modeladmin, request, \ context_instance = RequestContext(request) ) + def bulk_change_form_element_plugins(modeladmin, request, queryset): + """Bulk change FormElement plugins.""" return base_bulk_change_plugins( BulkChangeFormElementPluginsForm, 'admin:bulk_change_form_element_plugins', @@ -76,7 +80,9 @@ def bulk_change_form_element_plugins(modeladmin, request, queryset): queryset ) + def bulk_change_form_handler_plugins(modeladmin, request, queryset): + """Bulk change FormHandler plugins.""" return base_bulk_change_plugins( BulkChangeFormHandlerPluginsForm, 'admin:bulk_change_form_handler_plugins', @@ -95,28 +101,28 @@ def bulk_change_form_handler_plugins(modeladmin, request, queryset): # ******************************* Form entry admin **************************** # ***************************************************************************** + class FormElementEntryInlineAdmin(admin.TabularInline): - """ - Form element entry. - """ + """FormElementEntry inline admin.""" + model = FormElementEntry + form = FormElementEntryForm fields = ('form_entry', 'plugin_uid', 'plugin_data', 'position',) extra = 0 class FormHandlerEntryInlineAdmin(admin.TabularInline): - """ - Form element entry. - """ + """FormHandlerEntry inline admin.""" + model = FormHandlerEntry + form = FormHandlerEntryForm fields = ('form_entry', 'plugin_uid', 'plugin_data',) extra = 0 class FormEntryAdmin(admin.ModelAdmin): - """ - Form entry admin. - """ + """FormEntry admin.""" + list_display = ('name', 'slug', 'user', 'is_public', 'created', 'updated', 'is_cloneable',) list_editable = ('is_public', 'is_cloneable',) list_filter = ('is_public', 'is_cloneable',) @@ -155,10 +161,10 @@ admin.site.register(FormEntry, FormEntryAdmin) # ************************* Form fieldset entry admin ************************* # ***************************************************************************** + class FormFieldsetEntryAdmin(admin.ModelAdmin): - """ - Form fieldset entry admin. - """ + """FormEieldsetEntry admin.""" + list_display = ('form_entry', 'name', 'is_repeatable') list_editable = ('is_repeatable',) list_filter = ('is_repeatable',) @@ -180,9 +186,8 @@ class FormFieldsetEntryAdmin(admin.ModelAdmin): # ***************************************************************************** class FormElementEntryAdmin(admin.ModelAdmin): - """ - Form element entry admin. - """ + """FormElementEntry admin.""" + list_display = ('plugin_uid', 'plugin_uid_code', 'plugin_data', 'position', 'form_entry',) list_filter = ('form_entry', 'plugin_uid') @@ -220,9 +225,8 @@ class FormElementEntryAdmin(admin.ModelAdmin): # ***************************************************************************** class FormHandlerEntryAdmin(admin.ModelAdmin): - """ - Form handler entry admin. - """ + """FormHandlerEntry admin.""" + list_display = ('plugin_uid', 'plugin_uid_code', 'plugin_data', 'form_entry',) list_filter = ('form_entry', 'plugin_uid') @@ -263,10 +267,10 @@ class FormHandlerEntryAdmin(admin.ModelAdmin): # ********************************** Abstract ********************************* # ***************************************************************************** + class BasePluginModelAdmin(admin.ModelAdmin): - """ - Base plugin admin. - """ + """Base plugin admin.""" + list_display = ('plugin_uid_admin', 'users_list', 'groups_list') readonly_fields = ('plugin_uid', 'plugin_uid_admin') fieldsets = ( @@ -280,7 +284,8 @@ class BasePluginModelAdmin(admin.ModelAdmin): app_label = _('Fobi') def has_add_permission(self, request): - """ + """Has add permissions. + We don't want to allow to add form elements/handlers manually. It should happen using the management command ``fobi_sync_plugins`` instead. @@ -288,6 +293,7 @@ class BasePluginModelAdmin(admin.ModelAdmin): return False def __queryset(self, request): + """Internal method used in get_queryset or queryset methods.""" if DJANGO_LTE_1_5: queryset = super(BasePluginModelAdmin, self).queryset(request) else: @@ -300,17 +306,21 @@ class BasePluginModelAdmin(admin.ModelAdmin): queryset = __queryset def _get_bulk_change_form_class(self): + """Get change form class for bulk actions.""" raise NotImplemented("You should implement `get_bulk_change_form_class`") def _get_model(self): + """Get model.""" raise NotImplemented("You should implement `_get_model`") def _get_changelist_named_url(self): + """Get changelist named URL.""" raise NotImplemented("You should implement `_get_changelist_named_url`") @staff_member_required_m def bulk_change_plugins(self, request): - """ + """Bulk change plugins. + This is where the data is actually processed. """ changelist_named_url = self._get_changelist_named_url() @@ -374,9 +384,10 @@ class BasePluginModelAdmin(admin.ModelAdmin): # ********************************** Form element ***************************** # ***************************************************************************** + class FormElementAdmin(BasePluginModelAdmin): - """ - """ + """FormElement admin.""" + actions = [bulk_change_form_element_plugins,] def _get_bulk_change_form_class(self): @@ -403,9 +414,10 @@ admin.site.register(FormElement, FormElementAdmin) # *********************************** Form handler **************************** # ***************************************************************************** + class FormHandlerAdmin(BasePluginModelAdmin): - """ - """ + """FormHandler admin.""" + actions = [bulk_change_form_handler_plugins,] def _get_bulk_change_form_class(self): diff --git a/src/fobi/forms.py b/src/fobi/forms.py index 5d823c35..c2c36bb4 100644 --- a/src/fobi/forms.py +++ b/src/fobi/forms.py @@ -1,15 +1,6 @@ -__title__ = 'fobi.forms' -__author__ = 'Artur Barseghyan ' -__copyright__ = 'Copyright (c) 2014 Artur Barseghyan' -__license__ = 'GPL 2.0/LGPL 2.1' -__all__ = ( - 'FormEntryForm', 'FormFieldsetEntryForm', 'FormElementEntryFormSet', - 'BulkChangeFormElementPluginsForm', 'BulkChangeFormHandlerPluginsForm', - 'ImportFormEntryForm', -) +import socket from six.moves.urllib.parse import urlparse -import socket from django.forms.models import modelformset_factory from django import forms @@ -19,29 +10,45 @@ from fobi.models import ( FormElement, FormHandler, # Entries - FormEntry, FormFieldsetEntry, FormElementEntry + FormEntry, FormFieldsetEntry, FormElementEntry, FormHandlerEntry ) from fobi.constants import ACTION_CHOICES -from fobi.base import get_theme, get_registered_form_element_plugins +from fobi.base import ( + get_theme, get_registered_form_element_plugins, + get_registered_form_handler_plugins +) from fobi.validators import url_exists from fobi.exceptions import ImproperlyConfigured +__title__ = 'fobi.forms' +__author__ = 'Artur Barseghyan ' +__copyright__ = '2014-2016 Artur Barseghyan' +__license__ = 'GPL 2.0/LGPL 2.1' +__all__ = ( + 'FormEntryForm', 'FormFieldsetEntryForm', 'FormElementEntryFormSet', + 'BulkChangeFormElementPluginsForm', 'BulkChangeFormHandlerPluginsForm', + 'ImportFormEntryForm', 'FormHandlerForm', 'FormHandlerEntryForm' +) + # ***************************************************************************** # ***************************************************************************** # ******************************* Entry forms ********************************* # ***************************************************************************** # ***************************************************************************** + class FormEntryForm(forms.ModelForm): - """ - Form for ``fobi.models.FormEntry`` model. - """ + """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', + '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( @@ -79,8 +86,9 @@ class FormEntryForm(forms.ModelForm): # ) def clean_action(self): - """ - Validate the action (URL). Checks if URL exists. + """Validate the action (URL). + + Checks if URL exists. """ url = self.cleaned_data['action'] if url: @@ -117,14 +125,16 @@ class FormEntryForm(forms.ModelForm): class FormFieldsetEntryForm(forms.ModelForm): - """ - Form for ``fobi.models.FormFieldsetEntry`` model. - """ + """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( @@ -157,12 +167,41 @@ class FormElementEntryForm(forms.ModelForm): """Meta class.""" model = FormElementEntry - fields = ('form_entry', 'plugin_data', 'plugin_uid') + fields = ('form_entry', 'plugin_data', 'plugin_uid', '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', 'plugin_uid') + + +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') + # ***************************************************************************** # ***************************************************************************** # *********************************** Base ************************************ @@ -171,8 +210,7 @@ FormElementEntryFormSet = modelformset_factory( class BaseBulkChangePluginsForm(forms.ModelForm): - """ - Bulk change plugins form. + """Bulk change plugins form. - `selected_plugins` (str): List of comma separated values to be changed. @@ -181,6 +219,7 @@ class BaseBulkChangePluginsForm(forms.ModelForm): - `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 @@ -201,28 +240,35 @@ class BaseBulkChangePluginsForm(forms.ModelForm): ) 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',] @@ -232,10 +278,10 @@ class BulkChangeFormHandlerPluginsForm(BaseBulkChangePluginsForm): # ***************************************************************************** # ***************************************************************************** + class ImportFormEntryForm(forms.Form): - """ - Import form entry form. - """ + """Import form entry form.""" + file = forms.FileField(required=True, label=_("File")) # ignore_broken_form_element_entries = forms.BooleanField( # required=False, diff --git a/src/fobi/migrations/0006_auto_20160911_1549.py b/src/fobi/migrations/0006_auto_20160911_1549.py new file mode 100644 index 00000000..c961dee7 --- /dev/null +++ b/src/fobi/migrations/0006_auto_20160911_1549.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-09-11 20:49 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fobi', '0005_auto_20160908_1457'), + ] + + operations = [ + migrations.AlterField( + model_name='formhandler', + name='plugin_uid', + field=models.CharField(editable=False, max_length=255, unique=True, verbose_name='Plugin UID'), + ), + migrations.AlterField( + model_name='formhandlerentry', + name='plugin_uid', + field=models.CharField(max_length=255, verbose_name='Plugin name'), + ), + ] diff --git a/src/fobi/models.py b/src/fobi/models.py index e575a4c6..592ce443 100644 --- a/src/fobi/models.py +++ b/src/fobi/models.py @@ -160,7 +160,7 @@ class FormElement(AbstractPluginModel): """ plugin_uid = models.CharField( _("Plugin UID"), max_length=255, unique=True, editable=False, - #choices=get_registered_form_element_plugins() + # choices=get_registered_form_element_plugins() ) #objects = FormFieldPluginModelManager() @@ -191,7 +191,7 @@ class FormHandler(AbstractPluginModel): """ plugin_uid = models.CharField( _("Plugin UID"), max_length=255, unique=True, editable=False, - choices=get_registered_form_handler_plugins() + # choices=get_registered_form_handler_plugins() ) #objects = FormHandlerPluginModelManager() @@ -451,7 +451,7 @@ class FormElementEntry(AbstractPluginEntry): """ plugin_uid = models.CharField( _("Plugin name"), max_length=255, - #choices=get_registered_form_element_plugins() + # choices=get_registered_form_element_plugins() ) form_fieldset_entry = models.ForeignKey(FormFieldsetEntry, verbose_name=_("Form fieldset"), @@ -485,8 +485,10 @@ class FormHandlerEntry(AbstractPluginEntry): - `plugin_uid` (str): Plugin UID. - `plugin_data` (str): JSON formatted string with plugin data. """ - plugin_uid = models.CharField(_("Plugin name"), max_length=255, - choices=get_registered_form_handler_plugins()) + plugin_uid = models.CharField( + _("Plugin name"), max_length=255, + # choices=get_registered_form_handler_plugins() + ) class Meta: abstract = False