Passed
Pull Request — master (#1)
by
unknown
02:19
created

AdminLocalizedFieldWidget.render()   D

Complexity

Conditions 8

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 62.8719

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 8
c 1
b 0
f 1
dl 0
loc 27
rs 4
ccs 1
cts 20
cp 0.05
crap 62.8719
1 1
from typing import List
2
3 1
from django import forms
4 1
from django.conf import settings
5 1
from django.forms import MultiWidget
6 1
from django.contrib.admin import widgets
7 1
from django.template.loader import render_to_string
8
9 1
from .fields.localized_value import LocalizedValue
10
11
12 1
class LocalizedFieldWidget(MultiWidget):
13
    """Widget that has an input box for every language."""
14 1
    widget = forms.Textarea
15
16 1
    def __init__(self, *args, **kwargs):
17
        """Initializes a new instance of :see:LocalizedFieldWidget."""
18
19 1
        widgets = []
0 ignored issues
show
Comprehensibility Bug introduced by
widgets is re-defining a name which is already available in the outer-scope (previously defined on line 6).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
20
21 1
        for _ in settings.LANGUAGES:
22 1
            widgets.append(self.widget)
23
24 1
        super(LocalizedFieldWidget, self).__init__(widgets, *args, **kwargs)
25
26 1
    def decompress(self, value: LocalizedValue) -> List[str]:
27
        """Decompresses the specified value so
28
        it can be spread over the internal widgets.
29
30
        Arguments:
31
            value:
32
                The :see:LocalizedValue to display in this
33
                widget.
34
35
        Returns:
36
            All values to display in the inner widgets.
37
        """
38
39 1
        result = []
40
41 1
        for lang_code, _ in settings.LANGUAGES:
42 1
            if value:
43 1
                result.append(value.get(lang_code))
44
            else:
45 1
                result.append(None)
46
47 1
        return result
48
49
50 1
class LocalizedCharFieldWidget(LocalizedFieldWidget):
51
    """Widget that has an input box for every language."""
52 1
    widget = forms.TextInput
53
54
55 1
class AdminLocalizedFieldWidget(LocalizedFieldWidget):
56 1
    widget = widgets.AdminTextareaWidget
57 1
    template = 'localized_fields/admin/widget.html'
58
59 1
    def render(self, name, value, attrs=None):
60
        if self.is_localized:
61
            for widget in self.widgets:
62
                widget.is_localized = self.is_localized
63
        # value is a list of values, each corresponding to a widget
64
        # in self.widgets.
65
        if not isinstance(value, list):
66
            value = self.decompress(value)
67
        output = []
68
        final_attrs = self.build_attrs(attrs)
69
        id_ = final_attrs.get('id')
70
        for i, widget in enumerate(self.widgets):
71
            try:
72
                widget_value = value[i]
73
            except IndexError:
74
                widget_value = None
75
            if id_:
76
                final_attrs = dict(final_attrs, id='%s_%s' % (id_, i))
77
            widget_attrs = self.build_widget_attrs(widget, widget_value, final_attrs)
78
            output.append(widget.render(name + '_%s' % i, widget_value, widget_attrs))
79
        context = {
80
            'id': final_attrs.get('id'),
81
            'name': name,
82
            'widgets': zip([code for code, lang in settings.LANGUAGES], output),
83
            'available_languages': settings.LANGUAGES
84
        }
85
        return render_to_string(self.template, context)
86
87 1
    def build_widget_attrs(self, widget, value, attrs):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
88
        attrs = dict(attrs)  # Copy attrs to avoid modifying the argument.
89
        if (not widget.use_required_attribute(value) or not widget.is_required) \
90
                and 'required' in attrs:
91
            del attrs['required']
92
        return attrs
93
94 1
class AdminLocalizedCharFieldWidget(AdminLocalizedFieldWidget):
95
    widget = widgets.AdminTextInputWidget
96