from os.path import exists from importlib.machinery import SourceFileLoader from django.apps import apps from collections import OrderedDict import importlib from pprint import pprint def transfer_objects(data_type): for app in apps.get_app_configs(): if exists(f"{app.path}/transfer_data.py"): card_module = SourceFileLoader("transfer", f"{app.path}/transfer_data.py").load_module() if not hasattr(card_module, "data_types") or not isinstance(card_module.data_types, dict) or len(card_module.data_types) < 1: continue for module_data_type, transfer_funcs in card_module.data_types.items(): if data_type == module_data_type: # card['app_label'] = app.label # models_list[model] = card for transfer_func in transfer_funcs: print(f"========================== FUNCTION {transfer_func.__name__} ================================") transfer_func() # if len(models_list) < 1: # print(f"Models with data type {data_type} not found in structure") # exit(1) # models_list = sort_by_dependencies(models_list) # # for model, card in models_list.items(): # transfer_data(model, card) # TRANSFER DATA FUNCTION def transfer_data(model, card): legacy_model_queryset = get_legacy_data(card) print("==============================================================================") print(model) fields_map = get_fields_map(card, legacy_model_queryset) # ************************** UTILITIES ****************************** # Get map of fields def get_fields_map(card, queryset): relations = card['fields']['relations'] if "relations" in card['fields'] else None if relations: del (card['fields']['relations']) fields_list = list(card['fields'].values())[0] app_queryset_list = [] # print("==============================================================================") # pprint(card) # print("==============================================================================") for legacy_object in queryset.iterator(): app_queryset_dict = {} for app_field, legacy_field in fields_list.items(): app_value = convert_field_from_legacy_to_app(legacy_object, legacy_field) if app_value is not None: app_queryset_dict[app_field] = app_value if relations is not None: for relation_table, relation_data in relations.items(): # print(f"{relation_table.lower()}_set") print(legacy_object.pagetext) # relation_object = getattr(legacy_object, f"{relation_table.lower()}_set") # print(relation_object) print("==============================") app_queryset_list.append(app_queryset_dict) return app_queryset_list # Convert field def convert_field_from_legacy_to_app(legacy_object, legacy_field): result = None if isinstance(legacy_field, tuple): if isinstance(legacy_field[0], tuple): # legacy_attributes = {} # for legacy_attribute in legacy_field: print(legacy_field) else: if hasattr(legacy_object, legacy_field[0]): try: legacy_data = getattr(legacy_object, legacy_field[0]) except Exception as e: raise AttributeError(f"Attribute {legacy_field} not found in {legacy_object}: {e}") field_module = legacy_field[-1].split(".") try: field_type = getattr(importlib.import_module(".".join(field_module[:-1])), field_module[-1]) except Exception as e: raise ValueError(f"Cannot set new field type for field {legacy_field}: {e}") if len(legacy_field) == 3: result = field_type(**{legacy_field[1]: legacy_data}) elif len(legacy_field) == 2: result = field_type(legacy_data) else: print(f"Attribute {legacy_field} not found in {legacy_object.__dict__}") else: if hasattr(legacy_object, legacy_field): result = getattr(legacy_object, legacy_field) else: print(f"Attribute {legacy_field} not found in {legacy_object.__dict__}") return result # Get legacy model data def get_legacy_data(card): if "fields" not in card: print("You must set fields list") return card_fields = card['fields'] relations = card_fields['relations'] if 'relations' in card_fields else None if relations: del (card_fields['relations']) if len(card_fields) > 1: print("You must set one table to transfer") return try: legacy_table = list(card_fields.keys())[0] except Exception as e: print(f"Cannot get legacy table name from {card_fields.keys()}") return try: fields = list(card_fields.values())[0] except Exception as e: print(f"Cannot get legacy fields from {card_fields.values()}") return try: legacy_model = apps.get_model(app_label="transfer", model_name=legacy_table) except LookupError as e: print(f"ERROR: legacy model {legacy_table} can not be loaded: {e}") return legacy_fields = [] for legacy_field in fields.values(): if isinstance(legacy_field, str): legacy_fields.append(legacy_field) elif isinstance(legacy_field, tuple): if isinstance(legacy_field[0], tuple): """Группа полей""" for legacy_field_group in legacy_field: legacy_fields.append(legacy_field_group[1]) else: """Одиночное поле""" legacy_fields.append(legacy_field[0]) queryset = legacy_model.objects.all()[:50]# TODO: remove after debug # Возвращаем зависимости на место if relations is not None: queryset = add_legacy_relation_data(queryset, relations) card['fields']['relations'] = relations return queryset # Add relation data to queryset def add_legacy_relation_data(queryset, relations): for relation_table in relations.keys(): queryset = queryset.prefetch_related(relation_table.lower()) return queryset # Models sort def sort_by_dependencies(data): """Сортировка моделей по зависимостям""" """Сначала мы сортируем модели по зависимостям в обратном порядке, используя сортировку вставкой""" result = [] for model, card in data.items(): if "dependencies" in card and isinstance(card['dependencies'], tuple): for model_dependency in result: if model_dependency in card['dependencies']: result.insert(result.index(model_dependency), model) break else: result.append(model) """Затем мы создаём сортированный словарь из реверса получившегося результата""" result = OrderedDict( [(model, data[model]) for model in reversed(result)] ) return result