I like to moan on about how django templates can be too limiting sometimes. However, it's super easy to implement neat little filters once you quit b!tching for a couple of minutes and read the docs
I was thinking about pain in the template or pain in the models. Instead, I wrote this satisfying little template filter:
from django import template
register = template.Library()
def all_have(value, arg):
"""Do all the members of the iterable have a certain value?
{{ mylist|all_have:"certain_attr_bools_to_True" }}
returns True or False.
"""
return all([getattr(a, arg) for a in value])
register.filter('all_have', all_have)
"Do all the members of the iterable have a certain value?" should read Does the "arg" property of all members of the iterable bool to True? or sth like that, nub.
Also, this filter assumes that all of the members of the iterable already hasattr. The title of the post is misleading, getattr() is what I needed for my use case (all members of the iterable are guaranteed to have the property, I just need to know if it bools to True for all members).
The title of the post would more accurately match:
def all_have(value, arg):
"""Do all members of value hasattr arg?
{{ mylist|all_have:"attr_to_test_that_members_have" }}
returns True or False.
"""
return all([hasattr(a, arg) for a in value])
Don't forget about cousin, any_have:
def any_have(value, arg):
"""value is an iterable whose members have an attr, arg, check if any bool to True
{% if form_list|any_have:"errors" %} some of the forms in the list have errors.
"""
for i,f in enumerate(value):
if not hasattr(f, arg):
value.pop(i)
return any([getattr(a, arg) for a in value])
register.filter('any_have', any_have)
Here, we check hasattr() so that we can have NoneType objects in the list. We can update all_have to make this check as well:
def all_have(value, arg):
"""Does the "arg" property of all members of the iterable bool to True?
{{ mylist|all_have:"certain_attr_bools_to_True" }}
returns True or False.
"""
if not all([hasattr(a, arg) for a in value]):
return False
return all([getattr(a, arg) for a in value])
register.filter('all_have', all_have)