wagtail/docs/reference/contrib/frontendcache.rst

266 lines
9.1 KiB
ReStructuredText
Raw Normal View History

.. _frontend_cache_purging:
2015-05-14 14:27:14 +00:00
Frontend cache invalidator
==========================
2014-07-01 10:00:55 +00:00
2014-10-08 10:32:44 +00:00
.. versionchanged:: 0.7
* Multiple backend support added
* Cloudflare support added
2016-08-29 15:38:26 +00:00
.. versionchanged:: 1.7
* Amazon CloudFront support added
Many websites use a frontend cache such as Varnish, Squid, Cloudflare or CloudFront to gain extra performance. The downside of using a frontend cache though is that they don't respond well to updating content and will often keep an old version of a page cached after it has been updated.
2014-07-01 10:00:55 +00:00
This document describes how to configure Wagtail to purge old versions of pages from a frontend cache whenever a page gets updated.
Setting it up
-------------
2014-07-01 10:00:55 +00:00
Firstly, add ``"wagtail.contrib.wagtailfrontendcache"`` to your INSTALLED_APPS:
.. code-block:: python
INSTALLED_APPS = [
...
"wagtail.contrib.wagtailfrontendcache"
]
.. versionchanged:: 0.8
2014-07-01 10:00:55 +00:00
Signal handlers are now automatically registered
The ``wagtailfrontendcache`` module provides a set of signal handlers which will automatically purge the cache whenever a page is published or deleted. These signal handlers are automatically registered when the ``wagtail.contrib.wagtailfrontendcache`` app is loaded.
2014-07-01 10:00:55 +00:00
2014-10-08 10:32:44 +00:00
Varnish/Squid
^^^^^^^^^^^^^
2014-10-08 10:32:44 +00:00
2014-10-30 16:25:15 +00:00
Add a new item into the ``WAGTAILFRONTENDCACHE`` setting and set the ``BACKEND`` parameter to ``wagtail.contrib.wagtailfrontendcache.backends.HTTPBackend``. This backend requires an extra parameter ``LOCATION`` which points to where the cache is running (this must be a direct connection to the server and cannot go through another proxy).
2014-10-08 10:32:44 +00:00
.. code-block:: python
# settings.py
WAGTAILFRONTENDCACHE = {
'varnish': {
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.HTTPBackend',
'LOCATION': 'http://localhost:8000',
},
}
2014-07-01 10:00:55 +00:00
Finally, make sure you have configured your frontend cache to accept PURGE requests:
- `Varnish <https://www.varnish-cache.org/docs/3.0/tutorial/purging.html>`_
- `Squid <http://wiki.squid-cache.org/SquidFaq/OperatingSquid#How_can_I_purge_an_object_from_my_cache.3F>`_
.. _frontendcache_cloudflare:
2014-10-08 10:32:44 +00:00
Cloudflare
^^^^^^^^^^
2014-10-08 10:32:44 +00:00
2014-10-08 12:27:51 +00:00
Firstly, you need to register an account with Cloudflare if you haven't already got one. You can do this here: `Cloudflare Sign up <https://www.cloudflare.com/sign-up>`_
2014-10-08 10:32:44 +00:00
Add an item into the ``WAGTAILFRONTENDCACHE`` and set the ``BACKEND`` parameter to ``wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend``. This backend requires three extra parameters, ``EMAIL`` (your Cloudflare account email), ``TOKEN`` (your API token from Cloudflare), and ``ZONEID`` (for zone id for your domain, see below).
To find the ``ZONEID`` for your domain, read the `Cloudflare API Documentation <https://api.cloudflare.com/#getting-started-resource-ids>`_
2014-10-08 10:32:44 +00:00
.. code-block:: python
# settings.py
WAGTAILFRONTENDCACHE = {
'cloudflare': {
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.CloudflareBackend',
'EMAIL': 'your-cloudflare-email-address@example.com',
'TOKEN': 'your cloudflare api token',
'ZONEID': 'your cloudflare domain zone id',
2014-10-08 10:32:44 +00:00
},
}
2016-08-29 14:24:53 +00:00
.. _frontendcache_aws_cloudfront:
2014-10-08 10:32:44 +00:00
Amazon CloudFront
^^^^^^^^^^^^^^^^^
Within Amazon Web Services you will need at least one CloudFront web distribution. If you don't have one, you can get one here: `CloudFront getting started <https://aws.amazon.com/cloudfront/>`_
2016-10-20 14:25:27 +00:00
Add an item into the ``WAGTAILFRONTENDCACHE`` and set the ``BACKEND`` parameter to ``wagtail.contrib.wagtailfrontendcache.backends.CloudfrontBackend``. This backend requires one extra parameter, ``DISTRIBUTION_ID`` (your CloudFront generated distribution id).
.. code-block:: python
WAGTAILFRONTENDCACHE = {
'cloudfront': {
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.CloudfrontBackend',
'DISTRIBUTION_ID': 'your-distribution-id',
},
}
Configuration of credentials can done in multiple ways. You won't need to store them in your Django settings file. You can read more about this here: `Boto 3 Docs <http://boto3.readthedocs.org/en/latest/guide/configuration.html>`_
In case you run multiple sites with Wagtail and each site has its CloudFront distribution, provide a mapping instead of a single distribution. Make sure the mapping matches with the hostnames provided in your site settings.
.. code-block:: python
WAGTAILFRONTENDCACHE = {
'cloudfront': {
'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.CloudfrontBackend',
'DISTRIBUTION_ID': {
'www.wagtail.io': 'your-distribution-id',
'www.madewithwagtail.org': 'your-distribution-id',
},
},
}
2016-11-08 09:42:46 +00:00
.. note::
In most cases, absolute URLs with ``www`` prefixed domain names should be used in your mapping. Only drop the ``www`` prefix if you're absolutely sure you're not using it (e.g. a subdomain).
2014-08-08 08:42:12 +00:00
Advanced usage
--------------
2014-07-01 10:00:55 +00:00
2014-10-08 10:32:44 +00:00
Invalidating more than one URL per page
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2014-07-01 10:00:55 +00:00
By default, Wagtail will only purge one URL per page. If your page has more than one URL to be purged, you will need to override the ``get_cached_paths`` method on your page type.
.. code-block:: python
class BlogIndexPage(Page):
def get_blog_items(self):
# This returns a Django paginator of blog items in this section
return Paginator(self.get_children().live().type(BlogPage), 10)
def get_cached_paths(self):
# Yield the main URL
yield '/'
# Yield one URL per page in the paginator to make sure all pages are purged
2016-01-31 05:21:57 +00:00
for page_number in range(1, self.get_blog_items().num_pages + 1):
2014-07-01 10:00:55 +00:00
yield '/?page=' + str(page_number)
2014-10-08 10:32:44 +00:00
Invalidating index pages
^^^^^^^^^^^^^^^^^^^^^^^^
2014-07-01 10:00:55 +00:00
2017-08-31 13:26:29 +00:00
Another problem is pages that list other pages (such as a blog index) will not
be purged when a blog entry gets added, changed or deleted. You may want to
purge the blog index page so the updates are added into the listing quickly.
2014-07-01 10:00:55 +00:00
2017-08-31 13:26:29 +00:00
This can be solved by using the ``purge_page_from_cache`` utility function
which can be found in the ``wagtail.contrib.wagtailfrontendcache.utils`` module.
2014-07-01 10:00:55 +00:00
2017-08-31 13:26:29 +00:00
Let's take the the above BlogIndexPage as an example. We need to register a
signal handler to run when one of the BlogPages get updated/deleted. This
signal handler should call the ``purge_page_from_cache`` function on all
BlogIndexPages that contain the BlogPage being updated/deleted.
2014-07-01 10:00:55 +00:00
.. code-block:: python
# models.py
2015-04-01 16:14:20 +00:00
from django.dispatch import receiver
2014-07-01 10:00:55 +00:00
from django.db.models.signals import pre_delete
from wagtail.wagtailcore.signals import page_published
from wagtail.contrib.wagtailfrontendcache.utils import purge_page_from_cache
...
def blog_page_changed(blog_page):
2017-08-31 13:26:29 +00:00
# Find the blog index and purge it. Assuming there is just one on the site.
blog_index = BlogIndexPage.objects.first()
purge_page_from_cache(blog_index)
2014-07-01 10:00:55 +00:00
2015-04-01 16:14:20 +00:00
@receiver(page_published, sender=BlogPage):
2014-07-01 10:00:55 +00:00
def blog_published_handler(instance):
blog_page_changed(instance)
2015-04-01 16:14:20 +00:00
@receiver(pre_delete, sender=BlogPage)
2014-07-01 10:00:55 +00:00
def blog_deleted_handler(instance):
blog_page_changed(instance)
2014-10-08 10:32:44 +00:00
Invalidating individual URLs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2017-08-31 13:26:29 +00:00
``wagtail.contrib.wagtailfrontendcache.utils`` provides a function called ``purge_url_from_cache``. As the name suggests, this purges an individual URL from the cache.
2014-07-03 12:10:03 +00:00
For example, this could be useful for purging a single page of blogs:
.. code-block:: python
from wagtail.contrib.wagtailfrontendcache.utils import purge_url_from_cache
2014-07-03 12:10:03 +00:00
# Purge the first page of the blog index
purge_url_from_cache(blog_index.url + '?page=1')
2017-08-31 13:26:29 +00:00
Invaliding many URLs in batches
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. versionadded:: 1.13
If you have many pages/URLs that need to be purged at the same time, it's more
perfomant to use Wagtail's ``PurgeBatch`` class to build up a list of pages/URLs
to purge, and purge them all in a single request.
.. code-block:: python
# models.py
from django.dispatch import receiver
from django.db.models.signals import pre_delete
from wagtail.wagtailcore.signals import page_published
from wagtail.contrib.wagtailfrontendcache.utils import PurgeBatch
...
def blog_page_changed(blog_page):
# Find all the live BlogIndexPages that contain this blog_page
batch = PurgeBatch()
for blog_index in BlogIndexPage.objects.live():
if blog_page in blog_index.get_blog_items().object_list:
batch.add_page(blog_index)
# Purge all the blog indexes we found in a single request
batch.purge()
@receiver(page_published, sender=BlogPage):
def blog_published_handler(instance):
blog_page_changed(instance)
@receiver(pre_delete, sender=BlogPage)
def blog_deleted_handler(instance):
blog_page_changed(instance)
All of the methods available on ``PurgeBatch`` are listed bellow:
.. automodule:: wagtail.contrib.wagtailfrontendcache.utils
.. autoclass:: PurgeBatch
.. automethod:: add_url
.. automethod:: add_urls
.. automethod:: add_page
.. automethod:: add_pages
.. automethod:: purge