Skip to content

Commit

Permalink
Initial import
Browse files Browse the repository at this point in the history
  • Loading branch information
directeur committed Mar 21, 2009
0 parents commit f7ca4e4
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
.DS_Store
69 changes: 69 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
How to use django-sorting
----------------------------

``django-sorting`` allows for easy sorting, and tables headers (<th>) generation
without modifying your views.

There are really 5 steps to setting it up with your projects.

1. List this application in the ``INSTALLED_APPS`` portion of your settings
file. Your settings file might look something like::

INSTALLED_APPS = (
# ...
'sorting',
)

2. Install the sorting middleware. Your settings file might look something
like::

MIDDLEWARE_CLASSES = (
# ...
'sorting.middleware.SortingMiddleware',
)

3. If it's not already added in your setup, add the request context processor.
Note that context processors are set by default implicitly, so to set them
explicitly, you need to copy and paste this code into your under
the value TEMPLATE_CONTEXT_PROCESSORS::

("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request")

4. Add this line at the top of your template to load the sorting tags:

{% load sorting_tags %}


5. Decide on a variable that you would like to sort, and use the
autosort tag on that variable before iterating over it.

{% autosort object_list %}


6. Now, you want to display different headers with links to sort
your objects_list:

<tr>
{% th first_name Name %}
{% th creation_date Creation %}
...
</tr>

The first argument is a field of the objects list, and the second
one(optional) is a title that would be displayed. The previous
snippet will be rendered like this:

<tr>
<th><a href="?sort=first_name" title="Name">Name</a></th>
<th><a href="?sort=creation_date" title="Name">Creation</a></th>
...
</tr>


That's it!


1 change: 1 addition & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

20 changes: 20 additions & 0 deletions middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class SortingMiddleware(object):
"""
Inserts a variable representing the field (with direction of sorting)
onto the request object if it exists in either **GET** or **POST**
portions of the request.
"""
def process_request(self, request):
try:
request.field = str(request.REQUEST['sort'])
except (KeyError, ValueError, TypeError):
request.field = ''

try:
direction = str(request.REQUEST['dir'])
except (KeyError, ValueError, TypeError):
direction = 'desc'

if direction == 'asc' and request.field:
request.field = '-'+request.field

1 change: 1 addition & 0 deletions models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions templatetags/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

104 changes: 104 additions & 0 deletions templatetags/sorting_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
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' , '&uarr;')
DEFAULT_SORT_DOWN = getattr(settings, 'DEFAULT_SORT_DOWN' , '&darr;')

sort_directions = {
'asc': {'icon':DEFAULT_SORT_UP, 'inverse':'desc'},
'desc': {'icon':DEFAULT_SORT_DOWN, 'inverse':'asc'},
'': {'icon':DEFAULT_SORT_DOWN, 'inverse':'asc'},
}

def th(parser, token):
"""
Parses a tag that's supposed to be in this format:
{% sth field title%}
"""
bits = token.contents.split()
if len(bits) < 2:
raise TemplateSyntaxError, "th tag takes at least 1 argument"
try:
title = bits[2]
except IndexError:
title = bits[1].capitalize()
return SortHeaderNode(bits[1].strip(), title.strip())


class SortHeaderNode(template.Node):
"""
Renedrs a <th> 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.
{% th name Name %} generates
<th><a href="?sort=name" title="Name">Name</a></th>
"""
def __init__(self, field, title):
self.field = field
self.title = title

def render(self, context):
getvars = context['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 = ''
self.title = "%s %s" % (self.title, icon)

url = '?sort=%s%s' % (self.field, urlappend)
return '<th><a href="%s" title="%s">%s</a></th>' % (url, self.title,
self.title)


def autosort(parser, token):
bits = token.contents.split()
if len(bits) != 2:
raise TemplateSyntaxError, "autosort tag takes exactly one argument"
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):
key = self.queryset_var.var
value = self.queryset_var.resolve(context)
order_by = context['request'].field
if len(order_by) > 1:
context[key] = value.order_by(order_by)
else:
context[key] = value

return ''


th = register.tag(th)
autosort = register.tag(autosort)

0 comments on commit f7ca4e4

Please sign in to comment.