kopia lustrzana https://github.com/wagtail/wagtail
Move frontend cache purging to task
rodzic
65d3b34698
commit
79d129f8c2
|
@ -605,11 +605,13 @@ class TestDocumentCacheInvalidation(TestCase):
|
|||
signal_handlers.unregister_signal_handlers()
|
||||
|
||||
def test_resave_document_purges(self, purge):
|
||||
get_document_model().objects.get(id=5).save()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
get_document_model().objects.get(id=5).save()
|
||||
|
||||
purge.assert_any_call("http://api.example.com/api/main/documents/5/")
|
||||
|
||||
def test_delete_document_purges(self, purge):
|
||||
get_document_model().objects.get(id=5).delete()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
get_document_model().objects.get(id=5).delete()
|
||||
|
||||
purge.assert_any_call("http://api.example.com/api/main/documents/5/")
|
||||
|
|
|
@ -597,11 +597,13 @@ class TestImageCacheInvalidation(TestCase):
|
|||
signal_handlers.unregister_signal_handlers()
|
||||
|
||||
def test_resave_image_purges(self, purge):
|
||||
get_image_model().objects.get(id=5).save()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
get_image_model().objects.get(id=5).save()
|
||||
|
||||
purge.assert_any_call("http://api.example.com/api/main/images/5/")
|
||||
|
||||
def test_delete_image_purges(self, purge):
|
||||
get_image_model().objects.get(id=5).delete()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
get_image_model().objects.get(id=5).delete()
|
||||
|
||||
purge.assert_any_call("http://api.example.com/api/main/images/5/")
|
||||
|
|
|
@ -1886,22 +1886,26 @@ class TestPageCacheInvalidation(TestCase):
|
|||
signal_handlers.unregister_signal_handlers()
|
||||
|
||||
def test_republish_page_purges(self, purge):
|
||||
Page.objects.get(id=2).specific.save_revision().publish()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
Page.objects.get(id=2).specific.save_revision().publish()
|
||||
|
||||
purge.assert_any_call("http://api.example.com/api/main/pages/2/")
|
||||
|
||||
def test_unpublish_page_purges(self, purge):
|
||||
Page.objects.get(id=2).unpublish()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
Page.objects.get(id=2).unpublish()
|
||||
|
||||
purge.assert_any_call("http://api.example.com/api/main/pages/2/")
|
||||
|
||||
def test_delete_page_purges(self, purge):
|
||||
Page.objects.get(id=16).delete()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
Page.objects.get(id=16).delete()
|
||||
|
||||
purge.assert_any_call("http://api.example.com/api/main/pages/16/")
|
||||
|
||||
def test_save_draft_doesnt_purge(self, purge):
|
||||
Page.objects.get(id=2).specific.save_revision()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
Page.objects.get(id=2).specific.save_revision()
|
||||
|
||||
purge.assert_not_called()
|
||||
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
import logging
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from urllib.parse import urlsplit, urlunsplit
|
||||
|
||||
from django.conf import settings
|
||||
from django_tasks import task
|
||||
|
||||
from wagtail.coreutils import get_content_languages
|
||||
|
||||
from .utils import get_backends
|
||||
|
||||
logger = logging.getLogger("wagtail.frontendcache")
|
||||
|
||||
|
||||
@task()
|
||||
def purge_urls_from_cache_task(urls, backend_settings=None, backends=None):
|
||||
if not urls:
|
||||
return
|
||||
|
||||
backends = get_backends(backend_settings, backends)
|
||||
|
||||
# If no backends are configured, there's nothing to do
|
||||
if not backends:
|
||||
return
|
||||
|
||||
# Convert each url to urls one for each managed language (WAGTAILFRONTENDCACHE_LANGUAGES setting).
|
||||
# The managed languages are common to all the defined backends.
|
||||
# This depends on settings.USE_I18N
|
||||
# If WAGTAIL_I18N_ENABLED is True, this defaults to WAGTAIL_CONTENT_LANGUAGES
|
||||
wagtail_i18n_enabled = getattr(settings, "WAGTAIL_I18N_ENABLED", False)
|
||||
content_languages = get_content_languages() if wagtail_i18n_enabled else {}
|
||||
languages = getattr(
|
||||
settings, "WAGTAILFRONTENDCACHE_LANGUAGES", list(content_languages.keys())
|
||||
)
|
||||
if settings.USE_I18N and languages:
|
||||
langs_regex = "^/(%s)/" % "|".join(languages)
|
||||
new_urls = []
|
||||
|
||||
# Purge the given url for each managed language
|
||||
for isocode in languages:
|
||||
for url in urls:
|
||||
up = urlsplit(url)
|
||||
new_url = urlunsplit(
|
||||
(
|
||||
up.scheme,
|
||||
up.netloc,
|
||||
re.sub(langs_regex, "/%s/" % isocode, up.path),
|
||||
up.query,
|
||||
up.fragment,
|
||||
)
|
||||
)
|
||||
|
||||
# Check for best performance. True if re.sub found no match
|
||||
# It happens when i18n_patterns was not used in urls.py to serve content for different languages from different URLs
|
||||
if new_url in new_urls:
|
||||
continue
|
||||
|
||||
new_urls.append(new_url)
|
||||
|
||||
urls = new_urls
|
||||
|
||||
urls_by_hostname = defaultdict(list)
|
||||
|
||||
for url in urls:
|
||||
urls_by_hostname[urlsplit(url).netloc].append(url)
|
||||
|
||||
for hostname, urls in urls_by_hostname.items():
|
||||
backends_for_hostname = {
|
||||
backend_name: backend
|
||||
for backend_name, backend in backends.items()
|
||||
if backend.invalidates_hostname(hostname)
|
||||
}
|
||||
|
||||
if not backends_for_hostname:
|
||||
logger.info("Unable to find purge backend for %s", hostname)
|
||||
continue
|
||||
|
||||
for backend_name, backend in backends_for_hostname.items():
|
||||
for url in urls:
|
||||
logger.info("[%s] Purging URL: %s", backend_name, url)
|
||||
|
||||
backend.purge_batch(urls)
|
|
@ -447,32 +447,37 @@ class TestCachePurgingFunctions(TestCase):
|
|||
PURGED_URLS.clear()
|
||||
|
||||
def test_purge_url_from_cache(self):
|
||||
purge_url_from_cache("http://localhost/foo")
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
purge_url_from_cache("http://localhost/foo")
|
||||
self.assertEqual(PURGED_URLS, {"http://localhost/foo"})
|
||||
|
||||
def test_purge_urls_from_cache(self):
|
||||
purge_urls_from_cache(["http://localhost/foo", "http://localhost/bar"])
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
purge_urls_from_cache(["http://localhost/foo", "http://localhost/bar"])
|
||||
self.assertEqual(PURGED_URLS, {"http://localhost/foo", "http://localhost/bar"})
|
||||
|
||||
def test_purge_page_from_cache(self):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
purge_page_from_cache(page)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
purge_page_from_cache(page)
|
||||
self.assertEqual(
|
||||
PURGED_URLS, {"http://localhost/events/", "http://localhost/events/past/"}
|
||||
)
|
||||
|
||||
def test_purge_pages_from_cache(self):
|
||||
purge_pages_from_cache(EventIndex.objects.all())
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
purge_pages_from_cache(EventIndex.objects.all())
|
||||
self.assertEqual(
|
||||
PURGED_URLS, {"http://localhost/events/", "http://localhost/events/past/"}
|
||||
)
|
||||
|
||||
def test_purge_batch(self):
|
||||
batch = PurgeBatch()
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
batch.add_page(page)
|
||||
batch.add_url("http://localhost/foo")
|
||||
batch.purge()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
batch = PurgeBatch()
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
batch.add_page(page)
|
||||
batch.add_url("http://localhost/foo")
|
||||
batch.purge()
|
||||
|
||||
self.assertEqual(
|
||||
PURGED_URLS,
|
||||
|
@ -493,7 +498,8 @@ class TestCachePurgingFunctions(TestCase):
|
|||
)
|
||||
def test_invalidate_specific_location(self):
|
||||
with self.assertLogs(level="INFO") as log_output:
|
||||
purge_url_from_cache("http://localhost/foo")
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
purge_url_from_cache("http://localhost/foo")
|
||||
|
||||
self.assertEqual(PURGED_URLS, set())
|
||||
self.assertIn(
|
||||
|
@ -501,7 +507,8 @@ class TestCachePurgingFunctions(TestCase):
|
|||
log_output.output[0],
|
||||
)
|
||||
|
||||
purge_url_from_cache("http://example.com/foo")
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
purge_url_from_cache("http://example.com/foo")
|
||||
self.assertEqual(PURGED_URLS, {"http://example.com/foo"})
|
||||
|
||||
|
||||
|
@ -520,10 +527,11 @@ class TestCloudflareCachePurgingFunctions(TestCase):
|
|||
PURGED_URLS.clear()
|
||||
|
||||
def test_cloudflare_purge_batch_chunked(self):
|
||||
batch = PurgeBatch()
|
||||
urls = [f"https://localhost/foo{i}" for i in range(1, 65)]
|
||||
batch.add_urls(urls)
|
||||
batch.purge()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
batch = PurgeBatch()
|
||||
urls = [f"https://localhost/foo{i}" for i in range(1, 65)]
|
||||
batch.add_urls(urls)
|
||||
batch.purge()
|
||||
|
||||
self.assertCountEqual(PURGED_URLS, set(urls))
|
||||
|
||||
|
@ -543,24 +551,27 @@ class TestCachePurgingSignals(TestCase):
|
|||
PURGED_URLS.clear()
|
||||
|
||||
def test_purge_on_publish(self):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.save_revision().publish()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.save_revision().publish()
|
||||
self.assertEqual(
|
||||
PURGED_URLS, {"http://localhost/events/", "http://localhost/events/past/"}
|
||||
)
|
||||
|
||||
def test_purge_on_unpublish(self):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.unpublish()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.unpublish()
|
||||
self.assertEqual(
|
||||
PURGED_URLS, {"http://localhost/events/", "http://localhost/events/past/"}
|
||||
)
|
||||
|
||||
def test_purge_with_unroutable_page(self):
|
||||
root = Page.objects.get(url_path="/")
|
||||
page = EventIndex(title="new top-level page")
|
||||
root.add_child(instance=page)
|
||||
page.save_revision().publish()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
root = Page.objects.get(url_path="/")
|
||||
page = EventIndex(title="new top-level page")
|
||||
root.add_child(instance=page)
|
||||
page.save_revision().publish()
|
||||
self.assertEqual(PURGED_URLS, set())
|
||||
|
||||
@override_settings(
|
||||
|
@ -569,8 +580,9 @@ class TestCachePurgingSignals(TestCase):
|
|||
WAGTAILFRONTENDCACHE_LANGUAGES=["en", "fr", "pt-br"],
|
||||
)
|
||||
def test_purge_on_publish_in_multilang_env(self):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.save_revision().publish()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.save_revision().publish()
|
||||
|
||||
self.assertEqual(
|
||||
PURGED_URLS,
|
||||
|
@ -591,8 +603,9 @@ class TestCachePurgingSignals(TestCase):
|
|||
WAGTAIL_CONTENT_LANGUAGES=[("en", "English"), ("fr", "French")],
|
||||
)
|
||||
def test_purge_on_publish_with_i18n_enabled(self):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.save_revision().publish()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.save_revision().publish()
|
||||
|
||||
self.assertEqual(
|
||||
PURGED_URLS,
|
||||
|
@ -610,9 +623,10 @@ class TestCachePurgingSignals(TestCase):
|
|||
WAGTAIL_CONTENT_LANGUAGES=[("en", "English"), ("fr", "French")],
|
||||
)
|
||||
def test_purge_on_publish_without_i18n_enabled(self):
|
||||
# It should ignore WAGTAIL_CONTENT_LANGUAGES as WAGTAIL_I18N_ENABLED isn't set
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.save_revision().publish()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
# It should ignore WAGTAIL_CONTENT_LANGUAGES as WAGTAIL_I18N_ENABLED isn't set
|
||||
page = EventIndex.objects.get(url_path="/home/events/")
|
||||
page.save_revision().publish()
|
||||
self.assertEqual(
|
||||
PURGED_URLS,
|
||||
{"http://localhost/en/events/", "http://localhost/en/events/past/"},
|
||||
|
@ -696,7 +710,8 @@ class TestPurgeBatchClass(TestCase):
|
|||
batch.add_url("http://localhost/events/")
|
||||
|
||||
with self.assertLogs(level="ERROR") as log_output:
|
||||
batch.purge(backend_settings=backend_settings)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
batch.purge(backend_settings=backend_settings)
|
||||
|
||||
self.assertIn(
|
||||
"Couldn't purge 'http://localhost/events/' from Cloudflare. HTTPError: 500",
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
import logging
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from urllib.parse import urlsplit, urlunsplit
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.module_loading import import_string
|
||||
|
||||
from wagtail.coreutils import get_content_languages
|
||||
|
||||
logger = logging.getLogger("wagtail.frontendcache")
|
||||
|
||||
|
||||
|
@ -64,72 +59,9 @@ def purge_url_from_cache(url, backend_settings=None, backends=None):
|
|||
|
||||
|
||||
def purge_urls_from_cache(urls, backend_settings=None, backends=None):
|
||||
if not urls:
|
||||
return
|
||||
from .tasks import purge_urls_from_cache_task
|
||||
|
||||
backends = get_backends(backend_settings, backends)
|
||||
|
||||
# If no backends are configured, there's nothing to do
|
||||
if not backends:
|
||||
return
|
||||
|
||||
# Convert each url to urls one for each managed language (WAGTAILFRONTENDCACHE_LANGUAGES setting).
|
||||
# The managed languages are common to all the defined backends.
|
||||
# This depends on settings.USE_I18N
|
||||
# If WAGTAIL_I18N_ENABLED is True, this defaults to WAGTAIL_CONTENT_LANGUAGES
|
||||
wagtail_i18n_enabled = getattr(settings, "WAGTAIL_I18N_ENABLED", False)
|
||||
content_languages = get_content_languages() if wagtail_i18n_enabled else {}
|
||||
languages = getattr(
|
||||
settings, "WAGTAILFRONTENDCACHE_LANGUAGES", list(content_languages.keys())
|
||||
)
|
||||
if settings.USE_I18N and languages:
|
||||
langs_regex = "^/(%s)/" % "|".join(languages)
|
||||
new_urls = []
|
||||
|
||||
# Purge the given url for each managed language
|
||||
for isocode in languages:
|
||||
for url in urls:
|
||||
up = urlsplit(url)
|
||||
new_url = urlunsplit(
|
||||
(
|
||||
up.scheme,
|
||||
up.netloc,
|
||||
re.sub(langs_regex, "/%s/" % isocode, up.path),
|
||||
up.query,
|
||||
up.fragment,
|
||||
)
|
||||
)
|
||||
|
||||
# Check for best performance. True if re.sub found no match
|
||||
# It happens when i18n_patterns was not used in urls.py to serve content for different languages from different URLs
|
||||
if new_url in new_urls:
|
||||
continue
|
||||
|
||||
new_urls.append(new_url)
|
||||
|
||||
urls = new_urls
|
||||
|
||||
urls_by_hostname = defaultdict(list)
|
||||
|
||||
for url in urls:
|
||||
urls_by_hostname[urlsplit(url).netloc].append(url)
|
||||
|
||||
for hostname, urls in urls_by_hostname.items():
|
||||
backends_for_hostname = {
|
||||
backend_name: backend
|
||||
for backend_name, backend in backends.items()
|
||||
if backend.invalidates_hostname(hostname)
|
||||
}
|
||||
|
||||
if not backends_for_hostname:
|
||||
logger.info("Unable to find purge backend for %s", hostname)
|
||||
continue
|
||||
|
||||
for backend_name, backend in backends_for_hostname.items():
|
||||
for url in urls:
|
||||
logger.info("[%s] Purging URL: %s", backend_name, url)
|
||||
|
||||
backend.purge_batch(urls)
|
||||
purge_urls_from_cache_task.enqueue(list(urls), backend_settings, backends)
|
||||
|
||||
|
||||
def _get_page_cached_urls(page):
|
||||
|
|
|
@ -801,14 +801,15 @@ class TestRedirectsAddView(WagtailTestUtils, TestCase):
|
|||
self.assertTemplateUsed(response, "wagtailredirects/add.html")
|
||||
|
||||
def test_add(self):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": "",
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": "",
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
|
||||
# Should redirect back to index
|
||||
self.assertRedirects(response, reverse("wagtailredirects:index"))
|
||||
|
@ -827,15 +828,16 @@ class TestRedirectsAddView(WagtailTestUtils, TestCase):
|
|||
self.assertEqual(PURGED_URLS, {"http://localhost/test"})
|
||||
|
||||
def test_add_with_site(self):
|
||||
localhost = Site.objects.get(hostname="localhost")
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": localhost.id,
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
localhost = Site.objects.get(hostname="localhost")
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": localhost.id,
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
|
||||
# Should redirect back to index
|
||||
self.assertRedirects(response, reverse("wagtailredirects:index"))
|
||||
|
@ -849,72 +851,76 @@ class TestRedirectsAddView(WagtailTestUtils, TestCase):
|
|||
self.assertEqual(PURGED_URLS, {"http://localhost/test"})
|
||||
|
||||
def test_add_validation_error(self):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "",
|
||||
"site": "",
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "",
|
||||
"site": "",
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
|
||||
# Should not redirect to index
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(PURGED_URLS, set())
|
||||
|
||||
def test_cannot_add_duplicate_with_no_site(self):
|
||||
models.Redirect.objects.create(
|
||||
old_path="/test", site=None, redirect_link="http://elsewhere.com/"
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": "",
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
models.Redirect.objects.create(
|
||||
old_path="/test", site=None, redirect_link="http://elsewhere.com/"
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": "",
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
|
||||
# Should not redirect to index
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(PURGED_URLS, set())
|
||||
|
||||
def test_cannot_add_duplicate_on_same_site(self):
|
||||
localhost = Site.objects.get(hostname="localhost")
|
||||
models.Redirect.objects.create(
|
||||
old_path="/test", site=localhost, redirect_link="http://elsewhere.com/"
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": localhost.pk,
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
localhost = Site.objects.get(hostname="localhost")
|
||||
models.Redirect.objects.create(
|
||||
old_path="/test", site=localhost, redirect_link="http://elsewhere.com/"
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": localhost.pk,
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
|
||||
# Should not redirect to index
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(PURGED_URLS, set())
|
||||
|
||||
def test_can_reuse_path_on_other_site(self):
|
||||
localhost = Site.objects.get(hostname="localhost")
|
||||
contact_page = Page.objects.get(url_path="/home/contact-us/")
|
||||
other_site = Site.objects.create(
|
||||
hostname="other.example.com", port=80, root_page=contact_page
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
localhost = Site.objects.get(hostname="localhost")
|
||||
contact_page = Page.objects.get(url_path="/home/contact-us/")
|
||||
other_site = Site.objects.create(
|
||||
hostname="other.example.com", port=80, root_page=contact_page
|
||||
)
|
||||
|
||||
models.Redirect.objects.create(
|
||||
old_path="/test", site=localhost, redirect_link="http://elsewhere.com/"
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": other_site.pk,
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
models.Redirect.objects.create(
|
||||
old_path="/test", site=localhost, redirect_link="http://elsewhere.com/"
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": other_site.pk,
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "http://www.test.com/",
|
||||
}
|
||||
)
|
||||
|
||||
# Should redirect back to index
|
||||
self.assertRedirects(response, reverse("wagtailredirects:index"))
|
||||
|
@ -926,14 +932,15 @@ class TestRedirectsAddView(WagtailTestUtils, TestCase):
|
|||
self.assertEqual(PURGED_URLS, redirects.get().old_links())
|
||||
|
||||
def test_add_long_redirect(self):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": "",
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "https://www.google.com/search?q=this+is+a+very+long+url+because+it+has+a+huge+search+term+appended+to+the+end+of+it+even+though+someone+should+really+not+be+doing+something+so+crazy+without+first+seeing+a+psychiatrist",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"site": "",
|
||||
"is_permanent": "on",
|
||||
"redirect_link": "https://www.google.com/search?q=this+is+a+very+long+url+because+it+has+a+huge+search+term+appended+to+the+end+of+it+even+though+someone+should+really+not+be+doing+something+so+crazy+without+first+seeing+a+psychiatrist",
|
||||
}
|
||||
)
|
||||
|
||||
# Should redirect back to index
|
||||
self.assertRedirects(response, reverse("wagtailredirects:index"))
|
||||
|
@ -1002,14 +1009,15 @@ class TestRedirectsEditView(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
|
|||
self.assertEqual(self.get(redirect_id=100000).status_code, 404)
|
||||
|
||||
def test_edit(self):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"is_permanent": "on",
|
||||
"site": "",
|
||||
"redirect_link": "http://www.test.com/ive-been-edited",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"is_permanent": "on",
|
||||
"site": "",
|
||||
"redirect_link": "http://www.test.com/ive-been-edited",
|
||||
}
|
||||
)
|
||||
|
||||
# Should redirect back to index
|
||||
self.assertRedirects(response, reverse("wagtailredirects:index"))
|
||||
|
@ -1025,16 +1033,17 @@ class TestRedirectsEditView(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
|
|||
self.assertEqual(PURGED_URLS, {"http://localhost/test"})
|
||||
|
||||
def test_edit_with_site(self):
|
||||
localhost = Site.objects.get(hostname="localhost")
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
localhost = Site.objects.get(hostname="localhost")
|
||||
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"is_permanent": "on",
|
||||
"site": localhost.id,
|
||||
"redirect_link": "http://www.test.com/ive-been-edited",
|
||||
}
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/test",
|
||||
"is_permanent": "on",
|
||||
"site": localhost.id,
|
||||
"redirect_link": "http://www.test.com/ive-been-edited",
|
||||
}
|
||||
)
|
||||
|
||||
# Should redirect back to index
|
||||
self.assertRedirects(response, reverse("wagtailredirects:index"))
|
||||
|
@ -1049,31 +1058,33 @@ class TestRedirectsEditView(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
|
|||
self.assertEqual(PURGED_URLS, {"http://localhost/test"})
|
||||
|
||||
def test_edit_validation_error(self):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "",
|
||||
"is_permanent": "on",
|
||||
"site": "",
|
||||
"redirect_link": "http://www.test.com/ive-been-edited",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "",
|
||||
"is_permanent": "on",
|
||||
"site": "",
|
||||
"redirect_link": "http://www.test.com/ive-been-edited",
|
||||
}
|
||||
)
|
||||
|
||||
# Should not redirect to index
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(PURGED_URLS, set())
|
||||
|
||||
def test_edit_duplicate(self):
|
||||
models.Redirect.objects.create(
|
||||
old_path="/othertest", site=None, redirect_link="http://elsewhere.com/"
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/othertest",
|
||||
"is_permanent": "on",
|
||||
"site": "",
|
||||
"redirect_link": "http://www.test.com/ive-been-edited",
|
||||
}
|
||||
)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
models.Redirect.objects.create(
|
||||
old_path="/othertest", site=None, redirect_link="http://elsewhere.com/"
|
||||
)
|
||||
response = self.post(
|
||||
{
|
||||
"old_path": "/othertest",
|
||||
"is_permanent": "on",
|
||||
"site": "",
|
||||
"redirect_link": "http://www.test.com/ive-been-edited",
|
||||
}
|
||||
)
|
||||
|
||||
# Should not redirect to index
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
@ -1153,7 +1164,8 @@ class TestRedirectsDeleteView(WagtailTestUtils, TestCase):
|
|||
self.assertEqual(self.get(redirect_id=100000).status_code, 404)
|
||||
|
||||
def test_delete(self):
|
||||
response = self.post()
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
response = self.post()
|
||||
|
||||
# Should redirect back to index
|
||||
self.assertRedirects(response, reverse("wagtailredirects:index"))
|
||||
|
|
|
@ -41,28 +41,29 @@ class TestAutocreateRedirects(WagtailTestUtils, TestCase):
|
|||
page.save(log_action="wagtail.publish", user=self.user, clean=False)
|
||||
|
||||
def test_golden_path(self):
|
||||
# the page we'll be triggering the change for here is...
|
||||
test_subject = self.event_index
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
# the page we'll be triggering the change for here is...
|
||||
test_subject = self.event_index
|
||||
|
||||
# identify 'draft' pages in this section
|
||||
drafts = test_subject.get_descendants().not_live()
|
||||
self.assertEqual(len(drafts), 4)
|
||||
# identify 'draft' pages in this section
|
||||
drafts = test_subject.get_descendants().not_live()
|
||||
self.assertEqual(len(drafts), 4)
|
||||
|
||||
# gather urls for 'live' pages in this branch
|
||||
request = get_dummy_request()
|
||||
branch_urls = []
|
||||
for page in (
|
||||
test_subject.get_descendants(inclusive=True)
|
||||
.live()
|
||||
.specific(defer=True)
|
||||
.iterator()
|
||||
):
|
||||
main_url = page.get_url(request).rstrip("/")
|
||||
branch_urls.extend(
|
||||
main_url + path.rstrip("/") for path in page.get_cached_paths()
|
||||
)
|
||||
# gather urls for 'live' pages in this branch
|
||||
request = get_dummy_request()
|
||||
branch_urls = []
|
||||
for page in (
|
||||
test_subject.get_descendants(inclusive=True)
|
||||
.live()
|
||||
.specific(defer=True)
|
||||
.iterator()
|
||||
):
|
||||
main_url = page.get_url(request).rstrip("/")
|
||||
branch_urls.extend(
|
||||
main_url + path.rstrip("/") for path in page.get_cached_paths()
|
||||
)
|
||||
|
||||
self.trigger_page_slug_changed_signal(test_subject)
|
||||
self.trigger_page_slug_changed_signal(test_subject)
|
||||
|
||||
# gather all of the redirects that were created
|
||||
redirects = Redirect.objects.all()
|
||||
|
@ -97,32 +98,34 @@ class TestAutocreateRedirects(WagtailTestUtils, TestCase):
|
|||
)
|
||||
|
||||
def test_no_redirects_created_when_page_is_root_for_all_sites_it_belongs_to(self):
|
||||
self.trigger_page_slug_changed_signal(self.home_page)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
self.trigger_page_slug_changed_signal(self.home_page)
|
||||
self.assertFalse(Redirect.objects.exists())
|
||||
self.assertEqual(len(PURGED_URLS), 0)
|
||||
|
||||
def test_handling_of_existing_redirects(self):
|
||||
# the page we'll be triggering the change for here is...
|
||||
test_subject = self.event_index
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
# the page we'll be triggering the change for here is...
|
||||
test_subject = self.event_index
|
||||
|
||||
descendants = test_subject.get_descendants().live()
|
||||
descendants = test_subject.get_descendants().live()
|
||||
|
||||
# but before we do, let's add some redirects that we'll expect to conflict
|
||||
# with ones created by the signal handler
|
||||
redirect1 = Redirect.objects.create(
|
||||
old_path=Redirect.normalise_path(descendants.first().specific.url),
|
||||
site=self.site,
|
||||
redirect_link="/some-place",
|
||||
automatically_created=False,
|
||||
)
|
||||
redirect2 = Redirect.objects.create(
|
||||
old_path=Redirect.normalise_path(descendants.last().specific.url),
|
||||
site=self.site,
|
||||
redirect_link="/some-other-place",
|
||||
automatically_created=True,
|
||||
)
|
||||
# but before we do, let's add some redirects that we'll expect to conflict
|
||||
# with ones created by the signal handler
|
||||
redirect1 = Redirect.objects.create(
|
||||
old_path=Redirect.normalise_path(descendants.first().specific.url),
|
||||
site=self.site,
|
||||
redirect_link="/some-place",
|
||||
automatically_created=False,
|
||||
)
|
||||
redirect2 = Redirect.objects.create(
|
||||
old_path=Redirect.normalise_path(descendants.last().specific.url),
|
||||
site=self.site,
|
||||
redirect_link="/some-other-place",
|
||||
automatically_created=True,
|
||||
)
|
||||
|
||||
self.trigger_page_slug_changed_signal(test_subject)
|
||||
self.trigger_page_slug_changed_signal(test_subject)
|
||||
|
||||
# pre-existing manually-created redirects should be preserved
|
||||
from_db = Redirect.objects.get(id=redirect1.id)
|
||||
|
@ -163,17 +166,18 @@ class TestAutocreateRedirects(WagtailTestUtils, TestCase):
|
|||
)
|
||||
|
||||
def test_redirect_creation_for_custom_route_paths(self):
|
||||
# Add a page that has overridden get_route_paths()
|
||||
homepage = Page.objects.get(id=2)
|
||||
routable_page = homepage.add_child(
|
||||
instance=RoutablePageTest(
|
||||
title="Routable Page",
|
||||
live=True,
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
# Add a page that has overridden get_route_paths()
|
||||
homepage = Page.objects.get(id=2)
|
||||
routable_page = homepage.add_child(
|
||||
instance=RoutablePageTest(
|
||||
title="Routable Page",
|
||||
live=True,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# Move from below the homepage to below the event index
|
||||
routable_page.move(self.event_index, pos="last-child")
|
||||
# Move from below the homepage to below the event index
|
||||
routable_page.move(self.event_index, pos="last-child")
|
||||
|
||||
# Redirects should have been created for each path returned by get_route_paths()
|
||||
self.assertEqual(
|
||||
|
@ -206,23 +210,24 @@ class TestAutocreateRedirects(WagtailTestUtils, TestCase):
|
|||
)
|
||||
|
||||
def test_no_redirects_created_when_pages_are_moved_to_a_different_site(self):
|
||||
# Add a new home page
|
||||
homepage_2 = Page(
|
||||
title="Second home",
|
||||
slug="second-home",
|
||||
)
|
||||
root_page = Page.objects.get(depth=1)
|
||||
root_page.add_child(instance=homepage_2)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
# Add a new home page
|
||||
homepage_2 = Page(
|
||||
title="Second home",
|
||||
slug="second-home",
|
||||
)
|
||||
root_page = Page.objects.get(depth=1)
|
||||
root_page.add_child(instance=homepage_2)
|
||||
|
||||
# Create a site with the above as the root_page
|
||||
Site.objects.create(
|
||||
root_page=homepage_2,
|
||||
hostname="newsite.com",
|
||||
port=80,
|
||||
)
|
||||
# Create a site with the above as the root_page
|
||||
Site.objects.create(
|
||||
root_page=homepage_2,
|
||||
hostname="newsite.com",
|
||||
port=80,
|
||||
)
|
||||
|
||||
# Move the event index to the new site
|
||||
self.event_index.move(homepage_2, pos="last-child")
|
||||
# Move the event index to the new site
|
||||
self.event_index.move(homepage_2, pos="last-child")
|
||||
|
||||
# No redirects should have been created
|
||||
self.assertFalse(Redirect.objects.exists())
|
||||
|
@ -230,6 +235,7 @@ class TestAutocreateRedirects(WagtailTestUtils, TestCase):
|
|||
|
||||
@override_settings(WAGTAILREDIRECTS_AUTO_CREATE=False)
|
||||
def test_no_redirects_created_if_disabled(self):
|
||||
self.trigger_page_slug_changed_signal(self.event_index)
|
||||
with self.captureOnCommitCallbacks(execute=True):
|
||||
self.trigger_page_slug_changed_signal(self.event_index)
|
||||
self.assertFalse(Redirect.objects.exists())
|
||||
self.assertEqual(len(PURGED_URLS), 0)
|
||||
|
|
Ładowanie…
Reference in New Issue