Hi Aymeric,
Your message seems to be confusing the queryset API with the model-instance
API. Details below.
On Sunday 31 January 2016 21:24:17 Aymeric Augustin wrote:
>
> 1) Ignore some fields on updates
>
> Django already provides three ways to do this:
>
> MyModel.objects.defer(‘ignored_1’, ‘ignored_2’).save()
> MyModel.objects.only(‘included_1’, ‘included_2’).save()
> MyModel.objects.save(update_fields=[‘included_1’, ‘included_2’])
>
> While we’re there, I don’t know if there’s a reason why `update_fields`
> can’t be replaced with `only()`. Both appear to achieve the same effet and
> `only()` is shorter. Could we deprecate `update_fields`?
>
only() is a queryset method. save() is a model method. There is actually no
MyModel.objects.save(), just MyModel.objects.only('field1').get(...).save().
Adding only() to model instances makes very little sense (is it supposed to
defer fields which have already been fetched?).
>
> 2) Ignore some fields on inserts
>
> Since Django abstracts the insert/update distinction with its single API,
> `save()`, I’m reluctant to create insert_* / update_* APIs.
>
> I don’t know how `defer()` and `only()` behave on inserts.
They don't. Since they only apply to objects fetched from the database, they
can only have any effect on updates (and I'm not even sure they do that).
WRT the original request: Owais, your API now seems to have gone a bit beyond
the needs detailed in the ticket description. In detail:
1. I think the separation between "delegate" and "return" in field options is
artificial (I find even the separation between "on insert" and "on update"
questionable). Django models always read (and write) all the fields against the
database, unless specifically told otherwise, and when told otherwise, it is on
a per-query basis, not in field definitions. You don't have a "deferred" flag
on
any field, so it is odd to have an equivalent only for computed fields. Thus,
of
your field optinos, I'd use only the "is_delegated" flag -- perhaps I'd allow
it
to have, besides True and False, a value for "insert only" (I would have to
see an example where "update only" made sense before suggesting that too).
2. The name "delegated" is a bit odd. "db_computed" or "from_db" seem better
to me; "delegated" is just too abstract (doesn't say delegated to whom, and
there are many options).
3. Once the fields are marked as computed in the database, any attempt to set
them explicitly should either override the database calculation, or be an
error; regardless of the comments above on API for choosing the fields, your
example:
class MyModel(models.Model):
pytthon_ts = fields.DatetimeField()
db_ts = fields.DatetimeField(delegated=True)
# This will only update python_ts as db_ts is delegated to database
MyModel.objects.update(db_ts=now(), python_ts=now())
I wouldn't like that behavior; updating python_ts is sensible, erroring out is
sensible, quietly ignoring user input isn't. Also, disabling triggers on a
per-query basis is at best suspicious. As consequence from all these,
ignore_delegates() seems problematic.
4. This leaves us with a "hole" in the API: Current APIs let us pick fields to
retrieve when we're selecting (only() and defer()) and fields to save when
we're updating (save(update_fields=...)) but the new API gives us a way to
retrieve fields on saving, with no way to defer those. I'd handle that with a
new argument to save, say 'refresh_fields' -- if it is not given, all computed
fields are retrieved.
5. In very very general -- look at the use cases in the ticket. The first case,
database-defined defaults, was discussed on this list[1] and a different
solution was agreed upon (though I don't think it was implemented yet). It has
also been made a lot easier since the ticket was filed, because we now have
database functions which we didn't have back then. The other use-cases are for
fields whose values are always controlled in the database; so, you can make
this patch a lot simpler by dropping the option for a field to be updated from
both the database and the app.
Hope this helps,
(and like Aymeric, sorry I didn't find the time to react to this sooner),
Shai.
[1] https://groups.google.com/d/topic/django-developers/3mcro17Gb40/discussion