diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index a0abb58db..d7f66ec93 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,19 @@
Changelog
=========
+0.5 (xx.xx.20xx)
+~~~~~~~~~~~~~~~~
+ * Added RoutablePage model to allow embedding Django-style URL routing within a page
+ * Explorer nav now rendered separately and fetched with AJAX when needed
+ * Added decorator syntax for hooks
+ * Replaced lxml dependency with html5lib, to simplify installation
+ * Added page_unpublished signal
+
+0.4.1 (14.07.2014)
+~~~~~~~~~~~~~~~~~~
+ * ElasticSearch backend now respects the backward-compatible URLS configuration setting, in addition to HOSTS
+ * Documentation fixes
+
0.4 (10.07.2014)
~~~~~~~~~~~~~~~~
* ElasticUtils/pyelasticsearch swapped for elasticsearch-py
diff --git a/docs/building_your_site/djangodevelopers.rst b/docs/building_your_site/djangodevelopers.rst
index a2d196379..d1b69dcf3 100644
--- a/docs/building_your_site/djangodevelopers.rst
+++ b/docs/building_your_site/djangodevelopers.rst
@@ -197,13 +197,13 @@ In addition to the model fields provided, ``Page`` has many properties and metho
.. automodule:: wagtail.wagtailcore.models
.. autoclass:: Page
- .. method:: specific
+ .. autoattribute:: specific
- Return this page in its most specific subclassed form.
+ .. autoattribute:: specific_class
- .. automethod:: url
+ .. autoattribute:: url
- .. automethod:: full_url
+ .. autoattribute:: full_url
.. automethod:: relative_url
@@ -217,7 +217,7 @@ In addition to the model fields provided, ``Page`` has many properties and metho
.. automethod:: get_template
- .. automethod:: preview_modes
+ .. autoattribute:: preview_modes
.. automethod:: serve_preview
@@ -381,6 +381,8 @@ Examples:
.. automethod:: public
+ See: :ref:`private_pages`
+
.. note::
This doesn't filter out unpublished pages. If you want to only have published public pages, use ``.live().public()``
@@ -394,6 +396,8 @@ Examples:
.. automethod:: search
+ See: :ref:`wagtailsearch_for_python_developers`
+
Example:
.. code-block:: python
diff --git a/docs/conf.py b/docs/conf.py
index 36921d794..e0931da3b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -33,6 +33,9 @@ sys.path.insert(0, os.path.abspath('..'))
# be configured
os.environ['DJANGO_SETTINGS_MODULE'] = 'wagtail.tests.settings'
+# Use SQLite3 database engine so it doesn't attempt to use psycopg2 on RTD
+os.environ['DATABASE_ENGINE'] = 'django.db.backends.sqlite3'
+
# -- General configuration ------------------------------------------------
diff --git a/docs/editing_api.rst b/docs/editing_api.rst
index 48d766675..4d346a815 100644
--- a/docs/editing_api.rst
+++ b/docs/editing_api.rst
@@ -392,15 +392,28 @@ Admin Hooks
On loading, Wagtail will search for any app with the file ``wagtail_hooks.py`` and execute the contents. This provides a way to register your own functions to execute at certain points in Wagtail's execution, such as when a ``Page`` object is saved or when the main menu is constructed.
-Registering functions with a Wagtail hook follows the following pattern:
+.. versionadded:: 0.5
+ Decorator syntax was added in 0.5; earlier versions only supported ``hooks.register`` as an ordinary function call.
+
+Registering functions with a Wagtail hook is done through the ``@hooks.register`` decorator:
.. code-block:: python
from wagtail.wagtailcore import hooks
- hooks.register('hook', function)
+ @hooks.register('name_of_hook')
+ def my_hook_function(arg1, arg2...)
+ # your code here
-Where ``'hook'`` is one of the following hook strings and ``function`` is a function you've defined to handle the hook.
+
+Alternatively, ``hooks.register`` can be called as an ordinary function, passing in the name of the hook and a handler function defined elsewhere:
+
+.. code-block:: python
+
+ hooks.register('name_of_hook', my_hook_function)
+
+
+The available hooks are:
.. _before_serve_page:
@@ -413,11 +426,11 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
from wagtail.wagtailcore import hooks
+ @hooks.register('before_serve_page')
def block_googlebot(page, request, serve_args, serve_kwargs):
if request.META.get('HTTP_USER_AGENT') == 'GoogleBot':
return HttpResponse("
bad googlebot no cookie
")
- hooks.register('before_serve_page', block_googlebot)
.. _construct_wagtail_edit_bird:
@@ -433,10 +446,10 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
return '
'
+ @hooks.register('construct_wagtail_edit_bird')
def add_puppy_link_item(request, items):
return items.append( UserbarPuppyLinkItem() )
- hooks.register('construct_wagtail_edit_bird', add_puppy_link_item)
.. _construct_homepage_panels:
@@ -459,10 +472,10 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
""")
+ @hooks.register('construct_homepage_panels')
def add_another_welcome_panel(request, panels):
return panels.append( WelcomePanel() )
- hooks.register('construct_homepage_panels', add_another_welcome_panel)
.. _after_create_page:
@@ -475,9 +488,10 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
from wagtail.wagtailcore import hooks
+ @hooks.register('after_create_page')
def do_after_page_create(request, page):
return HttpResponse("Congrats on making content!", content_type="text/plain")
- hooks.register('after_create_page', do_after_page_create)
+
.. _after_edit_page:
@@ -508,11 +522,11 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
"I have approximate knowledge of many things!", \
content_type="text/plain")
+ @hooks.register('register_admin_urls')
def urlconf_time():
return [
url(r'^how_did_you_almost_know_my_name/$', admin_view, name='frank' ),
]
- hooks.register('register_admin_urls', urlconf_time)
.. _construct_main_menu:
@@ -526,11 +540,11 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
from wagtail.wagtailcore import hooks
from wagtail.wagtailadmin.menu import MenuItem
+ @hooks.register('construct_main_menu')
def construct_main_menu(request, menu_items):
menu_items.append(
MenuItem( 'Frank', reverse('frank'), classnames='icon icon-folder-inverse', order=10000)
)
- hooks.register('construct_main_menu', construct_main_menu)
.. _insert_editor_js:
@@ -545,6 +559,7 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
from wagtail.wagtailcore import hooks
+ @hooks.register('insert_editor_js')
def editor_js():
js_files = [
'demo/js/hallo-plugins/hallo-demo-plugin.js',
@@ -559,7 +574,7 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
"""
)
- hooks.register('insert_editor_js', editor_js)
+
.. _insert_editor_css:
@@ -573,11 +588,11 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
from wagtail.wagtailcore import hooks
+ @hooks.register('insert_editor_css')
def editor_css():
return format_html('')
- hooks.register('insert_editor_css', editor_css)
.. _construct_whitelister_element_rules:
@@ -595,12 +610,12 @@ Where ``'hook'`` is one of the following hook strings and ``function`` is a func
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.whitelist import attribute_rule, check_url, allow_without_attributes
+ @hooks.register('construct_whitelister_element_rules')
def whitelister_element_rules():
return {
'blockquote': allow_without_attributes,
'a': attribute_rule({'href': check_url, 'target': True}),
}
- hooks.register('construct_whitelister_element_rules', whitelister_element_rules)
Image Formats in the Rich Text Editor
diff --git a/docs/frontend_cache_purging.rst b/docs/frontend_cache_purging.rst
index c1b03624f..5f9f12ab3 100644
--- a/docs/frontend_cache_purging.rst
+++ b/docs/frontend_cache_purging.rst
@@ -3,6 +3,8 @@
Frontend cache purging
======================
+.. versionadded:: 0.4
+
Many websites use a frontend cache such as Varnish, Squid or Cloudflare 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.
This document describes how to configure Wagtail to purge old versions of pages from a frontend cache whenever a page gets updated.
diff --git a/docs/index.rst b/docs/index.rst
index 2ab429eb6..76f8c9444 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -16,6 +16,7 @@ It supports Django 1.6.2+ on Python 2.6, 2.7, 3.2, 3.3 and 3.4. Django 1.7 suppo
search/index
form_builder
model_recipes
+ routable_page
advanced_topics
deploying
performance
diff --git a/docs/performance.rst b/docs/performance.rst
index 09f06be0f..68c642520 100644
--- a/docs/performance.rst
+++ b/docs/performance.rst
@@ -3,11 +3,13 @@ Performance
Wagtail is designed for speed, both in the editor interface and on the front-end, but if you want even better performance or you need to handle very high volumes of traffic, here are some tips on eking out the most from your installation.
+
Editor interface
~~~~~~~~~~~~~~~~
We have tried to minimise external dependencies for a working installation of Wagtail, in order to make it as simple as possible to get going. However, a number of default settings can be configured for better performance:
+
Cache
-----
@@ -25,16 +27,19 @@ We recommend `Redis `_ as a fast, persistent cache. Install Re
Without a persistent cache, Wagtail will recreate all compressable assets at each server start, e.g. when any files change under ```./manage.py runserver```.
+
Search
------
Wagtail has strong support for `Elasticsearch `_ - both in the editor interface and for users of your site - but can fall back to a database search if Elasticsearch isn't present. Elasticsearch is faster and more powerful than the Django ORM for text search, so we recommend installing it or using a hosted service like `Searchly `_.
+
Database
--------
Wagtail is tested on SQLite, and should work on other Django-supported database backends, but we recommend PostgreSQL for production use.
+
Public users
~~~~~~~~~~~~
@@ -42,3 +47,7 @@ Caching proxy
-------------
To support high volumes of traffic with excellent response times, we recommend a caching proxy. Both `Varnish `_ and `Squid `_ have been tested in production. Hosted proxies like `Cloudflare `_ should also work well.
+
+.. versionadded:: 0.4
+
+ Wagtail supports automatic cache invalidation for Varnish/Squid. See :ref:`frontend_cache_purging` for more information.
diff --git a/docs/private_pages.rst b/docs/private_pages.rst
index 99b364176..33767a8b5 100644
--- a/docs/private_pages.rst
+++ b/docs/private_pages.rst
@@ -3,10 +3,13 @@
Private pages
=============
+.. versionadded:: 0.4
+
Users with publish permission on a page can set it to be private by clicking the 'Privacy' control in the top right corner of the page explorer or editing interface, and setting a password. Users visiting this page, or any of its subpages, will be prompted to enter a password before they can view the page.
Private pages work on Wagtail out of the box - the site implementer does not need to do anything to set them up. However, the default "password required" form is only a bare-bones HTML page, and site implementers may wish to replace this with a page customised to their site design.
+
Setting up a global "password required" page
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -52,6 +55,7 @@ A basic template suitable for use as ``PASSWORD_REQUIRED_TEMPLATE`` might look l