First, let me thank Malcolm for promptly fixing #10710. Unfortunately
#10733 is still barring the use of only() and select_related()
properly.

Given the models and admin defined above and the requirements that
 * admin changelist view should perform only a single query,
 * that should pull in only the fields that are actually used in
list_display,
the following should ideally work after #10733 is fixed:

    def queryset(self, request):
        qs = super(CAdmin, self).queryset(request)
        return qs.only('name', 'is_published', 'a', 'b',
            'a__name', 'b__name').select_related()

(actually, qs.only('name', 'is_published', 'a__name',
'b__name').select_related() would suffice.)

---

However, there's another bump on the Path to The One True Admin
Changelist Query.

If any of the related fields is nullable, e.g.

class C(Base):
    a = models.ForeignKey(A, blank=True, null=True)
    b = models.ForeignKey(B)
    is_published = models.BooleanField()

, select_related() does not pull them in by default (as Karen kindly
pointed out in #10722).

Forcing it explicitly as follows

    def queryset(self, request):
        qs = super(CAdmin, self).queryset(request)
        return qs.select_related('a', 'b')

has no effect, as ChangeList.get_query_set() blindly overrides it with
a plain select_related().

To get the desired behviour, three-valued logic is required for
ModelAdmin.list_select_related:
 * True -- always call select_related(),
 * False (the default) -- call select_related() if any of the fields
in list_display is a foreign key,
 * None (added) -- leave the queryset alone.

The patch is backwards-compatible, quite simple and the result is a
single query as expected:

--- django/contrib/admin/views/main.py  (revision 10405)
+++ django/contrib/admin/views/main.py  (working copy)
@@ -200,6 +200,8 @@
         # with a relationship.
         if self.list_select_related:
             qs = qs.select_related()
+        elif self.list_select_related is None:
+            pass
         else:
             for field_name in self.list_display:
                 try:

(validation changes omitted for clarity).

I've submitted the proposal in #10742 and am willing to drive it
further if it is accepted.
---

Finally, after #10733 and #10742 are fixed, the admin and The One True
Admin Changelist Query that satisfies the requirements is as follows:

class CAdmin(admin.ModelAdmin):
    list_display = ('name', 'a', 'b', 'is_published')
    list_select_related = None

    def queryset(self, request):
        qs = super(CAdmin, self).queryset(request)
        return qs.only('name', 'is_published', # 'a', 'b' ?
            'a__name', 'b__name').select_related('a', 'b')

Links:

#10733 -- http://code.djangoproject.com/ticket/10733
#10742 -- http://code.djangoproject.com/ticket/10742
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to