Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort on custom properties & default sort order #18

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
Changes to this fork
----------------------------

{% autosort %} can sort on custom fields (properties) in addition to regular fields

{% anchor %} can specify a default sort order as a third parameter.

<th>{% anchor first_name Name asc %}</th>
<th>{% anchor first_name Name desc %}</th>

How to use django-sorting
----------------------------

Expand Down
52 changes: 41 additions & 11 deletions django_sorting/templatetags/sorting_tags.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django import template
from django.http import Http404
from django.conf import settings
from django.core.exceptions import FieldError

register = template.Library()

Expand All @@ -17,17 +18,24 @@

def anchor(parser, token):
"""
Parses a tag that's supposed to be in this format: {% anchor field title %}
Parses a tag that's supposed to be in this format: {% anchor field title sortdir %}
"""
bits = [b.strip('"\'') for b in token.split_contents()]

if len(bits) < 2:
raise TemplateSyntaxError, "anchor tag takes at least 1 argument"
try:

field = bits[1].strip()
title = field.capitalize()
sortdir = ''

if len(bits) >= 3:
title = bits[2]
except IndexError:
title = bits[1].capitalize()
return SortAnchorNode(bits[1].strip(), title.strip())


if len(bits) == 4:
sortdir = bits[3]

return SortAnchorNode(field, title, sortdir)

class SortAnchorNode(template.Node):
"""
Expand All @@ -37,13 +45,14 @@ class SortAnchorNode(template.Node):
currently being sorted on.

Eg.
{% anchor name Name %} generates
<a href="/the/current/path/?sort=name" title="Name">Name</a>
{% anchor name Name asc %} generates
<a href="/the/current/path/?sort=name&dir=asc" title="Name">Name</a>

"""
def __init__(self, field, title):
def __init__(self, field, title, sortdir):
self.field = field
self.title = title
self.sortdir = sortdir

def render(self, context):
request = context['request']
Expand All @@ -53,20 +62,28 @@ def render(self, context):
del getvars['sort']
else:
sortby = ''

if 'dir' in getvars:
sortdir = getvars['dir']
del getvars['dir']
else:
sortdir = ''
sortdir = self.sortdir

if sortby == self.field:
getvars['dir'] = sort_directions[sortdir]['inverse']
icon = sort_directions[sortdir]['icon']
else:
# If we're not on the current field, use the default sortdir
# rather than the order
if self.sortdir:
getvars['dir'] = self.sortdir
icon = ''

if len(getvars.keys()) > 0:
urlappend = "&%s" % getvars.urlencode()
else:
urlappend = ''

if icon:
title = "%s %s" % (self.title, icon)
else:
Expand Down Expand Up @@ -96,7 +113,20 @@ def render(self, context):
order_by = context['request'].field
if len(order_by) > 1:
try:
context[key] = value.order_by(order_by)
try:
val = list(value.order_by(order_by))
context[key] = val
except:
## Support for sorting on properties

# Split off reverse sort
reverse = False
if order_by.startswith("-"):
order_by = order_by[1:]
reverse = True

context[key] = sorted(value, key=lambda v: getattr(v, order_by), reverse=reverse)

except template.TemplateSyntaxError:
if INVALID_FIELD_RAISES_404:
raise Http404('Invalid field sorting. If DEBUG were set to ' +
Expand Down