2

Here is my code:

 phones = Customer.objects.filter(active=True).values('name')\
        .annotate(count = Count('phone',filter=Q(phone__model__icontains=model_list[0]))
        .annotate(count1 = Count('phone',filter=Q(phone__model__icontains=model_list[1]))
        .annotate(count2 = Count('phone',filter=Q(phone__model__icontains=model_list[2]))
        .annotate(count3 = Count('phone',filter=Q(phone__model__icontains=model_list[3]))
        .annotate(count4 = Count('phone',filter=Q(phone__model__icontains=model_list[4]))
    ........

html

{% if phones %}
    {% for phone in phones %}
    <tr>
        <td>{{ phone.name }}</td>
        <td>{{ phone.count  }}</td>
        <td>{{ phone.count1  }}</td>
        <td>{{ phone.count2  }}</td>
        <td>{{ phone.count3  }}</td>
        <td>{{ phone.count4  }}</td>
    </tr>
    {% endfor %}
{% enfif %}

My model_list still has many models. What should I do to simplify these using for loop?

If my model_list has 100 models, this will be very complicated.

I've tried this:

for i in range(len(model_list)):
    phone= Customer.objects.filter(active=True).values('name')\
        .annotate(count = Count('phone',filter=Q(phone__model__icontains=model_list[i]))

html

{% if phones %}
{% for phone in phones %}
<tr>
    <td>{{ phone.name }}</td>
    <td>{{ phone.count  }}</td>
</tr>
{% endfor %}
{% endif %}

But the result is not what I want, because I only get one of the data. For example :model_list[0]

Daniel Holmes
  • 1,952
  • 2
  • 17
  • 28

3 Answers3

1

Do like this to query for counts:

phones = Customer.objects.filter(active=True).values('name')

for idx, model in enumerate(model_list):
    counts = {'count%s' % idx : Count('phone',filter=Q(phone__model__icontains=model)}
    phones = phones.annotate(**counts)

Then you would need to pass a range of models to the template (say in models_idx_range as context parameter models_idx_range=range(models_count)) and iterate over counts:

{% if phones %}
{% for phone in phones %}
<tr>
    <td>{{ phone.name }}</td>
    {% for idx in models_idx_range %}
        <td>{{ getattr(phone, 'count%s' % idx) }}</td>
</tr>
{% endfor %}
{% endif %}
0

I'm not a django expert but i think this is your error:

phone = Customer.objects.filter(active=True).values('name')

for i in range(len(model_list)):
     phone= phone.annotate(count = Count('phone',filter=Q(phone__model__icontains=model_list[i]))

You always override your phone with the last value from the for-loop

MisterMonk
  • 327
  • 1
  • 9
-1

Try this one

phones = Customer.objects.filter(active=True).values('name')\
    .annotate(count = Count('phone',filter=Q(phone__model__icontains=[i for i in model_list]))