diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-03-19 11:05:22 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-03-19 11:05:22 +0100 |
commit | 3039fae5124c00a67283c9b707e4a411149d93b1 (patch) | |
tree | 5d7fde3628825aebeeef3d85d2dfcf09a52116de /ishtar_common/widgets.py | |
parent | b38e35ad05ae5b7d1c3d45436921f573bc9e5ba6 (diff) | |
download | Ishtar-3039fae5124c00a67283c9b707e4a411149d93b1.tar.bz2 Ishtar-3039fae5124c00a67283c9b707e4a411149d93b1.zip |
Format - black: ishtar_common
Diffstat (limited to 'ishtar_common/widgets.py')
-rw-r--r-- | ishtar_common/widgets.py | 696 |
1 files changed, 390 insertions, 306 deletions
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 67a16e4b7..8f95f4521 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -29,8 +29,10 @@ from django.core.urlresolvers import reverse, NoReverseMatch from django.db.models import fields from django.forms import ClearableFileInput from django.forms.utils import flatatt -from django.forms.widgets import CheckboxSelectMultiple as \ - CheckboxSelectMultipleBase, NumberInput +from django.forms.widgets import ( + CheckboxSelectMultiple as CheckboxSelectMultipleBase, + NumberInput, +) from django.template import loader from django.template.defaultfilters import slugify from django.utils.encoding import smart_text @@ -48,8 +50,8 @@ reverse_lazy = lazy(reverse, str) class SelectReadonly(forms.Select): - template_name = 'blocks/readonly_input.html' - option_template_name = 'blocks/readonly_input_option.html' + template_name = "blocks/readonly_input.html" + option_template_name = "blocks/readonly_input_option.html" def __init__(self, attrs=None, choices=(), model=None, available=None): super(SelectReadonly, self).__init__(attrs, choices) @@ -63,7 +65,7 @@ class SelectReadonly(forms.Select): if value: q = q.filter(pk=value) for i in q.all(): - if hasattr(self.model, 'verbose_name'): + if hasattr(self.model, "verbose_name"): label = i.verbose_name else: label = str(i) @@ -77,18 +79,27 @@ class SelectReadonly(forms.Select): class SelectReadonlyField(forms.ChoiceField): - def __init__(self, choices=(), required=True, widget=None, label=None, - initial=None, help_text='', *args, **kwargs): + def __init__( + self, + choices=(), + required=True, + widget=None, + label=None, + initial=None, + help_text="", + *args, + **kwargs + ): self.available = False self.model = None - if 'model' in kwargs: - self.model = kwargs.pop('model') - if 'available' in kwargs: - self.available = kwargs.pop('available') + if "model" in kwargs: + self.model = kwargs.pop("model") + if "available" in kwargs: + self.available = kwargs.pop("available") widget = SelectReadonly(model=self.model, available=self.available) super(SelectReadonlyField, self).__init__( - choices, required, widget, label, initial, help_text, *args, - **kwargs) + choices, required, widget, label, initial, help_text, *args, **kwargs + ) def get_q(self): q = self.model.objects @@ -106,12 +117,10 @@ class Select2Media(object): @property def media(self): media = super(Select2Media, self).media - css = { - 'all': ('select2/css/select2.css',) - } - js = ['select2/js/select2.full.min.js'] + css = {"all": ("select2/css/select2.css",)} + js = ["select2/js/select2.full.min.js"] for lang_code, lang in settings.LANGUAGES: - js.append('select2/js/i18n/{}.js'.format(lang_code)) + js.append("select2/js/i18n/{}.js".format(lang_code)) media.add_css(css) media.add_js(js) return media @@ -123,20 +132,20 @@ class Select2Dynamic(Select2Media, forms.Select): """ def render(self, name, value, attrs=None, choices=()): - choices = choices or getattr(self, 'choices', []) + choices = choices or getattr(self, "choices", []) if value and value not in [key for key, v in choices]: choices.insert(1, (value, value)) self.choices = choices - klass = attrs and attrs.get('class') or '' - klass += ' ' if klass else '' + 'js-select2' + klass = attrs and attrs.get("class") or "" + klass += " " if klass else "" + "js-select2" if not attrs: attrs = {} - attrs['class'] = klass - if 'style' not in attrs: - if attrs.get('full-width', None): - attrs['style'] = "width: calc(100% - 60px)" + attrs["class"] = klass + if "style" not in attrs: + if attrs.get("full-width", None): + attrs["style"] = "width: calc(100% - 60px)" else: - attrs['style'] = "width: 370px" + attrs["style"] = "width: 370px" options = [ "tags: true", ] @@ -149,7 +158,7 @@ class Select2Dynamic(Select2Media, forms.Select): return confirm("{}"); }}""".format(msg)) ''' - if attrs.get('full-width', None): + if attrs.get("full-width", None): options.append("containerCssClass: 'full-width'") html = super(Select2Dynamic, self).render(name, value, attrs) @@ -157,7 +166,9 @@ class Select2Dynamic(Select2Media, forms.Select): $(document).ready(function() {{ $("#id_{}").select2({{ {} }}); }});</script> - """.format(name, ", ".join(options)) + """.format( + name, ", ".join(options) + ) return mark_safe(html) @@ -170,9 +181,7 @@ class Select2DynamicField(forms.ChoiceField): used. """ if value and '"' in value: - raise ValidationError( - _("The character \" is not accepted.") - ) + raise ValidationError(_('The character " is not accepted.')) def to_python(self, value): """ @@ -182,8 +191,9 @@ class Select2DynamicField(forms.ChoiceField): class Select2Base(Select2Media): - def __init__(self, attrs=None, choices=(), remote=None, model=None, - new=None, available=None): + def __init__( + self, attrs=None, choices=(), remote=None, model=None, new=None, available=None + ): self.remote = remote self.available = available self.model = model @@ -202,35 +212,36 @@ class Select2Base(Select2Media): def render(self, name, value, attrs=None, choices=()): self.remote = str(self.remote) - if self.remote in ('None', 'false'): + if self.remote in ("None", "false"): # test on lazy object is buggy... so we have this ugly test self.remote = None if not choices: if not self.remote and self.model: choices = self.get_choices() - if hasattr(self, 'choices') and self.choices: + if hasattr(self, "choices") and self.choices: choices = self.choices new_attrs = self.attrs.copy() new_attrs.update(attrs) attrs = new_attrs - klass = attrs and attrs.get('class') or '' - klass += ' ' if klass else '' + 'js-select2' + klass = attrs and attrs.get("class") or "" + klass += " " if klass else "" + "js-select2" if not attrs: attrs = {} - attrs['class'] = klass - if 'style' not in attrs: - if attrs.get('full-width', None): - attrs['style'] = "width: calc(100% - 60px)" + attrs["class"] = klass + if "style" not in attrs: + if attrs.get("full-width", None): + attrs["style"] = "width: calc(100% - 60px)" else: - attrs['style'] = "width: 370px" + attrs["style"] = "width: 370px" if value: if type(value) not in (list, tuple): - value = value.split(',') + value = value.split(",") options = "" if self.remote: - options = """{ + options = ( + """{ ajax: { url: '%s', delay: 250, @@ -249,7 +260,9 @@ class Select2Base(Select2Media): } } } - }""" % self.remote + }""" + % self.remote + ) if value: choices = [] for v in value: @@ -258,7 +271,7 @@ class Select2Base(Select2Media): except (self.model.DoesNotExist, ValueError): # an old reference? it should not happen pass - if attrs.get('full-width', None): + if attrs.get("full-width", None): if options: options = options[:-1] + ", " else: @@ -269,14 +282,16 @@ class Select2Base(Select2Media): new, html = "", "" if self.new: html = "<div class='input-group'>" - url_new = 'new-' + self.model.SLUG + url_new = "new-" + self.model.SLUG url_new = reverse(url_new, args=["id_" + name]) # WARNING: the modal for the form must be in the main template # "extra_form_modals" list is used for that in form or view - new = """<span class="input-group-append">"""\ - """<a href="#" class="add-button input-group-text" """\ - """onclick="dt_qa_open('{}', 'modal-dynamic-form-{}');">"""\ - """+</a></span></div>""".format(url_new, self.model.SLUG) + new = ( + """<span class="input-group-append">""" + """<a href="#" class="add-button input-group-text" """ + """onclick="dt_qa_open('{}', 'modal-dynamic-form-{}');">""" + """+</a></span></div>""".format(url_new, self.model.SLUG) + ) html += super(Select2Base, self).render(name, value, attrs) html += new @@ -284,7 +299,9 @@ class Select2Base(Select2Media): $(document).ready(function() {{ $("#id_{}").select2({}); }});</script> - """.format(name, options) + """.format( + name, options + ) return mark_safe(html) @@ -302,9 +319,10 @@ class CheckboxSelectMultiple(CheckboxSelectMultipleBase): Should be corrected on recent Django version. TODO: test and remove (test case: treatment type not keep on modif) """ + def render(self, name, value, attrs=None, choices=()): if type(value) in (str, str): - value = value.split(',') + value = value.split(",") if not isinstance(value, (list, tuple)): value = [value] return super(CheckboxSelectMultiple, self).render(name, value, attrs) @@ -315,36 +333,40 @@ class Select2BaseField(object): def __init__(self, *args, **kwargs): new = None - if 'new' in kwargs: - new = kwargs.pop('new') + if "new" in kwargs: + new = kwargs.pop("new") remote = None - if 'remote' in kwargs: - remote = kwargs.pop('remote') + if "remote" in kwargs: + remote = kwargs.pop("remote") self.model, self.remote = None, None - if 'model' in kwargs: - self.model = kwargs.pop('model') + if "model" in kwargs: + self.model = kwargs.pop("model") if remote: self.remote = reverse_lazy( - 'autocomplete-' + self.model.__name__.lower()) + "autocomplete-" + self.model.__name__.lower() + ) long_widget = False - if 'long_widget' in kwargs: - long_widget = kwargs.pop('long_widget') + if "long_widget" in kwargs: + long_widget = kwargs.pop("long_widget") self.available = False - if 'available' in kwargs: - self.available = kwargs.pop('available') + if "available" in kwargs: + self.available = kwargs.pop("available") attrs = {} if long_widget: - attrs['cols'] = True - attrs['full-width'] = True + attrs["cols"] = True + attrs["full-width"] = True if self.multiple: widget = Select2Multiple else: widget = Select2Simple if kwargs.get("style", None): attrs["style"] = kwargs.pop("style") - kwargs['widget'] = widget( - model=self.model, available=self.available, remote=self.remote, - new=new, attrs=attrs + kwargs["widget"] = widget( + model=self.model, + available=self.available, + remote=self.remote, + new=new, + attrs=attrs, ) super(Select2BaseField, self).__init__(*args, **kwargs) @@ -366,7 +388,7 @@ class Select2MultipleField(Select2BaseField, forms.MultipleChoiceField): def to_python(self, value): if not isinstance(value, (list, tuple)): if value: - value = value.split(',') + value = value.split(",") else: value = [] return super(Select2MultipleField, self).to_python(value) @@ -380,8 +402,8 @@ class DeleteWidget(forms.CheckboxInput): def render(self, name, value, attrs=None, renderer=None): final_attrs = flatatt( self.build_attrs( - attrs, {"name": name, "value": '1', - 'class': "btn btn-danger"}) + attrs, {"name": name, "value": "1", "class": "btn btn-danger"} + ) ) output = "<button%s>%s</button>" % (final_attrs, _("Delete")) @@ -394,22 +416,26 @@ class SwitchWidget(forms.CheckboxInput): def render(self, name, value, attrs=None, renderer=None): extra_class = (" " + self.extra_class) if self.extra_class else "" - default = {"name": name, "value": "1", - 'class': "switch" + extra_class, - 'type': 'checkbox'} + default = { + "name": name, + "value": "1", + "class": "switch" + extra_class, + "type": "checkbox", + } if value: - default['checked'] = 'checked' - attrs = self.build_attrs( - attrs, default - ) + default["checked"] = "checked" + attrs = self.build_attrs(attrs, default) final_attrs = flatatt(attrs) extra_label = "" if self.extra_label: - extra_label = '<label for="{}">{}</label>'.format(attrs['id'], - self.extra_label) + extra_label = '<label for="{}">{}</label>'.format( + attrs["id"], self.extra_label + ) output = """<span class="switch{}"> <input{}>{} -</span>""".format(extra_class, final_attrs, extra_label) +</span>""".format( + extra_class, final_attrs, extra_label + ) return mark_safe(output) @@ -419,7 +445,7 @@ class DeleteSwitchWidget(SwitchWidget): class ImageFileInput(ClearableFileInput): - template_name = 'widgets/image_input.html' + template_name = "widgets/image_input.html" NO_FORM_CONTROL = True def format_value(self, value): @@ -427,15 +453,16 @@ class ImageFileInput(ClearableFileInput): return value # try to display posted images try: - has_file = hasattr(value, 'file') + has_file = hasattr(value, "file") except ValueError: has_file = False if has_file: - if hasattr(value, 'file'): + if hasattr(value, "file"): full_path = str(value.file) if full_path.startswith(settings.MEDIA_ROOT): - value.url = settings.MEDIA_URL + full_path[ - len(settings.MEDIA_ROOT):] + value.url = ( + settings.MEDIA_URL + full_path[len(settings.MEDIA_ROOT) :] + ) elif value: full_path = settings.MEDIA_ROOT + str(value) try: @@ -450,16 +477,15 @@ class ImageFileInput(ClearableFileInput): def get_context(self, name, value, attrs): context = super(ImageFileInput, self).get_context(name, value, attrs) - if getattr(self, 'hidden', None): - context['hidden_value'] = self.hidden + if getattr(self, "hidden", None): + context["hidden_value"] = self.hidden # on post memory file is used: display the name - if getattr(self, 'hidden_name', None): - context['hidden_name_value'] = self.hidden_name + if getattr(self, "hidden_name", None): + context["hidden_name_value"] = self.hidden_name return context def value_from_datadict(self, data, files, name): - value = super(ImageFileInput, self).value_from_datadict( - data, files, name) + value = super(ImageFileInput, self).value_from_datadict(data, files, name) hidden_name = name + "-hidden" hidden_name_value = name + "-hidden-name" self.hidden, self.hidden_name = None, None @@ -482,11 +508,12 @@ class CustomWidget(forms.TextInput): def render(self, name, value, attrs=None, renderer=None): if not value: value = "" - final_attrs = flatatt( - self.build_attrs(attrs, {"name": name, "value": value})) - dct = {'final_attrs': final_attrs, - 'id': attrs['id'], - "safe_id": attrs['id'].replace('-', '_')} + final_attrs = flatatt(self.build_attrs(attrs, {"name": name, "value": value})) + dct = { + "final_attrs": final_attrs, + "id": attrs["id"], + "safe_id": attrs["id"].replace("-", "_"), + } dct.update(self.EXTRA_DCT) t = loader.get_template(self.TEMPLATE) rendered = t.render(dct) @@ -494,33 +521,33 @@ class CustomWidget(forms.TextInput): class SquareMeterWidget(CustomWidget): - TEMPLATE = 'widgets/SquareMeterWidget.html' - EXTRA_DCT = {'unit': settings.SURFACE_UNIT_LABEL} + TEMPLATE = "widgets/SquareMeterWidget.html" + EXTRA_DCT = {"unit": settings.SURFACE_UNIT_LABEL} class GramKilogramWidget(CustomWidget): - TEMPLATE = 'widgets/GramKilogramWidget.html' - EXTRA_DCT = {'unit': "g"} + TEMPLATE = "widgets/GramKilogramWidget.html" + EXTRA_DCT = {"unit": "g"} class CentimeterMeterWidget(CustomWidget): - TEMPLATE = 'widgets/CentimeterMeterWidget.html' - EXTRA_DCT = {'unit': "cm"} + TEMPLATE = "widgets/CentimeterMeterWidget.html" + EXTRA_DCT = {"unit": "cm"} AreaWidget = forms.TextInput -if settings.SURFACE_UNIT == 'square-metre': +if settings.SURFACE_UNIT == "square-metre": AreaWidget = SquareMeterWidget class ISBNWidget(CustomWidget): - TEMPLATE = 'widgets/CheckTextWidget.html' - EXTRA_DCT = {'validator': "is_valid_isbn"} + TEMPLATE = "widgets/CheckTextWidget.html" + EXTRA_DCT = {"validator": "is_valid_isbn"} class ISSNWidget(CustomWidget): - TEMPLATE = 'widgets/CheckTextWidget.html' - EXTRA_DCT = {'validator': "is_valid_issn"} + TEMPLATE = "widgets/CheckTextWidget.html" + EXTRA_DCT = {"validator": "is_valid_issn"} class CheckboxInput(forms.CheckboxInput): @@ -528,7 +555,7 @@ class CheckboxInput(forms.CheckboxInput): class SearchWidget(forms.TextInput): - template_name = 'widgets/search_input.html' + template_name = "widgets/search_input.html" def __init__(self, app_name=None, model=None, pin_model=None, attrs=None): super(SearchWidget, self).__init__(attrs) @@ -540,9 +567,9 @@ class SearchWidget(forms.TextInput): def get_context(self, name, value, attrs): context = super(SearchWidget, self).get_context(name, value, attrs) - context['app_name'] = self.app_name - context['model'] = self.model - context['pin_model'] = self.pin_model + context["app_name"] = self.app_name + context["model"] = self.model + context["pin_model"] = self.pin_model return context @@ -560,9 +587,7 @@ class ModelFieldMixin(object): values.append(self.model.objects.get(pk=v)) except self.model.DoesNotExist: raise ValidationError( - str( - _("{} is not a valid key for {}") - ).format(v, self.model) + str(_("{} is not a valid key for {}")).format(v, self.model) ) if not self.multiple: return values[0] @@ -576,32 +601,47 @@ class ModelChoiceField(ModelFieldMixin, forms.ChoiceField): super(ModelFieldMixin, self).__init__(*args, **kwargs) def valid_value(self, value): - if value and getattr(value, 'pk', None) in [v for v, l in self.choices]: + if value and getattr(value, "pk", None) in [v for v, l in self.choices]: return True return super(ModelChoiceField, self).valid_value(value) class ModelJQueryAutocompleteField(ModelFieldMixin, forms.CharField): - def __init__(self, model, multiple=False, new=False, long_widget=False, - *args, **kwargs): + def __init__( + self, model, multiple=False, new=False, long_widget=False, *args, **kwargs + ): self.model = model self.multiple = multiple attrs = {} if long_widget: - attrs['cols'] = True - attrs['full-width'] = True - kwargs['widget'] = JQueryAutoComplete( - reverse_lazy('autocomplete-' + self.model.SLUG), - associated_model=self.model, new=new, multiple=multiple, - attrs=attrs + attrs["cols"] = True + attrs["full-width"] = True + kwargs["widget"] = JQueryAutoComplete( + reverse_lazy("autocomplete-" + self.model.SLUG), + associated_model=self.model, + new=new, + multiple=multiple, + attrs=attrs, ) super(ModelJQueryAutocompleteField, self).__init__(*args, **kwargs) class JQueryAutoComplete(forms.TextInput): - def __init__(self, source, associated_model=None, options=None, attrs=None, - new=False, url_new='', multiple=False, limit=None, - dynamic_limit=None, detail=False, modify=False, tips=""): + def __init__( + self, + source, + associated_model=None, + options=None, + attrs=None, + new=False, + url_new="", + multiple=False, + limit=None, + dynamic_limit=None, + detail=False, + modify=False, + tips="", + ): """ Source can be a list containing the autocomplete values or a string containing the url used for the request. @@ -631,7 +671,7 @@ class JQueryAutoComplete(forms.TextInput): if not self.multiple: return data.get(name, None) if type(v) == str and "," in v: - return [item.strip() for item in v.split(',') if item.strip()] + return [item.strip() for item in v.split(",") if item.strip()] return data.getlist(name, None) def render_js(self, field_id, current_pk): @@ -643,36 +683,42 @@ class JQueryAutoComplete(forms.TextInput): try: source = "'" + str(self.source) + "'" except: - raise ValueError('{} source type is not valid'.format( - self.source)) + raise ValueError("{} source type is not valid".format(self.source)) dynamic_limit = [] for lim in self.dynamic_limit: - field_ids = field_id.split('-') + field_ids = field_id.split("-") if field_ids[1:-1]: dynamic_limit.append( - 'id_' + lim.replace('_', '') + '-' + - '-'.join(field_ids[1:-1]) + '-' + lim) + "id_" + + lim.replace("_", "") + + "-" + + "-".join(field_ids[1:-1]) + + "-" + + lim + ) else: - dynamic_limit.append('id_' + lim.replace('_', '')) - - dct = {'source': mark_safe(source), - 'field_id': field_id, - 'safe_field_id': field_id.replace("-", "_"), - "modify": self.modify, - 'dynamic_limit': dynamic_limit} + dynamic_limit.append("id_" + lim.replace("_", "")) + + dct = { + "source": mark_safe(source), + "field_id": field_id, + "safe_field_id": field_id.replace("-", "_"), + "modify": self.modify, + "dynamic_limit": dynamic_limit, + } if self.associated_model: model_name = self.associated_model._meta.object_name.lower() dct["model_name"] = model_name if self.detail: model_name = self.associated_model._meta.object_name.lower() - url_detail = '/detail-{}/'.format(model_name) + url_detail = "/detail-{}/".format(model_name) dct["detail"] = url_detail if self.options: - dct['options'] = mark_safe('%s' % self.options) + dct["options"] = mark_safe("%s" % self.options) - tpl = 'blocks/JQueryAutocomplete.js' + tpl = "blocks/JQueryAutocomplete.js" if self.multiple: - tpl = 'blocks/JQueryAutocompleteMultiple.js' + tpl = "blocks/JQueryAutocompleteMultiple.js" t = loader.get_template(tpl) js = t.render(dct) return js @@ -680,19 +726,19 @@ class JQueryAutoComplete(forms.TextInput): def render(self, name, value, attrs=None, renderer=None): attrs_hidden = self.build_attrs(attrs, {"name": name}) attrs_select = self.build_attrs(attrs) - attrs_select['placeholder'] = _("Search...") + attrs_select["placeholder"] = _("Search...") values = [] if value: hiddens = [] selects = [] if type(value) not in (list, tuple): values = str(escape(smart_text(value))) - values = values.replace('[', '').replace(']', '') - values = values.split(',') + values = values.replace("[", "").replace("]", "") + values = values.split(",") else: values = [] for v in value: - values += v.split(',') + values += v.split(",") for v in values: if not v: continue @@ -700,28 +746,27 @@ class JQueryAutoComplete(forms.TextInput): selects.append(v) if self.associated_model: try: - selects[-1] = str( - self.associated_model.objects.get(pk=v)) + selects[-1] = str(self.associated_model.objects.get(pk=v)) except (self.associated_model.DoesNotExist, ValueError): selects.pop() hiddens.pop() if self.multiple: - attrs_hidden['value'] = ", ".join(hiddens) + attrs_hidden["value"] = ", ".join(hiddens) if selects: selects.append("") - attrs_select['value'] = ", ".join(selects) + attrs_select["value"] = ", ".join(selects) else: if hiddens and selects: - attrs_hidden['value'] = hiddens[0] - attrs_select['value'] = selects[0] - if 'id' not in self.attrs: - attrs_hidden['id'] = 'id_%s' % name - attrs_select['id'] = 'id_select_%s' % name - if 'class' not in attrs_select: - attrs_select['class'] = 'autocomplete' - - has_previous_value = 'value' in attrs_select and attrs_select['value'] - attrs_select['class'] += ' form-control' + attrs_hidden["value"] = hiddens[0] + attrs_select["value"] = selects[0] + if "id" not in self.attrs: + attrs_hidden["id"] = "id_%s" % name + attrs_select["id"] = "id_select_%s" % name + if "class" not in attrs_select: + attrs_select["class"] = "autocomplete" + + has_previous_value = "value" in attrs_select and attrs_select["value"] + attrs_select["class"] += " form-control" new = "" html = "" if self.tips or self.new or self.modify: @@ -740,7 +785,9 @@ class JQueryAutoComplete(forms.TextInput): <span class="add-button input-group-text"> <em id="{}-tips">{}</em> </span></span> - """.format(attrs_hidden['id'], tips) + """.format( + attrs_hidden["id"], tips + ) if self.modify: new += """ <span class="input-group-append"> @@ -748,17 +795,16 @@ class JQueryAutoComplete(forms.TextInput): onclick="{}_modify();"> <i class="fa fa-pencil"></i></a> </span>""".format( - attrs_hidden['id'], - name.replace("-", "_")) + attrs_hidden["id"], name.replace("-", "_") + ) if self.new: limits = [] for k in self.limit: - limits.append(k + "__" + "-".join( - [str(v) for v in self.limit[k]])) - args = [attrs_select['id']] + limits.append(k + "__" + "-".join([str(v) for v in self.limit[k]])) + args = [attrs_select["id"]] if limits: - args.append(';'.join(limits)) - url_new = 'new-' + model_name + args.append(";".join(limits)) + url_new = "new-" + model_name if self.url_new: url_new = self.url_new url_new = reverse(url_new, args=args) @@ -767,12 +813,16 @@ class JQueryAutoComplete(forms.TextInput): <a href="#" class="add-button input-group-text" onclick="dt_qa_open('{}', 'modal-dynamic-form-{}');">+</a> </span> - """.format(url_new, model_name, model_name) + """.format( + url_new, model_name, model_name + ) new += "</div>" detail = "" if self.detail: detail = """<div class="form-control detail-value" id="{}-detail"> - </div>""".format(attrs_hidden['id']) + </div>""".format( + attrs_hidden["id"] + ) old_value = "" if has_previous_value: @@ -790,16 +840,17 @@ class JQueryAutoComplete(forms.TextInput): </span> </div>""".format( _("Prev.:"), - attrs_hidden['id'] + "_previous_label", - attrs_select['value'], - attrs_hidden['id'] + "_previous_button", - _("Restore previous") + attrs_hidden["id"] + "_previous_label", + attrs_select["value"], + attrs_hidden["id"] + "_previous_button", + _("Restore previous"), ) attrs_hidden_previous = attrs_hidden.copy() - attrs_hidden_previous['name'] += "_previous" - attrs_hidden_previous['id'] += "_previous" + attrs_hidden_previous["name"] += "_previous" + attrs_hidden_previous["id"] += "_previous" old_value += "<input type='hidden'{}>".format( - flatatt(attrs_hidden_previous)) + flatatt(attrs_hidden_previous) + ) pk = None if values: pk = values[0] @@ -813,8 +864,9 @@ class JQueryAutoComplete(forms.TextInput): old_value=old_value, attrs_select=flatatt(attrs_select), attrs_hidden=flatatt(attrs_hidden), - js=self.render_js(name, pk), new=new, - detail=detail + js=self.render_js(name, pk), + new=new, + detail=detail, ) return html @@ -824,8 +876,7 @@ class JQueryTown(forms.TextInput): Town fields with state and department pre-selections """ - def __init__(self, source, options={}, - attrs={}, new=False, limit={}): + def __init__(self, source, options={}, attrs={}, new=False, limit={}): self.options = None self.attrs = {} self.source = source @@ -841,37 +892,37 @@ class JQueryTown(forms.TextInput): encoded_src = JSONEncoder().encode(source) elif isinstance(source, str): src = escape(source) - if not src.endswith('/'): + if not src.endswith("/"): src += "/" encoded_src = "'%s'" % src else: try: src = str(source) - if not src.endswith('/'): + if not src.endswith("/"): src += "/" encoded_src = "'%s'" % src except: - raise ValueError('source type is not valid') + raise ValueError("source type is not valid") return encoded_src def render(self, name, value, attrs=None, renderer=None): attrs_hidden = self.build_attrs(attrs, {"name": name}) attrs_select = self.build_attrs(attrs) - attrs_select['placeholder'] = _("Search...") - selected = '' - selected_state = '' - selected_department = '' + attrs_select["placeholder"] = _("Search...") + selected = "" + selected_state = "" + selected_department = "" if value: hiddens = [] selects = [] if type(value) not in (list, tuple): values = str(escape(smart_text(value))) - values = values.replace('[', '').replace(']', '') - values = values.split(',') + values = values.replace("[", "").replace("]", "") + values = values.split(",") else: values = [] for v in value: - values += v.split(',') + values += v.split(",") for v in values: if not v: continue @@ -889,31 +940,35 @@ class JQueryTown(forms.TextInput): selects.pop() hiddens.pop() if hiddens and selects: - attrs_hidden['value'] = hiddens[0] - attrs_select['value'] = selects[0] - if 'id' not in self.attrs: - attrs_hidden['id'] = 'id_%s' % name - attrs_select['id'] = 'id_select_%s' % name - if 'class' not in attrs_select: - attrs_select['class'] = 'autocomplete' + attrs_hidden["value"] = hiddens[0] + attrs_select["value"] = selects[0] + if "id" not in self.attrs: + attrs_hidden["id"] = "id_%s" % name + attrs_select["id"] = "id_select_%s" % name + if "class" not in attrs_select: + attrs_select["class"] = "autocomplete" source = self.encode_source(self.source) - dct = {'source': mark_safe(source), - 'selected': selected, - 'safe_field_id': slugify(name).replace('-', '_'), - 'field_id': name} + dct = { + "source": mark_safe(source), + "selected": selected, + "safe_field_id": slugify(name).replace("-", "_"), + "field_id": name, + } if self.options: - dct['options'] = mark_safe('%s' % self.options) - - dct.update({'attrs_select': mark_safe(flatatt(attrs_select)), - 'attrs_hidden': mark_safe(flatatt(attrs_hidden)), - 'name': name, - 'states': models.State.objects.all().order_by('label'), - 'selected_department': selected_department, - 'selected_state': selected_state} - ) - html = loader.get_template('blocks/JQueryAdvancedTown.html')\ - .render(dct) + dct["options"] = mark_safe("%s" % self.options) + + dct.update( + { + "attrs_select": mark_safe(flatatt(attrs_select)), + "attrs_hidden": mark_safe(flatatt(attrs_hidden)), + "name": name, + "states": models.State.objects.all().order_by("label"), + "selected_department": selected_department, + "selected_state": selected_state, + } + ) + html = loader.get_template("blocks/JQueryAdvancedTown.html").render(dct) return html @@ -925,10 +980,18 @@ class JQueryPersonOrganization(forms.TextInput): * create new person and new organization """ - def __init__(self, source, edit_source, model, options={}, - attrs={}, new=False, limit={}, - html_template='blocks/PersonOrganization.html', - js_template='blocks/JQueryPersonOrganization.js'): + def __init__( + self, + source, + edit_source, + model, + options={}, + attrs={}, + new=False, + limit={}, + html_template="blocks/PersonOrganization.html", + js_template="blocks/JQueryPersonOrganization.js", + ): self.options = None self.attrs = {} self.model = model @@ -946,45 +1009,46 @@ class JQueryPersonOrganization(forms.TextInput): def encode_source(cls, source): if isinstance(source, list): encoded_src = JSONEncoder().encode(source) - elif isinstance(source, str) \ - or isinstance(source, str): + elif isinstance(source, str) or isinstance(source, str): encoded_src = "'%s'" % escape(source) else: try: encoded_src = "'" + str(source) + "'" except: - raise ValueError('source type is not valid') + raise ValueError("source type is not valid") return encoded_src - def render_js(self, field_id, selected=''): + def render_js(self, field_id, selected=""): source = self.encode_source(self.source) edit_source = self.encode_source(self.edit_source) - dct = {'source': mark_safe(source), - 'edit_source': mark_safe(edit_source), - 'selected': selected, - 'safe_field_id': slugify(field_id).replace('-', '_'), - 'field_id': field_id} + dct = { + "source": mark_safe(source), + "edit_source": mark_safe(edit_source), + "selected": selected, + "safe_field_id": slugify(field_id).replace("-", "_"), + "field_id": field_id, + } if self.options: - dct['options'] = mark_safe('%s' % self.options) + dct["options"] = mark_safe("%s" % self.options) js = loader.get_template(self.js_template).render(dct) return js def render(self, name, value, attrs=None, renderer=None): - attrs_hidden = self.build_attrs(attrs, {'name': name}) + attrs_hidden = self.build_attrs(attrs, {"name": name}) attrs_select = self.build_attrs(attrs) - attrs_select['placeholder'] = _("Search...") - selected = '' + attrs_select["placeholder"] = _("Search...") + selected = "" if value: hiddens = [] selects = [] if type(value) not in (list, tuple): values = str(escape(smart_text(value))) - values = values.replace('[', '').replace(']', '') - values = values.split(',') + values = values.replace("[", "").replace("]", "") + values = values.split(",") else: values = [] for v in value: - values += v.split(',') + values += v.split(",") for v in values: if not v: continue @@ -999,29 +1063,44 @@ class JQueryPersonOrganization(forms.TextInput): selects.pop() hiddens.pop() if hiddens and selects: - attrs_hidden['value'] = hiddens[0] - attrs_select['value'] = selects[0] - if 'id' not in self.attrs: - attrs_hidden['id'] = 'id_%s' % name - attrs_select['id'] = 'id_select_%s' % name - if 'class' not in attrs_select: - attrs_select['class'] = 'autocomplete' - new = '' - dct = {'attrs_select': mark_safe(flatatt(attrs_select)), - 'attrs_hidden': mark_safe(flatatt(attrs_hidden)), - 'name': name, - 'js': self.render_js(name, selected), - 'new': mark_safe(new)} + attrs_hidden["value"] = hiddens[0] + attrs_select["value"] = selects[0] + if "id" not in self.attrs: + attrs_hidden["id"] = "id_%s" % name + attrs_select["id"] = "id_select_%s" % name + if "class" not in attrs_select: + attrs_select["class"] = "autocomplete" + new = "" + dct = { + "attrs_select": mark_safe(flatatt(attrs_select)), + "attrs_hidden": mark_safe(flatatt(attrs_hidden)), + "name": name, + "js": self.render_js(name, selected), + "new": mark_safe(new), + } html = loader.get_template(self.html_template).render(dct) return html class DataTable(Select2Media, forms.RadioSelect): - def __init__(self, source, form, associated_model, attrs=None, - table_cols='TABLE_COLS', multiple=False, multiple_cols=None, - new=False, new_message="", source_full=None, - multiple_select=False, sortname="__default__", - col_prefix='', gallery=False, map=False): + def __init__( + self, + source, + form, + associated_model, + attrs=None, + table_cols="TABLE_COLS", + multiple=False, + multiple_cols=None, + new=False, + new_message="", + source_full=None, + multiple_select=False, + sortname="__default__", + col_prefix="", + gallery=False, + map=False, + ): """ DataTable widget init. @@ -1061,14 +1140,14 @@ class DataTable(Select2Media, forms.RadioSelect): self.user = None self.gallery = gallery self.map = map - if self.col_prefix and not self.col_prefix.endswith('__'): + if self.col_prefix and not self.col_prefix.endswith("__"): self.col_prefix += "__" def get_cols(self, python=False): jq_col_names, extra_cols = [], [] col_labels = {} - slug = getattr(self.associated_model, 'SLUG', None) - if hasattr(self.associated_model, 'COL_LABELS'): + slug = getattr(self.associated_model, "SLUG", None) + if hasattr(self.associated_model, "COL_LABELS"): col_labels = self.associated_model.COL_LABELS if slug in settings.TABLE_COLS: col_labels.update(settings.TABLE_COLS[slug]) @@ -1088,24 +1167,24 @@ class DataTable(Select2Media, forms.RadioSelect): col_names = [col_names] for col_name in col_names: field = self.associated_model - keys = col_name.split('__') - if '.' in col_name: - keys = col_name.split('.') + keys = col_name.split("__") + if "." in col_name: + keys = col_name.split(".") for key in keys: - if hasattr(field, 'rel') and field.rel: + if hasattr(field, "rel") and field.rel: field = field.rel.to try: field = field._meta.get_field(key) field_verbose_name = field.verbose_name except (fields.FieldDoesNotExist, AttributeError): - if hasattr(field, key + '_lbl'): - field_verbose_name = getattr(field, key + '_lbl') + if hasattr(field, key + "_lbl"): + field_verbose_name = getattr(field, key + "_lbl") else: continue if field_name: field_name += "__" if col_name.startswith(self.col_prefix): - field_name += col_name[len(self.col_prefix):] + field_name += col_name[len(self.col_prefix) :] else: field_name += col_name field_verbose_names.append(str(field_verbose_name)) @@ -1119,27 +1198,27 @@ class DataTable(Select2Media, forms.RadioSelect): elif col_names and col_names[0] in col_labels: jq_col_names.append(str(col_labels[col_names[0]])) else: - jq_col_names.append(settings.JOINT.join( - [f for f in field_verbose_names if f])) + jq_col_names.append( + settings.JOINT.join([f for f in field_verbose_names if f]) + ) extra_cols.append(field_name) return jq_col_names, extra_cols def render(self, name, value, attrs=None, renderer=None): # t = loader.get_template('blocks/form_flex_snippet.html') - t = loader.get_template('blocks/bs_form_snippet.html') + t = loader.get_template("blocks/bs_form_snippet.html") if self.user: form = self.form(user=self.user) - if self.user.ishtaruser and \ - self.user.ishtaruser.show_field_number(): + if self.user.ishtaruser and self.user.ishtaruser.show_field_number(): form.show_field_number = True else: form = self.form() - rendered = t.render({'form': form, 'search': True}) + rendered = t.render({"form": form, "search": True}) dct = {} if self.new: model_name = self.associated_model._meta.object_name.lower() - dct['url_new'] = reverse('new-' + model_name, args=['0']) - dct['new_message'] = self.new_message + dct["url_new"] = reverse("new-" + model_name, args=["0"]) + dct["new_message"] = self.new_message col_names, extra_cols = self.get_cols() @@ -1148,53 +1227,58 @@ class DataTable(Select2Media, forms.RadioSelect): col_idx.append('"%s"' % k) col_idx = col_idx and ", ".join(col_idx) or "" - dct['encoding'] = settings.ENCODING or 'utf-8' + dct["encoding"] = settings.ENCODING or "utf-8" try: - dct['source'] = str(self.source) + dct["source"] = str(self.source) except NoReverseMatch: - logger.warning('Cannot resolve source for {} widget'.format( - self.form)) + logger.warning("Cannot resolve source for {} widget".format(self.form)) # full CSV export currently disabled - #if str(self.source_full) and str(self.source_full) != 'None': + # if str(self.source_full) and str(self.source_full) != 'None': # dct['source_full'] = str(self.source_full) - dct['extra_sources'] = [] - dct['quick_actions'] = [] + dct["extra_sources"] = [] + dct["quick_actions"] = [] if self.associated_model: - dct['current_model'] = self.associated_model + dct["current_model"] = self.associated_model model_name = "{}.{}".format( - self.associated_model.__module__, - self.associated_model.__name__) + self.associated_model.__module__, self.associated_model.__name__ + ) for imp in models.ImporterType.objects.filter( - slug__isnull=False, associated_models__klass=model_name, - is_template=True).all(): - dct['extra_sources'].append(( - imp.slug, imp.name, - reverse('get-by-importer', args=[imp.slug]))) + slug__isnull=False, + associated_models__klass=model_name, + is_template=True, + ).all(): + dct["extra_sources"].append( + (imp.slug, imp.name, reverse("get-by-importer", args=[imp.slug])) + ) if hasattr(self.associated_model, "QUICK_ACTIONS"): - dct['quick_actions'] = \ - self.associated_model.get_quick_actions(user=self.user) + dct["quick_actions"] = self.associated_model.get_quick_actions( + user=self.user + ) source = str(self.source) - dct.update({'name': name, - 'col_names': col_names, - 'extra_cols': extra_cols, - 'source': source, - 'col_idx': col_idx, - 'no_result': str(_("No results")), - 'loading': str(_("Loading...")), - 'remove': str(_("Remove")), - 'sname': name.replace('-', ''), - 'gallery': self.gallery, - 'use_map': self.map() if callable(self.map) else self.map, - 'multiple': self.multiple, - 'multiple_select': self.multiple_select, - 'multi_cols': ",".join(('"%d"' % col - for col in self.multiple_cols))}) - t = loader.get_template('blocks/DataTables.html') + dct.update( + { + "name": name, + "col_names": col_names, + "extra_cols": extra_cols, + "source": source, + "col_idx": col_idx, + "no_result": str(_("No results")), + "loading": str(_("Loading...")), + "remove": str(_("Remove")), + "sname": name.replace("-", ""), + "gallery": self.gallery, + "use_map": self.map() if callable(self.map) else self.map, + "multiple": self.multiple, + "multiple_select": self.multiple_select, + "multi_cols": ",".join(('"%d"' % col for col in self.multiple_cols)), + } + ) + t = loader.get_template("blocks/DataTables.html") rendered += t.render(dct) return mark_safe(rendered) class RangeInput(NumberInput): - input_type = 'range' + input_type = "range" |