diff --git a/kobo/apps/reports/report_data.py b/kobo/apps/reports/report_data.py index 0661ec3324..cb90a15411 100644 --- a/kobo/apps/reports/report_data.py +++ b/kobo/apps/reports/report_data.py @@ -6,6 +6,7 @@ from rest_framework import serializers from formpack import FormPack +from kpi.utils.bugfix import repair_file_column_content_and_save from kpi.utils.log import logging from .constants import ( FUZZY_VERSION_ID_KEY, @@ -21,6 +22,10 @@ def build_formpack(asset, submission_stream=None, use_all_form_versions=True): are assumed to have been collected with that version of the form. """ + # Cope with kobotoolbox/formpack#322, which wrote invalid content into the + # database + repair_file_column_content_and_save(asset) + if asset.has_deployment: if use_all_form_versions: _versions = asset.deployed_versions diff --git a/kpi/models/asset_version.py b/kpi/models/asset_version.py index eeea8423ad..0bddf9e528 100644 --- a/kpi/models/asset_version.py +++ b/kpi/models/asset_version.py @@ -29,6 +29,8 @@ class AssetVersion(models.Model): ) version_content = models.JSONField() uid_aliases = models.JSONField(null=True) + # Tee hee, `deployed_content` is never written to the database! + # TODO: It should be changed to a property instead, no? deployed_content = models.JSONField(null=True) _deployment_data = models.JSONField(default=dict) deployed = models.BooleanField(default=False) diff --git a/kpi/serializers/v2/asset.py b/kpi/serializers/v2/asset.py index ebe0b9576d..96e696a780 100644 --- a/kpi/serializers/v2/asset.py +++ b/kpi/serializers/v2/asset.py @@ -893,6 +893,7 @@ def validate_settings(self, settings: dict) -> dict: return {**self.instance.settings, **settings} def _content(self, obj): + # FIXME: Is this dead code? return json.dumps(obj.content) def _get_status(self, perm_assignments): diff --git a/kpi/views/v2/asset.py b/kpi/views/v2/asset.py index 36845e5401..1e70df08ca 100644 --- a/kpi/views/v2/asset.py +++ b/kpi/views/v2/asset.py @@ -55,8 +55,9 @@ AssetListSerializer, AssetSerializer, ) -from kpi.utils.hash import calculate_hash from kpi.serializers.v2.reports import ReportsDetailSerializer +from kpi.utils.bugfix import repair_file_column_content_and_save +from kpi.utils.hash import calculate_hash from kpi.utils.kobo_to_xlsform import to_xlsform_structure from kpi.utils.ss_structure_to_mdtable import ss_structure_to_mdtable from kpi.utils.object_permission import ( @@ -403,6 +404,16 @@ def get_object(self): raise Http404 self.check_object_permissions(self.request, asset) + + # Cope with kobotoolbox/formpack#322, which wrote invalid content + # into the database. For performance, consider only the current + # content, not previous versions. Previous versions are handled in + # `kobo.apps.reports.report_data.build_formpack()` + if self.request.method == 'GET': + repair_file_column_content_and_save( + asset, include_versions=False + ) + return asset return super().get_object()