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
This commit is contained in:
Scot Hacker 2019-03-25 23:19:11 -07:00 committed by GitHub
parent 184084c6a8
commit 4a99d90d1e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 599 additions and 15 deletions

View file

@ -0,0 +1,85 @@
{% extends "todo/base.html" %}
{% load static %}
{% block title %}Import CSV{% endblock %}
{% block content %}
<h2>
Import CSV
</h2>
<p>
Batch-import tasks by uploading a specifically-formatted CSV.
See documentation for formatting rules.
Successs and failures will be reported here.
</p>
{% if results %}
<div class="card mb-4">
<div class="card-header">
Results of CSV upload
</div>
<div class="card-body">
{% if results.summaries %}
<p>
<b>Summary:</b>
</p>
<ul>
{% for line in results.summaries %}
<li>{{ line }}</li>
{% endfor %}
</ul>
{% endif %}
{% if results.upserts %}
<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>
{% endif %}
<div class="card">
<div class="card-header">
Upload Tasks
</div>
<div class="card-body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div>
<input type="file" name="csvfile" accept="text/csv">
</div>
<button type="submit" class="btn btn-primary mt-4">Upload</button>
</form>
</div>
</div>
{% endblock %}