Skip to content

Commit 8b3eaf9

Browse files
authored
Merge pull request #201 from cmu-delphi/development
Development
2 parents d7ec0aa + 526656c commit 8b3eaf9

File tree

8 files changed

+154
-46
lines changed

8 files changed

+154
-46
lines changed

src/base/resources.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
"display_order_number": 2,
1010
"short_name": "HHS",
1111
},
12+
"hhs-region": {
13+
"display_name": "U.S. HHS Region",
14+
"display_order_number": 2,
15+
"short_name": "HHS",
16+
},
1217
"census-region": {
1318
"display_name": "U.S. Census Region",
1419
"display_order_number": 3,
@@ -34,40 +39,66 @@
3439
"display_order_number": 7,
3540
"short_name": "ADM 3",
3641
},
37-
"hrr": {
42+
"hsa": {
3843
"display_name": "Hospital Referral Region (HRR)",
3944
"display_order_number": 8,
45+
"short_name": "HSA-NCI",
46+
},
47+
"hrr": {
48+
"display_name": "Hospital Referral Region (HRR)",
49+
"display_order_number": 9,
4050
"short_name": "HRR",
4151
},
4252
"msa": {
4353
"display_name": "Metropolitan Statistical Area (MSA)",
44-
"display_order_number": 9,
54+
"display_order_number": 10,
4555
"short_name": "MSA",
4656
},
4757
"dma": {
4858
"display_name": "Designated Market Area (DMA)",
49-
"display_order_number": 10,
59+
"display_order_number": 11,
5060
"short_name": "DMA",
5161
},
5262
"other_substate_region": {
5363
"display_name": "Other Substate Region",
54-
"display_order_number": 11,
64+
"display_order_number": 12,
5565
"short_name": "Other Substate Region",
5666
},
5767
"FluSurv-Net site": {
5868
"display_name": "FluSurv-Net site (see documentation)",
59-
"display_order_number": 12,
69+
"display_order_number": 13,
6070
"short_name": "FluSurv-Net site",
6171
},
6272
"facility": {
6373
"display_name": 'Hospital ("Facility")',
64-
"display_order_number": 13,
74+
"display_order_number": 14,
6575
"short_name": "Facility",
6676
},
6777
"lat_long": {
6878
"display_name": "Lat/Long",
69-
"display_order_number": 14,
79+
"display_order_number": 15,
7080
"short_name": "Lat/Long",
7181
},
72-
"N/A": {"display_name": "N/A", "display_order_number": 15, "short_name": "N/A"},
82+
"N/A": {"display_name": "N/A", "display_order_number": 16, "short_name": "N/A"},
7383
}
84+
85+
86+
def get_geographic_mapping_by_name(name):
87+
"""
88+
Get geographic granularity mapping by key or by display_name.
89+
90+
First tries to get by key, then searches by display_name if not found.
91+
Returns a tuple (key, value) where key is the dictionary key and value
92+
is the mapping dict, or None if not found.
93+
"""
94+
# First try to get by key
95+
mapping = GEOGRAPHIC_GRANULARITY_MAPPING.get(name)
96+
if mapping:
97+
return (name, mapping)
98+
99+
# If not found, search by display_name
100+
for key, value in GEOGRAPHIC_GRANULARITY_MAPPING.items():
101+
if value.get("display_name") == name:
102+
return (key, value)
103+
104+
return None

src/epiportal/settings.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636
"other_endpoint_source_subdivisions": "https://docs.google.com/spreadsheets/d/1zb7ItJzY5oq1n-2xtvnPBiJu2L3AqmCKubrLkKJZVHs/export?format=csv&gid=214580132",
3737
"indicator_sets": "https://docs.google.com/spreadsheets/d/1zb7ItJzY5oq1n-2xtvnPBiJu2L3AqmCKubrLkKJZVHs/export?format=csv&gid=1266808975",
3838
"non_delphi_indicator_sets": "https://docs.google.com/spreadsheets/d/1zb7ItJzY5oq1n-2xtvnPBiJu2L3AqmCKubrLkKJZVHs/export?format=csv&gid=1266477926",
39-
"indicators": "https://docs.google.com/spreadsheets/d/1MdT5y1etftBQd4f1rmcZxfedi7ESSsoBhAs0cf5PCKM/export?format=csv&gid=329338228",
40-
"other_endpoint_indicators": "https://docs.google.com/spreadsheets/d/1MdT5y1etftBQd4f1rmcZxfedi7ESSsoBhAs0cf5PCKM/export?format=csv&gid=1364181703",
41-
"non_delphi_indicators": "https://docs.google.com/spreadsheets/d/1MdT5y1etftBQd4f1rmcZxfedi7ESSsoBhAs0cf5PCKM/export?format=csv&gid=493612863",
39+
"indicators": "https://docs.google.com/spreadsheets/d/1zb7ItJzY5oq1n-2xtvnPBiJu2L3AqmCKubrLkKJZVHs/export?format=csv&gid=329338228",
40+
"other_endpoint_indicators": "https://docs.google.com/spreadsheets/d/1zb7ItJzY5oq1n-2xtvnPBiJu2L3AqmCKubrLkKJZVHs/export?format=csv&gid=1364181703",
41+
"non_delphi_indicators": "https://docs.google.com/spreadsheets/d/1zb7ItJzY5oq1n-2xtvnPBiJu2L3AqmCKubrLkKJZVHs/export?format=csv&gid=493612863",
4242
"us_state_indicator_sets": "https://docs.google.com/spreadsheets/d/1zb7ItJzY5oq1n-2xtvnPBiJu2L3AqmCKubrLkKJZVHs/export?format=csv&gid=232438393",
4343
"us_state_indicators": "https://docs.google.com/spreadsheets/d/1zb7ItJzY5oq1n-2xtvnPBiJu2L3AqmCKubrLkKJZVHs/export?format=csv&gid=1158629578"
4444
}

src/fixtures/geographic_granularities.json

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,24 @@
7676
"short_name": "ADM 3"
7777
}
7878
},
79+
{
80+
"model": "base.Geography",
81+
"pk": 14,
82+
"fields": {
83+
"name": "hsa",
84+
"display_name": "Health Service Area (HSA-NCI)",
85+
"display_order_number": 8,
86+
"used_in": "indicatorsets",
87+
"short_name": "HSA-NCI"
88+
}
89+
},
7990
{
8091
"model": "base.Geography",
8192
"pk": 8,
8293
"fields": {
8394
"name": "hrr",
8495
"display_name": "Hospital Referral Region (HRR)",
85-
"display_order_number": 8,
96+
"display_order_number": 9,
8697
"used_in": "indicatorsets",
8798
"short_name": "HRR"
8899
}
@@ -93,7 +104,7 @@
93104
"fields": {
94105
"name": "msa",
95106
"display_name": "Metropolitan Statistical Area (MSA)",
96-
"display_order_number": 9,
107+
"display_order_number": 10,
97108
"used_in": "indicatorsets",
98109
"short_name": "MSA"
99110
}
@@ -104,7 +115,7 @@
104115
"fields": {
105116
"name": "dma",
106117
"display_name": "Designated Market Area (DMA)",
107-
"display_order_number": 10,
118+
"display_order_number": 11,
108119
"used_in": "indicatorsets",
109120
"short_name": "DMA"
110121
}
@@ -115,7 +126,7 @@
115126
"fields": {
116127
"name": "facility",
117128
"display_name": "Hospital (\"Facility\")",
118-
"display_order_number": 11,
129+
"display_order_number": 12,
119130
"used_in": "indicatorsets",
120131
"short_name": "Facility"
121132
}
@@ -126,7 +137,7 @@
126137
"fields": {
127138
"name": "FluSurv-Net site",
128139
"display_name": "FluSurv-Net site (see documentation)",
129-
"display_order_number": 12,
140+
"display_order_number": 13,
130141
"used_in": "indicatorsets",
131142
"short_name": "FluSurv-Net site"
132143
}
@@ -137,7 +148,7 @@
137148
"fields": {
138149
"name": "N/A",
139150
"display_name": "N/A",
140-
"display_order_number": 13,
151+
"display_order_number": 14,
141152
"used_in": "indicatorsets",
142153
"short_name": "N/A"
143154
}

src/indicators/admin.py

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,26 @@
33
from django.urls import path
44
from import_export.admin import ImportExportModelAdmin
55

6+
from base.models import Geography, Pathogen, SeverityPyramidRung
67
from base.utils import download_source_file, import_data
7-
from indicators.models import (Category, FormatType, Indicator,
8-
IndicatorGeography, IndicatorType,
9-
NonDelphiIndicator, OtherEndpointIndicator,
10-
USStateIndicator)
11-
from indicators.resources import (IndicatorBaseResource, IndicatorResource,
12-
NonDelphiIndicatorResource,
13-
OtherEndpointIndicatorResource,
14-
USStateIndicatorResource)
8+
from indicators.models import (
9+
Category,
10+
FormatType,
11+
Indicator,
12+
IndicatorGeography,
13+
IndicatorType,
14+
NonDelphiIndicator,
15+
OtherEndpointIndicator,
16+
USStateIndicator,
17+
)
18+
from indicators.resources import (
19+
IndicatorBaseResource,
20+
IndicatorResource,
21+
NonDelphiIndicatorResource,
22+
OtherEndpointIndicatorResource,
23+
USStateIndicatorResource,
24+
)
25+
1526

1627
@admin.register(IndicatorType)
1728
class IndicatorTypeAdmin(admin.ModelAdmin):
@@ -47,8 +58,35 @@ class IndicatorGeographyAdmin(admin.ModelAdmin):
4758
list_select_related = True
4859

4960

61+
class BaseIndicatorAdmin(ImportExportModelAdmin):
62+
def formfield_for_manytomany(self, db_field, request, **kwargs):
63+
"""
64+
Filter geographic_levels field to show only a subset of Geography objects.
65+
Modify the filter criteria as needed.
66+
"""
67+
if db_field.name == "geographic_levels":
68+
# Filter to show only geographies used in indicatorsets
69+
# You can modify this filter to show a different subset
70+
kwargs["queryset"] = Geography.objects.filter(
71+
used_in="indicators"
72+
).order_by("display_order_number")
73+
if db_field.name == "pathogens":
74+
# Filter to show only geographies used in indicatorsets
75+
# You can modify this filter to show a different subset
76+
kwargs["queryset"] = Pathogen.objects.filter(used_in="indicators").order_by(
77+
"display_order_number"
78+
)
79+
if db_field.name == "severity_pyramid_rungs":
80+
# Filter to show only geographies used in indicatorsets
81+
# You can modify this filter to show a different subset
82+
kwargs["queryset"] = SeverityPyramidRung.objects.filter(
83+
used_in="indicators"
84+
).order_by("display_order_number")
85+
return super().formfield_for_manytomany(db_field, request, **kwargs)
86+
87+
5088
@admin.register(Indicator)
51-
class IndicatorAdmin(ImportExportModelAdmin):
89+
class IndicatorAdmin(BaseIndicatorAdmin):
5290
list_display = (
5391
"name",
5492
"description",
@@ -102,7 +140,7 @@ def download_indicator(self, request):
102140

103141

104142
@admin.register(OtherEndpointIndicator)
105-
class OtherEndpointIndicatorAdmin(ImportExportModelAdmin):
143+
class OtherEndpointIndicatorAdmin(BaseIndicatorAdmin):
106144
list_display = (
107145
"name",
108146
"description",
@@ -138,9 +176,7 @@ def get_urls(self):
138176
),
139177
path(
140178
"download-source-file",
141-
self.admin_site.admin_view(
142-
self.download_other_endpoint_indicator
143-
),
179+
self.admin_site.admin_view(self.download_other_endpoint_indicator),
144180
name="download_other_endpoint_indicator",
145181
),
146182
]
@@ -162,7 +198,7 @@ def download_other_endpoint_indicator(self, request):
162198

163199

164200
@admin.register(NonDelphiIndicator)
165-
class NonDelphiIndicatorAdmin(ImportExportModelAdmin):
201+
class NonDelphiIndicatorAdmin(BaseIndicatorAdmin):
166202
list_display = (
167203
"name",
168204
"member_name",
@@ -214,7 +250,7 @@ def download_nondelphi_indicator(self, request):
214250

215251

216252
@admin.register(USStateIndicator)
217-
class USStateIndicatorAdmin(ImportExportModelAdmin):
253+
class USStateIndicatorAdmin(BaseIndicatorAdmin):
218254
list_display = ("name", "indicator_set")
219255
search_fields = ("name", "indicator_set")
220256
ordering = ("name",)
@@ -257,4 +293,4 @@ def download_us_state_indicator(self, request):
257293
return download_source_file(
258294
settings.SPREADSHEET_URLS["us_state_indicators"],
259295
"US_State_Indicators.csv",
260-
)
296+
)

src/indicatorsets/admin.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.urls import path
44
from import_export.admin import ImportExportModelAdmin
55

6+
from base.models import Geography, Pathogen, SeverityPyramidRung
67
from base.utils import download_source_file, import_data
78
from indicatorsets.models import (
89
ColumnDescription,
@@ -15,9 +16,36 @@
1516
from indicatorsets.resources import USStateIndicatorSetResource
1617

1718

19+
class BaseIndicatorSetAdmin(ImportExportModelAdmin):
20+
def formfield_for_manytomany(self, db_field, request, **kwargs):
21+
"""
22+
Filter geographic_levels field to show only a subset of Geography objects.
23+
Modify the filter criteria as needed.
24+
"""
25+
if db_field.name == "geographic_levels":
26+
# Filter to show only geographies used in indicatorsets
27+
# You can modify this filter to show a different subset
28+
kwargs["queryset"] = Geography.objects.filter(
29+
used_in="indicatorsets"
30+
).order_by("display_order_number")
31+
if db_field.name == "pathogens":
32+
# Filter to show only geographies used in indicatorsets
33+
# You can modify this filter to show a different subset
34+
kwargs["queryset"] = Pathogen.objects.filter(
35+
used_in="indicatorsets"
36+
).order_by("display_order_number")
37+
if db_field.name == "severity_pyramid_rungs":
38+
# Filter to show only geographies used in indicatorsets
39+
# You can modify this filter to show a different subset
40+
kwargs["queryset"] = SeverityPyramidRung.objects.filter(
41+
used_in="indicatorsets"
42+
).order_by("display_order_number")
43+
return super().formfield_for_manytomany(db_field, request, **kwargs)
44+
45+
1846
# Register your models here.
1947
@admin.register(IndicatorSet)
20-
class IndicatorSetAdmin(ImportExportModelAdmin):
48+
class IndicatorSetAdmin(BaseIndicatorSetAdmin):
2149
"""
2250
Admin interface for the IndicatorSet model.
2351
"""
@@ -78,7 +106,7 @@ def download_indicator_set(self, request):
78106

79107

80108
@admin.register(NonDelphiIndicatorSet)
81-
class NonDelphiIndicatorSetAdmin(ImportExportModelAdmin):
109+
class NonDelphiIndicatorSetAdmin(BaseIndicatorSetAdmin):
82110
"""
83111
Admin interface for the IndicatorSet model.
84112
"""
@@ -141,7 +169,7 @@ def download_nondelphi_indicator_set(self, request):
141169

142170

143171
@admin.register(USStateIndicatorSet)
144-
class USStateIndicatorSetAdmin(ImportExportModelAdmin):
172+
class USStateIndicatorSetAdmin(BaseIndicatorSetAdmin):
145173
"""
146174
Admin interface for the USStateIndicatorSet model.
147175
"""

src/indicatorsets/forms.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class IndicatorSetFilterForm(forms.ModelForm):
5454
)
5555

5656
hosted_by_delphi = forms.BooleanField(
57-
label="Hosted by Delphi",
57+
label="Delphi-hosted Only",
5858
required=False,
5959
widget=forms.CheckboxInput(attrs={"value": "on"}),
6060
)
@@ -90,4 +90,4 @@ def __init__(self, *args, **kwargs) -> None:
9090
if field_name != "hosted_by_delphi":
9191
field.label = ""
9292
else:
93-
field.label = "Hosted by Delphi"
93+
field.label = "Delphi-hosted Only"

src/indicatorsets/resources.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from import_export.widgets import ForeignKeyWidget, ManyToManyWidget
55

66
from base.models import GeographicScope, Geography, Pathogen, SeverityPyramidRung
7-
from base.resources import GEOGRAPHIC_GRANULARITY_MAPPING
7+
from base.resources import get_geographic_mapping_by_name
88
from indicatorsets.models import (
99
IndicatorSet,
1010
NonDelphiIndicatorSet,
@@ -70,9 +70,11 @@ def process_available_geographies(row) -> None:
7070
for geography in available_geographies:
7171
geography_name = geography.strip()
7272
default_params = {"used_in": "indicatorsets"}
73-
try:
74-
default_params.update(GEOGRAPHIC_GRANULARITY_MAPPING[geography_name])
75-
except KeyError:
73+
result = get_geographic_mapping_by_name(geography_name)
74+
if result:
75+
geography_name, mapping = result
76+
default_params.update(mapping)
77+
else:
7678
max_display_order_number = Geography.objects.filter(
7779
used_in="indicatorsets"
7880
).aggregate(Max("display_order_number"))["display_order_number__max"]

0 commit comments

Comments
 (0)