On Sun, 2008-04-27 at 20:18 -0700, Ken Arnold wrote:
> On Apr 27, 8:58 pm, Malcolm Tredinnick <[EMAIL PROTECTED]>
> wrote:
> > On Sun, 2008-04-27 at 17:52 -0700, [EMAIL PROTECTED] wrote:
> > > I'd like to point out that in #2705, the patch creators have put the
> > > API on the side of the get(), as for_update(), so that the decision
> > > about whether the save should update or create is saved as state on
> > > the model instances themselves.  I don't really like that syntax, but
> > > it is probably worth noting.
> >
> > I know about that, but it's an entirely different problem (and more
> > complex).
> 
> 
> I think floguy has a point: how you get at the model object specifies
> the saving behavior that you want.

Only sometimes. And "select for update" is very heavyweight method of
doing so. If you crash or hang and don't release the lock correctly, you
mess up everybody. So now your code has another place where it has to
trust everything else (the current case of that is manual transaction
management). An unlikely failure mode, but very serious when it happens
(trying to track down problems caused by incorrectly unreleased locks
can be unnecessarily time consuming on a busy system).

> If you did `Model.objects.get()`, then saving the resulting object
> clearly means updating that specific object (and probably you want to
> error if it no longer exists)

Probably/possibly, but not always. Making it invariable would be an
error.

> If you did `Model.objects.create()`, then you just created it anyway
> But that currently creates an object with the constructor and calls
> `save()` on it. This is Malcolm's problem case: that `save` is
> semantically identical to an update, though it shouldn't be.
> 
> Possible fix: define more clearly whether Django thinks that the model
> is in the database or not. Currently that's (IIRC) based on whether
> the model has a primary key. But as Malcolm points out, a semantic
> primary key breaks this assumption.

> 
> Maybe a model can have some generic "database pointer" attribute. It's
> `None` for a newly-created model, so the `save` in `create` does the
> right thing: it always tries to make a new object, even if the primary
> key was specified in the arguments. 

We still need a way to specify that the initial save should be an update
because you don't always need to retrieve before creating something to
update. I've got one application in production that updates a database
table based on information coming from an RSS feed. The identifiers it
gets from the feed may exist or they may not (in the database). I don't
care: I enter the latest value in any case because it's correct. So
Django's current save() behaviour is ideal there.

This isn't to say the "default" action idea is bad. It's something I was
thinking of as the next step here (there are a few next steps). First we
need a way to control saving one way or the other, then we need can add
things that might take advantage of it automatically.

I mentioned session management in my earlier reply to Adrian; that's a
case where "only update" is a reasonable default save behaviour. I
suspect only update is a pretty good default for most stuff retrieved
from the database, but it needs a way to be controlled. And I'd like
save() to still be usable as a single call. Having to do

        obj.set_must_create()
        obj.save()
        
rather than

        obj.save(force_create=True)
        
means there are two lines that must stay together. Not horrible, but one
is less than two and it's not really less readable.

Now, save() inside could very well make its default behaviour vary based
on whether the model was loaded from the database or not, but this must
be controllable.

So I think this feature is worth having, but it doesn't remove the
initial API requirement, whether it be at the save() or save_base()
level and I can't see a reason not to expose it via save().

Regards,
Malcolm

-- 
Everything is _not_ based on faith... take my word for it. 
http://www.pointy-stick.com/blog/


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to