Skip to content

Commit

Permalink
perf: relegate optgroup calculation to superclass (#4540)
Browse files Browse the repository at this point in the history
  • Loading branch information
zawan-ila authored Jan 13, 2025
1 parent de1caa7 commit 9c571cb
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 26 deletions.
51 changes: 36 additions & 15 deletions course_discovery/apps/course_metadata/tests/test_widgets.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
import ddt
import itertools

from bs4 import BeautifulSoup
from django.test import TestCase
from django.urls import reverse

from course_discovery.apps.api.tests.mixins import SiteMixin
from course_discovery.apps.core.tests.factories import USER_PASSWORD, UserFactory
from course_discovery.apps.course_metadata.tests.factories import CourseFactory, ProgramFactory


from course_discovery.apps.course_metadata.widgets import SortedModelSelect2Multiple
class SortedModelSelect2MultipleTests(SiteMixin, TestCase):
def setUp(self):
super().setUp()
self.user = UserFactory(is_staff=True, is_superuser=True)
self.client.login(username=self.user.username, password=USER_PASSWORD)

def test_program_ordered_m2m(self):
"""
Verify that program page sorted m2m fields render in order. The sorted
m2m field chosen for the test is the courses field
"""

@ddt.ddt
class SortedModelSelect2MultipleTests(TestCase):
@ddt.data(
(['1', '2'], [1, 2]),
(['2', '1'], [2, 1]),
(['3'], [3,]),
)
@ddt.unpack
def test_optgroups_are_sorted(self, value, result_order):
choices = ((1, 'one'), (2, 'two'), (3, 'three'))
widget = SortedModelSelect2Multiple(url='requiredurl', choices=choices)
result = widget.optgroups('test', value)
assert result_order == [x[1][0]['value'] for x in result]
for courses in itertools.permutations(
[
CourseFactory(title="Blade Runner 2049"),
CourseFactory(title="History of Western Literature"),
CourseFactory(title="Urdu Poetry")
],
2
):
program = ProgramFactory(courses=courses)
response = self.client.get(reverse('admin:course_metadata_program_change', args=(program.id,)))
response_content = BeautifulSoup(response.content)
options = response_content.find('select', {'name': 'courses'}).find_all('option')
assert len(options) == len(courses)
for idx, opt in enumerate(options):
assert 'selected' in opt.attrs
assert opt.get_text().endswith(courses[idx].title)
assert opt.attrs['value'] == str(courses[idx].id)
13 changes: 2 additions & 11 deletions course_discovery/apps/course_metadata/widgets.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from itertools import chain

from dal import autocomplete


Expand All @@ -8,16 +6,9 @@ def optgroups(self, name, value, attrs=None):
"""
Return a sorted list of optgroups for this widget.
This is a simplified version of Django's version. The big difference is that we keep the results sorted and
only support one main group (because that's all we need right now).
This is a simplified version of Django's version. The big difference is that we keep the results sorted.
"""
selected = []
for index, (option_value, option_label) in enumerate(chain(self.choices)):
is_selected = str(option_value) in value
if is_selected:
subgroup = [self.create_option(name, option_value, option_label, is_selected, index, attrs=attrs)]
item = (None, subgroup, index)
selected.append(item)
selected = super().optgroups(name, value, attrs)

ordered = []
for value_id in value:
Expand Down

0 comments on commit 9c571cb

Please sign in to comment.