gault-millau/apps/transfer/utils.py
2019-10-15 12:05:49 +03:00

206 lines
6.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):
models_list = {}
for app in apps.get_app_configs():
if exists(f"{app.path}/transfer.py"):
card_module = SourceFileLoader("transfer", f"{app.path}/transfer.py").load_module()
if not hasattr(card_module, "card") or len(card_module.card) < 1:
continue
for model, card in card_module.card.items():
if "data_type" in card and data_type == card["data_type"]:
card['app_label'] = app.label
models_list[model] = card
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)
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 = []
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
app_queryset_list.append(app_queryset_dict)
# pprint(card)
# print("*************************************")
# pprint(fields_list)
# print("*************************************")
# pprint(relations)
# print("*************************************")
# pprint(len(queryset))
print("==============================")
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.only(*legacy_fields)
# Возвращаем зависимости на место
if relations:
card['fields']['relations'] = relations
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