arlyon
arlyon

Reputation: 135

Using a variable to extract data from a database in Django

I'm making a small site in Django with 'items' and 'characters' in a sqlite database based on the app in the 'first steps' on the documentation page. The tables (currently) follow a similar format so I want to try and make a flexible template. In my views.py, the two views are set up like so:

def characters(request):
    sortby = 'lastname'
    data_list = Characters.objects.order_by(sortby)
    template = loader.get_template('database.html')
    context = {
        'data_list': data_list,
        'directory': 'wiki/characters',
        'sortby': sortby,
    }
    return HttpResponse(template.render(context, request))

def items(request):
    sortby = 'name'
    data_list = Clothes.objects.order_by(sortby)
    template = loader.get_template('database.html')
    context = {
        'data_list': data_list,
        'directory': 'wiki/items',
        'sortby': sortby,
    }
    return HttpResponse(template.render(context, request))

The only difference being the sortby variable and the directory variable. The problem is, I would like to sort the characters by their lastname, and the items by their name. The issue arises in my template, specifically data.sortby:

{% if data_list %}
    <ul>
        {% for data in data_list %}
            <li><a href="{{data.id}}/">{{data.sortby}}</a></li>
        {% endfor %}
    </ul>
{% else %}
    <p>No characters,</p>
{% endif %}

If I manually reference the field I want without brackets it works fine, so I'm sure it's the string causing the issue. How do I sort by the field I specify in views.py?

Thanks in advance from a noob.

Upvotes: 0

Views: 671

Answers (1)

user2390182
user2390182

Reputation: 73490

You can get an idea in this (a little outdated) answer, but the bottom line is that there is no built-in way to access attributes by name getattr()-style in django templates. So you would need to write a custom filter, as described in the django docs:

# app/templatetags/attr_tags.py

from django import template

register = template.Library()

@register.filter
def get_attribute(value, arg):
    return getattr(value, arg)

Now you can do in your template:

{% load attr_tags %}
# ...
{{ data|get_attribute:sortby }}  

# {{ data.sortby }} can't work because that tries to access 
# an attribute named 'sortby', not an attribute with the name
# stored in the context variable of the name 'sortby'

Upvotes: 1

Related Questions