Skip to content

Commit

Permalink
Added sorting on calculated fields chapter
Browse files Browse the repository at this point in the history
  • Loading branch information
shabda committed Feb 6, 2018
1 parent 7da12ca commit 3b4c9b9
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 1 deletion.
Binary file added docs/no_sorting.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/optimize_queries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ How to optimize queries in Django admin?
If you have a lot of calculated fields in your admin, you can be running multipel queries per object leading to your admin can becoming quite slow.
To fix this you can override the :code:`get_queryset` method on model admin to annotate the calculated fields.

Lets take the example of this `ModelAdmin` we have for `Origin`::
Lets take the example of this :code:`ModelAdmin` we have for :code:`Origin`::

@admin.register(Origin)
class OriginAdmin(admin.ModelAdmin):
Expand Down
Binary file added docs/sorting_calculated_field.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions docs/sorting_calculated_fields.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,42 @@
How to enable sorting on calculated fields?
===========================================================

Django adds sorting capabilities on fields which are attributes on the models.
When you add a calculated field Django doesn't know how to do a :code:`order_by`, so it doesn't a sorting capability on that field.

If you want to add sorting on a caluclated field, you have to tell Django, what to pass to :code:`order_by`. You can do this by setting
:code:`admin_order_field` attribute on the calculated field method.

You start from the admin you wrote in the pervious chapter (:doc:`optimize_queries`).::

hero_count.admin_order_field = '_hero_count'
villain_count.admin_order_field = '_villain_count'


With these changes your admin becomes::

@admin.register(Origin)
class OriginAdmin(admin.ModelAdmin):
list_display = ("name", "hero_count", "villain_count")

def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.annotate(
_hero_count=Count("hero", distinct=True),
_villain_count=Count("villain", distinct=True),
)
return queryset

def hero_count(self, obj):
return obj._hero_count

def villain_count(self, obj):
return obj._villain_count

hero_count.admin_order_field = '_hero_count'
villain_count.admin_order_field = '_villain_count'


Here is the admin sorted on :code:`hero_count`

.. image:: sorting_calculated_field.png
3 changes: 3 additions & 0 deletions heroes_and_monsters/entities/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ def hero_count(self, obj):

def villain_count(self, obj):
return obj._villain_count

hero_count.admin_order_field = '_hero_count'
villain_count.admin_order_field = '_villain_count'

0 comments on commit 3b4c9b9

Please sign in to comment.