Two template tags (I keep them in an app called "utils") handy for building menus out of flatpages. I only have two levels of hierarchy, and the frontpage is dynamic, so that's what it does. There is some flexibility, however, in that you can change the regex that defines a "root" page.
You can pass it the flatpage object that is normally given to a flatpage template, or you can pass it a string (for any other page).
Deliberatley does not create any markup -- flexibility is key, so it adds the list of root urls or child urls as a name in the current context. You get to pick the name.
Please visit the GitHub archive where i keep this up to date, there's a better explanation and you can see it in use.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | from django import template
import re
from django.contrib.flatpages.models import FlatPage
register = template.Library()
def do_flatpage_root(parser, token):
"""
This tag creates a queryset containing all the top-level flatpages,
adding it to the current context with the given name.
This does not include "/", if there is a flatpage with that url.
For example::
{% flatpage_root as root %}
adds a queryset of flatpages whose url can be matched with ^/[^/]*/$ to
the current context, named root. It can then be used::
{% for page in root %}
and so forth.
"""
bits = token.contents.split()
if len(bits) != 3 or bits[1] != "as":
raise template.TemplateSyntaxError("%r expected format is 'flatpage_root as name'" % bits[0])
return FlatpageRoot(bits[2])
class FlatpageRoot(template.Node):
# this regex is the definition of a top-level flatpage
# override in a subclass if you have a different idea!
root_regex = r'^/[^/]*/$'
def __init__(self, context_name):
self.context_name = context_name
def render(self, context):
context[self.context_name] = FlatPage.objects.filter(url__regex=self.root_regex)
return ""
register.tag('flatpage_root', do_flatpage_root)
def do_flatpage_children(parser, token):
"""
This tag creates a queryset containing all flatpages below a given root
url, adding it to the current context with the given name.
A "root url" is any url matched by ^/[^/]*/$.
Typically, this would be used to get a list of children of a parent url::
{% flatpage_children "/about/" as children}
This adds a queryset of all deeper urls, such as "/about/author/" and
"/about/pants/" to the current context, named children.
If the url given is "/", the tag doesn't do anything.
If the url given is not a root url, for example "/about/pants/", only the
root url portion of the argument is used. Thus, "/about/" and
"/about/pants/" will return the same result, assuming both those flatpages
exist.
If the first argument is not in quotes, it is assumed to be in the current
context::
{% flatpage_children flatpage.url as children %}
This adds a queryset of all urls deeper than the root url of the current
flatpage.
"""
bits = token.contents.split()
if len(bits) != 4 or bits[2] != "as":
raise template.TemplateSyntaxError("%r expected format is 'flatpage_children URL as name'" % bits[0])
return FlatpageChildren(bits[1], bits[3])
class FlatpageChildren(template.Node):
# this regex is the definition of a top-level flatpage
# override in a subclass if you have a different idea!
# note the difference from root_regex in FlatpageRoot:
# the string is allowed to continue past the first slash...
root_regex = r'^(/[^/]*?/)'
def __init__(self, url, context_name):
self.url = url
self.context_name = context_name
def render(self, context):
if self.url[0] in ('"',"'"):
if self.url[0] == self.url[-1] and len(self.url) > 3:
urlcontent = self.url
else:
return ""
else:
urlcontent = template.Variable(self.url).resolve(context)
m = re.search(self.root_regex, urlcontent)
if not m:
return ""
root = m.group(1)
context[self.context_name] = FlatPage.objects.filter(
url__gt=root,
url__startswith=root
)
return ""
register.tag('flatpage_children', do_flatpage_children)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
I've since gone on to make this a context manager instead. I'll post that later.
#
Please login first before commenting.