Skip to content

Commit 379d65b

Browse files
Merge pull request #1769 from IFRCGo/fix/no-search-for-only-district-name
Refactor of Project importer
2 parents 13fec18 + 5ee8901 commit 379d65b

File tree

2 files changed

+31
-30
lines changed

2 files changed

+31
-30
lines changed

api/management/commands/ingest_appealdocs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ def handle(self, **_):
4848
self.stdout.write('Fetching data for appeal_docs:: PUBLIC')
4949
self.load(PUBLIC_SOURCE, False)
5050
# Private
51-
self.stdout.write('\nFetching data for appeal_docs:: FEDNET')
51+
self.stdout.write('Fetching data for appeal_docs:: FEDNET')
5252
self.load(FEDNET_SOURCE, True)

deployments/forms.py

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -172,31 +172,34 @@ def _parse_integer(integer):
172172
programme_types = {label.lower(): value for value, label in ProgrammeTypes.choices}
173173
statuses = {label.lower(): value for value, label in Statuses.choices}
174174

175-
# Not enums, but maybe could be used later to avoid multiple queries for id-s: FIXME
176-
# sectors = {t.title.lower(): t.id for t in Sector.objects.all()}
177-
# sector_tags = {t.title.lower(): t.id for t in SectorTag.objects.all()}
178-
# disaster_types ?
175+
# Not enums, but can be used to avoid multiple queries for foreign key id-s
176+
sectors = {t.title.lower(): t.id for t in Sector.objects.all()}
177+
sector_tags = {t.title.lower(): t.id for t in SectorTag.objects.all()}
178+
disaster_types = {t.name.lower(): t.id for t in DisasterType.objects.all()}
179179

180180
c = self.Columns
181181

182182
# Extract from import csv file
183183
for row_number, row in enumerate(reader, start=2):
184-
district_names = [
185-
d.strip() for d in row[c.DISTRICT].split(',')
186-
] if row[c.DISTRICT].lower() not in ['countrywide', ''] else []
184+
district_names = list({d.strip() for d in filter(
185+
lambda x: x.strip() != '', row[c.DISTRICT].split(','))
186+
}) if row[c.DISTRICT].lower() not in ['countrywide', ''] else []
187187
reporting_ns_name = row[c.REPORTING_NS].strip()
188188
country_name = row[c.COUNTRY].strip()
189189
disaster_type_name = row[c.DISASTER_TYPE].strip()
190190
sector_name = row[c.PRIMARY_SECTOR].strip()
191-
tag_names = [
192-
d.strip() for d in row[c.TAGS].split(',')
193-
]
191+
tag_names = list({d.strip() for d in filter(
192+
lambda x: x.strip() != '', row[c.TAGS].split(','))
193+
})
194194

195195
reporting_ns = Country.objects.filter(
196196
Q(name__iexact=reporting_ns_name) | Q(society_name__iexact=reporting_ns_name)
197197
).first()
198-
project_sector = Sector.objects.filter(title=sector_name).first()
199-
disaster_type = DisasterType.objects.filter(name__iexact=disaster_type_name).first()
198+
199+
# Cheaper than: Sector.objects.filter(title=sector_name).first()
200+
project_sector_id = sectors[sector_name.lower()] if sector_name else None
201+
# Cheaper than: DisasterType.objects.filter(name__iexact=disaster_type_name).first()
202+
disaster_type_id = disaster_types[disaster_type_name.lower()] if disaster_type_name else None
200203

201204
row_errors = {}
202205
project_districts = []
@@ -223,36 +226,34 @@ def _parse_integer(integer):
223226
if project_country is None:
224227
row_errors['project_country'] = [f'Country "{country_name}" is not available.']
225228

226-
227-
project_sectortags = []
229+
project_sectortag_ids = [] # if we use sectortag objects, not only id-s, the "project_sectortags" would be better.
228230
if tag_names:
229-
project_sectortags = list(SectorTag.objects.filter(
230-
reduce(lambda acc, item: acc | item,
231-
[Q(title=title) for title in tag_names],
232-
)
233-
).all())
234-
# Check if all tag_names is available in db
235-
if len(project_sectortags) != len(tag_names):
236-
# A validation error will be raised. This is just a custom message
237-
row_errors['project_sectortags'] = [f'Given tags: "{tag_names}" are not all available.']
231+
all_ok = True
232+
for t in tag_names:
233+
if t.lower() not in sector_tags:
234+
all_ok = False
235+
row_errors['project_sectortags'] = [f'Given tag: "{t}" is not all available.']
236+
if all_ok:
237+
# Cheaper than: list(SectorTag.objects.filter(reduce(lambda acc, item: acc | item, [Q(title=title) for title in tag_names],)).all())
238+
project_sectortag_ids = {title: sector_tags[title.lower()] for title in tag_names}.values()
238239

239240
if reporting_ns is None:
240241
row_errors['reporting_ns'] = [f'Given country "{reporting_ns_name}" is not available.']
241242
# Optional, but can be invalid
242-
if disaster_type is None and disaster_type_name != '':
243+
if disaster_type_id is None and disaster_type_name != '':
243244
row_errors['disaster_type'] = [f'Given disaster type "{disaster_type_name}" is not available.']
244245

245246
project = Project(
246247
user=user,
247248
reporting_ns=reporting_ns,
248249
project_country=project_country,
249250
# project_districts and secondary_sectors are M2M fields, they will be added later.
250-
dtype=disaster_type,
251+
primary_sector_id=project_sector_id,
252+
dtype_id=disaster_type_id,
251253

252254
# Enum fields
253255
operation_type=operation_types.get(_key_clean(row[c.OPERATION_TYPE])),
254256
programme_type=programme_types.get(_key_clean(row[c.PROGRAMME_TYPE])),
255-
primary_sector=project_sector,
256257
status=statuses.get(_key_clean(row[c.STATUS])),
257258

258259
name=row[c.PROJECT_NAME],
@@ -273,7 +274,7 @@ def _parse_integer(integer):
273274
try:
274275
project.full_clean()
275276
if len(row_errors) == 0:
276-
projects.append([project, project_districts, project_sectortags])
277+
projects.append([project, project_districts, project_sectortag_ids])
277278
else:
278279
errors.append(_get_error_message(row_number, row_errors))
279280
except ValidationError as e:
@@ -285,9 +286,9 @@ def _parse_integer(integer):
285286

286287
Project.objects.bulk_create([p[0] for p in projects])
287288
# Set M2M Now
288-
for project, project_districts, project_sectortags in projects:
289+
for project, project_districts, project_sectortag_ids in projects:
289290
project.project_districts.set(project_districts)
290-
project.secondary_sectors.set(project_sectortags)
291+
project.secondary_sectors.set(project_sectortag_ids)
291292
# Return projects for ProjectImport
292293
return [p[0] for p in projects]
293294

0 commit comments

Comments
 (0)