split - django count specific rows in queryset -
class order(models.model): name = models.charfield(max_length=100) # other fields.. user = models.foreginkey(user) old = models.booleanfield(default=false)
i want display orders of specific user, want split them "old" , ones not.
so, in views.py
:
orders = order.objects.filter(user=user)
in template:
first table:
<table> {% order in orders %} {% if not order.old %} <tr> <td>... </td> </tr> {% endif %} {% endfor %} </table>
and table:
{% order in orders %} {% if order.old %} <tr> <td>...</td> <tr> {% endif %} {% endfor %}
this way have drawbacks, first, want count how many of orders "old", display number in template. can't, unless query. possible annotate(number_of_old=count('old'))
? or have query?
so best?
1. 2 queries, 1 old=false, old=true, , pass 2 querysets template. , use |len
filter on querysets
2. 1 query , split them somehow in python? less convenient have similar structures want split that.
and should call db .count() @ all?
edit:
if write model this:
class order(models.model): name = models.charfield(max_length=100) # other fields.. user = models.foreginkey(user) old = models.booleanfield(default=false) objects = custommanager() # custom manager class customqueryset(models.queryset): def no_old(self): return self.filter(old=false) class custommanager(models.manager): def get_queryset(self): return customqueryset(model=self.model, using=self._db)
is template code produce 1 or 2 queries ?
{% if orders.no_old %} {% order orders.no_old %} ... {% endfor %} {% endif %}
you can't annotations, , there no need make .count()
since have data in memory. between:
orders = order.objects.filter(user=user) old_orders = [o o in orders if o.old] new_orders = [o o in orders if not o.old] #or old_orders = order.objects.filter(user=user, old=true) new_orders = order.objects.filter(user=user, old=false)
in specific scenario, don't think there performance difference. choose 2nd approach 2 queries.
a read tips problem: django database access optimization
update
about custom manager introduce. don't think doing correctly think want this:
class customqueryset(models.queryset): def no_old(self): return self.filter(old=false) class order(models.model): name = models.charfield(max_length=100) # other fields.. user = models.foreginkey(user) old = models.booleanfield(default=false) #if have manager #objects = custommanager.from_queryset(customqueryset)() #if dont: objects = customqueryset.as_manager()
so having:
orders = order.objects.filter(user=user)
if {% if orders.no_old %}
query, because this new queryset
instance has no cache..
about {% regroup %} tag
as mention, in order use it, need .order_by('old')
, , if have order, can still use it, apply order after old
, e.g. .order_by('old', 'another_field')
. way use 1 query , save 1 iteration on list (because django split list iterating once), less readability in template.
Comments
Post a Comment