> Following up on the discussion on:
https://groups.google.com/forum/?fromgroups=#!topic/django-developers...
>
> I'd like to start a clear discussion about re-opening ticket 901.
https://code.djangoproject.com/ticket/901
>
> Ticket 901 was marked 7 years ago as won't fix and has been subject of
> debate since.
>
> I must say that I for myself was looking for such a method until I found
> that foo = Foo.objects.get(id=
foo.id) would work; which did not seem
> obvious to me then and now.
>
> Brandon put forward an argument, which is:
> reload() would cover an important use case that did not get a hearing in
> the above discussion: that you might already have handed the object off to
> some other library, which is keeping a reference from somewhere deep in its
> data structures for use when you make a final call to it. If one or more
> data structures that are being built already hold the object, then it is
> not reasonable to have to track down the object and try to swap in a new
> copy everywhere. There should be a simple way to have the existing object's
> attributes update in-place.
>
> and Anssi thinks it is a good idea to implement this.
The reasons why I think a reload() or refresh() method is a good idea:
- The above mentioned fact that if foo is already in data structure,
then you can't just reassign to foo. This is more and more an issue in
Django itself due to caching of related objects and
prefetch_related().
- If you are in some of the model's methods you can't do self =
qs.get(pk=
self.pk), more generally reassignment in any method/function
will not refresh the object in the caller of the method/function.
- We could implement deferred loading using reload/refresh(), and
thus allow for a way to customize how deferred loading happens. An
example is the idea of loading all fields at a time instead of the
current default of loading one deferred field at a time.
- This could also work as a way for allowing related objects cache
invalidation. The related objects are cached on first access, and
after that you don't have any way to force reload of the cached
object. (Maybe separate issue to be dealt with later on. But refresh()
as a name, and then eventually adding cached object invalidation seems
like a good idea to me.)
- While it might seem trivial to implement reload()/refresh() when
needed, there are some bugs waiting to happen:
- Not going through setattr() - if you assign to self.__dict__
directly you might miss __setattr__ or a descriptor's __set__ (this is
a problem for custom fields defining to_python() for example).
- Reloading fields for deferred models with qs.values() doesn't
work correctly. Django uses descriptors for both to_python()
conversion and for deferred fields implementation, so if you use
values() to_python() will not be called for deferred fields as the
deferred descriptor overrides the normal descriptor. See SubfieldBase
or FileField for problematic cases.
- Not handling field.attname/
field.name distinction correctly. For
example consider
self.user.pk vs self.user_id. If you reload user_id,
but don't invalidate self.user the values will not necessarily match.
> My question is, can we please re-open this ticket and/or discuss here what
> are the benefits and drawbacks of having a method reload() ?
Benefits mentioned above, the only drawback I can see is the addition
of one more method to Model API. So, +1 from me to the feature.
- Anssi