from zipfile import BadZipFile from openpyxl import load_workbook, Workbook from .models import Product, Producer PRODUCT_FIELDS = {"ref", "name", "price"} PRODUCER_FIELDS = {"id"} def append_list(field, item): field.append(item) def append_dict(field, item): field[item.id] = item def items_from_xlsx(data, items, model_class, required_fields, append_method): if not data: raise ValueError headers = data[0] if not set(headers) >= required_fields: raise ValueError(f"Colonnes obligatoires: {', '.join(required_fields)}.") for row in data[1:]: raw = {k: v for k, v in dict(zip(headers, row)).items() if v} try: append_method(items, model_class(**raw)) except TypeError: raise ValueError(f"Erreur durant l'importation de {raw['ref']}") return items def products_and_producers_from_xlsx(delivery, data): if not isinstance(data, Workbook): try: data = load_workbook(data) except BadZipFile: raise ValueError("Impossible de lire le fichier") sheet_names = data.get_sheet_names() if len(sheet_names) != 2: raise ValueError("Le fichier doit comporter deux onglets.") # First, get the products data from the first tab. products_sheet = data.get_sheet_by_name(sheet_names[0]) delivery.products = items_from_xlsx( list(products_sheet.values), [], Product, PRODUCT_FIELDS, append_list ) # Then import producers info producers_sheet = data.get_sheet_by_name(sheet_names[1]) delivery.producers = items_from_xlsx( list(producers_sheet.values), {}, Producer, PRODUCER_FIELDS, append_dict ) delivery.persist()