How can I get the reverse url for a Django Flatpages template
10 Answers
I prefer the following solution (require Django >= 1.0).
settings.py
INSTALLED_APPS+= ('django.contrib.flatpages',)
urls.py
urlpatterns+= patterns('django.contrib.flatpages.views',
url(r'^about-us/$', 'flatpage', {'url': '/about-us/'}, name='about'),
url(r'^license/$', 'flatpage', {'url': '/license/'}, name='license'),
)
In your templates
[...]
<a href="{% url about %}"><span>{% trans "About us" %}</span></a>
<a href="{% url license %}"><span>{% trans "Licensing" %}</span></a>
[...]
Or in your code
from django.core.urlresolvers import reverse
[...]
reverse('license')
[...]
That way you don't need to use django.contrib.flatpages.middleware.FlatpageFallbackMiddleware
and the reverse works as usual without writing so much code as in the other solutions.
Cheers.

- 3,153
- 31
- 36
-
1The only real difference between your solution and mine (which doesn't require the `FlatPageFallbackMiddleware` either), is the use of named urlpatterns (not available pre-1.0, as you pointed out). That said, I suppose it might be better (for maintainability) to have all your URLs listed in a urlconf, rather than in templates, at the expense of a little verbosity. +1 – elo80ka Apr 05 '11 at 07:54
Include flatpages in your root urlconf:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
('^pages/', include('django.contrib.flatpages.urls')),
)
Then, in your view you can call reverse like so:
from django.core.urlresolvers import reverse
reverse('django.contrib.flatpages.views.flatpage', kwargs={'url': '/about-us/'})
# Gives: /pages/about-us/
In templates, use the {% url %} tag (which calls reverse internally):
<a href='{% url django.contrib.flatpages.views.flatpage url="/about-us/" %}'>About Us</a>

- 14,837
- 3
- 36
- 43
-
elo80ka, Thanks for laying that out so well. That looks like even I can follow it. It seems like this violates the DRY principle slightly (I hope I understand what DRY is) but I imagine there is no way around that for this goal. – Travis Jan 22 '10 at 23:16
-
Great answer, only thing I wonder is in regards to the template. By placing "/about-us/" in the template, it defeats the purpose. If I go into django admin and change /about-us/ to something else, the template no longer functions. Or am I missing something here? – Chris Aug 04 '12 at 18:41
-
1@Chris: you're quite right...you'd likely get 404'd. I'd say you have a few alternatives: (a) use a context processor to look up the URLs for all flatpages, and push those into the template, or (b) use tools like Selenium/Webdriver to test all URLs and catch 404's. Oh, there's also (c) Don't use Flatpages :) – elo80ka Aug 05 '12 at 14:15
Write your base urls conf to point to your flatpages. Assume it is under pages:
urlpatterns = patterns('',
...
url(r'^pages/', include('project.pages.urls')),
...
)
Then write your flatpages as normal:
urlpatterns = patterns('django.views.generic.simple',
url(regex=r'^resume/$', view='direct_to_template', kwargs={'template': 'resume.html'}, name='resume'),
url(regex=r'^about/$', view='direct_to_template', kwargs={'template': 'about.html'}, name='about'),
url(regex=r'^books/$', view='direct_to_template', kwargs={'template': 'library.html'},name='books'),
)
Then your template just refers to them in the usual fashion:
<div id="pages">
...
<div class="pagelinks">
<a href="{% url about %}">ABOUT</a>
</div>
</div>

- 47,733
- 20
- 85
- 108
I thought the advantage of Flatpages was you didn't have to create any view stubs or url confs? It's a bit pointless otherwise... if you're creating views and urls you may as well save the flatpage content as template html instead.
try this instead: https://github.com/0sn/nameremoved/wiki/flatpages

- 1,287
- 1
- 11
- 15

- 32,188
- 12
- 99
- 147
None of the solutions mentioned sufficiently followed the DRY principle in my opinion, so I just did this:
# core/templatetags/hacks.py
from django import template
register = template.Library()
@register.simple_tag
def flaturl(title):
"""
Returns the url for a flatpage based on the title.
NOTE: Obviously the title must be unique.
"""
from django.contrib.flatpages.models import FlatPage
try:
page = FlatPage.objects.get(title=title)
except:
return ""
return page.url
Then in any template that needs to make a link, I did this:
{% load hacks %}
...
<a href="{% flaturl 'My Page Title' %}">Page Title</a>
I might add some caching in there to keep the performance up, but this works for me.

- 6,010
- 6
- 38
- 61
I agree with Anentropic that there is no point in using Django Flatpages if you need to write urlconfs to employ them. It's much more straightforward to use generic views such as TemplateView
directly:
from django.conf.urls import patterns, url
from django.views.generic import TemplateView
urlpatterns = patterns('',
url(r'^about/$', TemplateView.as_view(template_name="about.html"), name="about"),
)
Flatpages take advantage of FlatpageFallbackMiddleware
, which catches 404 errors and tries to find content for requested url in your database. The major advantage is that you don't have to touch your templates directly each time you have to change something in them, the downside is the need to use a database :)
If you still choose to use Flatpages app, you'd better use get_flatpages
template tag:
{% load flatpages %}
<ul>
{% for page in get_flatpages %}
<li><a href="{{ page.url }}">{{ page.title }}</a></li>
{% endfor %}
</ul>
Personally, I rarely reference flatpages outside of website's main menu, which is included via {% include 'includes/nav.html' %}
and looks like this:
<ul>
<li><a href="/about/">About</a></li>
<li><a href="/credits/">Credits</a></li>
...
</ul>
I don't feel I violate any DRY KISS or something:)
-
2Yes `get_flatpages` is perfect for creating footer menus, sitemaps, etc. [Flatpages also supports](https://docs.djangoproject.com/en/dev/ref/contrib/flatpages/#getting-a-list-of-flatpage-objects-in-your-templates) getting only flatpages that start with a base url: `{% get_flatpages '/about/' as about_pages %}`. – Carl G Jun 20 '12 at 06:12
You need to redeclare the url conf and cannot rely on the official 'django.contrib.flatpages.urls'
that the doc is encouraging us to use.
This won't be more difficult, just include in your urls.py
from django.conf.urls import patterns, url
urlpatterns += patterns('',
...
url(r'^pages(?P<url>.*)$', 'django.contrib.flatpages.views.flatpage', name='flatpage'),
...
)
And now you can use your usual reverse url template tag
<a href='{% url 'flatpage' url="/about-us/" %}'>About Us</a>
Or to display a list of all flat pages
<ul>
{% get_flatpages as flatpages %}
{% for page in flatpages %}
<li><a href="{% url 'flatpage' url=page.url %}">{{ page.title }}</a></li>
{% endfor %}
</ul>

- 1,148
- 11
- 12
When you create any flatpage, you need to specify an URL which is saved as part of the model. Hence you can retrieve the URL from any flatpage object. In a template:
{{ flatpage.url }}
Remapping flatpage URLs in urls.py
and then having to use reverse sort of defeats the purpose of the flatpages app.

- 222,467
- 53
- 283
- 367

- 1,602
- 11
- 11
proper Django>= 1.10:
urls.py
urlpatterns += [
url(r'^(?P<url>.*/)$', flatpage, name='flatpage'),
]
easy lookup inside the template:
{% url "flatpage" url="SOME_URL" %}
where SOME_URL is the value frome the flatpage.url
field

- 764
- 1
- 8
- 19
According to this django documentation for flatpages
You can simply do
{% load flatpages %}
{% get_flatpages as flatpages %}
<ul>
{% for page in flatpages %}
<li><a href="{{ page.url }}">{{ page.title }}</a></li>
{% endfor %}
</ul>
In your template.

- 425
- 7
- 9
-
This is good for looping through all of the flatpages, but falls short if you only want a specific flatpage URL. – nicorellius Feb 14 '20 at 21:51