class ProfileKeyMetricsAdmin(SortableAdminMixin, BaseAdminModel): list_display = ( "label", description("Variable", lambda x: x.variable.name), description("Profile", lambda x: x.subcategory.category.profile.name), description("Subcategory", lambda x: x.subcategory.name), description("Category", lambda x: x.subcategory.category.name), "order" ) form = ProfileKeyMetricsForm list_filter = ( ("subcategory__category__profile", customTitledFilter("Profile")), ('subcategory__category__name', customTitledFilter('Category')), ('subcategory__name', customTitledFilter('Subcategory')), ) help_texts = ["denominator", ] class Media: js = ( "/static/js/jquery-ui.min.js", "/static/js/variable_subindicators.js", )
class ProfileKeyMetricsAdmin(SortableAdminMixin, BaseAdminModel): exclude_common_list_display = True list_display = ( "label", description("Variable", lambda x: x.variable.name), description("Profile", lambda x: x.subcategory.category.profile.name), description("Subcategory", lambda x: x.subcategory.name), description("Category", lambda x: x.subcategory.category.name), "created", "updated", "order" ) form = ProfileKeyMetricsForm list_filter = ( filters.ProfileNameFilter, CategoryMetricsFilter, filters.SubCategoryFilter, ) help_texts = ["denominator", ] fields = ["profile", "variable", "subindicator", "subcategory", "denominator", "label"] search_fields = ("label", ) class Media: js = ( "/static/js/variable_subindicators.js", ) def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) qs = form.base_fields["subcategory"].queryset if obj: profile_id = obj.profile_id if request.method == "POST": profile_id = request.POST.get("profile", profile_id) qs = models.IndicatorSubcategory.objects.filter( category__profile_id=profile_id ) elif not obj and request.method == "GET": qs = qs = models.IndicatorSubcategory.objects.none() form.base_fields["subcategory"].queryset = qs return form
class ProfileIndicatorAdmin(SortableAdminMixin, BaseAdminModel): list_filter = ( filters.ProfileNameFilter, CategoryIndicatorFilter, filters.SubCategoryFilter, ) exclude_common_list_display = True list_display = ( "profile", "label", description("Indicator", lambda x: x.indicator.name), description("Category", lambda x: x.subcategory.category.name), "subcategory", "created", "updated", "order", ) fieldsets = (("Database fields (can't change after being created)", { 'fields': ('profile', 'indicator') }), ("Profile fields", { 'fields': ('label', 'subcategory', 'description', 'choropleth_method') }), ("Subindicators", { 'fields': ('subindicators', ) })) search_fields = ("label", ) form = ProfileIndicatorAdminForm formfield_overrides = { fields.JSONField: { "widget": SortableWidget }, } help_texts = [ "choropleth_method", ] def get_readonly_fields(self, request, obj=None): if obj: # editing an existing object return ("profile", ) + self.readonly_fields return self.readonly_fields def save_model(self, request, obj, form, change): if not change: obj.subindicators = obj.indicator.subindicators super().save_model(request, obj, form, change)
class GroupAdmin(DatasetBaseAdminModel): list_display = ( "name", "dataset", description("Profile", lambda x: x.dataset.profile), ) form = GroupAdminForm list_filter = ( GroupProfileFilter, GroupDatasetFilter, ) formfield_overrides = { fields.JSONField: { "widget": SortableWidget }, } readonly_fields = ("dataset", "name") fieldsets = (("General", { 'fields': ('name', 'dataset') }), ("Subindicators", { 'fields': ('subindicators', ) }))
class ProfileHighlightAdmin(SortableAdminMixin, BaseAdminModel): list_filter = (("profile__name", customTitledFilter("Profile")), ) list_display = ( "profile", "label", description("Indicator", lambda x: x.indicator.name), "order", ) fieldsets = (("Database fields (can't change after being created)", { "fields": ("profile", "indicator") }), ("Profile fields", { "fields": ("label", "subindicator", "denominator") })) form = ProfileHighlightForm help_texts = [ "denominator", ] def get_readonly_fields(self, request, obj=None): if obj: # editing an existing object return ("profile", ) + self.readonly_fields return self.readonly_fields class Media: js = ( "/static/js/jquery-ui.min.js", "/static/js/variable_subindicators.js", )
class ProfileHighlightAdmin(SortableAdminMixin, BaseAdminModel): list_filter = (filters.ProfileNameFilter, ) exclude_common_list_display = True list_display = ( "profile", "label", description("Indicator", lambda x: x.indicator.name), "created", "updated", "order", ) fieldsets = (("Database fields (can't change after being created)", { "fields": ("profile", "indicator") }), ("Profile fields", { "fields": ("label", "subindicator", "denominator") })) form = ProfileHighlightForm search_fields = ("label", ) help_texts = [ "denominator", ] def get_readonly_fields(self, request, obj=None): if obj: # editing an existing object return ("profile", ) + self.readonly_fields return self.readonly_fields class Media: js = ("/static/js/variable_subindicators.js", )
class DatasetAdmin(DatasetBaseAdminModel): exclude = ("groups", ) inlines = (MetaDataInline,) actions = (set_to_public, set_to_private, delete_selected_data,) list_display = ("name", "permission_type", "geography_hierarchy", "profile", description("source", get_source)) list_filter = ( PermissionTypeFilter, filters.GeographyHierarchyFilter, filters.ProfileFilter, filters.DatasetMetaDataFilter ) form = DatasetAdminForm search_fields = ("name", ) fieldsets = ( ("", { "fields": ( "profile", "name", "geography_hierarchy", "permission_type" ) }), ("Dataset Imports", { "fields": ( "import_dataset", "imported_dataset", ) }), ) readonly_fields = ("imported_dataset", ) class Media: js = ("/static/js/geography_hierarchy.js",) def imported_dataset(self, obj): def get_url(file_obj): return '<a href="%s">%s</a>' % (reverse( 'admin:%s_%s_change' % ( file_obj._meta.app_label, file_obj._meta.model_name ), args=[file_obj.id] ), F"{file_obj.name}-{file_obj.id}") if obj: dataset_file_links = [ get_url(file_obj) for file_obj in models.DatasetFile.objects.filter( dataset_id=obj.id, dataset_id__isnull=False ) ] if dataset_file_links: return mark_safe(", ".join(dataset_file_links)) return "-" imported_dataset.short_description = 'Previously Imported' def get_related_fields_data(self, obj): return [{ "name": "dataset data", "count": obj.datasetdata_set.count() }, { "name": "indicator", "count": obj.indicator_set.count() }] def save_model(self, request, obj, form, change): is_new = obj.pk == None and change == False is_profile_updated = change and "profile" in form.changed_data super().save_model(request, obj, form, change) if is_new or is_profile_updated: assign_perms_to_group(obj.profile.name, obj, is_profile_updated) dataset_import_file = form.cleaned_data.get("import_dataset", None) logger.debug(f"Dataset import file: {dataset_import_file}") if dataset_import_file: datasetfile_obj = models.DatasetFile.objects.create( name=obj.name, document=dataset_import_file, dataset_id=obj.id ) logger.debug(f"""Starting async task: Task name: wazimap_ng.datasets.tasks.process_uploaded_file Datasetfile_obj: {datasetfile_obj} Object: {obj} Hook: wazimap_ng.datasets.hooks.process_task_info, key: {request.session.session_key}, type: upload, assign: True, notify: True """) task = async_task( "wazimap_ng.datasets.tasks.process_uploaded_file", datasetfile_obj, obj, task_name=f"Uploading data: {obj.name}", hook="wazimap_ng.datasets.hooks.process_task_info", key=request.session.session_key, type="upload", assign=True, notify=True ) hooks.add_to_task_list(request.session, task) hooks.custom_admin_notification( request.session, "info", "Data upload for %s started. We will let you know when process is done." % ( obj.name ) ) return obj def get_search_results(self, request, queryset, search_term): queryset, use_distinct = super().get_search_results(request, queryset, search_term) if "autocomplete" in request.path: dataset_ids = queryset.values_list("id", flat=True) in_progress_uploads = models.DatasetFile.objects.filter( task_id=None, dataset_id__in=dataset_ids ).values_list("dataset_id", flat=True) #queryset = queryset.exclude(id__in=in_progress_uploads) return queryset, use_distinct
class IndicatorAdmin(DatasetBaseAdminModel): list_display = ( "name", "dataset", "universe", description("source", get_source) ) list_filter = ( DatasetsWithPermissionFilter, "dataset__metadata__source" ) form = IndicatorAdminForm fieldsets = [ (None, { 'fields': ('dataset', 'groups','universe', 'name',) } ), ] class Media: js = ("/static/js/jquery-ui.min.js", "/static/js/indicator-admin.js",) def get_readonly_fields(self, request, obj=None): if obj: to_add = ('dataset',"groups", "universe",) return self.readonly_fields + to_add return self.readonly_fields def get_related_fields_data(self, obj): return [{ "name": "indicator data", "count": obj.indicatordata_set.count() }] def save_model(self, request, obj, form, change): """ During Step 1, no background tasks are run because only the Dataset is available. """ run_task = False if change else True super().save_model(request, obj, form, change) if run_task: task = async_task( "wazimap_ng.datasets.tasks.indicator_data_extraction", obj, task_name=f"Data Extraction: {obj.name}", hook="wazimap_ng.datasets.hooks.process_task_info", key=request.session.session_key, type="data_extraction", assign=False, notify=True ) hooks.add_to_task_list(request.session, task) hooks.custom_admin_notification( request.session, "info", "Process of Data extraction started for %s. We will let you know when process is done." % ( obj.name ) ) return obj def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) if request.method == "GET": form.group_choices = [["", "-----------"]] form.universe_queryset = models.Universe.objects.none() else: if not obj: dataset_id = request.POST.get('dataset', "") dataset = models.Dataset.objects.filter(id=dataset_id).first() groups = dataset.groups form.group_choices = [[group, group] for group in dataset.groups] condition = reduce( operator.or_, [Q(as_string__icontains=group) for group in groups] ) # form.universe_queryset = models.Universe.objects.annotate( # as_string=Cast('filters', CharField()) # ).filter(condition) form.universe_queryset = models.Universe.objects.annotate( as_string=Cast('filters', CharField()) ) return form
class IndicatorSubcategoryAdmin(SortableAdminMixin, BaseAdminModel): list_display = ("name", "category", description("Profile", lambda x: x.category.profile), "order") list_filter = ("category", "category__profile")
class DatasetAdmin(DatasetBaseAdminModel): exclude = ("groups", ) inlines = (MetaDataInline, ) actions = ( set_to_public, set_to_private, delete_selected_data, ) list_display = ("name", "permission_type", "geography_hierarchy", "profile", description("source", get_source)) list_filter = ("permission_type", "geography_hierarchy", "profile", "metadata__source") form = DatasetAdminForm fieldsets = ( ("", { "fields": ("profile", "name", "geography_hierarchy", "permission_type") }), ("Dataset Imports", { "fields": ( "import_dataset", "imported_dataset", ) }), ) readonly_fields = ("imported_dataset", ) def imported_dataset(self, obj): def get_url(file_obj): return '<a href="%s">%s</a>' % (reverse( 'admin:%s_%s_change' % (file_obj._meta.app_label, file_obj._meta.model_name), args=[file_obj.id]), F"{file_obj.name}-{file_obj.id}") if obj: dataset_file_links = [ get_url(file_obj) for file_obj in models.DatasetFile.objects.filter( dataset_id=obj.id, dataset_id__isnull=False) ] if dataset_file_links: return mark_safe(", ".join(dataset_file_links)) return "-" imported_dataset.short_description = 'Previously Imported' def get_related_fields_data(self, obj): return [{ "name": "dataset data", "count": obj.datasetdata_set.count() }, { "name": "indicator", "count": obj.indicator_set.count() }] def save_model(self, request, obj, form, change): is_new = obj.pk == None and change == False is_profile_updated = change and "profile" in form.changed_data super().save_model(request, obj, form, change) if is_new or is_profile_updated: assign_perms_to_group(obj.profile.name, obj, is_profile_updated) dataset_import_file = form.cleaned_data.get("import_dataset", None) if dataset_import_file: datasetfile_obj = models.DatasetFile.objects.create( name=obj.name, document=dataset_import_file, dataset_id=obj.id) task = async_task( "wazimap_ng.datasets.tasks.process_uploaded_file", datasetfile_obj, obj, task_name=f"Uploading data: {obj.name}", hook="wazimap_ng.datasets.hooks.process_task_info", key=request.session.session_key, type="upload", assign=True, notify=True) hooks.add_to_task_list(request.session, task) hooks.custom_admin_notification( request.session, "info", "Data upload for %s started. We will let you know when process is done." % (obj.name)) return obj