2010-07-29 12 views
4

J'essaie de stocker des sections d'un document dans une application Django. Le modèle ressemble:Django: stocker des données hiérarchiques

class Section(models.Model): 
    project = models.ForeignKey(Project) 
    parent_section = models.ForeignKey('Section', blank=True, null=True, related_name='child_set') 
    predecessor_section = models.ForeignKey('Section', blank=True, null=True, related_name='predecessor_set') 
    name = models.CharField(max_length=100) 
    text = models.TextField(blank=True, null=True) 

Je crée beaucoup de sections, les lier (parent_section, predecessor_section) et de les stocker en appelant chacun de leurs méthodes sauver. Toutefois, lorsque je regarde dans la table après l'avoir enregistrée, les paramètres parent_section_id et predecessor_section_id ne sont pas définis, même si des objets y étaient attachés avant l'enregistrement. Je suppose que cela a à voir avec le fait que certaines instances parent_section n'ont pas d'identifiant assigné car leur instance n'a pas encore été stockée, mais l'utilisation de transactions manuelles n'a pas pu résoudre le problème.

Des commentaires à ce sujet?

Cheers, Max

+0

J'ai juste essayé de stocker les références de parent et de prédécesseur avant l'instance réelle, mais cela n'a pas aidé non plus. – Max

Répondre

0

objets N'ayez pas d'ID avant de les avoir enregistrés dans Django ORM. Donc, je dirais que vous devez sauvegarder() l'objet, puis le référencer dans vos sections parent/enfant (et sauvegarder à nouveau les sections). Cependant, une autre option pour stocker prec et next comme pointeurs est de stocker un sequence_index (espacé de 10 pour permettre d'autres insertions sans réordonner) et d'ordonner par cet index.

+0

pour un autre échantillon pour stocker les données commandées dans un db: http://stackoverflow.com/questions/547022/how-do-i-store-orders#547076 – makapuf

+0

Balayer toutes les entités deux fois et appeler save() devrait également fonctionner (étant donné que les références sont définies initialement). Pour une raison quelconque, il ne ... – Max

+0

Ok. Je pense que je l'ai résolu. Tu avais raison, mettre la relation à nouveau est nécessaire. J'ai stocké les entités une fois et dans le 2ème passage, j'ai mis les identifiants des relations manuellement (section.parent_section_id = section.parent_section.id). Django semble les mettre automatiquement seulement quand les relations sont assignées. Les relations déjà attachées sont ignorées dans save(). – Max

0

Essayez de faire une sauvegarde() sur tous les objets, puis mettre à jour leurs relations, puis enregistrez() à nouveau tous.

Lorsque vous affectez une clé étrangère, l'ID de l'objet associé (cible) est copié. car au moment de l'attribution des relations (parent_section, predecessor_section) les objets connexes n'ont pas encore un identifiant, vous obtenez un résultat génial:

A = Section(name='A') 
B = Section(name='B') 
B.parent_section = A 
A.save() 
B.save() 
B.parent_section # this will say A 
B.parent_section_id # this will say **None** 

Mais cela devrait fonctionner:

A = Section(name='A') 
B = Section(name='B') 
A.save() 
B.save() 
B.parent_section = A 
B.parent_section # this will say A 
B.parent_section_id # this will say A.id 
B.save() # don't forget this one :) 
+0

Vous ne savez pas exactement ce que vous voulez dire par "mettre à jour leurs relations". Les relations sont déjà définies avant de sauvegarder les entités. Mais j'ai sauvegardé toutes les entités deux fois, ce qui signifie que toute relation qui n'a pas persisté lors de la première exécution persiste dans la seconde. - Les relations n'ont pas été sauvegardées ... – Max

+0

Ça ne marchera pas. les objets associés doivent avoir leurs identifiants avant de les affecter dans une relation. faites-le en 2 boucles: 1er créez tous les objets, avec juste leurs propriétés internes (ne concernant pas les autres objets Section), et save() tous. Puis, dans une autre boucle, affectez toutes les relations (parent_section, predecessor_section), puis de nouveau save(). –

+0

Oui, vous avez raison. Voir mon message ci-dessus. – Max

Questions connexes