2

I have a model that allows my client to create menus for his restaurant. Everything works great except I would like to set the explicit ordering by the string value of a model. For instance; he is creating sections like Salads, Pastas, Pizzas etc.. but they are displayed through the template in the order they are added to the system. How can I add a sort to my query that I can set the order manually? Below is my current snippet.

I am using Django 1.10.5, Wagtail 1.9, Python 3.5x

Snippet

@register.inclusion_tag('tags/_lunch-menu-list.html', takes_context=True)
def lunch_products(context):
    sections = Section.objects.all().prefetch_related('product').filter(product__lunch_menu=True).distinct()
    return {
        'sections': sections,
        'request': context['request'],
    }
Charles Smith
  • 3,201
  • 4
  • 36
  • 80

2 Answers2

4

I don't think Django queryset has a mechanism to order by a list of field value.

Option 1:
Order in Python. Keep it mind it will return a list, not a queryset anymore (inspired from this answer) and that you end up using magic strings (what if the user uses Entrées instead of Starters?):

sections = Section.objects.all()
order = ['Starters', 'Salads', 'Desserts']
order = {key: i for i, key in enumerate(order)}
ordered_sections = sorted(sections, key=lambda section: order.get(section.name, 0))

Option 2:
Add a menu_order integer field on the Section object and order_by on this field. This is not the best UX though since you'll need to edit each section to set the order and will have to remember what number you've used for each of them.

Option 3:
Create a Menu object with orderable sections (see how they order carousel item in the demo app), but this looks a bit overkill for you since it seems you will always ever have 1 order.

Community
  • 1
  • 1
Loïc Teixeira
  • 1,404
  • 9
  • 19
  • Since my clients menu sections are static and not likely to change, I added an order field, did an ordering in the model meta, then opened the database and manually added the ordering there instead of making it visible in modeladmin. This allowed me to order the sections in a slightly hackish way without the client having to deal with it. – Charles Smith Mar 10 '17 at 14:19
0

You should use order_by() to sort query sets. For example, if you have a name attribute in your models, you'd just add .order_by("name") to the end of your query.

NS0
  • 6,016
  • 1
  • 15
  • 14
  • 5
    Thats just going to order_by() alphabetically; I need something like order_by(name=['Starters', 'Salads', 'Desserts'..... etc... ]) – Charles Smith Mar 08 '17 at 22:38