Skip to content

Commit 6063f69

Browse files
committed
Added models for Column/Filter descriptions (now they can be edited from admin page)
1 parent 8c03983 commit 6063f69

File tree

6 files changed

+132
-35
lines changed

6 files changed

+132
-35
lines changed

src/fixtures/column_descriptions.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"model": "indicatorsets.columndescription", "pk": 18, "fields": {"name": "name", "description": "Hover over the indicator's name to see a brief description."}}, {"model": "indicatorsets.columndescription", "pk": 19, "fields": {"name": "geographic_coverage", "description": "The countries or world regions covered by this indicator. These are typically covered at finer geographic levels / jurisdictions."}}, {"model": "indicatorsets.columndescription", "pk": 20, "fields": {"name": "geographic_levels", "description": "All the geographic levels at which this indicator is available. Larger jurisdictions are often based on aggregation of data from constituent jurisdictions."}}, {"model": "indicatorsets.columndescription", "pk": 21, "fields": {"name": "temporal_scope_start", "description": "The earliest date for which this indicator is available."}}, {"model": "indicatorsets.columndescription", "pk": 22, "fields": {"name": "temporal_scope_end", "description": "The latest date for which this indicator is available."}}, {"model": "indicatorsets.columndescription", "pk": 23, "fields": {"name": "temporal_granularity", "description": "The temporal resolution of this indicator (not of the reporting). Might not be the same as Reporting Cadence (e.g. a daily indicator may be reported only once a week)."}}, {"model": "indicatorsets.columndescription", "pk": 24, "fields": {"name": "reporting_cadence", "description": "The frequency with which this indicator is reported. This may be different from the temporal granularity."}}, {"model": "indicatorsets.columndescription", "pk": 25, "fields": {"name": "reporting_lag", "description": "The number of days from the last day of a reported period until the first reported value for that period is usually available in Delphi Epidata. E.g. if reporting U.S. epiweeks (Sunday through Saturday), and the first report is usually available in Delphi Epidata on the following Friday, The Reporting Lag is 6. By \"usually available\" we mean when it\\'s \"supposed to be\" available based on our current understanding of the data provider\\'s operations and Delphi\\'s ingestion pipeline. That is the date on which we think of the data as showing up \"on time\", and relative to which we track unusual delays."}}, {"model": "indicatorsets.columndescription", "pk": 26, "fields": {"name": "revision_cadende", "description": "How frequently are revised values (e.g. \"backfill\") usually reported (if any)?"}}, {"model": "indicatorsets.columndescription", "pk": 27, "fields": {"name": "population", "description": "The population or demographic group reflected by the indicator (\"All\" means the entire population)"}}, {"model": "indicatorsets.columndescription", "pk": 28, "fields": {"name": "population_stratifiers", "description": "What population or demographic stratifiers are available, if any?"}}, {"model": "indicatorsets.columndescription", "pk": 29, "fields": {"name": "surveillance_categories", "description": "Which surveillance categories or rungs in the Severity Pyramid does this indicator attempt to track? Some indicators may approximately track multiple categories."}}, {"model": "indicatorsets.columndescription", "pk": 30, "fields": {"name": "original_data_provider", "description": "The owner or supplier of the original or raw data used to create this indicator."}}, {"model": "indicatorsets.columndescription", "pk": 31, "fields": {"name": "pre_processing", "description": "Brief description of main data processing used in creating this set of indicators, including smoothing and aggregation. For more details, see the documentation."}}, {"model": "indicatorsets.columndescription", "pk": 32, "fields": {"name": "censoring", "description": "Is any of the data being censored (e.g. small counts)? If so how, and how much impact does it have (e.g. approximate fraction of values affected)."}}, {"model": "indicatorsets.columndescription", "pk": 33, "fields": {"name": "dua_required", "description": "Applicable data use terms (may apply even to publicly accessible indicators)."}}]

src/fixtures/filter_descriptions.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"model": "indicatorsets.filterdescription", "pk": 9, "fields": {"name": "pathogens", "description": "List only indicators related to these pathogens, syndromes or diseases."}}, {"model": "indicatorsets.filterdescription", "pk": 10, "fields": {"name": "geographic_scope", "description": "List only indicators that cover any of the selected countries or world regions."}}, {"model": "indicatorsets.filterdescription", "pk": 11, "fields": {"name": "geographic_levels", "description": "List only indicators that are available at any of the selected geographic levels."}}, {"model": "indicatorsets.filterdescription", "pk": 12, "fields": {"name": "severity_pyramid_rungs", "description": "List only indicators that are directly related to any of the selected rungs."}}, {"model": "indicatorsets.filterdescription", "pk": 13, "fields": {"name": "original_data_provider", "description": "List only indicator that are based on data from one of the selected sources."}}, {"model": "indicatorsets.filterdescription", "pk": 14, "fields": {"name": "temporal_granularity", "description": "The temporal resolution of this indicator (not of the reporting). Might not be the same as Reporting Cadence (e.g. a daily indicator may be reported only once a week)."}}, {"model": "indicatorsets.filterdescription", "pk": 15, "fields": {"name": "temporal_scope_end", "description": "The latest date for which this indicator is available."}}, {"model": "indicatorsets.filterdescription", "pk": 16, "fields": {"name": "location_search", "description": "Enter one or more locations for which you are looking for indicator coverage, or leave empty for all locations. Start entering a location name to see all compatible locations. Auto-complete with [Tab] or [Enter]. Currently works only for U.S. locations."}}]

src/indicatorsets/admin.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
from django.contrib import admin
22

33
from import_export.admin import ImportExportModelAdmin
4-
from indicatorsets.models import IndicatorSet, NonDelphiIndicatorSet
4+
from indicatorsets.models import (
5+
IndicatorSet,
6+
NonDelphiIndicatorSet,
7+
FilterDescription,
8+
ColumnDescription,
9+
)
510
from indicatorsets.resources import IndicatorSetResource, NonDelphiIndicatorSetResource
611

712

@@ -55,3 +60,29 @@ class NonDelphiIndicatorSetAdmin(ImportExportModelAdmin):
5560
search_fields = ("name", "short_name", "description")
5661
ordering = ["name"]
5762
list_filter = ["original_data_provider", "source_type"]
63+
64+
65+
@admin.register(FilterDescription)
66+
class FilterDescriptionAdmin(admin.ModelAdmin):
67+
"""
68+
Admin interface for the FilterDescription model.
69+
"""
70+
71+
list_display = ("name", "description")
72+
search_fields = ("name", "description")
73+
ordering = ["name"]
74+
list_filter = ["name"]
75+
list_editable = ("description",)
76+
77+
78+
@admin.register(ColumnDescription)
79+
class ColumnDescriptionAdmin(admin.ModelAdmin):
80+
"""
81+
Admin interface for the ColumnDescription model.
82+
"""
83+
84+
list_display = ("name", "description")
85+
search_fields = ("name", "description")
86+
ordering = ["name"]
87+
list_filter = ["name"]
88+
list_editable = ("description",)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Generated by Django 5.0.7 on 2025-05-13 12:26
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('indicatorsets', '0003_indicatorset_source_type'),
10+
]
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name='ColumnDescription',
15+
fields=[
16+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17+
('name', models.CharField(max_length=255, unique=True, verbose_name='Name')),
18+
('description', models.TextField(blank=True, verbose_name='Description')),
19+
],
20+
options={
21+
'verbose_name': 'Column Description',
22+
'verbose_name_plural': 'Column Descriptions',
23+
'ordering': ['name'],
24+
'indexes': [models.Index(fields=['name'], name='column_description_name_idx')],
25+
},
26+
),
27+
migrations.CreateModel(
28+
name='FilterDescription',
29+
fields=[
30+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31+
('name', models.CharField(max_length=255, unique=True, verbose_name='Name')),
32+
('description', models.TextField(blank=True, verbose_name='Description')),
33+
],
34+
options={
35+
'verbose_name': 'Filter Description',
36+
'verbose_name_plural': 'Filter Descriptions',
37+
'ordering': ['name'],
38+
'indexes': [models.Index(fields=['name'], name='filter_description_name_idx')],
39+
},
40+
),
41+
]

src/indicatorsets/models.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,53 @@ class Meta:
223223
proxy = True
224224
verbose_name = "Non-Delphi Indicator Set"
225225
verbose_name_plural = "Non-Delphi Indicators Sets"
226+
227+
228+
class FilterDescription(models.Model):
229+
230+
name = models.CharField(verbose_name="Name", max_length=255, unique=True)
231+
description: models.TextField = models.TextField(
232+
verbose_name="Description", blank=True
233+
)
234+
235+
class Meta:
236+
verbose_name = "Filter Description"
237+
verbose_name_plural = "Filter Descriptions"
238+
ordering = ["name"]
239+
indexes = [
240+
models.Index(fields=["name"], name="filter_description_name_idx"),
241+
]
242+
243+
def __str__(self):
244+
return self.name
245+
246+
@classmethod
247+
def get_all_descriptions_as_dict(cls):
248+
descriptions = cls.objects.values("name", "description")
249+
return {desc["name"]: desc["description"] for desc in descriptions}
250+
251+
252+
class ColumnDescription(models.Model):
253+
254+
name: models.CharField = models.CharField(
255+
verbose_name="Name", max_length=255, unique=True
256+
)
257+
description: models.TextField = models.TextField(
258+
verbose_name="Description", blank=True
259+
)
260+
261+
class Meta:
262+
verbose_name = "Column Description"
263+
verbose_name_plural = "Column Descriptions"
264+
ordering = ["name"]
265+
indexes = [
266+
models.Index(fields=["name"], name="column_description_name_idx"),
267+
]
268+
269+
def __str__(self):
270+
return self.name
271+
272+
@classmethod
273+
def get_all_descriptions_as_dict(cls):
274+
descriptions = cls.objects.values("name", "description")
275+
return {desc["name"]: desc["description"] for desc in descriptions}

src/indicatorsets/views.py

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import json
33
import logging
44
import requests
5-
from bs4 import BeautifulSoup
65

76

87
from django.conf import settings
@@ -12,7 +11,7 @@
1211
from base.models import Geography, GeographyUnit
1312
from indicatorsets.filters import IndicatorSetFilter
1413
from indicatorsets.forms import IndicatorSetFilterForm
15-
from indicatorsets.models import IndicatorSet
14+
from indicatorsets.models import IndicatorSet, FilterDescription, ColumnDescription
1615
from indicatorsets.utils import (
1716
generate_epivis_custom_title,
1817
generate_random_color,
@@ -21,36 +20,6 @@
2120

2221
logger = logging.getLogger(__name__)
2322

24-
FILTERS_DESCRIPTIONS = {
25-
"pathogens": "List only indicators related to these pathogens, syndromes or diseases.",
26-
"geographic_scope": "List only indicators that cover any of the selected countries or world regions.",
27-
"geographic_levels": "List only indicators that are available at any of the selected geographic levels.",
28-
"severity_pyramid_rungs": "List only indicators that are directly related to any of the selected rungs.",
29-
"original_data_provider": "List only indicator that are based on data from one of the selected sources.",
30-
"temporal_granularity": "The temporal resolution of this indicator (not of the reporting). Might not be the same as Reporting Cadence (e.g. a daily indicator may be reported only once a week).",
31-
"temporal_scope_end": "The latest date for which this indicator is available.",
32-
"location_search": "Enter one or more locations for which you are looking for indicator coverage, or leave empty for all locations. Start entering a location name to see all compatible locations. Auto-complete with [Tab] or [Enter]. Currently works only for U.S. locations.",
33-
}
34-
35-
COLUMNS_DESCRIPTIONS = {
36-
"name": "Hover over the indicator's name to see a brief description.",
37-
"geographic_coverage": "The countries or world regions covered by this indicator. These are typically covered at finer geographic levels / jurisdictions.",
38-
"geographic_levels": "All the geographic levels at which this indicator is available. Larger jurisdictions are often based on aggregation of data from constituent jurisdictions.",
39-
"temporal_scope_start": "The earliest date for which this indicator is available.",
40-
"temporal_scope_end": "The latest date for which this indicator is available.",
41-
"temporal_granularity": "The temporal resolution of this indicator (not of the reporting). Might not be the same as Reporting Cadence (e.g. a daily indicator may be reported only once a week).",
42-
"reporting_cadence": "The frequency with which this indicator is reported. This may be different from the temporal granularity.",
43-
"reporting_lag": 'The number of days from the last day of a reported period until the first reported value for that period is usually available in Delphi Epidata. E.g. if reporting U.S. epiweeks (Sunday through Saturday), and the first report is usually available in Delphi Epidata on the following Friday, The Reporting Lag is 6. By "usually available" we mean when it\'s "supposed to be" available based on our current understanding of the data provider\'s operations and Delphi\'s ingestion pipeline. That is the date on which we think of the data as showing up "on time", and relative to which we track unusual delays.',
44-
"revision_cadende": 'How frequently are revised values (e.g. "backfill") usually reported (if any)?',
45-
"population": 'The population or demographic group reflected by the indicator ("All" means the entire population)',
46-
"population_stratifiers": "What population or demographic stratifiers are available, if any?",
47-
"surveillance_categories": "Which surveillance categories or rungs in the Severity Pyramid does this indicator attempt to track? Some indicators may approximately track multiple categories.",
48-
"original_data_provider": "The owner or supplier of the original or raw data used to create this indicator.",
49-
"pre_processing": "Brief description of main data processing used in creating this set of indicators, including smoothing and aggregation. For more details, see the documentation.",
50-
"censoring": "Is any of the data being censored (e.g. small counts)? If so how, and how much impact does it have (e.g. approximate fraction of values affected).",
51-
"dua_required": "Applicable data use terms (may apply even to publicly accessible indicators).",
52-
}
53-
5423
HEADER_DESCRIPTION = "Discover, display and download real-time infectious disease indicators (time series) that track a variety of pathogens, diseases and syndromes in a variety of locations (primarily within the USA). Browse the list, or filter it first by locations and pathogens of interest, by surveillance categories, and more. Expand any row to expose and select from a set of related indicators, then hit 'Show Selected Indicators' at bottom to plot or export your selected indicators, or to generate code snippets to retrieve them from the Delphi Epidata API. Most indicators are served from the Delphi Epidata real-time repository, but some may be available only from third parties or may require prior approval."
5524

5625
FLUVIEW_INDICATORS_MAPPING = {"wili": "%wILI", "ili": "%ILI"}
@@ -193,8 +162,12 @@ def get_context_data(self, **kwargs):
193162
filter.indicators_qs, filter.qs.values_list("id", flat=True)
194163
)
195164
)
196-
context["filters_descriptions"] = FILTERS_DESCRIPTIONS
197-
context["columns_descriptions"] = COLUMNS_DESCRIPTIONS
165+
context["filters_descriptions"] = (
166+
FilterDescription.get_all_descriptions_as_dict()
167+
)
168+
context["columns_descriptions"] = (
169+
ColumnDescription.get_all_descriptions_as_dict()
170+
)
198171
context["header_description"] = HEADER_DESCRIPTION
199172
context["available_geographies"] = Geography.objects.filter(
200173
used_in="indicators"

0 commit comments

Comments
 (0)