migration imports to new DB structure

This commit is contained in:
Hayden 2021-01-12 13:35:41 -09:00
commit e38bb01635
8 changed files with 115 additions and 14 deletions

0
dev/manual_tests.md Normal file
View file

Binary file not shown.

View file

@ -1,6 +1,7 @@
from fastapi import APIRouter, HTTPException from fastapi import APIRouter, HTTPException
from models.backup_models import BackupJob, Imports from models.backup_models import BackupJob, Imports
from services.backups.export import backup_all from services.backups.exports import backup_all
from services.backups.imports import ImportDatabase
from settings import BACKUP_DIR, TEMPLATE_DIR from settings import BACKUP_DIR, TEMPLATE_DIR
from utils.snackbar import SnackResponse from utils.snackbar import SnackResponse
@ -39,7 +40,14 @@ async def export_database(data: BackupJob):
) )
async def import_database(file_name: str): async def import_database(file_name: str):
""" Import a database backup file generated from Mealie. """ """ Import a database backup file generated from Mealie. """
imported = import_from_archive(file_name) import_db = ImportDatabase(
zip_archive=file_name,
import_recipes=True,
import_settings=False,
import_themes=False,
)
imported = import_db.run()
return imported return imported

View file

@ -1,9 +0,0 @@
import json
import shutil
import zipfile
from pathlib import Path
from utils.logger import logger
from settings import IMG_DIR, BACKUP_DIR, TEMPLATE_DIR, TEMP_DIR

View file

@ -0,0 +1,103 @@
import json
import shutil
import zipfile
from pathlib import Path
from typing import List
from services.recipe_services import Recipe
from settings import BACKUP_DIR, IMG_DIR, TEMP_DIR, TEMPLATE_DIR
from utils.logger import logger
class ImportDatabase:
def __init__(
self,
zip_archive: str,
import_recipes: bool = True,
import_settings: bool = True,
import_themes: bool = True,
force_import: bool = False,
rebase: bool = False,
) -> None:
self.archive = BACKUP_DIR.joinpath(zip_archive)
self.imp_recipes = import_recipes
self.imp_settings = import_settings
self.imp_themes = import_themes
self.force_imports = force_import
self.force_rebase = rebase
if self.archive.is_file():
self.import_dir = TEMP_DIR.joinpath("active_import")
self.import_dir.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(self.archive, "r") as zip_ref:
zip_ref.extractall(self.import_dir)
pass
else:
raise Exception("Import file does not exist")
def run(self):
if self.imp_recipes:
report = self.import_recipes()
if self.imp_settings:
self.import_settings()
if self.imp_themes:
self.import_themes()
self.clean_up()
return report if report else None
def import_recipes(self):
recipe_dir: Path = self.import_dir.joinpath("recipes")
successful_imports = []
failed_imports = []
for recipe in recipe_dir.glob("*.json"):
with open(recipe, "r") as f:
recipe_dict = json.loads(f.read())
recipe_dict = ImportDatabase._recipe_migration(recipe_dict)
try:
recipe_obj = Recipe(**recipe_dict)
recipe_obj.save_to_db()
successful_imports.append(recipe.stem)
logger.info(f"Imported: {recipe.stem}")
except:
logger.info(f"Failed Import: {recipe.stem}")
failed_imports.append(recipe.stem)
self._import_images(successful_imports)
return {"successful": successful_imports, "failed": failed_imports}
@staticmethod
def _recipe_migration(recipe_dict: dict) -> dict:
try:
del recipe_dict["_id"]
del recipe_dict["dateAdded"]
except:
logger.info("Detected new backup Schema, skipping migration...")
return recipe_dict
# Migration from list to Object Type Data
if type(recipe_dict["extras"]) == list:
recipe_dict["extras"] = {}
return recipe_dict
def _import_images(self, successful_imports: List[str]):
image_dir = self.import_dir.joinpath("images")
for image in image_dir.iterdir():
if image.stem in successful_imports:
shutil.copy(image, IMG_DIR)
def import_themes(self):
pass
def import_settings(self):
pass
def clean_up(self):
shutil.rmtree(TEMP_DIR)

View file

@ -6,9 +6,8 @@ from pathlib import Path
from services.recipe_services import IMG_DIR, Recipe from services.recipe_services import IMG_DIR, Recipe
from services.scrape_services import normalize_data, process_recipe_data from services.scrape_services import normalize_data, process_recipe_data
from settings import TEMP_DIR
CWD = Path(__file__).parent CWD = Path(__file__).parent
TEMP_DIR = CWD.parent.parent.joinpath("data", "temp")
MIGRTAION_DIR = CWD.parent.parent.joinpath("data", "migration") MIGRTAION_DIR = CWD.parent.parent.joinpath("data", "migration")

View file

@ -5,7 +5,7 @@ import requests
from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.background import BackgroundScheduler
from utils.logger import logger from utils.logger import logger
from services.backups.export import auto_backup_job from services.backups.exports import auto_backup_job
from services.meal_services import MealPlan from services.meal_services import MealPlan
from services.recipe_services import Recipe from services.recipe_services import Recipe
from services.settings_services import SiteSettings from services.settings_services import SiteSettings