views:

46

answers:

2

Hi,

I'm trying to store sections of a document in a Django app. The model looks like:

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)

I create a whole lot of sections, link them (parent_section, predecessor_section) and store them by calling each of their save methods. However, when I look into the table after saving it, the parent_section_id and the predecessor_section_id are not set, even though I had objects attached to them before saving.

I assume it has to do with the fact that some parent_section instances don't have an id assigned as their instance hasn't been stored yet, but using manual transactions couldn't solve the problem.

Any thoughts on that?

Cheers, Max

A: 

Try doing a save() on all the objects, then update their relations, and then save() all of them again.

When you assign a foreignkey, the related (target) object's id is copied. since at the moment of assigning the relations (parent_section, predecessor_section) the related objects don't have an id yet, you get a funky result:

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**

But this should work:

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 :)
Ofri Raviv
Not quite sure what you mean with "update their relations". The relations are already set prior to saving the entities. But I saved all entities twice, which means any relation that wasn't persisted in the first run is persisted in the 2nd one. - The relationships weren't saved...
Max
It won't work. the related objects need to have their ids prior to assigning them in a relation. do it in 2 loops: 1st create all the objects, with just their internal properties (not relating to other Section objects), and save() all of them. Then in another loop assign all the relations (parent_section, predecessor_section), and then save() again.
Ofri Raviv
Yes, you're right. See my post above.
Max
A: 

objects do not have an id until you save them in Django ORM.

So I'd say you need to save() the object, then reference it in your parent/child sections (and re-save the sections).

However, another option to storing prec and next as pointers is to store an sequence_index (spaced by 10 to allow further inserts wiothout reordering) and order by this index.

makapuf
for another sample to store ordered data in a db : http://stackoverflow.com/questions/547022/how-do-i-store-orders#547076
makapuf
Sweeping through all the entities twice and calling save() should also work (given that the references are set initially). For some reason it doesn't...
Max
Ok. I think I solved it. You were right, setting the relation again is necessary. I stored the entities once and in the 2nd pass, I set the ids of the relations manually (section.parent_section_id = section.parent_section.id). Django seems to be setting those automatically only when the relations are assigned. Already attached relations are ignore in save().
Max