diff --git a/cookie_consent/cache.py b/cookie_consent/cache.py index 50f8fb4..9c61fb8 100644 --- a/cookie_consent/cache.py +++ b/cookie_consent/cache.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- from django.core.cache import caches -from cookie_consent.conf import settings +from .conf import settings +from .models import CookieGroup CACHE_KEY = "cookie_consent_cache" -CACHE_TIMEOUT = 60 * 60 +CACHE_TIMEOUT = 60 * 60 # 60 minutes def _get_cache(): @@ -23,20 +24,22 @@ def delete_cache(): cache.delete(CACHE_KEY) +def _get_cookie_groups_from_db(): + qs = CookieGroup.objects.filter(is_required=False).prefetch_related("cookie_set") + return qs.in_bulk(field_name="varname") + + def all_cookie_groups(): + """ + Get all cookie groups that are optional. + + Reads from the cache where possible, sets the value in the cache if there's a + cache miss. + """ cache = _get_cache() - items = cache.get(CACHE_KEY) - if items is None: - from cookie_consent.models import CookieGroup - - qs = CookieGroup.objects.filter(is_required=False) - qs = qs.prefetch_related("cookie_set") - # items = qs.in_bulk(field_name="varname") - # FIXME -> doesn't work because varname is not a unique fieldl, we need to - # make this unique - items = {group.varname: group for group in qs} - cache.set(CACHE_KEY, items, CACHE_TIMEOUT) - return items + return cache.get_or_set( + CACHE_KEY, _get_cookie_groups_from_db, timeout=CACHE_TIMEOUT + ) def get_cookie_group(varname): diff --git a/cookie_consent/migrations/0003_alter_cookiegroup_varname.py b/cookie_consent/migrations/0003_alter_cookiegroup_varname.py new file mode 100644 index 0000000..96a62d8 --- /dev/null +++ b/cookie_consent/migrations/0003_alter_cookiegroup_varname.py @@ -0,0 +1,32 @@ +# Generated by Django 4.2.13 on 2024-05-09 19:01 + +import re + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("cookie_consent", "0002_auto__add_logitem"), + ] + + operations = [ + migrations.AlterField( + model_name="cookiegroup", + name="varname", + field=models.CharField( + max_length=32, + unique=True, + validators=[ + django.core.validators.RegexValidator( + re.compile("^[-_a-zA-Z0-9]+$"), + "Enter a valid 'varname' consisting of letters, numbers, underscores or hyphens.", + "invalid", + ) + ], + verbose_name="Variable name", + ), + ), + ] diff --git a/cookie_consent/models.py b/cookie_consent/models.py index 3c67f91..7fe0d85 100644 --- a/cookie_consent/models.py +++ b/cookie_consent/models.py @@ -6,8 +6,6 @@ from django.db import models from django.utils.translation import gettext_lazy as _ -from cookie_consent.cache import delete_cache - COOKIE_NAME_RE = re.compile(r"^[-_a-zA-Z0-9]+$") validate_cookie_name = RegexValidator( COOKIE_NAME_RE, @@ -21,6 +19,8 @@ def clear_cache_after(func): def wrapper(*args, **kwargs): + from .cache import delete_cache + return_value = func(*args, **kwargs) delete_cache() return return_value @@ -50,7 +50,10 @@ def update(self, **kwargs): class CookieGroup(models.Model): varname = models.CharField( - _("Variable name"), max_length=32, validators=[validate_cookie_name] + _("Variable name"), + max_length=32, + unique=True, + validators=[validate_cookie_name], ) name = models.CharField(_("Name"), max_length=100, blank=True) description = models.TextField(_("Description"), blank=True) diff --git a/docs/changelog.rst b/docs/changelog.rst index 2214fa8..ad28241 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,15 @@ Changelog ========= +0.6.0 (unreleased) +------------------ + +💥 This feature release has a potential breaking change. The ``CookieGroup.varname`` +field now has a unique constraint on it. If you have duplicate values, this migration +will crash. + +* ... + 0.5.0b0 (2023-09-24) -------------------- diff --git a/testapp/templates/show-cookie-bar-script.html b/testapp/templates/show-cookie-bar-script.html index 269edf8..caaba5f 100644 --- a/testapp/templates/show-cookie-bar-script.html +++ b/testapp/templates/show-cookie-bar-script.html @@ -21,6 +21,8 @@ }, onDecline: () => document.querySelector('body').classList.remove('with-cookie-bar'), }); + + document.getElementById('loading-marker').style.display = 'inline';