7

Let these models:

class Category(models.Model):
    name = models.CharField(max_length=20)

class Word(models.Model):
    name = models.CharField(max_length=200)
    votes = models.IntegerField(default=1)
    categories = models.ManyToManyField(Category, null=True, blank=True)

this view:

def main_page(request):
    words = Word.objects.all()
    categories = Category.objects.all()
    return render(request, "main_page.html", {'words': words})

and this template:

{% for category in categories %}
    {% for word in category.word_set.all %}
    <p>{{ word }}</p>
    {% endfor %}
{% endfor %}

I'd like to sort words in template by number of votes and by pub date, separately. How can I do this?

msampaio
  • 3,394
  • 6
  • 33
  • 53
  • In your template, where do you get 'category' from? Cant see it in your view. – Jingo Sep 02 '12 at 20:36
  • @Jingo, My code was incomplete. I updated view and template with `category`. – msampaio Sep 02 '12 at 20:58
  • why don't you use jquery sortable. Such things can be and should be handled by js instead of doing in template. It will unnecessarily slow down your response time. – Sushant Gupta Sep 02 '12 at 21:25

3 Answers3

17

You can make custom template tag or filter, which gets words set and sorting type as parameters.

For example (haven't tested):

custom_tags.py:

from django import template
register = template.Library()

@register.filter
def sort_by(queryset, order):
    return queryset.order_by(order)

template.html

{% load custom_tags %}
...
{% for word in category.word_set.all|sort_by:'-votes' %}
    <p>{{ word }}</p>
{% endfor %}
...
Serhii Holinei
  • 5,758
  • 2
  • 32
  • 46
5

You can do it in the views

words = Word.objects.all().order_by('votes', 'pub_date')
Rakesh
  • 81,458
  • 17
  • 76
  • 113
  • I updated my question. If I use `{% for word in words %}`, your solution works. But not using `{% for word in category.word_set.all %}`. – msampaio Sep 02 '12 at 19:36
  • 4
    That kind of things is of course subjective, but IMHO it is better to manage such things in the views as Rakesh suggested. Django deliberately is very restrictive about the amount of logic you can put in a template, and this is exactly to encourage keeping proper MVT separation. If you really want to do that in the template, custom template tags and filters are the way to go (see goliney's answer). – niconoe Sep 02 '12 at 21:16
0

You can also:

  1. add special method in Category model,
  2. add simple shortcut method in custom Related Manager for Word,
  3. make this ordering default one in Word (I don't like this one to be honest)
jasisz
  • 1,288
  • 8
  • 9