We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Indicator target and disaggregation targets bugs


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `akvo/rest/serializers/indicator.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 # Akvo RSR is covered by the GNU Affero General Public License.
4 # See more details in the license.txt file located at the root folder of the Akvo RSR module.
5 # For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
6 
7 from akvo.rest.serializers.indicator_period import (
8     IndicatorPeriodFrameworkSerializer, IndicatorPeriodFrameworkLiteSerializer,
9     IndicatorPeriodFrameworkNotSoLiteSerializer, create_or_update_disaggregation_targets)
10 from akvo.rest.serializers.indicator_dimension_name import IndicatorDimensionNameSerializer
11 from akvo.rest.serializers.indicator_custom_field import IndicatorCustomValueSerializer
12 from akvo.rest.serializers.indicator_reference import IndicatorReferenceSerializer
13 from akvo.rest.serializers.rsr_serializer import BaseRSRSerializer
14 from akvo.rsr.models import (
15     Indicator, IndicatorDimensionName, IndicatorLabel, IndicatorDisaggregationTarget)
16 
17 from rest_framework import serializers
18 
19 
20 def serialize_disaggregation_targets(indicator):
21     return [
22         {
23             'id': t.id,
24             'value': t.value,
25             'dimension_value': t.dimension_value_id,
26             'indicator': indicator.id,
27         }
28         for t in indicator.disaggregation_targets.all()
29     ]
30 
31 
32 class IndicatorDisaggregationTargetNestedSerializer(BaseRSRSerializer):
33     id = serializers.IntegerField()
34 
35     class Meta:
36         model = IndicatorDisaggregationTarget
37         fields = ('id', 'value', 'dimension_value', 'indicator')
38         read_only_fields = ('id', 'indicator')
39 
40     def to_internal_value(self, data):
41         if 'value' in data:
42             data['value'] = str(data['value']).replace(',', '.')
43         return super().to_internal_value(data)
44 
45 
46 class LabelListingField(serializers.RelatedField):
47 
48     def to_representation(self, labels):
49         if isinstance(labels, IndicatorLabel):
50             value = labels.label_id
51         else:
52             value = list(labels.values_list('label_id', flat=True))
53         return value
54 
55     def to_internal_value(self, org_label_ids):
56         indicator = self.root.instance
57         existing_labels = set(indicator.labels.values_list('label_id', flat=True))
58         new_labels = set(org_label_ids) - existing_labels
59         deleted_labels = existing_labels - set(org_label_ids)
60         labels = [IndicatorLabel(indicator=indicator, label_id=org_label_id) for org_label_id in new_labels]
61         IndicatorLabel.objects.bulk_create(labels)
62         if deleted_labels:
63             IndicatorLabel.objects.filter(label_id__in=deleted_labels).delete()
64 
65         return indicator.labels.all()
66 
67 
68 class IndicatorSerializer(BaseRSRSerializer):
69 
70     result_unicode = serializers.ReadOnlyField(source='result.__str__')
71     measure_label = serializers.ReadOnlyField(source='iati_measure_unicode')
72     children_aggregate_percentage = serializers.ReadOnlyField()
73     dimension_names = serializers.PrimaryKeyRelatedField(
74         many=True, queryset=IndicatorDimensionName.objects.all())
75     disaggregation_targets = serializers.SerializerMethodField()
76 
77     def get_disaggregation_targets(self, obj):
78         return serialize_disaggregation_targets(obj)
79 
80     class Meta:
81         model = Indicator
82         exclude = ['enumerators']
83 
84     # TODO: add validation for parent_indicator
85 
86 
87 class IndicatorFrameworkSerializer(BaseRSRSerializer):
88 
89     periods = IndicatorPeriodFrameworkSerializer(many=True, required=False, read_only=True)
90     parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')
91     children_aggregate_percentage = serializers.ReadOnlyField()
92     dimension_names = IndicatorDimensionNameSerializer(many=True, required=False, read_only=True)
93     labels = LabelListingField(queryset=IndicatorLabel.objects.all(), required=False)
94     disaggregation_targets = IndicatorDisaggregationTargetNestedSerializer(many=True, required=False)
95 
96     class Meta:
97         model = Indicator
98         exclude = ['enumerators']
99 
100     def update(self, instance, validated_data):
101         disaggregation_targets = validated_data.pop('disaggregation_targets', [])
102         instance = super().update(instance, validated_data)
103         create_or_update_disaggregation_targets(instance, disaggregation_targets)
104         return instance
105 
106     def validate_disaggregation_targets(self, data):
107         for target in data:
108             if 'value' not in target:
109                 raise serializers.ValidationError('Disaggregation targets should have a value')
110             if 'dimension_value' not in target:
111                 raise serializers.ValidationError(
112                     'Disaggregation targets should have "dimension_value"')
113         return data
114 
115     def to_internal_value(self, data):
116         if 'target_value' in data:
117             data['target_value'] = str(data['target_value']).replace(',', '.')
118         return super().to_internal_value(data)
119 
120 
121 class IndicatorFrameworkLiteSerializer(BaseRSRSerializer):
122 
123     periods = IndicatorPeriodFrameworkLiteSerializer(many=True, required=False, read_only=True)
124     references = IndicatorReferenceSerializer(many=True, required=False, read_only=True)
125     parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')
126     children_aggregate_percentage = serializers.ReadOnlyField()
127     dimension_names = IndicatorDimensionNameSerializer(many=True, required=False, read_only=True)
128     labels = LabelListingField(read_only=True)
129     disaggregation_targets = serializers.SerializerMethodField()
130     custom_values = IndicatorCustomValueSerializer(many=True, required=False)
131 
132     def get_disaggregation_targets(self, obj):
133         return serialize_disaggregation_targets(obj)
134 
135     class Meta:
136         model = Indicator
137         exclude = ['enumerators']
138 
139 
140 class IndicatorFrameworkNotSoLiteSerializer(BaseRSRSerializer):
141 
142     periods = IndicatorPeriodFrameworkNotSoLiteSerializer(many=True, required=False, read_only=True)
143     parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')
144     children_aggregate_percentage = serializers.ReadOnlyField()
145     labels = LabelListingField(read_only=True)
146     disaggregation_targets = serializers.SerializerMethodField()
147     dimension_names = serializers.SerializerMethodField()
148 
149     def get_disaggregation_targets(self, obj):
150         return serialize_disaggregation_targets(obj)
151 
152     def get_dimension_names(self, obj):
153         return [
154             {
155                 'id': n.id,
156                 'name': n.name,
157                 'dimension_values': [{'id': v.id, 'value': v.value} for v in n.dimension_values.all()]
158             }
159             for n in obj.dimension_names.all()
160         ]
161 
162     class Meta:
163         model = Indicator
164         fields = (
165             'id',
166             'periods',
167             'parent_indicator',
168             'children_aggregate_percentage',
169             'labels',
170             'title',
171             'type',
172             'measure',
173             'ascending',
174             'description',
175             'baseline_year',
176             'baseline_value',
177             'baseline_comment',
178             'order',
179             'export_to_iati',
180             'result',
181             'disaggregation_targets',
182             'dimension_names',
183             'scores',
184         )
185
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/akvo/rest/serializers/indicator.py b/akvo/rest/serializers/indicator.py
--- a/akvo/rest/serializers/indicator.py
+++ b/akvo/rest/serializers/indicator.py
@@ -37,8 +37,8 @@
         read_only_fields = ('id', 'indicator')
 
     def to_internal_value(self, data):
-        if 'value' in data:
-            data['value'] = str(data['value']).replace(',', '.')
+        value = data.get('value', None)
+        data['value'] = str(value).replace(',', '.') if value is not None else None
         return super().to_internal_value(data)
 
 
@@ -112,8 +112,10 @@
         return data
 
     def to_internal_value(self, data):
-        if 'target_value' in data:
+        if 'target_value' in data and data['target_value'] is not None:
             data['target_value'] = str(data['target_value']).replace(',', '.')
+        if 'disaggregation_targets' in data:
+            data['disaggregation_targets'] = [dt for dt in data['disaggregation_targets'] if dt]
         return super().to_internal_value(data)

{"golden_diff": "diff --git a/akvo/rest/serializers/indicator.py b/akvo/rest/serializers/indicator.py\n--- a/akvo/rest/serializers/indicator.py\n+++ b/akvo/rest/serializers/indicator.py\n@@ -37,8 +37,8 @@\n         read_only_fields = ('id', 'indicator')\n \n     def to_internal_value(self, data):\n-        if 'value' in data:\n-            data['value'] = str(data['value']).replace(',', '.')\n+        value = data.get('value', None)\n+        data['value'] = str(value).replace(',', '.') if value is not None else None\n         return super().to_internal_value(data)\n \n \n@@ -112,8 +112,10 @@\n         return data\n \n     def to_internal_value(self, data):\n-        if 'target_value' in data:\n+        if 'target_value' in data and data['target_value'] is not None:\n             data['target_value'] = str(data['target_value']).replace(',', '.')\n+        if 'disaggregation_targets' in data:\n+            data['disaggregation_targets'] = [dt for dt in data['disaggregation_targets'] if dt]\n         return super().to_internal_value(data)\n", "issue": "Indicator target and disaggregation targets bugs\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Akvo RSR is covered by the GNU Affero General Public License.\n# See more details in the license.txt file located at the root folder of the Akvo RSR module.\n# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.\n\nfrom akvo.rest.serializers.indicator_period import (\n    IndicatorPeriodFrameworkSerializer, IndicatorPeriodFrameworkLiteSerializer,\n    IndicatorPeriodFrameworkNotSoLiteSerializer, create_or_update_disaggregation_targets)\nfrom akvo.rest.serializers.indicator_dimension_name import IndicatorDimensionNameSerializer\nfrom akvo.rest.serializers.indicator_custom_field import IndicatorCustomValueSerializer\nfrom akvo.rest.serializers.indicator_reference import IndicatorReferenceSerializer\nfrom akvo.rest.serializers.rsr_serializer import BaseRSRSerializer\nfrom akvo.rsr.models import (\n    Indicator, IndicatorDimensionName, IndicatorLabel, IndicatorDisaggregationTarget)\n\nfrom rest_framework import serializers\n\n\ndef serialize_disaggregation_targets(indicator):\n    return [\n        {\n            'id': t.id,\n            'value': t.value,\n            'dimension_value': t.dimension_value_id,\n            'indicator': indicator.id,\n        }\n        for t in indicator.disaggregation_targets.all()\n    ]\n\n\nclass IndicatorDisaggregationTargetNestedSerializer(BaseRSRSerializer):\n    id = serializers.IntegerField()\n\n    class Meta:\n        model = IndicatorDisaggregationTarget\n        fields = ('id', 'value', 'dimension_value', 'indicator')\n        read_only_fields = ('id', 'indicator')\n\n    def to_internal_value(self, data):\n        if 'value' in data:\n            data['value'] = str(data['value']).replace(',', '.')\n        return super().to_internal_value(data)\n\n\nclass LabelListingField(serializers.RelatedField):\n\n    def to_representation(self, labels):\n        if isinstance(labels, IndicatorLabel):\n            value = labels.label_id\n        else:\n            value = list(labels.values_list('label_id', flat=True))\n        return value\n\n    def to_internal_value(self, org_label_ids):\n        indicator = self.root.instance\n        existing_labels = set(indicator.labels.values_list('label_id', flat=True))\n        new_labels = set(org_label_ids) - existing_labels\n        deleted_labels = existing_labels - set(org_label_ids)\n        labels = [IndicatorLabel(indicator=indicator, label_id=org_label_id) for org_label_id in new_labels]\n        IndicatorLabel.objects.bulk_create(labels)\n        if deleted_labels:\n            IndicatorLabel.objects.filter(label_id__in=deleted_labels).delete()\n\n        return indicator.labels.all()\n\n\nclass IndicatorSerializer(BaseRSRSerializer):\n\n    result_unicode = serializers.ReadOnlyField(source='result.__str__')\n    measure_label = serializers.ReadOnlyField(source='iati_measure_unicode')\n    children_aggregate_percentage = serializers.ReadOnlyField()\n    dimension_names = serializers.PrimaryKeyRelatedField(\n        many=True, queryset=IndicatorDimensionName.objects.all())\n    disaggregation_targets = serializers.SerializerMethodField()\n\n    def get_disaggregation_targets(self, obj):\n        return serialize_disaggregation_targets(obj)\n\n    class Meta:\n        model = Indicator\n        exclude = ['enumerators']\n\n    # TODO: add validation for parent_indicator\n\n\nclass IndicatorFrameworkSerializer(BaseRSRSerializer):\n\n    periods = IndicatorPeriodFrameworkSerializer(many=True, required=False, read_only=True)\n    parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')\n    children_aggregate_percentage = serializers.ReadOnlyField()\n    dimension_names = IndicatorDimensionNameSerializer(many=True, required=False, read_only=True)\n    labels = LabelListingField(queryset=IndicatorLabel.objects.all(), required=False)\n    disaggregation_targets = IndicatorDisaggregationTargetNestedSerializer(many=True, required=False)\n\n    class Meta:\n        model = Indicator\n        exclude = ['enumerators']\n\n    def update(self, instance, validated_data):\n        disaggregation_targets = validated_data.pop('disaggregation_targets', [])\n        instance = super().update(instance, validated_data)\n        create_or_update_disaggregation_targets(instance, disaggregation_targets)\n        return instance\n\n    def validate_disaggregation_targets(self, data):\n        for target in data:\n            if 'value' not in target:\n                raise serializers.ValidationError('Disaggregation targets should have a value')\n            if 'dimension_value' not in target:\n                raise serializers.ValidationError(\n                    'Disaggregation targets should have \"dimension_value\"')\n        return data\n\n    def to_internal_value(self, data):\n        if 'target_value' in data:\n            data['target_value'] = str(data['target_value']).replace(',', '.')\n        return super().to_internal_value(data)\n\n\nclass IndicatorFrameworkLiteSerializer(BaseRSRSerializer):\n\n    periods = IndicatorPeriodFrameworkLiteSerializer(many=True, required=False, read_only=True)\n    references = IndicatorReferenceSerializer(many=True, required=False, read_only=True)\n    parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')\n    children_aggregate_percentage = serializers.ReadOnlyField()\n    dimension_names = IndicatorDimensionNameSerializer(many=True, required=False, read_only=True)\n    labels = LabelListingField(read_only=True)\n    disaggregation_targets = serializers.SerializerMethodField()\n    custom_values = IndicatorCustomValueSerializer(many=True, required=False)\n\n    def get_disaggregation_targets(self, obj):\n        return serialize_disaggregation_targets(obj)\n\n    class Meta:\n        model = Indicator\n        exclude = ['enumerators']\n\n\nclass IndicatorFrameworkNotSoLiteSerializer(BaseRSRSerializer):\n\n    periods = IndicatorPeriodFrameworkNotSoLiteSerializer(many=True, required=False, read_only=True)\n    parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')\n    children_aggregate_percentage = serializers.ReadOnlyField()\n    labels = LabelListingField(read_only=True)\n    disaggregation_targets = serializers.SerializerMethodField()\n    dimension_names = serializers.SerializerMethodField()\n\n    def get_disaggregation_targets(self, obj):\n        return serialize_disaggregation_targets(obj)\n\n    def get_dimension_names(self, obj):\n        return [\n            {\n                'id': n.id,\n                'name': n.name,\n                'dimension_values': [{'id': v.id, 'value': v.value} for v in n.dimension_values.all()]\n            }\n            for n in obj.dimension_names.all()\n        ]\n\n    class Meta:\n        model = Indicator\n        fields = (\n            'id',\n            'periods',\n            'parent_indicator',\n            'children_aggregate_percentage',\n            'labels',\n            'title',\n            'type',\n            'measure',\n            'ascending',\n            'description',\n            'baseline_year',\n            'baseline_value',\n            'baseline_comment',\n            'order',\n            'export_to_iati',\n            'result',\n            'disaggregation_targets',\n            'dimension_names',\n            'scores',\n        )\n", "path": "akvo/rest/serializers/indicator.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Akvo RSR is covered by the GNU Affero General Public License.\n# See more details in the license.txt file located at the root folder of the Akvo RSR module.\n# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.\n\nfrom akvo.rest.serializers.indicator_period import (\n    IndicatorPeriodFrameworkSerializer, IndicatorPeriodFrameworkLiteSerializer,\n    IndicatorPeriodFrameworkNotSoLiteSerializer, create_or_update_disaggregation_targets)\nfrom akvo.rest.serializers.indicator_dimension_name import IndicatorDimensionNameSerializer\nfrom akvo.rest.serializers.indicator_custom_field import IndicatorCustomValueSerializer\nfrom akvo.rest.serializers.rsr_serializer import BaseRSRSerializer\nfrom akvo.rsr.models import (\n    Indicator, IndicatorDimensionName, IndicatorLabel, IndicatorDisaggregationTarget)\n\nfrom rest_framework import serializers\n\n\ndef serialize_disaggregation_targets(indicator):\n    return [\n        {\n            'id': t.id,\n            'value': t.value,\n            'dimension_value': t.dimension_value_id,\n            'indicator': indicator.id,\n        }\n        for t in indicator.disaggregation_targets.all()\n    ]\n\n\nclass IndicatorDisaggregationTargetNestedSerializer(BaseRSRSerializer):\n    id = serializers.IntegerField()\n\n    class Meta:\n        model = IndicatorDisaggregationTarget\n        fields = ('id', 'value', 'dimension_value', 'indicator')\n        read_only_fields = ('id', 'indicator')\n\n    def to_internal_value(self, data):\n        value = data.get('value', None)\n        data['value'] = str(value).replace(',', '.') if value is not None else None\n        return super().to_internal_value(data)\n\n\nclass LabelListingField(serializers.RelatedField):\n\n    def to_representation(self, labels):\n        if isinstance(labels, IndicatorLabel):\n            value = labels.label_id\n        else:\n            value = list(labels.values_list('label_id', flat=True))\n        return value\n\n    def to_internal_value(self, org_label_ids):\n        indicator = self.root.instance\n        existing_labels = set(indicator.labels.values_list('label_id', flat=True))\n        new_labels = set(org_label_ids) - existing_labels\n        deleted_labels = existing_labels - set(org_label_ids)\n        labels = [IndicatorLabel(indicator=indicator, label_id=org_label_id) for org_label_id in new_labels]\n        IndicatorLabel.objects.bulk_create(labels)\n        if deleted_labels:\n            IndicatorLabel.objects.filter(label_id__in=deleted_labels).delete()\n\n        return indicator.labels.all()\n\n\nclass IndicatorSerializer(BaseRSRSerializer):\n\n    result_unicode = serializers.ReadOnlyField(source='result.__str__')\n    measure_label = serializers.ReadOnlyField(source='iati_measure_unicode')\n    children_aggregate_percentage = serializers.ReadOnlyField()\n    dimension_names = serializers.PrimaryKeyRelatedField(\n        many=True, queryset=IndicatorDimensionName.objects.all())\n    disaggregation_targets = serializers.SerializerMethodField()\n\n    def get_disaggregation_targets(self, obj):\n        return serialize_disaggregation_targets(obj)\n\n    class Meta:\n        model = Indicator\n        exclude = ['enumerators']\n\n    # TODO: add validation for parent_indicator\n\n\nclass IndicatorFrameworkSerializer(BaseRSRSerializer):\n\n    periods = IndicatorPeriodFrameworkSerializer(many=True, required=False, read_only=True)\n    parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')\n    children_aggregate_percentage = serializers.ReadOnlyField()\n    dimension_names = IndicatorDimensionNameSerializer(many=True, required=False, read_only=True)\n    labels = LabelListingField(queryset=IndicatorLabel.objects.all(), required=False)\n    disaggregation_targets = IndicatorDisaggregationTargetNestedSerializer(many=True, required=False)\n\n    class Meta:\n        model = Indicator\n        exclude = ['enumerators']\n\n    def update(self, instance, validated_data):\n        disaggregation_targets = validated_data.pop('disaggregation_targets', [])\n        instance = super().update(instance, validated_data)\n        create_or_update_disaggregation_targets(instance, disaggregation_targets)\n        return instance\n\n    def validate_disaggregation_targets(self, data):\n        for target in data:\n            if 'value' not in target:\n                raise serializers.ValidationError('Disaggregation targets should have a value')\n            if 'dimension_value' not in target:\n                raise serializers.ValidationError(\n                    'Disaggregation targets should have \"dimension_value\"')\n        return data\n\n    def to_internal_value(self, data):\n        if 'target_value' in data and data['target_value'] is not None:\n            data['target_value'] = str(data['target_value']).replace(',', '.')\n        if 'disaggregation_targets' in data:\n            data['disaggregation_targets'] = [dt for dt in data['disaggregation_targets'] if dt]\n        return super().to_internal_value(data)\n\n\nclass IndicatorFrameworkLiteSerializer(BaseRSRSerializer):\n\n    periods = IndicatorPeriodFrameworkLiteSerializer(many=True, required=False, read_only=True)\n    parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')\n    children_aggregate_percentage = serializers.ReadOnlyField()\n    dimension_names = IndicatorDimensionNameSerializer(many=True, required=False, read_only=True)\n    labels = LabelListingField(read_only=True)\n    disaggregation_targets = serializers.SerializerMethodField()\n    custom_values = IndicatorCustomValueSerializer(many=True, required=False)\n\n    def get_disaggregation_targets(self, obj):\n        return serialize_disaggregation_targets(obj)\n\n    class Meta:\n        model = Indicator\n        exclude = ['enumerators']\n\n\nclass IndicatorFrameworkNotSoLiteSerializer(BaseRSRSerializer):\n\n    periods = IndicatorPeriodFrameworkNotSoLiteSerializer(many=True, required=False, read_only=True)\n    parent_indicator = serializers.ReadOnlyField(source='parent_indicator_id')\n    children_aggregate_percentage = serializers.ReadOnlyField()\n    labels = LabelListingField(read_only=True)\n    disaggregation_targets = serializers.SerializerMethodField()\n    dimension_names = serializers.SerializerMethodField()\n\n    def get_disaggregation_targets(self, obj):\n        return serialize_disaggregation_targets(obj)\n\n    def get_dimension_names(self, obj):\n        return [\n            {\n                'id': n.id,\n                'name': n.name,\n                'dimension_values': [{'id': v.id, 'value': v.value} for v in n.dimension_values.all()]\n            }\n            for n in obj.dimension_names.all()\n        ]\n\n    class Meta:\n        model = Indicator\n        fields = (\n            'id',\n            'periods',\n            'parent_indicator',\n            'children_aggregate_percentage',\n            'labels',\n            'title',\n            'type',\n            'measure',\n            'ascending',\n            'description',\n            'baseline_year',\n            'baseline_value',\n            'baseline_comment',\n            'order',\n            'export_to_iati',\n            'result',\n            'disaggregation_targets',\n            'dimension_names',\n            'scores',\n        )\n", "path": "akvo/rest/serializers/indicator.py"}]}