admin: prevent too big join by get_search_results (#80932)
gitea/docbow/pipeline/head This commit looks good Details

This commit is contained in:
Benjamin Dauvergne 2023-09-06 11:33:37 +02:00
parent 28a3800d4d
commit dcb24b4d19
2 changed files with 29 additions and 6 deletions

View File

@ -1,8 +1,12 @@
import functools
import operator
import django.contrib.admin as admin
from django.conf import settings
from django.contrib.auth import admin as auth_admin
from django.contrib.auth import models as auth_models
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.urls import NoReverseMatch, re_path, reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
@ -19,6 +23,13 @@ from docbow_project.docbow import actions, auth_views, forms, models, notificati
TITLE = "Plate-forme sécurisée d'échange de documents"
class GetSearchResultsMixin:
def get_search_results(self, request, queryset, search_term):
search_fields = self.get_search_fields(request)
orm_lookups = [Q(**{f'{field}__icontains': search_term}) for field in search_fields]
return queryset.filter(functools.reduce(operator.or_, orm_lookups)), False
class DocbowAdminSite(admin.AdminSite):
site_title = TITLE
site_header = TITLE
@ -56,7 +67,7 @@ class SendingLimitationAdmin(admin.ModelAdmin):
filetypes_list.short_description = _('Limitation des types de fichier')
class MailingListAdmin(admin.ModelAdmin):
class MailingListAdmin(GetSearchResultsMixin, admin.ModelAdmin):
list_display = ['name', 'is_active']
list_filter = ['is_active']
search_fields = ['name', 'members__username', 'members__first_name', 'members__last_name']
@ -235,7 +246,7 @@ class FileTypeAdmin(admin.ModelAdmin):
inlines = [FileTypeAttachedFileKindAdmin]
class NotificationAdmin(admin.ModelAdmin):
class NotificationAdmin(GetSearchResultsMixin, admin.ModelAdmin):
search_fields = [
'user__username',
'user__first_name',

View File

@ -124,10 +124,10 @@ def test_admin_mailing_list(admin, client):
users = []
mls = []
for i in range(20):
users.append(User.objects.create(username='%s' % i))
users.append(User.objects.create(username='user%s' % i))
sublist = []
for i in range(19, -1, -1):
mls.insert(0, MailingList.objects.create(name='%s' % i))
mls.insert(0, MailingList.objects.create(name='ml%s' % i))
mls[0].members.set([users[i]])
mls[0].mailing_list_members.set(sublist)
sublist = [mls[0]]
@ -137,8 +137,20 @@ def test_admin_mailing_list(admin, client):
from django.test.utils import CaptureQueriesContext
with CaptureQueriesContext(conn) as context:
resp = client.get('/admin/docbow/mailinglist/?q=' + ('a%20' * 10))
assert context[-1]['sql'].count('UPPER') == 80
resp = client.get('/admin/docbow/mailinglist/?q=' + ('user19 ml18 a%20' * 10))
assert context[-1]['sql'].count('UPPER') == 8
from bs4 import BeautifulSoup
resp = client.get('/admin/docbow/mailinglist/?q=user19')
soup = BeautifulSoup(resp.content)
tags = soup.find_all('th', {'class': 'field-name'})
assert {tag.text for tag in tags} == {'ml19'}
resp = client.get('/admin/docbow/mailinglist/?q=ml18')
soup = BeautifulSoup(resp.content)
tags = soup.find_all('th', {'class': 'field-name'})
assert {tag.text for tag in tags} == {'ml18'}
class MailingListCycle(TestCase):