import csv ui
This commit is contained in:
parent
5911d422f5
commit
1d7816d9d7
4 changed files with 91 additions and 1 deletions
|
@ -333,7 +333,8 @@ class CsvImporter(Task):
|
|||
success = import_function(row)
|
||||
self.progress(success)
|
||||
|
||||
def validate_file(self, filename: str) -> bool:
|
||||
@classmethod
|
||||
def validate_file(cls, filename: str) -> bool:
|
||||
"""Validate that the given file is a valid CSV export ZIP file.
|
||||
|
||||
Args:
|
||||
|
|
|
@ -213,6 +213,66 @@
|
|||
</form>
|
||||
</details>
|
||||
</article>
|
||||
<article>
|
||||
<details>
|
||||
<summary>{% trans 'Import marks, reviews and notes from CSV' %}</summary>
|
||||
<form action="{% url 'users:import_csv' %}"
|
||||
method="post"
|
||||
enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<ul>
|
||||
<li>{% trans 'Upload a ZIP file containing CSV files exported from NeoDB.' %}</li>
|
||||
<li>{% trans 'Existing marks and reviews with newer dates will be preserved.' %}</li>
|
||||
</ul>
|
||||
<br>
|
||||
<input type="file" name="file" required accept=".zip">
|
||||
<p>
|
||||
{% trans 'Visibility' %}:
|
||||
<br>
|
||||
<label for="csv_visibility_0">
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="0"
|
||||
required=""
|
||||
id="csv_visibility_0"
|
||||
checked>
|
||||
{% trans 'Public' %}
|
||||
</label>
|
||||
<label for="csv_visibility_1">
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="1"
|
||||
required=""
|
||||
id="csv_visibility_1">
|
||||
{% trans 'Followers Only' %}
|
||||
</label>
|
||||
<label for="csv_visibility_2">
|
||||
<input type="radio"
|
||||
name="visibility"
|
||||
value="2"
|
||||
required=""
|
||||
id="csv_visibility_2">
|
||||
{% trans 'Mentioned Only' %}
|
||||
</label>
|
||||
</p>
|
||||
<input type="submit" value="{% trans 'Import' %}" />
|
||||
<small>
|
||||
{% if csv_import_task %}
|
||||
<br>
|
||||
{% trans 'Last import started' %}: {{ csv_import_task.created_time }}
|
||||
{% trans 'Status' %}: {{ csv_import_task.get_state_display }}。
|
||||
<br>
|
||||
{{ csv_import_task.message }}
|
||||
{% if csv_import_task.metadata.failed_items %}
|
||||
{% trans 'Failed items' %}:
|
||||
<br>
|
||||
<textarea readonly>{% for item in csv_import_task.metadata.failed_items %}{{item}} {% endfor %}</textarea>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</small>
|
||||
</form>
|
||||
</details>
|
||||
</article>
|
||||
<article>
|
||||
<details>
|
||||
<summary>{% trans 'Export Data' %}</summary>
|
||||
|
|
|
@ -15,6 +15,7 @@ urlpatterns = [
|
|||
path("data/import/douban", import_douban, name="import_douban"),
|
||||
path("data/import/letterboxd", import_letterboxd, name="import_letterboxd"),
|
||||
path("data/import/opml", import_opml, name="import_opml"),
|
||||
path("data/import/csv", import_csv, name="import_csv"),
|
||||
path("data/export/reviews", export_reviews, name="export_reviews"),
|
||||
path("data/export/marks", export_marks, name="export_marks"),
|
||||
path("data/export/csv", export_csv, name="export_csv"),
|
||||
|
|
|
@ -14,6 +14,7 @@ from django.utils.translation import gettext as _
|
|||
from common.utils import GenerateDateUUIDMediaFilePath
|
||||
from journal.exporters import CsvExporter, DoufenExporter, NdjsonExporter
|
||||
from journal.importers import (
|
||||
CsvImporter,
|
||||
DoubanImporter,
|
||||
GoodreadsImporter,
|
||||
LetterboxdImporter,
|
||||
|
@ -98,6 +99,7 @@ def data(request):
|
|||
"import_task": DoubanImporter.latest_task(request.user),
|
||||
"export_task": DoufenExporter.latest_task(request.user),
|
||||
"csv_export_task": CsvExporter.latest_task(request.user),
|
||||
"csv_import_task": CsvImporter.latest_task(request.user),
|
||||
"ndjson_export_task": NdjsonExporter.latest_task(request.user),
|
||||
"letterboxd_task": LetterboxdImporter.latest_task(request.user),
|
||||
"goodreads_task": GoodreadsImporter.latest_task(request.user),
|
||||
|
@ -319,3 +321,29 @@ def import_opml(request):
|
|||
else:
|
||||
messages.add_message(request, messages.ERROR, _("Invalid file."))
|
||||
return redirect(reverse("users:data"))
|
||||
|
||||
|
||||
@login_required
|
||||
def import_csv(request):
|
||||
if request.method == "POST":
|
||||
f = (
|
||||
settings.MEDIA_ROOT
|
||||
+ "/"
|
||||
+ GenerateDateUUIDMediaFilePath("x.zip", settings.SYNC_FILE_PATH_ROOT)
|
||||
)
|
||||
os.makedirs(os.path.dirname(f), exist_ok=True)
|
||||
with open(f, "wb+") as destination:
|
||||
for chunk in request.FILES["file"].chunks():
|
||||
destination.write(chunk)
|
||||
if not CsvImporter.validate_file(f):
|
||||
messages.add_message(request, messages.ERROR, _("Invalid file."))
|
||||
return redirect(reverse("users:data"))
|
||||
CsvImporter.create(
|
||||
request.user,
|
||||
visibility=int(request.POST.get("visibility", 0)),
|
||||
file=f,
|
||||
).enqueue()
|
||||
messages.add_message(
|
||||
request, messages.INFO, _("File is uploaded and will be imported soon.")
|
||||
)
|
||||
return redirect(reverse("users:data"))
|
||||
|
|
Loading…
Add table
Reference in a new issue