Skip to content

Commit

Permalink
Merge pull request #821 from uktrade/cache-draft
Browse files Browse the repository at this point in the history
Cache draft pages
  • Loading branch information
richtier authored Apr 21, 2020
2 parents 8173627 + 176ed98 commit 9e9fe26
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Implemented enhancements
- CI-677 - Add CTA link field to Capital Investment homepage hero
- no ticket - Add cache supoort to draft pages

## Hotfix
- No ticket - v3-cipipeline manifest.yml file fix
Expand Down
17 changes: 17 additions & 0 deletions core/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,18 @@ def populate_sync(cls, instance):
data=serializer.data,
lang=language_code,
)
if instance.has_unpublished_changes:
draft_instance = instance.get_latest_nested_revision_as_page()
draft_serializer = serializer_class(
instance=draft_instance,
context={'is_draft': True}
)
page_cache.set(
page_id=instance.id,
data=draft_serializer.data,
lang=language_code,
draft_version=True
)

@classmethod
def delete(cls, instance):
Expand All @@ -138,6 +150,11 @@ def delete(cls, instance):
page_id=instance.id,
lang=language_code,
)
page_cache.delete(
page_id=instance.id,
lang=language_code,
draft_version=True
)


class PageIDCache:
Expand Down
6 changes: 1 addition & 5 deletions core/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,13 @@ def to_representation(self, instance):
class MetaDictField(fields.DictField):

def get_attribute(self, instance):
if 'request' in self.context:
is_draft = helpers.is_draft_requested(self.context['request'])
else:
is_draft = False
return {
'languages': [
(code, label) for (code, label) in settings.LANGUAGES_LOCALIZED
if code in instance.specific.translated_languages
],
'url': instance.specific.get_url(
is_draft=is_draft,
is_draft=self.context.get('is_draft', False),
language_code=settings.LANGUAGE_CODE,
),
'slug': instance.slug,
Expand Down
21 changes: 16 additions & 5 deletions core/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from logging import getLogger

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.exceptions import ValidationError
from rest_framework.renderers import JSONRenderer
Expand All @@ -22,6 +24,9 @@
from core.serializer_mapping import MODELS_SERIALIZERS_MAPPING


logger = getLogger(__name__)


class PageNotSerializableError(NotImplementedError):
pass

Expand Down Expand Up @@ -89,14 +94,13 @@ def detail_view(self, request, **kwargs):
# Exit early if there are any issues
self.check_parameter_validity()

variation_kwargs = {'lang': translation.get_language()}

if helpers.is_draft_requested(request):
return super().detail_view(request, pk=None)
variation_kwargs['draft_version'] = True

# Return a cached response if one is available
cached_data = cache.PageCache.get(
page_id=self.object_id,
lang=translation.get_language(),
)
cached_data = cache.PageCache.get(page_id=self.object_id, **variation_kwargs)
if cached_data:
cached_response = helpers.CachedResponse(cached_data)
cached_response['etag'] = cached_data.get('etag', None)
Expand All @@ -108,15 +112,22 @@ def detail_view(self, request, **kwargs):

# No cached response available
response = super().detail_view(request, pk=None)

if response.status_code == 200:
# Reuse the already-fetched object to populate the cache
cache.CachePopulator.populate_async(self.get_object())

logger.warn(f'Page cache miss')
# No etag is set for this response because creating one is expensive.
# If API caching is enabled, one will be added to the cached version
# created above.
return response

def get_serializer_context(self):
context = super().get_serializer_context()
context['is_draft'] = helpers.is_draft_requested(self.request)
return context


class PagesOptionalDraftAPIEndpoint(APIEndpointBase):
def listing_view(self, request):
Expand Down
19 changes: 13 additions & 6 deletions tests/core/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,23 @@ class TestSubscriber(cache.DatabaseCacheSubscriber):
model_classes = [Page]

instance = mock.Mock(
id=1, slug='some-slug', service_name='thing',
id=2, slug='some-slug', service_name='thing',
translated_languages=['en-gb']
)
TestSubscriber.delete(sender=None, instance=instance)

assert mock_delete.call_count == 1
assert mock_delete.call_args == mock.call(
page_id=1,
lang='en-gb',
)
assert mock_delete.call_count == 2
assert mock_delete.call_args_list == [
mock.call(
page_id=2,
lang='en-gb',
),
mock.call(
page_id=2,
lang='en-gb',
draft_version=True,
)
]


@mock.patch('django.core.cache.cache.set')
Expand Down
4 changes: 1 addition & 3 deletions tests/core/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from wagtail.core.fields import StreamField

from core import fields
from core import permissions
from great_international.serializers import InternationalSectorPageSerializer, InternationalArticlePageSerializer
from tests.great_international.factories import InternationalSectorPageFactory

Expand Down Expand Up @@ -103,10 +102,9 @@ def test_meta_field_draft(international_root_page, rf):
parent=international_root_page,
slug='test-slug',
)
request = rf.get('/', {permissions.DraftTokenPermisison.TOKEN_PARAM: '1'})
serializer = InternationalSectorPageSerializer(
instance=sector_page,
context={'request': request}
context={'is_draft': True}
)

assert serializer.data['meta']['url'] == sector_page.get_url(is_draft=True)
Expand Down

0 comments on commit 9e9fe26

Please sign in to comment.