def translate_info_fields(sheet: SheetBinding, products: List[Product], language_code: str, ws: Worksheet): """ translating ProductInfo :param sheet: current sheet :param products: products to translate :param language_code: :param ws: """ info_columns_to_translate = sheet.columns\ .filter(is_info=True, **{f'column_name_{language_code}__isnull': False}) \ .all() logger.info( f'info columns for translation' f'={list(map(lambda x: x.column_name, info_columns_to_translate))}') info_column_names_translation_map = { getattr(c, f'column_name_{language_code}'): c.column_name_ru for c in info_columns_to_translate } for product in products: row = parser.find_row(sheet.id_column.column_name, product.xlsx_alias, ws) xlsx_product = parser.parse_row(row, ws) # activating language_code required for parse_xlsx_product_info, # otherwise it will be looking for column names in wrong language translation.activate(language_code) # parsing products from xlsx all_parsed_product_info = parser.parse_xlsx_product_info( info_columns_to_translate, xlsx_product) translation.activate(DEFAULT_LANGUAGE_CODE) # iterating over column bindings for parsed_product_info in all_parsed_product_info: parsed_product_info_name = getattr(parsed_product_info, f'name_{language_code}') # looking for current product in db, searching by main language # we are searching by main language because language_code might not be set db_product_info = product.all_info\ .filter(name=info_column_names_translation_map[parsed_product_info_name])\ .first() translation.activate(language_code) db_product_info.name = parsed_product_info.name db_product_info.description = parsed_product_info.description db_product_info.save() translation.activate(DEFAULT_LANGUAGE_CODE) logger.info( f'translated ProductInfo id={db_product_info.id} name={db_product_info.name} ' f'for Product alias={product.xlsx_alias}')
def translate_colors_field(sheet: SheetBinding, products: List[Product], language_code: str, ws: Worksheet): """ translating ProductColors names :param sheet: :param products: :param language_code: :param ws: """ for product in products: row = parser.find_row(sheet.id_column.column_name, product.xlsx_alias, ws) xlsx_product = parser.parse_row(row, ws) all_colors = parser.parse_xlsx_colors(sheet, xlsx_product) for color in filter(lambda x: x.image_name != '', all_colors): db_color = product.all_colors.filter( image_name=color.image_name).first() translation.activate(language_code) db_color.color_name = color.color_name translation.activate(DEFAULT_LANGUAGE_CODE) db_color.save()
def translate_base_fields(sheet: SheetBinding, products: List[Product], language_code: str, ws: Worksheet): """ translating base fields, which are not is_info and not is_options :param sheet: current sheet :param products: products to translate :param language_code: :param ws: """ field_columns_to_translate = sheet.columns \ .filter(is_options=False, is_info=False, field_name__in=ProductTranslationOptions.fields). \ all() logger.info( f'basic columns(fields only) for translation' f'={list(map(lambda x: x.column_name, field_columns_to_translate))}') for product in products: row = parser.find_row(sheet.id_column.column_name, product.xlsx_alias, ws) # parsing product from xlsx xlsx_product = parser.parse_row(row, ws) # iterating over basic columns and translating corresponding fields for column in field_columns_to_translate: logger.info(f'translating {column.field_name} for ' f'Product alias={product.xlsx_alias}') setattr(product, f'{column.field_name}_{language_code}', xlsx_product[column.column_name]) product.save()
def create_new_product(sheet: SheetBinding, wb: Workbook, alias: str): """ Create new product with product info, colors, product_options, thumbnail image, creating collection if not found in db. :param sheet: current sheet binding :param wb: current workbook :param alias: product alias """ row = parser.find_row(sheet.id_column.column_name, alias, wb.active) # getting data from xlsx xlsx_product = parser.parse_row(row, wb.active) pr = Product() # setting all basic attributes parser.parse_xlsx_product(pr, sheet, xlsx_product) pr.xlsx_alias = alias pr.category = sheet.category if sheet.collection_column: pr.collection = get_or_create_collection( sheet.category, xlsx_product[sheet.collection_column.column_name]) pr.save() info_columns_bindings = sheet.columns.filter(is_info=True).all() all_product_info = parser.parse_xlsx_product_info(info_columns_bindings, xlsx_product) for product_info in all_product_info: product_info.product = pr product_info.save() all_colors = parser.parse_xlsx_colors(sheet, xlsx_product) for color in all_colors: color.product = pr color.save() options_columns = sheet.columns.filter(is_options=True).all() all_product_options = parser.parse_xlsx_product_options( sheet, wb, options_columns, xlsx_product) for (product_options, options) in all_product_options: product_options.product = pr product_options.save() for option in options: option.parent = product_options option.save() thumbnail_image = ProductThumbnailImage( color=pr.all_non_blank_colors.first()) thumbnail_image.save() pr.thumbnail_image = thumbnail_image pr.save() logger.info(f'new product added with alias={alias}')
def parse_xlsx(file: io.BytesIO, update_products: bool, is_update_product_compilations: bool, remove_old_products: bool): wb = load_workbook(filename=file, data_only=True) sheet_bindings = SheetBinding.objects.all() for sheet in sheet_bindings: if sheet.sheet_name in wb.sheetnames: wb.active = wb.get_sheet_by_name(sheet.sheet_name) columns_names = parser.get_columns_names(wb.active) logger.info( f'\nworking on sheet={sheet.sheet_name} collection_name={sheet.category.name}' ) products = Product.objects.filter(category=sheet.category).all() db_aliases = set([product.xlsx_alias for product in products]) sheet_aliases = set( parser.get_all_column_values( columns_names.index(sheet.id_column.column_name) + 1, wb.active)) # deleting all products which weren't found deleted_aliases = db_aliases - sheet_aliases if remove_old_products: for alias in deleted_aliases: Product.objects.filter(xlsx_alias=alias).delete() logger.info(f'deleted {len(deleted_aliases)} products') # creating and adding new products new_aliases = sheet_aliases - db_aliases for new_alias in new_aliases: logger.info(f'\ncreating new product with alias={new_alias}') create_new_product(sheet, wb, new_alias) # updating old products if update_products: old_aliases = sheet_aliases - new_aliases for alias in old_aliases: logger.info(f'\nupdating product with alias={alias}') row = parser.find_row(sheet.id_column.column_name, alias, wb.active) xlsx_product = parser.parse_row(row, wb.active) db_product = Product.objects.get(xlsx_alias=alias) parser.parse_xlsx_product(db_product, sheet, xlsx_product) logger.info('updating product info') updating_helpers.update_product_info( sheet, db_product, xlsx_product) logger.info('updating product colors') updating_helpers.update_product_colors( sheet, db_product, xlsx_product) logger.info('updating product thumbnail') # should be called after updating product colors, ProductColor delete is overridden updating_helpers.update_product_thumbnail(db_product) logger.info('updating product options') updating_helpers.update_product_options( sheet, wb, db_product, xlsx_product) if db_product.category != sheet.category: db_product.category = sheet.category if sheet.collection_column: db_product.collection = \ get_or_create_collection(sheet.category, xlsx_product[sheet.collection_column.column_name]) db_product.save() # updating product compilations for this category if is_update_product_compilations: updating_helpers.update_product_compilations(sheet, wb)
def translate_options_field(sheet: SheetBinding, products: List[Product], language_code: str, wb: Workbook): """ translating ProductOptions and ProductOption :param sheet: :param products: :param language_code: :param wb: """ ws = wb.active options_columns_to_translate = sheet.columns \ .filter(is_options=True, **{f'column_name_{language_code}__isnull': False}) \ .all() logger.info( f'options columns for translation' f'={list(map(lambda x: x.column_name, options_columns_to_translate))}') options_column_names_translation_map = { getattr(c, f'column_name_{language_code}'): c.column_name_ru for c in options_columns_to_translate } for product in products: row = parser.find_row(sheet.id_column.column_name, product.xlsx_alias, ws) xlsx_product = parser.parse_row(row, ws) # activating language_code required for parse_xlsx_product_options, # otherwise it will be looking for column names in wrong language translation.activate(language_code) # parsing product options from xlsx all_product_options = parser\ .parse_xlsx_product_options(sheet, wb, options_columns_to_translate, xlsx_product) translation.activate(DEFAULT_LANGUAGE_CODE) for (product_options_obj, options) in all_product_options: title_in_language_code = getattr(product_options_obj, f'title_{language_code}') db_product_options_obj = product.all_options\ .filter(title=options_column_names_translation_map[title_in_language_code])\ .first() logger.info( f'translating ProductOptions title={product_options_obj.title} for ' f'Product alias={product.xlsx_alias}') translation.activate(language_code) db_product_options_obj.title = product_options_obj.title db_product_options_obj.description = product_options_obj.description translation.activate(DEFAULT_LANGUAGE_CODE) for option in options: # looking for the same option by its row db_option = db_product_options_obj.options\ .filter(xlsx_row=option.xlsx_row)\ .first() logger.info( f'translating ProductOptions title={product_options_obj.title} ' f'ProductOption name={db_option.name} for ' f'Product alias={product.xlsx_alias}') translation.activate(language_code) db_option.name = option.name translation.activate(DEFAULT_LANGUAGE_CODE) db_option.save() db_product_options_obj.save()