Bail on incorrect headers
This commit is contained in:
parent
37a698c77b
commit
aa9bdacb18
3 changed files with 67 additions and 55 deletions
|
@ -37,17 +37,20 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
# Report successes, failures and summaries
|
# Report successes, failures and summaries
|
||||||
print()
|
print()
|
||||||
for upsert_msg in results.get("upserts"):
|
if results.get("upserts"):
|
||||||
print(upsert_msg)
|
for upsert_msg in results.get("upserts"):
|
||||||
|
print(upsert_msg)
|
||||||
|
|
||||||
# Stored errors has the form:
|
# Stored errors has the form:
|
||||||
# self.errors = [{3: ["Incorrect foo", "Non-existent bar"]}, {7: [...]}]
|
# self.errors = [{3: ["Incorrect foo", "Non-existent bar"]}, {7: [...]}]
|
||||||
for error_dict in results.get("errors"):
|
if results.get("errors"):
|
||||||
for k, error_list in error_dict.items():
|
for error_dict in results.get("errors"):
|
||||||
print(f"\nSkipped CSV row {k}:")
|
for k, error_list in error_dict.items():
|
||||||
for msg in error_list:
|
print(f"\nSkipped CSV row {k}:")
|
||||||
print(f"- {msg}")
|
for msg in error_list:
|
||||||
|
print(f"- {msg}")
|
||||||
|
|
||||||
print()
|
print()
|
||||||
for summary_msg in results.get("summaries"):
|
if results.get("summaries"):
|
||||||
print(summary_msg)
|
for summary_msg in results.get("summaries"):
|
||||||
|
print(summary_msg)
|
||||||
|
|
|
@ -17,9 +17,11 @@ class CSVImporter:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.error_msgs = []
|
self.results = {
|
||||||
self.upsert_msgs = []
|
"errors": [],
|
||||||
self.summary_msgs = []
|
"upserts": [],
|
||||||
|
"summaries": [],
|
||||||
|
}
|
||||||
self.line_count = 0
|
self.line_count = 0
|
||||||
self.upsert_count = 0
|
self.upsert_count = 0
|
||||||
|
|
||||||
|
@ -39,6 +41,13 @@ class CSVImporter:
|
||||||
# fileobj comes from browser upload (in-memory)
|
# fileobj comes from browser upload (in-memory)
|
||||||
csv_reader = csv.DictReader(codecs.iterdecode(fileobj, "utf-8"))
|
csv_reader = csv.DictReader(codecs.iterdecode(fileobj, "utf-8"))
|
||||||
|
|
||||||
|
# DI check: Do we have expected header row?
|
||||||
|
header = csv_reader.fieldnames
|
||||||
|
expected = ['Title', 'Group', 'Task List', 'Created Date', 'Due Date', 'Completed', 'Created By', 'Assigned To', 'Note', 'Priority']
|
||||||
|
if not header == expected:
|
||||||
|
self.results.get('summaries').append(f"Inbound data does not have expected columns.\nShould be: {expected}")
|
||||||
|
return self.results
|
||||||
|
|
||||||
for row in csv_reader:
|
for row in csv_reader:
|
||||||
self.line_count += 1
|
self.line_count += 1
|
||||||
|
|
||||||
|
@ -64,18 +73,13 @@ class CSVImporter:
|
||||||
f'Upserted task {obj.id}: "{obj.title}"'
|
f'Upserted task {obj.id}: "{obj.title}"'
|
||||||
f' in list "{obj.task_list}" (group "{obj.task_list.group}")'
|
f' in list "{obj.task_list}" (group "{obj.task_list.group}")'
|
||||||
)
|
)
|
||||||
self.upsert_msgs.append(msg)
|
self.results.get("upserts").append(msg)
|
||||||
|
|
||||||
self.summary_msgs.append(f"\nProcessed {self.line_count} CSV rows")
|
self.results.get('summaries').append(f"\nProcessed {self.line_count} CSV rows")
|
||||||
self.summary_msgs.append(f"Upserted {self.upsert_count} rows")
|
self.results.get('summaries').append(f"Upserted {self.upsert_count} rows")
|
||||||
self.summary_msgs.append(f"Skipped {self.line_count - self.upsert_count} rows")
|
self.results.get('summaries').append(f"Skipped {self.line_count - self.upsert_count} rows")
|
||||||
|
|
||||||
_res = {
|
return self.results
|
||||||
"errors": self.error_msgs,
|
|
||||||
"upserts": self.upsert_msgs,
|
|
||||||
"summaries": self.summary_msgs,
|
|
||||||
}
|
|
||||||
return _res
|
|
||||||
|
|
||||||
def validate_row(self, row):
|
def validate_row(self, row):
|
||||||
"""Perform data integrity checks and set default values. Returns a valid object for insertion, or False.
|
"""Perform data integrity checks and set default values. Returns a valid object for insertion, or False.
|
||||||
|
@ -174,7 +178,7 @@ class CSVImporter:
|
||||||
|
|
||||||
# #######################
|
# #######################
|
||||||
if row_errors:
|
if row_errors:
|
||||||
self.error_msgs.append({self.line_count: row_errors})
|
self.results.get("errors").append({self.line_count: row_errors})
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# No errors:
|
# No errors:
|
||||||
|
|
|
@ -21,40 +21,45 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
<p>
|
{% if results.summaries %}
|
||||||
<b>Summary:</b>
|
<p>
|
||||||
</p>
|
<b>Summary:</b>
|
||||||
<ul>
|
</p>
|
||||||
{% for line in results.summaries %}
|
<ul>
|
||||||
<li>{{ line }}</li>
|
{% for line in results.summaries %}
|
||||||
{% endfor %}
|
<li>{{ line }}</li>
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Upserts (tasks created or updated):</b>
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
{% for line in results.upserts %}
|
|
||||||
<li>{{ line }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<b>Errors (tasks NOT created or updated):</b>
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
{% for error_row in results.errors %}
|
|
||||||
{% for k, error_list in error_row.items %}
|
|
||||||
<li>CSV row {{ k }}</li>
|
|
||||||
<ul>
|
|
||||||
{% for err in error_list %}
|
|
||||||
<li>{{ err }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% if results.upserts %}
|
||||||
</ul>
|
<p>
|
||||||
|
<b>Upserts (tasks created or updated):</b>
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
{% for line in results.upserts %}
|
||||||
|
<li>{{ line }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if results.errors %}
|
||||||
|
<p>
|
||||||
|
<b>Errors (tasks NOT created or updated):</b>
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
{% for error_row in results.errors %}
|
||||||
|
{% for k, error_list in error_row.items %}
|
||||||
|
<li>CSV row {{ k }}</li>
|
||||||
|
<ul>
|
||||||
|
{% for err in error_list %}
|
||||||
|
<li>{{ err }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue