Количество фильтров просмотра Django

#django #django-views

Вопрос:

Я хочу узнать количество «задач» (Pendentes) для каждого «Клиента» (Cliente)

У меня есть эти модели в моем models.py:

 class Cliente(models.Model):
    id = models.IntegerField(primary_key=True)
    nome = models.CharField(max_length=200, help_text="Nome")
    localidade = models.CharField(max_length=100, help_text="Localidade")
    [...]

class Pendente(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text="ID Unico")
    cliente = models.ForeignKey('Cliente', on_delete=models.RESTRICT, blank=True, null=True)
    memo = models.TextField(null=True, blank=True, help_text="Memória Descritiva", max_length=200)
    criado = models.DateField(default=date.today, null=True, blank=True, help_text="Data registo ")
    concluir = models.DateField(null=True, blank=True, help_text="Data de execução máxima ")
    tecnico = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
    tecnicoatribuido = models.ForeignKey('TecnicoAtribuido', on_delete=models.SET_NULL, blank=True, null=True)
 

В основном я хочу запустить этот sql:

 "select A.id, A.nome, A.localidade, count(B.id) as tarefas
from todolist_pendente B 
LEFT JOIN todolist_cliente A
ON A.id = B.cliente_id
GROUP by A.id;"
 

Похоже, я не могу понять, как это будет работать с видом.

Я могу подсчитать количество клиентов с помощью :

resultado = Pendente.объекты.значения(‘cliente’).order_by(‘cliente’).аннотировать(количество=Количество(‘идентификатор’))

Но это не отображает имя каждого клиента в шаблоне.

В моем шаблоне, который я использую :

   <ul>
    {% for obj in resultado %}
    <li>{{ obj.cliente}} : {{ obj.count}}</li>
    {% endfor %}
  </ul>
 

Это рендеринг:

 6 : 2
35 : 1
40 : 1
92 : 1
106 : 1
105 : 1
 

есть ли способ получить значение внешнего ключа «ном», чтобы его можно было отобразить следующим образом:

 id  Nome    Localidade  Tarefas
6   Cliente A   Quarteira   2
35  Cliente B   Lisboa  1
40  Cliente C   Barreiro    1
92  Cliente D   Lisboa  1
105 Cliente E   Faro    1
106 Cliente F   Barreiro    1
 

Помощь была бы признательна…

Ответ №1:

Вы можете попробовать этот подход:

 class Cliente(models.Model):
    id = models.IntegerField(primary_key=True)
    nome = models.CharField(max_length=200, help_text="Nome")
    localidade = models.CharField(max_length=100, help_text="Localidade")
    [...]

    @property
    def pendente_count(self):
      return Pendente.objects.filter(cliente=self).count()


# from client object now you can access pendente_count property

# If you pass client queryset context with your template
queryset = Cliente.objects.all()

# inside template
{% for client in queryset %}
  {{ client.nome }}  {{ client.pendente_count }}
{% endfor %}


# or you can use this without adding a new property in you model
{{ client.pendente_set.all.count }}
 

Ответ №2:

Спасибо за помощь! Исправил это с помощью следующего:

views.py :

 resultado = Cliente.objects.annotate(pendente_count=Count('pendente')
 

Шаблон (нужны были только клиенты, у которых были Pendentes, поэтому я добавил предложение if):

     <tbody>
  {% for cliente in resultado3 %} {% if cliente.pendente_count > 0 %}
  <tr>
    <td>{{ cliente.id }}</td>
    <td>{{ cliente.nome }}</td>
    <td>{{ cliente.localidade }}</td>
    <td>{{ cliente.pendente_count }}</td>
  </tr>
  {% endif %} {% endfor %}
</tbody>
 

Спасибо!
Я чувствовал себя Хомяком на колодце 🙂

Комментарии:

1. Я бы посоветовал фильтровать в представлении, а не в шаблоне, так как, фильтруя в шаблоне, вы получите Client s, которые затем просто отфильтруете. Обычно лучше отфильтровать как можно больше с помощью запроса.

2. Привет, Виллем, я согласен, и в итоге я изменил qs, чтобы включить фильтр.

Ответ №3:

Вы можете аннотировать каждый Cliente из них количеством связанных с Pendente :

 from django.db.models import Count

resultado = Cliente.objects.annotate(
    pendente_count=Count('pendente')
) 

вы также можете отфильтровать Client буквы s, чтобы они, по крайней мере, имели одну Pendente :

 from django.db.models import Count

resultado = Cliente.objects.annotate(
    pendente_count=Count('pendente')
).filter(pendente_count__gt=0) 

Это приведет к попаданию в базу данных с помощью одного запроса и, таким образом, позволит базе данных подсчитать количество связанных Pendente запросов Cliente .

затем в вашем шаблоне вы можете отобразить это с помощью:

 <table>
  <thead>
    <tr>
      <th>id</th><th>Nome</th><th>Localidade</th><th>Tarefas</th>
    </tr>
  </thead>
  <tbody>
    {% for cliente in resultado %}
        <tr><td>{{ cliente.id }}</td><td>{{ cliente.nome }}</td><td>{{ cliente.localidade }}</td><td>{{ cliente.pendente_count }}</td></tr>
    {% endfor %}
  </tbody>
</tble>