10

Django1.4: How to use order_by in template?

models.py

from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Note(models.Model):
    contents = models.TextField()
    writer = models.ForeignKey(User, to_field='username')
    date = models.DateTimeField(auto_now_add=True)

    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')


class Customer(models.Model):
    name = models.CharField(max_length=50,)
    notes = generic.GenericRelation(Note, null=True)

Above is my models.py.

I want to use 'order_by'(https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by)

And...

views.py

from django.views.generic import DetailView
from crm.models import *

class customerDetailView(DetailView):
    context_object_name = 'customerDetail'
    template_name = "customerDetail.html"
    allow_empty = True
    model = Customer
    slug_field = 'name'

My views.py use DetailView(https://docs.djangoproject.com/en/1.4/ref/class-based-views/#detailview).

And

customerDetail.html

<table class="table table-bordered" style="width: 100%;">
    <tr>
        <td>Note</td>
    </tr>
    {% for i in customerDetail.notes.all.order_by %}<!-- It's not working -->
        <tr>
            <th>({{ i.date }}) {{ i.contents }}[{{ i.writer }}]</th>
        </tr>
    {% endfor %}
</table>

I want to use order_by in template...

What should I do?

chobo
  • 4,830
  • 5
  • 23
  • 36
  • 1
    have you tried `queryset = Customer.objects.order_by()` in `customerDetailView`? – rxdazn Feb 13 '13 at 14:47
  • Yeah, I tried `queryset = Customer.objects.order_by('note__date')` and `queryset = Customer.objects.order_by('note__date')`. But failed... – chobo Feb 13 '13 at 15:02

2 Answers2

13

Check out the dictsort filter, it's pretty much what you're looking for I think.

msc
  • 3,780
  • 1
  • 22
  • 27
8

The order_by needs at least one argument, and Django does not allow you to pass arguments to a function or method inside a template.

Some alternatives are:

  • Use Jinja2 template engine instead of Django's one (Jinja2 will let you pass arguments to methods and is said to perform better)
  • order the dataset in the view
  • use the "Meta:ordering" attribute to define a default ordering criteria for your models
  • write a custom filter so you can queryset|order_by:'somefield' (see this snippet)
  • as suggested by Michal, you can write a custom Manager with predefined methods for the orderings you need
Community
  • 1
  • 1
Paulo Scardine
  • 73,447
  • 11
  • 124
  • 153
  • ...or use custom Manager for the class which will provide you predefined ways of ordering – Michal Čihař Feb 13 '13 at 14:53
  • I don't know understand fourth tip "write a custom filter so you can `queryset|order_by:'somefield'`". Could you give me ... some example code? – chobo Feb 13 '13 at 15:04
  • 4
    Anyway I solved it. `class Meta: ordering = ['date']` (in models.py) – chobo Feb 13 '13 at 15:06
  • cathy answer has such sample code, seems like she is using the same [snippet](http://djangosnippets.org/snippets/741/) (but she forgot to attribute the solution to the [original author](http://djangosnippets.org/users/marinho/)). Also, you need to place this file in [some specific location](https://docs.djangoproject.com/en/dev/howto/custom-template-tags/) in order to be able to load it inside the template. – Paulo Scardine Feb 13 '13 at 15:09
  • @chobo regarding the fourth tip, you may use the link he has provided or refer to this link. https://www.pluralsight.com/guides/create-custom-template-tags-and-filters-in-django . The fourth tip worked for me – Muhammad Zubair Mar 12 '22 at 09:39