coins-demo/todo/management/commands/import_csv.py
Scot Hacker 4a99d90d1e
Import tasks via CSV (#51)
* Bare start on CSV support

* Move core of CSV importer to operations

* More validations, break out validation function

* Validate dates and TaskList; convert errors to list of dictionaries

* Finish upsert code, and documentation

* Print msgs from the mgmt command, not the operations module

* Handle BOM marks

* Handle both in-memory and local file objects

* Update readme

* Working browser-upload view

* Bail on incorrect headers

* Fix default values and finish example spreadsheet

* Change column order, update docs

* Update index.md for RTD

* First round of responses to PR feedback

* Restore independent summaries/errors/upserts properties

* PR responses

* Split off reusable date validator into separate function

* Fix URLs append

* General test suite for CSV importer
2019-03-25 23:19:11 -07:00

57 lines
2 KiB
Python

import sys
from typing import Any
from pathlib import Path
from django.core.management.base import BaseCommand, CommandParser
from todo.operations.csv_importer import CSVImporter
class Command(BaseCommand):
help = """Import specifically formatted CSV file containing incoming tasks to be loaded.
For specfic format of inbound CSV, see data/import_example.csv.
For documentation on upsert logic and required fields, see README.md.
"""
def add_arguments(self, parser: CommandParser) -> None:
parser.add_argument(
"-f", "--file", dest="file", default=None, help="File to to inbound CSV file."
)
def handle(self, *args: Any, **options: Any) -> None:
# Need a file to proceed
if not options.get("file"):
print("Sorry, we need a filename to work from.")
sys.exit(1)
filepath = Path(options["file"])
if not filepath.exists():
print(f"Sorry, couldn't find file: {filepath}")
sys.exit(1)
# Encoding "utf-8-sig" means "ignore byte order mark (BOM), which Excel inserts when saving CSVs."
with filepath.open(mode="r", encoding="utf-8-sig") as fileobj:
importer = CSVImporter()
results = importer.upsert(fileobj, as_string_obj=True)
# Report successes, failures and summaries
print()
if results["upserts"]:
for upsert_msg in results["upserts"]:
print(upsert_msg)
# Stored errors has the form:
# self.errors = [{3: ["Incorrect foo", "Non-existent bar"]}, {7: [...]}]
if results["errors"]:
for error_dict in results["errors"]:
for k, error_list in error_dict.items():
print(f"\nSkipped CSV row {k}:")
for msg in error_list:
print(f"- {msg}")
print()
if results["summaries"]:
for summary_msg in results["summaries"]:
print(summary_msg)