#17030: Remove special handling of deferred models in queryset iterators
-------------------------------------+-------------------------------------
     Reporter:  akaariai             |                    Owner:  nobody
         Type:                       |                   Status:  new
  Cleanup/optimization               |                  Version:  1.3
    Component:  Database layer       |               Resolution:
  (models, ORM)                      |             Triage Stage:  Design
     Severity:  Normal               |  decision needed
     Keywords:                       |      Needs documentation:  0
    Has patch:  1                    |  Patch needs improvement:  0
  Needs tests:  0                    |                    UI/UX:  0
Easy pickings:  0                    |
-------------------------------------+-------------------------------------
Changes (by akaariai):

 * cc: anssi.kaariainen@… (added)


Comment:

 The idea of this ticket isn't backwards compatible. Assume you have a
 model with fields a and b. Now, if you do qs.only('b'), the `__init__`
 will be called with args=[val_for_b]. If somebody has overriden the
 model's `__init__` this will break the contract of the `__init__` args. If
 args are given, the first one must be the value for first field, but after
 this patch it will be value for the second field. Hence this is backwards
 incompatible.

 So this would break:
 {{{
 class SomeModel:
    a = TextField()
    b = TextField()

    def __init__(self, *args, **kwargs):
        a_val = args[0] if args else kwargs.get('a')
        if a_val == 'some value':
            do_something()
        super(SomeModel, self).__init__(*args, **kwargs)
 }}}
 Using the attached patch .only('b') will give b's value as first arg.
 Current code will init the model with kwargs['b'] = b's value.

 Wontfixing this is a bit sad, as the speedup of 1.5-2x for .defer/.only
 queries and over 2x for .raw queries can be important. These methods are
 often used for performance reasons.

 There is one trick that could be used: detect if the model has overridden
 `__init__` method (`Model.__init__ <> deferred_class.__init__`). If there
 is no overridden `__init__`, then it is safe to use the fast-path. However
 that feels a little dirty, so maybe this one should be given a wontfix:
 backwards incompatible resolution.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/17030#comment:2>
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 post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to