|
|
@ -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): |
|
|
|