On Monday, February 1, 2016 at 10:33:26 AM UTC+2, Aymeric Augustin wrote: > > > On 31 janv. 2016, at 22:55, Shai Berger <sh...@platonix.com > <javascript:>> wrote: > > > > Your message seems to be confusing the queryset API with the > model-instance > > API. > > Oops :-( > > Anyway, it seems that we agree on: > > - controlling this behavior in the query rather than in the field > definition — this avoids the awkward “ignore what the field says” query > parameter > - trying not to provide separate APIs for insert and update behavior > - improving the save(update_fields=…) API to support inserts as well as > updates >
For the .save() method we could go with a new argument fields=[...]. The way it works is that only the mentioned fields are inserted or updated. If you want the current behavior of update_fields, set force_update=True. The main reason why update_fields patch didn't ever try to target insert statements was that the feature didn't make much sense. We didn't have database defaults and we didn't have any other sort of expressions support for inserts. There was very limited use cases for skipping fields in insert. I'm not sure we have much of an use case now either (notably one can write DbDefaultExpression that compiles to sql, params = "default", [] already). What is the main use case for this feature? I've been toying around with an idea that we add a non-data descriptor (one implementing just __get__) for all fields of an model, and use this for deferred loading. Currently we use dynamically created subclasses of the model which is a hack. The way this would work is that if an instance's __dict__ doesn't have any value for given field, then we interpret that field as deferred. This would also give a natural way to refresh a given field from DB. You would set a field "deferred" manually by "del instance.field", and after that instance.field would reload that field. The descriptor wouldn't cost much, as non-data descriptors don't add any measurable overhead when the attribute is set on the instance's __dict__. I think the feature would be backwards compatible (though without trying it is hard to be sure). This feature would also allow skipping fields on insert: instance = MyModel(); del instance.some_field; instance.save() -> some_field is skipped as it is deferred; instance.some_field -> some_field is refreshed from DB. This would close the gap in the APIs. I would like to see support for expressions that can tell Django the field should be skipped in update/insert and if the field should be refreshed from database after update/insert. This would give a nice low-level API for manipulating the behavior of save() and bulk_insert(). I don't see a need to mix this with the current pull request. The biggest problem for such expressions is that they don't make any sense when using a model. For example TransactionNow() isn't a nice value for last_update field in any other context than saving. Not sure this is a big enough problem to worry, but something to consider anyways. Refreshable expressions would give a natural way for skipping fields on insert. Also, things such as database defaults would be easy to use with the ORM: class DbDefault(Expression): refresh_on_insert = True refresh_on_update = True def as_sql(self, compiler, connection): return "default", [] my_instance = MyInstance(uuid=DbDefault()) print(my_instance.uuid) -> "DbDefault()" my_instance.save() print(my_instance.uuid) -> "f81d4fae-7dec-11d0-a765-00a0c91e6bf6" (or whatever the DB happens to generate) - Anssi -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To post to this group, send email to django-developers@googlegroups.com. Visit this group at https://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/5310c9fc-d26a-469b-9a9c-dcdd437195b1%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.