Outra advertência ao migrar para Django MPTT

É importante enfatizar algo aqui.

Sempre que você salva um modelo Django-MPTT, ele irá, por padrão, reconstruir a árvore (em parte)

O que isso significa para suas migrações? Bem, digamos que você já tenha criado um relacionamento baseado em pais e filhos. Você passou pelo tutorial Django-MPTT, configurou sua TreeForeignKey, etc, e agora, você precisa de uma migração de dados para reestruturar seu banco de dados de produção para usar este novo esquema.

Originalmente, antes de pensar sobre essa advertência, implementei algo assim:

for obj in MyMPTTModel.objects.all():
obj
.lft, obj.rght, obj.parent = (0, 0, obj.old_parent)
obj
.save()
MyMPTTModel.tree.rebuild()

É bastante claro porque isso não funciona, especialmente com a minha explicação acima. Cada vez que salvamos um objeto, a árvore tenta se reconstruir. Como estamos salvando um objeto por vez, e não particularmente em uma ordem limpa, podemos acabar tendo movimentos de nó ilegais e, portanto, nossa migração falhará.

A solução? Não use o método de salvamento padrão do objeto. Tudo o que queremos fazer é salvar os 3 campos de informações no banco de dados, sem acionar uma reconstrução. Portanto, usamos o método de Model, com uma mudança simples:

obj.save() # Old
Model.save(obj) # New

Isso garante que nenhuma das coisas do MPTT seja executada (até que executemos a reconstrução manualmente), e não há verificação de ordem mal-intencionada ou qualquer outro código estranho ou classes de proxy que apenas complicariam e possivelmente quebrariam as coisas para nós.

Observe que isso é bom aqui porque é um único local que não queremos que ocorra a reconstrução. Em outros casos, eu recomendaria usar um modelo de proxy.

Links!