Instantly share code, notes, and snippets.
Created
June 15, 2010 20:33
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save camilonova/439688 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django import template | |
from django.http import Http404 | |
from django.conf import settings | |
register = template.Library() | |
DEFAULT_SORT_UP = getattr(settings, 'DEFAULT_SORT_UP' , '↑') | |
DEFAULT_SORT_DOWN = getattr(settings, 'DEFAULT_SORT_DOWN' , '↓') | |
INVALID_FIELD_RAISES_404 = getattr(settings, | |
'SORTING_INVALID_FIELD_RAISES_404' , False) | |
sort_directions = { | |
'asc': {'icon':DEFAULT_SORT_UP, 'inverse': 'desc'}, | |
'desc': {'icon':DEFAULT_SORT_DOWN, 'inverse': 'asc'}, | |
'': {'icon':DEFAULT_SORT_DOWN, 'inverse': 'asc'}, | |
} | |
def anchor(parser, token): | |
""" | |
Parses a tag that's supposed to be in this format: {% anchor field title %} | |
""" | |
bits = [b.strip('"\'') for b in token.split_contents()] | |
if len(bits) < 2: | |
raise template.TemplateSyntaxError, "anchor tag takes at least 1 argument" | |
try: | |
title = bits[2] | |
except IndexError: | |
title = bits[1].capitalize() | |
return SortAnchorNode(bits[1].strip(), title.strip()) | |
class SortAnchorNode(template.Node): | |
""" | |
Renders an <a> HTML tag with a link which href attribute | |
includes the field on which we sort and the direction. | |
and adds an up or down arrow if the field is the one | |
currently being sorted on. | |
Eg. | |
{% anchor name Name %} generates | |
<a href="/the/current/path/?sort=name" title="Name">Name</a> | |
""" | |
def __init__(self, field, title): | |
self.field = field | |
self.title = title | |
def render(self, context): | |
request = context['request'] | |
getvars = request.GET.copy() | |
if 'sort' in getvars: | |
sortby = getvars['sort'] | |
del getvars['sort'] | |
else: | |
sortby = '' | |
if 'dir' in getvars: | |
sortdir = getvars['dir'] | |
del getvars['dir'] | |
else: | |
sortdir = '' | |
if sortby == self.field: | |
getvars['dir'] = sort_directions[sortdir]['inverse'] | |
icon = sort_directions[sortdir]['icon'] | |
else: | |
icon = '' | |
if len(getvars.keys()) > 0: | |
urlappend = "&%s" % getvars.urlencode() | |
else: | |
urlappend = '' | |
if icon: | |
title = "%s %s" % (self.title, icon) | |
else: | |
title = self.title | |
url = '%s?sort=%s%s' % (request.path, self.field, urlappend) | |
return '<a href="%s" title="%s">%s</a>' % (url, self.title, title) | |
def autosort(parser, token): | |
bits = token.split_contents() | |
if len(bits) not in (2, 4): | |
raise template.TemplateSyntaxError, "autosort tag takes exactly one argument" | |
try: | |
if bits[2] != 'as': | |
raise template.TemplateSyntaxError( | |
"Context variable assignment must take the form of {%% %s" | |
" queryset as context_var_name %%}" % bits[0] | |
) | |
except IndexError: | |
pass | |
try: | |
return SortedDataNode(bits[1], bits[-1]) | |
except IndexError: | |
return SortedDataNode(bits[1]) | |
class SortedDataNode(template.Node): | |
""" | |
Automatically sort a queryset with {% autosort queryset %} | |
""" | |
def __init__(self, queryset_var, context_var=None): | |
self.queryset_var = template.Variable(queryset_var) | |
self.context_var = context_var | |
def render(self, context): | |
if self.context_var is None: | |
key = self.queryset_var.var | |
else: | |
key = self.context_var | |
value = self.queryset_var.resolve(context) | |
order_by = context['request'].field | |
if len(order_by) > 1: | |
try: | |
context[key] = value.order_by(order_by) | |
# Test if the queryset can be executed | |
context[key].all().exist() | |
except: | |
if INVALID_FIELD_RAISES_404: | |
raise Http404('Invalid field sorting. If DEBUG were set to ' + | |
'False, an HTTP 404 page would have been shown instead.') | |
context[key] = value | |
else: | |
context[key] = value | |
return '' | |
anchor = register.tag(anchor) | |
autosort = register.tag(autosort) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment