Code

Opened 6 months ago

Closed 5 months ago

Last modified 5 months ago

#21370 closed New feature (wontfix)

Add new generic "getter" filter

Reported by: zuck Owned by: nobody
Component: Template system Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Very often happens we have some arbitrary objects in the template context and we want to retrieve some of their data based on some other variables.

So, I propose to add a generic getter filter with a very basic API:

{{ obj|get:attr_name }}

i.e. Access to model data based on a dynamic list of fields

<table>
    {% for obj in object_list %}
    <tr>
        {% for f in field_list %}
        <td>{{ obj|get:f }}</td>
        {% endfor %}
    </tr>
    {% endfor %}
</table>

i.e. Access to dict values based on a dynamic list of keys

{% for key in key_list %}
{{ dict|get:key }}
{% endfor %}

i.e. Access to a variable index of a list

{{ list|get:var_index }}

The last use case is the only which is (maybe, I'm not sure) currently possible, using nested "slice" and "first/last" filters, but it's a lot more verbose and error-prone. Otherwise you have to use forloops with index checking, which is computation-heavy and really verbose on the code side.

In the built-in library, for example, there's already a get_digit filter, which looks very restricted to just one use-case and could be covered by this, more generic (and useful), filter.

The following is a basic untested implementation:

@register.filter
def get(obj, attr_name):
    """Returns the attr value for the given object.

    Example usage: {{ object|get:"pk" }}
    """
    if isinstance(obj, dict):
        return obj.get(attr_name, "")

    elif isinstance(obj, (list, tuple))
    and (isinstance(attr_name, int)
         or attr_name.isdigit()):
        return obj[attr_name]

    elif hasattr(obj, attr_name):
        value = getattr(obj, attr_name)
        if callable(value):
            return value()
        return value

    return ""

Attachments (0)

Change History (3)

comment:1 Changed 5 months ago by chrismedrela

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

There is also a thread on stackoverflow: http://stackoverflow.com/questions/844746/performing-a-getattr-style-lookup-in-a-django-template.

I'd suggest to create a new thread on django-developers mailing list to get more attention.

comment:2 Changed 5 months ago by russellm

  • Resolution set to wontfix
  • Status changed from new to closed

Procedurally, I'm marking this wontfix. However, this shouldn't be interpreted as "don't pursue this idea" -- I'm just recognising that the Django core team has historically rejected this idea, so it clearly isn't "accepted". Once upon a time, it would have been triaged to "design decision needed", but we removed that state because it because a limbo state from which nothing ever returned.

So - This needs to be discussed on Django Developers (and there is a thread now); if that thread determines that this idea has been accepted, *then* we can reopen the ticket.

comment:3 Changed 5 months ago by thepapermen

Just in case: here is a similar rejected ticket which I filled back in 2011. Back in the day there was no sufficient interest in the feature.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.