From 7c8cf74e15092c0e46bdacd2d1de3ce0ebd0e73a Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sat, 20 Jun 2015 22:01:34 -0300 Subject: [PATCH] Migrate legacy tables without a pk --- legacy/scripts/migration.py | 102 ++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 39 deletions(-) diff --git a/legacy/scripts/migration.py b/legacy/scripts/migration.py index 241c78d80..35a54a933 100644 --- a/legacy/scripts/migration.py +++ b/legacy/scripts/migration.py @@ -1,14 +1,13 @@ from django.apps.config import AppConfig from django.core.exceptions import ObjectDoesNotExist -from django.db import connection, models +from django.db import connections, models from django.db.models.base import ModelBase +from model_mommy import mommy from field_mappings import field_mappings -from migration_base import legacy_app +from migration_base import legacy_app, appconfs from parlamentares.models import Parlamentar -from model_mommy import mommy - def info(msg): print 'INFO: ' + msg @@ -36,7 +35,7 @@ def none_to_false(value): return bool(value) -def migrate(obj, count_limit=None): +def migrate(obj=appconfs, count_limit=None): # warning: model/app migration order is of utmost importance to_delete = [] @@ -59,12 +58,23 @@ def _do_migrate(obj, to_delete, count_limit=None): raise TypeError('Parameter must be a Model, AppConfig or a sequence of them') -def exec_sql(sql): - cursor = connection.cursor() +def exec_sql(sql, db='default'): + cursor = connections[db].cursor() cursor.execute(sql) return cursor +def iter_sql_records(sql, db): + class Record(object): + pass + cursor = exec_sql(sql, db) + fieldnames = [name[0] for name in cursor.description] + for row in cursor.fetchall(): + record = Record() + record.__dict__.update(zip(fieldnames, row)) + yield record + + def save_with_id(new, id): sequence_name = '%s_id_seq' % type(new)._meta.db_table cursor = exec_sql('SELECT last_value from %s;' % sequence_name) @@ -93,42 +103,56 @@ def migrate_model(model, to_delete, count_limit=None): legacy_model = legacy_app.get_model(model.__name__) old_pk_name = legacy_model._meta.pk.name + + # setup migration strategy for tables with or without a pk if old_pk_name == 'id': # There is no pk in the legacy table - pass - # ... - # ... + + def get_old_pk(old): + return '-- WITHOUT PK --' + + def save(new, id): + new.save() + + old_records = iter_sql_records( + 'select * from ' + legacy_model._meta.db_table, 'legacy') else: - for old in legacy_model.objects.all().order_by(old_pk_name)[:count_limit]: - old_pk = getattr(old, old_pk_name) - new = model() - for new_field, old_field in field_mappings[model].items(): - value = getattr(old, old_field) - model_field = model._meta.get_field(new_field) - transform = special_transforms.get(model_field) - if transform: - value = transform(value) - else: - # check for a relation - if isinstance(model_field, models.ForeignKey) and value is not None: - try: - value = model_field.related_model.objects.get(id=value) - except ObjectDoesNotExist: - msg = 'FK [%s (%s) : %s] not found for value %s' % ( - model.__name__, old_pk, model_field.name, value) - if value == 0: - # we interpret FK == 0 as actually FK == NONE - value = None - warn(msg + ' => NONE for zero value') - else: - value = make_stub(model_field.related_model, value) - warn(msg + ' => STUB CREATED') + def get_old_pk(old): + return getattr(old, old_pk_name) + save = save_with_id + old_records = legacy_model.objects.all().order_by(old_pk_name)[:count_limit] + + # convert old records to new ones + for old in old_records: + old_pk = get_old_pk(old) + new = model() + for new_field, old_field in field_mappings[model].items(): + value = getattr(old, old_field) + model_field = model._meta.get_field(new_field) + transform = special_transforms.get(model_field) + if transform: + value = transform(value) + else: + # check for a relation + if isinstance(model_field, models.ForeignKey) and value is not None: + try: + value = model_field.related_model.objects.get(id=value) + except ObjectDoesNotExist: + msg = 'FK [%s (%s) : %s] not found for value %s' % ( + model.__name__, old_pk, model_field.name, value) + if value == 0: + # we interpret FK == 0 as actually FK == NONE + value = None + warn(msg + ' => NONE for zero value') else: - assert value - setattr(new, new_field, value) - save_with_id(new, old_pk) - if getattr(old, 'ind_excluido', False): - to_delete.append(new) + value = make_stub(model_field.related_model, value) + warn(msg + ' => STUB CREATED') + else: + assert value + setattr(new, new_field, value) + save(new, old_pk) + if getattr(old, 'ind_excluido', False): + to_delete.append(new) def get_ind_excluido(obj):