import csv import os import shutil import tempfile from django.conf import settings from catalog.common.models import Item from catalog.models import ItemCategory from common.utils import GenerateDateUUIDMediaFilePath from journal.models import Note, Review, ShelfMember, q_item_in_category from users.models import Task # _mark_heading = [ "title", "info", "links", "timestamp", "status", "rating", "comment", "tags", ] _review_heading = [ "title", "info", "links", "timestamp", "title", "content", ] _note_heading = [ "title", "info", "links", "timestamp", "progress", "title", "content", ] class CsvExporter(Task): class Meta: app_label = "journal" # workaround bug in TypedModel TaskQueue = "export" DefaultMetadata = { "file": None, "total": 0, } @property def filename(self) -> str: d = self.created_time.strftime("%Y%m%d%H%M%S") return f"neodb_{self.user.username}_{d}_csv" def get_item_info(self, item: Item) -> str: s = [] for a in [ "imdb", "isbn", "year", "pub_year", "season_number", "episode_number", ]: if hasattr(item, a) and getattr(item, a): s.append(f"{a}:{getattr(item, a)}") for a in ["author", "artist", "director", "host"]: if hasattr(item, a) and getattr(item, a): s.append(f"{a}:{'/'.join(getattr(item, a))}") return " ".join(s) def get_item_links(self, item: Item) -> str: links = [item.absolute_url] for ext in item.external_resources.all(): links.append(ext.url) return " ".join(links) def run(self): user = self.user temp_dir = tempfile.mkdtemp() temp_folder_path = os.path.join(temp_dir, self.filename) os.makedirs(temp_folder_path) total = 0 for category in [ ItemCategory.Movie, ItemCategory.TV, ItemCategory.Music, ItemCategory.Book, ItemCategory.Game, ItemCategory.Podcast, ItemCategory.Performance, ]: q = q_item_in_category(category) csv_file_path = os.path.join(temp_folder_path, f"{category}") marks = ( ShelfMember.objects.filter(owner=user.identity) .filter(q) .order_by("created_time") ) with open(csv_file_path + "_mark.csv", "w") as csvfile: writer = csv.writer(csvfile) writer.writerow(_mark_heading) for mark in marks: total += 1 item = mark.item line = [ item.display_title, self.get_item_info(item), self.get_item_links(item), mark.created_time.isoformat(), mark.shelf_type, mark.rating_grade, mark.comment_text, " ".join(mark.tags), ] writer.writerow(line) reviews = ( Review.objects.filter(owner=user.identity) .filter(q) .order_by("created_time") ) with open(csv_file_path + "_review.csv", "w") as csvfile: writer = csv.writer(csvfile) writer.writerow(_review_heading) for review in reviews: total += 1 item = review.item line = [ item.display_title, self.get_item_info(item), self.get_item_links(item), review.created_time.isoformat(), review.title, review.body, ] writer.writerow(line) with open(csv_file_path + "_note.csv", "w") as csvfile: writer = csv.writer(csvfile) writer.writerow(_note_heading) notes = ( Note.objects.filter(owner=user.identity) .filter(q) .order_by("created_time") ) for note in notes: total += 1 item = note.item line = [ item.display_title, self.get_item_info(item), self.get_item_links(item), note.created_time.isoformat(), note.progress_display, note.title, note.content, ] writer.writerow(line) filename = GenerateDateUUIDMediaFilePath( "f.zip", settings.MEDIA_ROOT + "/" + settings.EXPORT_FILE_PATH_ROOT ) if not os.path.exists(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) shutil.make_archive(filename[:-4], "zip", temp_folder_path) self.metadata["file"] = filename self.metadata["total"] = total self.message = f"{total} records exported." self.save()