We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
wagtailfrontendcache throws an error when a root page is created without a site
On a new install of wagtail w/ wagtailfrontendcache enabled, I go through the following steps:
1. Go to the admin
2. Delete the default "welcome" page from the database
3. Create a new root page

After I create the new root page, I get the following error:

```
[17/Apr/2015 20:02:28] ERROR [django.request:231] Internal Server Error: /admin/pages/new/pages/genericpage/1/
Traceback (most recent call last):
  File "/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/wagtail/wagtailadmin/views/pages.py", line 211, in create
    revision.publish()
  File "/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/wagtail/wagtailcore/models.py", line 1141, in publish
    page_published.send(sender=page.specific_class, instance=page.specific)
  File "/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/django/dispatch/dispatcher.py", line 198, in send
    response = receiver(signal=self, sender=sender, **named)
  File "/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/wagtail/contrib/wagtailfrontendcache/signal_handlers.py", line 9, in page_published_signal_handler
    purge_page_from_cache(instance)
  File "/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/wagtail/contrib/wagtailfrontendcache/utils.py", line 100, in purge_page_from_cache
    logger.info("[%s] Purging URL: %s", backend_name, page.full_url + path[1:])
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'
```

Digging into the code, this error is the request of the following line:

```
logger.info("[%s] Purging URL: %s", backend_name, page.full_url + path[1:])
```

This line failes because `page.full_url` is set to `None` when it executes, which results in the line throwing an exception. The new page model is still saved, so I just need to refresh the admin in my browser to get back into a good working state.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `wagtail/contrib/wagtailfrontendcache/utils.py`
Content:
```
1 import logging
2 
3 from django.conf import settings
4 from django.utils.module_loading import import_string
5 from django.core.exceptions import ImproperlyConfigured
6 
7 
8 logger = logging.getLogger('wagtail.frontendcache')
9 
10 
11 class InvalidFrontendCacheBackendError(ImproperlyConfigured):
12     pass
13 
14 
15 def get_backends(backend_settings=None, backends=None):
16     # Get backend settings from WAGTAILFRONTENDCACHE setting
17     if backend_settings is None:
18         backend_settings = getattr(settings, 'WAGTAILFRONTENDCACHE', None)
19 
20     # Fallback to using WAGTAILFRONTENDCACHE_LOCATION setting (backwards compatibility)
21     if backend_settings is None:
22         cache_location = getattr(settings, 'WAGTAILFRONTENDCACHE_LOCATION', None)
23 
24         if cache_location is not None:
25             backend_settings = {
26                 'default': {
27                     'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.HTTPBackend',
28                     'LOCATION': cache_location,
29                 },
30             }
31 
32     # No settings found, return empty list
33     if backend_settings is None:
34         return {}
35 
36     backend_objects = {}
37 
38     for backend_name, _backend_config in backend_settings.items():
39         if backends is not None and backend_name not in backends:
40             continue
41 
42         backend_config = _backend_config.copy()
43         backend = backend_config.pop('BACKEND')
44 
45         # Try to import the backend
46         try:
47             backend_cls = import_string(backend)
48         except ImportError as e:
49             raise InvalidFrontendCacheBackendError("Could not find backend '%s': %s" % (
50                 backend, e))
51 
52         backend_objects[backend_name] = backend_cls(backend_config)
53 
54     return backend_objects
55 
56 
57 def purge_url_from_cache(url, backend_settings=None, backends=None):
58     for backend_name, backend in get_backends(backend_settings=backend_settings, backends=backends).items():
59         logger.info("[%s] Purging URL: %s", backend_name, url)
60         backend.purge(url)
61 
62 
63 def purge_page_from_cache(page, backend_settings=None, backends=None):
64     for backend_name, backend in get_backends(backend_settings=backend_settings, backends=backends).items():
65         # Purge cached paths from cache
66         for path in page.specific.get_cached_paths():
67             logger.info("[%s] Purging URL: %s", backend_name, page.full_url + path[1:])
68             backend.purge(page.full_url + path[1:])
69
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/wagtail/contrib/wagtailfrontendcache/utils.py b/wagtail/contrib/wagtailfrontendcache/utils.py
--- a/wagtail/contrib/wagtailfrontendcache/utils.py
+++ b/wagtail/contrib/wagtailfrontendcache/utils.py
@@ -61,8 +61,12 @@
 
 
 def purge_page_from_cache(page, backend_settings=None, backends=None):
+    page_url = page.full_url
+    if page_url is None:  # nothing to be done if the page has no routable URL
+        return
+
     for backend_name, backend in get_backends(backend_settings=backend_settings, backends=backends).items():
         # Purge cached paths from cache
         for path in page.specific.get_cached_paths():
-            logger.info("[%s] Purging URL: %s", backend_name, page.full_url + path[1:])
-            backend.purge(page.full_url + path[1:])
+            logger.info("[%s] Purging URL: %s", backend_name, page_url + path[1:])
+            backend.purge(page_url + path[1:])

{"golden_diff": "diff --git a/wagtail/contrib/wagtailfrontendcache/utils.py b/wagtail/contrib/wagtailfrontendcache/utils.py\n--- a/wagtail/contrib/wagtailfrontendcache/utils.py\n+++ b/wagtail/contrib/wagtailfrontendcache/utils.py\n@@ -61,8 +61,12 @@\n \n \n def purge_page_from_cache(page, backend_settings=None, backends=None):\n+    page_url = page.full_url\n+    if page_url is None:  # nothing to be done if the page has no routable URL\n+        return\n+\n     for backend_name, backend in get_backends(backend_settings=backend_settings, backends=backends).items():\n         # Purge cached paths from cache\n         for path in page.specific.get_cached_paths():\n-            logger.info(\"[%s] Purging URL: %s\", backend_name, page.full_url + path[1:])\n-            backend.purge(page.full_url + path[1:])\n+            logger.info(\"[%s] Purging URL: %s\", backend_name, page_url + path[1:])\n+            backend.purge(page_url + path[1:])\n", "issue": "wagtailfrontendcache throws an error when a root page is created without a site\nOn a new install of wagtail w/ wagtailfrontendcache enabled, I go through the following steps:\n1. Go to the admin\n2. Delete the default \"welcome\" page from the database\n3. Create a new root page\n\nAfter I create the new root page, I get the following error:\n\n```\n[17/Apr/2015 20:02:28] ERROR [django.request:231] Internal Server Error: /admin/pages/new/pages/genericpage/1/\nTraceback (most recent call last):\n  File \"/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/django/core/handlers/base.py\", line 111, in get_response\n    response = wrapped_callback(request, *callback_args, **callback_kwargs)\n  File \"/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/django/contrib/auth/decorators.py\", line 21, in _wrapped_view\n    return view_func(request, *args, **kwargs)\n  File \"/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/wagtail/wagtailadmin/views/pages.py\", line 211, in create\n    revision.publish()\n  File \"/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/wagtail/wagtailcore/models.py\", line 1141, in publish\n    page_published.send(sender=page.specific_class, instance=page.specific)\n  File \"/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/django/dispatch/dispatcher.py\", line 198, in send\n    response = receiver(signal=self, sender=sender, **named)\n  File \"/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/wagtail/contrib/wagtailfrontendcache/signal_handlers.py\", line 9, in page_published_signal_handler\n    purge_page_from_cache(instance)\n  File \"/Users/jryding/.virtualenvs/cms/lib/python2.7/site-packages/wagtail/contrib/wagtailfrontendcache/utils.py\", line 100, in purge_page_from_cache\n    logger.info(\"[%s] Purging URL: %s\", backend_name, page.full_url + path[1:])\nTypeError: unsupported operand type(s) for +: 'NoneType' and 'str'\n```\n\nDigging into the code, this error is the request of the following line:\n\n```\nlogger.info(\"[%s] Purging URL: %s\", backend_name, page.full_url + path[1:])\n```\n\nThis line failes because `page.full_url` is set to `None` when it executes, which results in the line throwing an exception. The new page model is still saved, so I just need to refresh the admin in my browser to get back into a good working state.\n\n", "before_files": [{"content": "import logging\n\nfrom django.conf import settings\nfrom django.utils.module_loading import import_string\nfrom django.core.exceptions import ImproperlyConfigured\n\n\nlogger = logging.getLogger('wagtail.frontendcache')\n\n\nclass InvalidFrontendCacheBackendError(ImproperlyConfigured):\n    pass\n\n\ndef get_backends(backend_settings=None, backends=None):\n    # Get backend settings from WAGTAILFRONTENDCACHE setting\n    if backend_settings is None:\n        backend_settings = getattr(settings, 'WAGTAILFRONTENDCACHE', None)\n\n    # Fallback to using WAGTAILFRONTENDCACHE_LOCATION setting (backwards compatibility)\n    if backend_settings is None:\n        cache_location = getattr(settings, 'WAGTAILFRONTENDCACHE_LOCATION', None)\n\n        if cache_location is not None:\n            backend_settings = {\n                'default': {\n                    'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.HTTPBackend',\n                    'LOCATION': cache_location,\n                },\n            }\n\n    # No settings found, return empty list\n    if backend_settings is None:\n        return {}\n\n    backend_objects = {}\n\n    for backend_name, _backend_config in backend_settings.items():\n        if backends is not None and backend_name not in backends:\n            continue\n\n        backend_config = _backend_config.copy()\n        backend = backend_config.pop('BACKEND')\n\n        # Try to import the backend\n        try:\n            backend_cls = import_string(backend)\n        except ImportError as e:\n            raise InvalidFrontendCacheBackendError(\"Could not find backend '%s': %s\" % (\n                backend, e))\n\n        backend_objects[backend_name] = backend_cls(backend_config)\n\n    return backend_objects\n\n\ndef purge_url_from_cache(url, backend_settings=None, backends=None):\n    for backend_name, backend in get_backends(backend_settings=backend_settings, backends=backends).items():\n        logger.info(\"[%s] Purging URL: %s\", backend_name, url)\n        backend.purge(url)\n\n\ndef purge_page_from_cache(page, backend_settings=None, backends=None):\n    for backend_name, backend in get_backends(backend_settings=backend_settings, backends=backends).items():\n        # Purge cached paths from cache\n        for path in page.specific.get_cached_paths():\n            logger.info(\"[%s] Purging URL: %s\", backend_name, page.full_url + path[1:])\n            backend.purge(page.full_url + path[1:])\n", "path": "wagtail/contrib/wagtailfrontendcache/utils.py"}], "after_files": [{"content": "import logging\n\nfrom django.conf import settings\nfrom django.utils.module_loading import import_string\nfrom django.core.exceptions import ImproperlyConfigured\n\n\nlogger = logging.getLogger('wagtail.frontendcache')\n\n\nclass InvalidFrontendCacheBackendError(ImproperlyConfigured):\n    pass\n\n\ndef get_backends(backend_settings=None, backends=None):\n    # Get backend settings from WAGTAILFRONTENDCACHE setting\n    if backend_settings is None:\n        backend_settings = getattr(settings, 'WAGTAILFRONTENDCACHE', None)\n\n    # Fallback to using WAGTAILFRONTENDCACHE_LOCATION setting (backwards compatibility)\n    if backend_settings is None:\n        cache_location = getattr(settings, 'WAGTAILFRONTENDCACHE_LOCATION', None)\n\n        if cache_location is not None:\n            backend_settings = {\n                'default': {\n                    'BACKEND': 'wagtail.contrib.wagtailfrontendcache.backends.HTTPBackend',\n                    'LOCATION': cache_location,\n                },\n            }\n\n    # No settings found, return empty list\n    if backend_settings is None:\n        return {}\n\n    backend_objects = {}\n\n    for backend_name, _backend_config in backend_settings.items():\n        if backends is not None and backend_name not in backends:\n            continue\n\n        backend_config = _backend_config.copy()\n        backend = backend_config.pop('BACKEND')\n\n        # Try to import the backend\n        try:\n            backend_cls = import_string(backend)\n        except ImportError as e:\n            raise InvalidFrontendCacheBackendError(\"Could not find backend '%s': %s\" % (\n                backend, e))\n\n        backend_objects[backend_name] = backend_cls(backend_config)\n\n    return backend_objects\n\n\ndef purge_url_from_cache(url, backend_settings=None, backends=None):\n    for backend_name, backend in get_backends(backend_settings=backend_settings, backends=backends).items():\n        logger.info(\"[%s] Purging URL: %s\", backend_name, url)\n        backend.purge(url)\n\n\ndef purge_page_from_cache(page, backend_settings=None, backends=None):\n    page_url = page.full_url\n    if page_url is None:  # nothing to be done if the page has no routable URL\n        return\n\n    for backend_name, backend in get_backends(backend_settings=backend_settings, backends=backends).items():\n        # Purge cached paths from cache\n        for path in page.specific.get_cached_paths():\n            logger.info(\"[%s] Purging URL: %s\", backend_name, page_url + path[1:])\n            backend.purge(page_url + path[1:])\n", "path": "wagtail/contrib/wagtailfrontendcache/utils.py"}]}