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.

Reply via email to