Created
November 26, 2024 17:27
-
-
Save cnk/c50ea546b66449c7930bf65db4ad7823 to your computer and use it in GitHub Desktop.
Overriding RoutablePage to add caching headers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BasePage(RobotsTxtMixin, Page): | |
""" | |
BasePage exists to provide the default functionality that we want all (or nearly all) of our Page models to have. | |
Currently, that includes the following: | |
* RobotsTxtMixin adds the ability to place the Page into our robots.txt file, to hide it from search engines. | |
* The serve() method in this class adds Cache-Control headers to every Page when it gets served by Wagtail. | |
The values for the Cache-Control headers are a work in progress, and for now are basically either "don't cache | |
locally or on Cloudflare" OR "please cache on Cloudflare". | |
I am not setting a browser cache time because it makes it harder for me to test rules. And I am using the more | |
general "CDN-Cache-Control" header so I can see that the value is getting served. When I use | |
"Cloudflare-CDN-Cache-Control" the header gets stripped, so I can't be sure it got served or what value it had. | |
""" | |
def is_private(self): | |
restricted_pages = PageViewRestriction.objects.values('page_id') | |
return self.get_ancestors(inclusive=True).filter(id__in=restricted_pages).exists() | |
def _public_cache_control_header(self, duration=DEFAULT_PAGE_CACHE_TIME): | |
""" | |
Override this in a subclass to define a custom public cache control header, most likely by using | |
PUBLIC_PAGE_CACHE_HEADER_TEMPLATE.format(some_other_duration). | |
""" | |
return PUBLIC_PAGE_CACHE_HEADER_TEMPLATE.format(duration) | |
def add_cache_control_headers(self, response): | |
""" | |
Adds our custom cache control headers to the given HttpResponse object. | |
""" | |
if self.is_private(): | |
response.headers['Cache-Control'] = PRIVATE_PAGE_CACHE_HEADER | |
else: | |
response.headers['CDN-Cache-Control'] = self._public_cache_control_header() | |
# To enable chaining, this method also returns the response. | |
return response | |
def serve(self, request, *args, **kwargs): | |
""" | |
Add Cache-Control headers to all pages served, depending on page privacy. | |
""" | |
response = super().serve(request, *args, **kwargs) | |
return self.add_cache_control_headers(response) | |
def serve_preview(self, request, mode_name): | |
""" | |
Adds the appropriate Cache-Control header for Page previews. | |
""" | |
response = super().serve_preview(request, mode_name) | |
response.headers['Cache-Control'] = PRIVATE_PAGE_CACHE_HEADER | |
return response | |
class Meta: | |
abstract = True | |
class RoutableBasePage(RoutablePageMixin, BasePage): | |
""" | |
A RoutablePage class based on BasePage. | |
""" | |
def render(self, request, *args, template=None, context_overrides=None, **kwargs): | |
""" | |
We override this method so that every time a RoutablePage view is rendered, we add our cache control headers. | |
""" | |
response = super().render(request, *args, template=template, context_overrides=context_overrides, **kwargs) | |
return self.add_cache_control_headers(response) | |
class Meta: | |
abstract = True | |
############# | |
class MasterCalendarPage2(RoutableBasePage): | |
""" | |
A MasterCalendarPage acts as the entry point to the Master Calendar functionality on a given Site. Every part of the | |
Master Calendar for its Site is served by this Page. | |
""" | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment