Reputation: 7014
I have similar models:
class BaseInfo(models.Model):
is_active = models.BooleanField(default=True)
# other fields..
class Meta:
abstract = True
class Customer(BaseInfo):
name = models.CharField(max_length=50)
## other fields..
In template I want to display a table of this model, but I want to highlight the inactive ones. So I have this fragment in template:
{% for c in customers %}
<tr {%if not c.is_active %}class="not-active" {%endif%}>
<td>..</td>
</tr>
{% endfor %}
Now next to this I want to display the NUMBER of active ones. I could do this in view:
all = Customer.objects.filter(name="foo")
excludeInactive = all.filter(is_active=False)
and then pass both in the context. But I would prefer something like this in template:
{{customers.exclude_deleted.count}}
or maybe:
{{customers.exclude_deleted|length}}
?
I have more models which inherit this abstract class. So I think a manager on the base class could work? I just couldn't understand how to write one..
Also, what about performance? If I do two calls to .filter()
will that result in two db queries, even though the second query is a subset of an already evaluated queryset?
Upvotes: 0
Views: 835
Reputation: 670
You can do it in many ways. Some of them:
Make all calculation in the view and pass to the context prepared data:
customers = Customer.objects.filter(name="foo")
active_customers_count = customers.filter(is_active=True)
Custom template tag (docs):
tag
from django import template
register = template.Library()
@register.assignment_tag
def filter_qs(qs, **kwargs):
return qs.filter(**kwargs)
template
{% filter_qs customers is_active=True as active_customers %}
{{ active_customers|length }}
Custom Manager with custom QuerySet (docs):
models
class IsActiveQuerySet(models.QuerySet):
def active(self):
return self.filter(is_active=True)
class IsActiveManager(models.Manager):
def get_queryset(self):
return IsActiveQuerySet(self.model, using=self._db)
class Customer(BaseInfo):
objects = IsActiveManager()
name = models.CharField(max_length=50)
template
{{ customers.active|length }}
I would strongly recommend you to go with the first option, it will be the most "Pythonic" way. Anyway django will make 2 separate sql queries for any of solution listed above.
Upvotes: 1