#31680: Preventing DeferredAttribute .__ get__ method unnecessary calls
-------------------------------------+-------------------------------------
               Reporter:  Sultan     |          Owner:  nobody
                   Type:             |         Status:  new
  Cleanup/optimization               |
              Component:  Database   |        Version:  3.1
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 To retrieve a deferred model attributes, the __get__ method is called
 twice. This is because it uses the getattr() function, which in turn
 causes the __get__ method to be called again.


 {{{
     def __get__(self, instance, cls=None):
         """
         Retrieve and caches the value from the datastore on the first
 lookup.
         Return the cached value.
         """
         if instance is None:
             return self
         data = instance.__dict__
         field_name = self.field.attname
         if field_name not in data:
             # Let's see if the field is part of the parent chain. If so we
             # might be able to reuse the already loaded value. Refs
 #18343.
             val = self._check_parent_chain(instance)
             if val is None:
                 instance.refresh_from_db(fields=[field_name])
                 **val = getattr(instance, field_name)**
             data[field_name] = val
         return data[field_name]
 }}}


 To prevent this unnecessary call, we can simply extract the value from the
 instance dict (at that moment it already contains the searched value):


 {{{
     def __get__(self, instance, cls=None):
         """
         Retrieve and caches the value from the datastore on the first
 lookup.
         Return the cached value.
         """
         if instance is None:
             return self
         data = instance.__dict__
         field_name = self.field.attname
         if field_name not in data:
             # Let's see if the field is part of the parent chain. If so we
             # might be able to reuse the already loaded value. Refs
 #18343.
             val = self._check_parent_chain(instance)
             if val is None:
                 instance.refresh_from_db(fields=[field_name])
                 # Now the instance dict contains the reloaded data.
                 # Using getattr() will do extra call to __get__ method.
                 **val = data[field_name]**
             data[field_name] = val
         return data[field_name]
 }}}

 This reduces the number of method calls.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31680>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.748859a81cf1f192d81263291afdff95%40djangoproject.com.

Reply via email to