Adding custom URLs

Page types can provide custom URL patterns. These URL patterns are relative to the place where the page is added to the page tree.

This feature is useful for example to:

  • Have a “Shop” page type where all products are sub pages.
  • Have a “Blog” page type where all articles are displayed below.

To use this feature, provide a URLconf or an inline patterns() list in the page type plugin.

Basic example

To have a plugin with custom views, add the urls attribute:

@page_type_pool.register
class ProductCategoryPagePlugin(PageTypePlugin):
    # ...

    urls = patterns('myshop.views',
        url('^(?P<slug>[^/]+)/$', 'product_details'),
    )

The view is just a plain Django view:

from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from myshop.models import Product

def product_details(request, slug):
    product = get_object_or_404(Product, slug=slug)
    return render(request, 'products/product_details.html', {
        'product': product
    })

Other custom views can be created in the same way.

Resolving URLs

The URLs can’t be resolved using the standard reverse() function unfortunately. The main reason is that it caches results internally for the lifetime of the WSGI container, meanwhile pages may be rearranged by the admin.

Hence, a app_reverse() function is available. It can be used to resolve the product page:

from fluent_pages.urlresolvers import app_reverse

app_reverse('product_details', kwargs={'slug': 'myproduct'})

In templates, there is an appurl tag which accomplishes the same effect:

{% load appurl_tags %}

<a href="{% appurl 'product_details' slug='myproduct' %}">My Product</a>

See also

The example application in the source demonstrates this feature.

Compatibility with regular URLconf

An application can provide a standard urls.py for regular Django support, and still support page type URLs too. For this special case, the mixed_reverse() function is available. It attemps to resolve the view in the standard URLconf first, and falls back to app_reverse() if the view is not found there.

A mixedurl template tag has to be included in the application itself. Use the following code as example:

@register.tag
def mixedurl(parser, token):
    if 'fluent_pages' in settings.INSTALLED_APPS:
        from fluent_pages.templatetags.appurl_tags import appurl
        return appurl(parser, token)
    else:
        from django.template.defaulttags import url
        return url(parser, token)

See also

The django-fluent-blogs application uses this feature to optionally integrate the blog articles to the page tree.