Gotcha, thanks Malcolm.

On Mar 11, 8:26 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:
> On Wed, 2009-03-11 at 19:21 -0700, Margie wrote:
> > I have a Tile model that contains a foreign to a Chip:
>
> > class Tile(models.Model):
> >     name=models.CharField(max_length=NAME_LENGTH)
> >     chip = models.ForeignKey(Chip)
>
> > I find that I get an integrity error if I create a tile that refers to
> > a chip that has not yet been saved:
>
> > >>> c = Chip(name="chip")
> > >>> t = Tile(name="tile", chip=c)
> > >>> t.save()
> > [stack trace omitted]
> > IntegrityError: chipvision_tile.chip_id may not be NULL
>
> > This is reasonable.  So I then saved the chip and then tried to save
> > the tile, but I still get the integrity error:
> > >>> c.save()
> > >>> t.chip
> > <Chip: xchip>
> > >>> t.chip.id
> > 5
> > >>> t.save()
> > [stack trace omitted]
> > IntegrityError: chipvision_tile.chip_id may not be NULL
>
> There are some implementation details going on here and we should
> probably try to raise an error a bit earlier. The behaviour is expected
> and the solution is to not assign unsaved objects.
>
> What's going on, if you care, is that there are two attributes involved.
> The t.chip attribute is a copy of the Python object (the Chip instance).
> The t.chip_id attribute holds the value of foreign key and when you
> first assigned to t.chip, t.chip_id was set to None. That "None" isn't a
> reference to anything, so when t.chip was updated (since it's a
> reference), the t.chip_id value was not.
>
> There are a couple of potential things Django could do better here,
> including resetting the chip_id value just before saving (a little risky
> -- I think I worked out a way to do stupid things once, but I can't
> remember what it is now) or just reporting an error when you wrote
> t.chip = chip originally.
>
> Regards,
> Malcolm
>
>
>
> > However, if I then reset the chip field of the tile (just by
> > reassigning t.chip = t.chip) and then save the tile, the save now
> > works fine:
>
> > >>> t.chip = t.chip
> > >>> t.save()  # this save works!
>
> That's because setting the 'chip' attribute calls a setter method that
> also updates t.chip_id. Odd if you don't realise what's going on.
> Consistent in an implementation sense, but, as I mention, we can do
> better.
>
> Regards,
> Malcolm
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to