Remove the dependency of floppyforms

django-floppyforms is not very well supported anymore
and was dropped from Ubuntu in Xenial.

Closes-bug: #1805193
Change-Id: I46bf2d43794a67a4dc080afa9f1740a582cb7631
This commit is contained in:
zhurong 2019-02-26 15:47:27 +08:00
parent 2afddfb50e
commit dc0bc45713
4 changed files with 130 additions and 5 deletions

View File

@ -20,7 +20,6 @@ Django==1.11
django-appconf==1.0.2
django-babel==0.6.2
django-compressor==2.0
django-floppyforms==1.7.0
django-formtools==2.0
django-pyscss==2.0.2
docutils==0.14

View File

@ -25,6 +25,8 @@ import pytz
import six
import yaql
from django.template import Context
from horizon.utils import functions as utils
# WrappingColumn is only available in N-horizon
@ -35,6 +37,18 @@ except ImportError:
from horizon.tables import Column as Column # noqa
REQUIRED_CONTEXT_ATTRIBTUES = (
'_form_config',
'_form_render',
)
# We need a custom subclass of dict here in order to allow setting attributes
# on it like _form_config and _form_render.
class DictContext(dict):
pass
def parse_api_error(api_error_html):
error_html = bs4.BeautifulSoup(api_error_html, "html.parser")
body = error_html.find('body')
@ -131,3 +145,24 @@ class CustomUnpickler(object):
return yaql_expression.YAQL
else:
raise pickle.UnpicklingError('Invalid persistent id')
def flatten_context(context):
if isinstance(context, Context):
flat = {}
for d in context.dicts:
flat.update(d)
return flat
else:
return context
def flatten_contexts(*contexts):
new_context = DictContext()
for context in contexts:
if context is not None:
new_context.update(flatten_context(context))
for attr in REQUIRED_CONTEXT_ATTRIBTUES:
if hasattr(context, attr):
setattr(new_context, attr, getattr(context, attr))
return new_context

View File

@ -14,10 +14,103 @@
import itertools as it
import floppyforms as floppy
from django import forms
from django.template import loader
from django.utils.encoding import force_text
from django.utils import formats
from muranodashboard.common import utils
class TriStateCheckboxSelectMultiple(floppy.widgets.Input):
# Widge and Input code is copied from https://github.com/gregmuellegger/
# django-floppyforms/blob/master/floppyforms/widgets.py to remove the
# dependency of django-floppyforms due to not very well supported anymore
# and was dropped from Ubuntu in Xenial.
class Widget(forms.Widget):
is_required = False
# Backported from Django 1.7
@property
def is_hidden(self):
return self.input_type == 'hidden' \
if hasattr(self, 'input_type') else False
# Backported from Django 1.9
if not hasattr(forms.Widget, 'format_value'):
def format_value(self, value):
return self._format_value(value)
class Input(Widget):
template_name = 'common/tri_state_checkbox/base.html'
input_type = None
datalist = None
def __init__(self, *args, **kwargs):
datalist = kwargs.pop('datalist', None)
if datalist is not None:
self.datalist = datalist
template_name = kwargs.pop('template_name', None)
if template_name is not None:
self.template_name = template_name
super(Input, self).__init__(*args, **kwargs)
# This attribute is used to inject a surrounding context in the
# floppyforms templatetags, when rendered inside a complete form.
self.context_instance = None
def get_context_data(self):
return {}
def _format_value(self, value):
if self.is_localized:
value = formats.localize_input(value)
return force_text(value)
def get_context(self, name, value, attrs=None):
context = {
'type': self.input_type,
'name': name,
'hidden': self.is_hidden,
'required': self.is_required,
'True': True,
}
# True is injected in the context to allow stricter comparisons
# for widget attrs. See #25.
if self.is_hidden:
context['hidden'] = True
if value is None:
value = ''
if value != '':
# Only add the value if it is non-empty
context['value'] = self.format_value(value)
context.update(self.get_context_data())
context['attrs'] = self.build_attrs(attrs)
for key, attr in context['attrs'].items():
if attr == 1:
# 1 == True so 'key="1"' will show up only as 'key'
# Casting to a string so that it doesn't equal to True
# See #25.
if not isinstance(attr, bool):
context['attrs'][key] = str(attr)
if self.datalist is not None:
context['datalist'] = self.datalist
return context
def render(self, name, value, attrs=None, **kwargs):
template_name = kwargs.pop('template_name', None)
if template_name is None:
template_name = self.template_name
context = self.get_context(name, value, attrs=attrs or {})
context = utils.flatten_contexts(self.context_instance, context)
return loader.render_to_string(template_name, context)
class TriStateCheckboxSelectMultiple(Input):
"""Renders tri-state multi-selectable checkbox.
.. note:: Subclassed from ``CheckboxSelectMultiple`` and not from
@ -28,7 +121,6 @@ class TriStateCheckboxSelectMultiple(floppy.widgets.Input):
Otherwise template ``horizon/common/_form_field.html`` would render
this widget slightly incorrectly.
"""
template_name = 'common/tri_state_checkbox/base.html'
VALUES_MAP = {
'True': True,

View File

@ -12,7 +12,6 @@ pytz>=2013.6 # MIT
PyYAML>=3.12 # MIT
yaql>=1.1.3 # Apache 2.0 License
castellan>=0.18.0 # Apache-2.0
django-floppyforms>=1.7.0,<2 # BSD
oslo.log>=3.36.0 # Apache-2.0
semantic-version>=2.3.1 # BSD