2010-02-24 18 views
7

Utilizzo lo fork di Ben Firshman di django-MPTT (hat tip a Daniel Roseman per recommendation).Riordinare i nodi figlio in django-MPTT

Mi sono bloccato cercando di riordinare i nodi che condividono un genitore comune. Ho un elenco di chiavi primarie, in questo modo:

ids = [5, 9, 7, 3] 

Tutti questi nodi hanno un genitore, dire con chiave primaria 1.

Allo stato attuale, questi nodi sono ordinate [5, 3, 9, 7], come posso riordinarli a [5, 9, 7, 3]?

Ho provato qualcosa di simile:

last_m = MyModel.get(pk = ids.pop(0)) 
last_m.move_to(last_m.parent, position='first-child') 

for id in ids: 
    m = MyModel.get(pk = id) 
    m.move_to(last_m, position='right') 

che mi aspetto di fare quello che voglio, per il docs on move_to, ma non sembra cambiare nulla. A volte sembra spostare il primo elemento in ids per essere il primo figlio del suo genitore, a volte no.

ho ragione nella mia lettura dei documenti per move_to che chiamare move_to su un nodo n con position=right e un obiettivo che è un fratello di n si sposterà n a subito dopo l'obiettivo?

È possibile che abbia rovinato la tabella dei miei modelli nel tentativo di capirlo, quindi forse il codice sopra è effettivamente corretto. È anche possibile che ci sia un modo molto più elegante per farlo (forse uno che non coinvolge gli O(n) e gli aggiornamenti O(n)).

Ho frainteso qualcosa?

Domanda bonus: esiste un modo per forzare django-MPTT a ricostruire i valori lft e rght per tutte le istanze di un determinato modello?

risposta

5

Penso che questo sia un artefatto di un errore in MPTT che ho menzionato prima - quando sposti i nodi, aggiorna correttamente l'istanza del nodo che stai spostando, ma non aggiorna l'istanza di l'obiettivo (anche se viene aggiornato nel database).

La conseguenza di questo è che nel codice, ogni m viene spostato a destra del last_m - ma i valori della last_m riflettono ancora la posizione prima dello spostamento, in modo che la prossima mossa utilizza i valori originali LFT/destra invece dei nuovi post-move.

La soluzione è per ricaricare last_m ogni volta:

for id in ids: 
    last_m = MyModel.objects.get(pk=last_m.id) 
    m = MyModel.get(pk = id) 
    m.move_to(last_m, position='right') 
+0

ho sospettato che fosse qualcosa a che fare con quella - dopo aver letto alcune delle vostre risposte alle domande MPTT. Darò questo andare. Hai qualche idea sulla domanda bonus? –

+0

@Daniel - ha dimenticato di chiudere il ciclo su quello. La tua risposta ha funzionato alla grande. Ancora un po 'nervoso per MPTT e la possibilità che l'albero si metta in cattive condizioni: hai qualche consiglio per gestirlo? –

+3

Vecchia domanda, ma per tutti quelli che inciampa qui - puoi ricostruire un albero MPTT con ModelName.tree.rebuild(). Questo è utile se hai definito il campo MPTTMeta order_insertion_by e hai bisogno di aggiornare l'ordine del tuo albero. – Nagyman

Problemi correlati