gault-millau/apps/transfer/utils.py
2019-10-20 17:59:18 +03:00

237 lines
7.3 KiB
Python

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