prepare 0.6.10; Moved field choices from model level to form level for

This commit is contained in:
Artur Barseghyan 2016-09-11 22:50:34 +02:00
parent abf6608f46
commit 7f852e51ea
7 changed files with 170 additions and 85 deletions

View file

@ -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
-----

View file

@ -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

View file

@ -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',
# ***********************************************************************

View file

@ -1,8 +1,3 @@
__title__ = 'fobi.admin'
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
__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 <artur.barseghyan@gmail.com>'
__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):

View file

@ -1,15 +1,6 @@
__title__ = 'fobi.forms'
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
__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 <artur.barseghyan@gmail.com>'
__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,

View file

@ -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'),
),
]

View file

@ -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