Skip to content

Commit

Permalink
Merge pull request #11 from open-formulieren/issue/9-default-choices
Browse files Browse the repository at this point in the history
[#9] Make retrieval of Open Forms choices lazy
  • Loading branch information
stevenbal authored Jun 21, 2024
2 parents 16ba410 + 105d753 commit c2c9db7
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 24 deletions.
45 changes: 23 additions & 22 deletions openformsclient/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.db.models.fields import BLANK_CHOICE_DASH
from django.forms.fields import TypedChoiceField
from django.forms.widgets import Select
from django.utils.functional import cached_property
from django.utils.functional import cached_property, lazy
from django.utils.text import capfirst
from django.utils.translation import gettext_lazy as _

Expand Down Expand Up @@ -107,8 +107,7 @@ def formfield(self, **kwargs):
"widget": Select,
}

if self.choices is None:
defaults["choices"] = self.get_choices(include_blank=self.blank)
defaults["choices"] = self.get_choices(include_blank=self.blank)
defaults["coerce"] = self.to_python

return TypedChoiceField(**defaults)
Expand All @@ -120,25 +119,27 @@ def get_choices(
limit_choices_to=None,
ordering=(),
):
cache_key = f"openformsclient.models.OpenFormsFieldMixin.get_choices__use_uuids_{self.use_uuids}"

choices = cache.get(cache_key)
if choices is None:
try:
choices = get_form_choices(use_uuids=self.use_uuids)
except Exception as e:
logger.exception(e)
choices = []
else:
cache.set(cache_key, choices, timeout=60)

if choices:
if include_blank:
blank_defined = any(choice in ("", None) for choice, _ in choices)
if not blank_defined:
choices = blank_choice + choices

return choices
def _fetch():
cache_key = f"openformsclient.models.OpenFormsBaseField.get_choices__use_uuids_{self.use_uuids}"

choices = cache.get(cache_key)
if choices is None:
try:
choices = get_form_choices(use_uuids=self.use_uuids)
except Exception as exc:
logger.exception(exc)
choices = []
else:
cache.set(cache_key, choices, timeout=60)

if choices:
if include_blank:
blank_defined = any(choice in ("", None) for choice, _ in choices)
if not blank_defined:
choices = blank_choice + choices
return choices

return lazy(_fetch, list)


class OpenFormsUUIDField(OpenFormsBaseField, models.UUIDField):
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ tests_require =
isort
black
flake8
time-machine

[options.packages.find]
include =
Expand All @@ -56,6 +57,7 @@ tests =
isort
black
flake8
time-machine
pep8 = flake8
coverage = pytest-cov
docs =
Expand Down
24 changes: 22 additions & 2 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import datetime
from uuid import UUID

from django.forms import modelform_factory
from django.test import TestCase

import requests_mock
import time_machine

from openformsclient.models import Configuration
from testapp.models import Page
Expand Down Expand Up @@ -41,7 +43,7 @@ def test_values_in_slug_form_field(self, m):
page_form = PageForm()

self.assertListEqual(
page_form.fields["form_slug"].choices,
list(page_form.fields["form_slug"].choices),
[
("", "---------"),
("test-1", "Test 1"),
Expand All @@ -56,7 +58,7 @@ def test_values_in_uuid_form_field(self, m):
page_form = PageForm()

self.assertListEqual(
page_form.fields["form_uuid"].choices,
list(page_form.fields["form_uuid"].choices),
[
("", "---------"),
("f4423c99-6341-442e-aedc-b47779579f4d", "Test 1"),
Expand Down Expand Up @@ -129,3 +131,21 @@ def test_slug_form_field_blank(self, m):

self.assertEqual(Page.objects.count(), 1)
self.assertEqual(Page.objects.get().form_slug, "")

def test_form_retrieval_cache(self, m):
self._prepare_mock(m)

PageForm = modelform_factory(Page, fields=["form_slug"])
page_form = PageForm()

with time_machine.travel(0) as traveller:
list(page_form.fields["form_slug"].choices)
list(page_form.fields["form_slug"].choices)

self.assertEqual(m.call_count, 1)

traveller.shift(datetime.timedelta(seconds=60))

list(page_form.fields["form_slug"].choices)

self.assertEqual(m.call_count, 2)

0 comments on commit c2c9db7

Please sign in to comment.