diff --git a/django_sorting/middleware.py b/django_sorting/middleware.py
index cd8a076..9a67d47 100644
--- a/django_sorting/middleware.py
+++ b/django_sorting/middleware.py
@@ -1,17 +1,39 @@
+try:
+ from django.utils.deprecation import MiddlewareMixin
+except ImportError:
+ MiddlewareMixin = object
+
+
def get_field(self):
try:
- field = self.REQUEST['sort']
- except (KeyError, ValueError, TypeError):
+ get = self.GET
+ if 'sort' in get:
+ field = get['sort']
+ else:
+ post = self.POST
+ if 'sort' in post:
+ field = post['sort']
+ else:
+ field = ''
+ except AttributeError:
field = ''
return (self.direction == 'desc' and '-' or '') + field
def get_direction(self):
try:
- return self.REQUEST['dir']
- except (KeyError, ValueError, TypeError):
+ get = self.GET
+ if 'dir' in get:
+ return get['dir']
+ else:
+ post = self.POST
+ if 'dir' in post:
+ return post['sort']
+ else:
+ return 'desc'
+ except AttributeError:
return 'desc'
-class SortingMiddleware(object):
+class SortingMiddleware(MiddlewareMixin):
"""
Inserts a variable representing the field (with direction of sorting)
onto the request object if it exists in either **GET** or **POST**
@@ -19,4 +41,4 @@ class SortingMiddleware(object):
"""
def process_request(self, request):
request.__class__.field = property(get_field)
- request.__class__.direction = property(get_direction)
\ No newline at end of file
+ request.__class__.direction = property(get_direction)
diff --git a/django_sorting/templatetags/sorting_tags.py b/django_sorting/templatetags/sorting_tags.py
index 7cdeb42..fae37db 100644
--- a/django_sorting/templatetags/sorting_tags.py
+++ b/django_sorting/templatetags/sorting_tags.py
@@ -6,34 +6,33 @@
DEFAULT_SORT_UP = getattr(settings, 'DEFAULT_SORT_UP' , '↑')
DEFAULT_SORT_DOWN = getattr(settings, 'DEFAULT_SORT_DOWN' , '↓')
-INVALID_FIELD_RAISES_404 = getattr(settings,
+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'},
+ '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 TemplateSyntaxError, "anchor tag takes at least 1 argument"
+ Parses a tag that's supposed to be in this format: {% anchor field title %}
+ """
try:
- title = bits[2]
+
+ tag_name, field, title = token.split_contents()
except IndexError:
- title = bits[1].capitalize()
- return SortAnchorNode(bits[1].strip(), title.strip())
-
+ tag_name, field = token.split_contents()
+ title = field.capitalize()
+ return SortAnchorNode(field, title)
+
class SortAnchorNode(template.Node):
"""
- Renders an HTML tag with a link which href attribute
+ Renders an 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
+ and adds an up or down arrow if the field is the one
currently being sorted on.
Eg.
@@ -42,10 +41,21 @@ class SortAnchorNode(template.Node):
"""
def __init__(self, field, title):
- self.field = field
- self.title = title
+ self.field = template.Variable(field)
+ self.title = template.Variable(title)
def render(self, context):
+ try:
+ self.rendered_field = self.field.resolve(context)
+ except template.VariableDoesNotExist:
+ self.rendered_field = str(self.field)
+ try:
+ self.rendered_title = self.title.resolve(context)
+ except template.VariableDoesNotExist:
+ self.rendered_title = str(self.title)
+ except AttributeError:
+ self.rendered_title = str(self.title)
+
request = context['request']
getvars = request.GET.copy()
if 'sort' in getvars:
@@ -58,7 +68,7 @@ def render(self, context):
del getvars['dir']
else:
sortdir = ''
- if sortby == self.field:
+ if sortby == self.rendered_field:
getvars['dir'] = sort_directions[sortdir]['inverse']
icon = sort_directions[sortdir]['icon']
else:
@@ -67,20 +77,34 @@ def render(self, context):
urlappend = "&%s" % getvars.urlencode()
else:
urlappend = ''
+
if icon:
- title = "%s %s" % (self.title, icon)
+ title = "%s %s" % (self.rendered_title, icon)
else:
- title = self.title
+ title = self.rendered_title
+
+ url = '%s?sort=%s%s' % (request.path, self.rendered_field, urlappend)
+ return '%s' % (url, self.rendered_title, title)
- url = '%s?sort=%s%s' % (request.path, self.field, urlappend)
- return '%s' % (url, self.title, title)
def autosort(parser, token):
- bits = [b.strip('"\'') for b in token.split_contents()]
- if len(bits) != 2:
- raise TemplateSyntaxError, "autosort tag takes exactly one argument"
- return SortedDataNode(bits[1])
+ 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):
"""
@@ -91,7 +115,10 @@ def __init__(self, queryset_var, context_var=None):
self.context_var = context_var
def render(self, context):
- key = self.queryset_var.var
+ 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:
@@ -109,4 +136,3 @@ def render(self, context):
anchor = register.tag(anchor)
autosort = register.tag(autosort)
-