Browse Source

Melhora desempenho da migracao

pull/1477/head
Marcio Mazza 7 years ago
parent
commit
ac03224316
  1. 125
      sapl/legacy/migration.py

125
sapl/legacy/migration.py

@ -1,5 +1,6 @@
import re
from datetime import date
from functools import lru_cache
from subprocess import PIPE, call
import pkg_resources
@ -11,7 +12,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.db import ProgrammingError, connections, models
from django.db import ProgrammingError, connections, models, transaction
from django.db.models import CharField, Count, Max, TextField
from django.db.models.base import ModelBase
from model_mommy import mommy
@ -122,17 +123,24 @@ class ForeignKeyFaltando(ObjectDoesNotExist):
pass
@lru_cache()
def _get_all_ids_from_model(model):
# esta função para uso apenas em get_fk_related
return set(model.objects.values_list('id', flat=True))
def get_fk_related(field, value, label=None):
if value is None and field.null:
return None
# if field.related_model.objects.filter(id=value).exists():
if value in _get_all_ids_from_model(field.related_model):
return value
else:
try:
return field.related_model.objects.get(id=value)
except ObjectDoesNotExist as ex:
msg = 'FK [%s] não encontrada para o valor %s (em %s %s)' % (
field.name, value, field.model.__name__, label or '---')
warn(msg)
raise ForeignKeyFaltando(msg)
msg = 'FK [%s] não encontrada para o valor %s (em %s %s)' % (
field.name, value, field.model.__name__, label or '---')
warn(msg)
raise ForeignKeyFaltando(msg)
def get_field(model, fieldname):
@ -410,37 +418,39 @@ class DataMigrator:
field_type = field.get_internal_type()
if old_field_name:
old_value = getattr(old, old_field_name)
if isinstance(field, models.ForeignKey):
old_type = type(old) # not necessarily a model
if hasattr(old_type, '_meta') and \
old_type._meta.pk.name != 'id':
if field_type == 'ForeignKey':
# not necessarily a model
if hasattr(old, '_meta') and old._meta.pk.name != 'id':
label = old.pk
else:
label = '-- SEM PK --'
fk_field_name = '{}_id'.format(field.name)
value = get_fk_related(field, old_value, label)
setattr(new, fk_field_name, value)
else:
value = getattr(old, old_field_name)
# TODO rever esse DateField após as mudança para datas com
# timezone
if field_type == 'DateField' and \
not field.null and value is None:
# TODO REVER ISSO
descricao = 'A data 1111-11-11 foi colocada no lugar'
problema = 'O valor da data era nulo ou inválido'
warn("O valor do campo %s (%s) do model %s "
"era inválido => %s" % (
field.name, field_type,
field.model.__name__, descricao))
value = date(1111, 11, 11)
self.data_mudada['obj'] = new
self.data_mudada['descricao'] = descricao
self.data_mudada['problema'] = problema
self.data_mudada.setdefault('nome_campo', []).\
append(field.name)
if (field_type in ['CharField', 'TextField']
and value in [None, 'None']):
value = ''
setattr(new, field.name, value)
# TODO rever esse DateField após as mudança para datas com
# timezone
if field_type == 'DateField' and \
not field.null and value is None:
# TODO REVER ISSO
descricao = 'A data 1111-11-11 foi colocada no lugar'
problema = 'O valor da data era nulo ou inválido'
warn("O valor do campo %s (%s) do model %s "
"era inválido => %s" % (
field.name, field_type,
field.model.__name__, descricao))
value = date(1111, 11, 11)
self.data_mudada['obj'] = new
self.data_mudada['descricao'] = descricao
self.data_mudada['problema'] = problema
self.data_mudada.setdefault('nome_campo', []).\
append(field.name)
if (field_type in ['CharField', 'TextField']
and value in [None, 'None']):
value = ''
setattr(new, field.name, value)
def migrate(self, obj=appconfs, interativo=True):
# warning: model/app migration order is of utmost importance
@ -527,29 +537,32 @@ class DataMigrator:
ajuste_depois_salvar = AJUSTE_DEPOIS_SALVAR.get(model)
# convert old records to new ones
for old in old_records:
if getattr(old, 'ind_excluido', False):
# não migramos registros marcados como excluídos
continue
new = model()
try:
self.populate_renamed_fields(new, old)
if ajuste_antes_salvar:
ajuste_antes_salvar(new, old)
except ForeignKeyFaltando:
# tentamos preencher uma FK e o ojeto relacionado não existe
# então este é um objeo órfão: simplesmente ignoramos
continue
else:
save(new, old)
if ajuste_depois_salvar:
ajuste_depois_salvar(new, old)
with transaction.atomic():
for old in old_records:
if getattr(old, 'ind_excluido', False):
# não migramos registros marcados como excluídos
continue
new = model()
try:
self.populate_renamed_fields(new, old)
if ajuste_antes_salvar:
ajuste_antes_salvar(new, old)
except ForeignKeyFaltando:
# tentamos preencher uma FK e o ojeto relacionado
# não existe
# então este é um objeo órfão: simplesmente ignoramos
continue
else:
save(new, old)
if ajuste_depois_salvar:
ajuste_depois_salvar(new, old)
if self.data_mudada:
with reversion.create_revision():
save_relation(**self.data_mudada)
self.data_mudada.clear()
reversion.set_comment('Ajuste de data pela migração')
if self.data_mudada:
with reversion.create_revision():
save_relation(**self.data_mudada)
self.data_mudada.clear()
reversion.set_comment(
'Ajuste de data pela migração')
# necessário para ajustar sequence da tabela para o ultimo valor de id
ultimo_valor = get_last_value(model)
@ -650,7 +663,7 @@ def adjust_parlamentar(new, old):
def adjust_participacao(new, old):
composicao = Composicao()
composicao.comissao, composicao.periodo = [
composicao.comissao_id, composicao.periodo_id = [
get_fk_related(Composicao._meta.get_field(name), value)
for name, value in (('comissao', old.cod_comissao),
('periodo', old.cod_periodo_comp))]

Loading…
Cancel
Save