Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions django_mongodb_backend/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from django.contrib import admin
from django.contrib.admin.options import IncorrectLookupParameters
from django.contrib.admin.views.main import ChangeList
from django.core.paginator import InvalidPage, Paginator
from django.utils.functional import cached_property


class EncryptedPaginator(Paginator):
@cached_property
def count(self):
return len(self.object_list)


class EncryptedChangeList(ChangeList):
def get_results(self, request):
"""
This is django.contrib.admin.views.main.ChangeList.get_results with
a single modification to avoid COUNT queries.
"""
paginator = self.model_admin.get_paginator(request, self.queryset, self.list_per_page)
result_count = paginator.count
if self.model_admin.show_full_result_count:
# Modification: avoid COUNT query by using len() on the root queryset
full_result_count = len(self.root_queryset)
else:
full_result_count = None
can_show_all = result_count <= self.list_max_show_all
multi_page = result_count > self.list_per_page
if (self.show_all and can_show_all) or not multi_page:
result_list = self.queryset._clone()
else:
try:
result_list = paginator.page(self.page_num).object_list
except InvalidPage as err:
raise IncorrectLookupParameters from err
self.result_count = result_count
self.show_full_result_count = self.model_admin.show_full_result_count
self.show_admin_actions = not self.show_full_result_count or bool(full_result_count)
self.full_result_count = full_result_count
self.result_list = result_list
self.can_show_all = can_show_all
self.multi_page = multi_page
self.paginator = paginator


class EncryptedModelAdmin(admin.ModelAdmin):
"""
A ModelAdmin that uses EncryptedPaginator and EncryptedChangeList
to avoid COUNT queries in the admin changelist.
"""

def get_paginator(self, request, queryset, per_page):
return EncryptedPaginator(queryset, per_page)

def get_changelist(self, request, **kwargs):
return EncryptedChangeList
34 changes: 34 additions & 0 deletions docs/ref/contrib/admin.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
=====
Admin
=====

Django MongoDB Backend supports the Django admin interface. To enable it, ensure
that you have :ref:`specified the default pk field
<specifying the-default-pk-field>` for the
:class:`~django.contrib.admin.apps.AdminConfig` class as described in the
:doc:`Getting Started </intro/configure>` guide.

``EncryptedModelAdmin``
=======================

.. class:: EncryptedModelAdmin

.. versionadded:: 5.2.3

A :class:`~django.contrib.admin.ModelAdmin` subclass that supports models
with encrypted fields. Use this class as a base class for your model's admin
class to ensure that encrypted fields are handled correctly in the admin
interface.

Register encrypted models with the Django admin using the
``EncryptedModelAdmin`` as shown below::

# myapp/admin.py
from django.contrib import admin
from django_mongodb_backend.admin import EncryptedModelAdmin
from .models import Patient


@admin.register(Patient)
class PatientAdmin(EncryptedModelAdmin):
pass