Add FilteredSelectionForm class

Use FilteredSelectionForm to reduce boilerplate code for
TagMultipleSelectionForm.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2019-04-14 16:53:58 -04:00
parent 5127712711
commit 6411433b24
9 changed files with 94 additions and 40 deletions
+2
View File
@@ -55,6 +55,8 @@
* Reduce form boilerplate code with new FormOptions class.
* Use FormOptions for the DetailForm class.
* DetailForm now support help text on extra fields.
* Add FilteredSelectionForm class.
* Use FilteredSelectionForm for TagMultipleSelectionForm.
3.1.11 (2019-04-XX)
===================
+2
View File
@@ -79,6 +79,8 @@ Other changes
* Reduce form boilerplate code with new FormOptions class.
* Use FormOptions for the DetailForm class.
* DetailForm now support help text on extra fields.
* Add FilteredSelectionForm class.
* Use FilteredSelectionForm for TagMultipleSelectionForm.
Removals
--------
+71 -1
View File
@@ -6,11 +6,13 @@ from django import forms
from django.conf import settings
from django.contrib.admin.utils import label_for_field
from django.contrib.auth import get_user_model
from django.core.exceptions import FieldDoesNotExist
from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
from django.db import models
from django.utils.module_loading import import_string
from django.utils.translation import ugettext_lazy as _
from mayan.apps.acls.models import AccessControlList
from .classes import Package
from .models import UserLocaleProfile
from .utils import introspect_attribute, resolve_attribute
@@ -198,6 +200,74 @@ class FileDisplayForm(forms.Form):
self.fields['text'].initial = file_object.read()
class FilteredSelectionFormOptions(FormOptions):
# Dictionary list of option names and default values
option_definitions = {
'allow_multiple': False,
'field_name': None,
'help_text': None,
'label': None,
'model': None,
'permission': None,
'queryset': None,
'required': True,
'user': None,
'widget_class': None,
'widget_attributes': {'size': '10'},
}
class FilteredSelectionForm(forms.Form):
"""
Form to select the from a list of choice filtered by access. Can be
configure to allow single or multiple selection.
"""
def __init__(self, *args, **kwargs):
opts = FilteredSelectionFormOptions(
form=self, kwargs=kwargs, options=getattr(self, 'Meta', None)
)
if opts.queryset is None:
if not opts.model:
raise ImproperlyConfigured(
'{} requires a queryset or a model to be specified as '
'a meta option or passed during initialization.'.format(
self.__class__.__name__
)
)
queryset = opts.model.objects.all()
else:
queryset = opts.queryset
if opts.allow_multiple:
extra_kwargs = {}
field_class = forms.ModelMultipleChoiceField
widget_class = forms.widgets.SelectMultiple
else:
extra_kwargs = {'empty_label': None}
field_class = forms.ModelChoiceField
widget_class = forms.widgets.Select
if opts.widget_class:
widget_class = opts.widget_class
if opts.permission:
queryset = AccessControlList.objects.filter_by_access(
permission=opts.permission, queryset=queryset,
user=opts.user
)
super(FilteredSelectionForm, self).__init__(*args, **kwargs)
self.fields[opts.field_name] = field_class(
help_text=opts.help_text, label=opts.label,
queryset=queryset, required=opts.required,
widget=widget_class(attrs=opts.widget_attributes),
**extra_kwargs
)
class LicenseForm(FileDisplayForm):
DIRECTORY = ()
FILENAME = 'LICENSE'
+9 -29
View File
@@ -1,40 +1,20 @@
from __future__ import absolute_import, unicode_literals
import logging
from django import forms
from django.utils.translation import ugettext_lazy as _
from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.forms import FilteredSelectionForm
from .models import Tag
from .permissions import permission_tag_view
from .widgets import TagFormWidget
logger = logging.getLogger(__name__)
class TagMultipleSelectionForm(forms.Form):
class TagMultipleSelectionForm(FilteredSelectionForm):
class Media:
js = ('tags/js/tags_form.js',)
def __init__(self, *args, **kwargs):
help_text = kwargs.pop('help_text', None)
permission = kwargs.pop('permission', permission_tag_view)
queryset = kwargs.pop('queryset', Tag.objects.all())
user = kwargs.pop('user', None)
logger.debug('user: %s', user)
super(TagMultipleSelectionForm, self).__init__(*args, **kwargs)
queryset = AccessControlList.objects.filter_by_access(
permission=permission, queryset=queryset, user=user
)
self.fields['tags'] = forms.ModelMultipleChoiceField(
label=_('Tags'), help_text=help_text,
queryset=queryset, required=False,
widget=TagFormWidget(
attrs={'class': 'select2-tags'}, queryset=queryset
)
)
class Meta:
allow_multiple = True
field_name = 'tags'
label = _('Tags')
required = False
widget_class = TagFormWidget
widget_attributes = {'class': 'select2-tags'}
@@ -1,2 +0,0 @@
{% include 'django/forms/widgets/select_option.html' %}
+2
View File
@@ -69,6 +69,7 @@ class TagAttachActionView(MultipleObjectFormActionView):
result = {
'help_text': _('Tags to be attached.'),
'permission': permission_tag_attach,
'queryset': Tag.objects.all(),
'user': self.request.user
}
@@ -311,6 +312,7 @@ class TagRemoveActionView(MultipleObjectFormActionView):
result = {
'help_text': _('Tags to be removed.'),
'permission': permission_tag_remove,
'queryset': Tag.objects.all(),
'user': self.request.user
}
+4 -6
View File
@@ -10,19 +10,17 @@ from .permissions import permission_tag_view
class TagFormWidget(forms.SelectMultiple):
option_template_name = 'tags/forms/widgets/tag_select_option.html'
def __init__(self, *args, **kwargs):
self.queryset = kwargs.pop('queryset')
return super(TagFormWidget, self).__init__(*args, **kwargs)
def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
result = super(TagFormWidget, self).create_option(
name=name, value=value, label='{}'.format(conditional_escape(label)),
selected=selected, index=index, subindex=subindex, attrs=attrs
attrs=attrs, index=index,
label='{}'.format(conditional_escape(label)), name=name,
selected=selected, subindex=subindex, value=value
)
result['attrs']['data-color'] = self.queryset.get(pk=value).color
result['attrs']['data-color'] = self.choices.queryset.get(pk=value).color
return result
+4
View File
@@ -9,6 +9,8 @@ from django.utils.translation import ugettext_lazy as _
from mayan.apps.sources.wizards import WizardStep
from .forms import TagMultipleSelectionForm
from .models import Tag
from .permissions import permission_tag_attach
class WizardStepTags(WizardStep):
@@ -26,6 +28,8 @@ class WizardStepTags(WizardStep):
def get_form_kwargs(self, wizard):
return {
'help_text': _('Tags to be attached.'),
'model': Tag,
'permission': permission_tag_attach,
'user': wizard.request.user
}
-2
View File
@@ -28,7 +28,6 @@ class AttachTagAction(WorkflowAction):
'tags': {
'class': 'tags.widgets.TagFormWidget', 'kwargs': {
'attrs': {'class': 'select2-tags'},
'queryset': Tag.objects.none()
}
}
}
@@ -43,7 +42,6 @@ class AttachTagAction(WorkflowAction):
)
self.fields['tags']['kwargs']['queryset'] = queryset
self.widgets['tags']['kwargs']['queryset'] = queryset
return {
'fields': self.fields,