Как отфильтровать набор запросов на основе булевого значения, а затем подсчитать в шаблоне

Я хочу подсчитать, сколько заданий открыто и сколько закрыто. Я не понимаю, почему это не работает, я добавил {{ap.id}} и {{open.line_num_id }} после цикла forloop, чтобы посмотреть, что получилось. Я бы подумал, что если они совпадают, то они добавляются в счетчик. Это не так, все задания подсчитываются независимо от оператора "if". Совершенно не понимаю, что происходит и почему. Любая помощь будет очень признательна .

У меня есть две модели:

class Airplane(models.Model):
    line_num = models.CharField(max_length=10, unique=True)
    vh_num = models.CharField(max_length=4, unique=True)
    vz_num = models.CharField(max_length=4, unique=True)
    stall = models.CharField(max_length=30, choices=stall_picker)
    status = models.CharField(max_length=30, choices=status_picker)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    is_completed = models.BooleanField(default=False)
    pm = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.line_num

class Job(models.Model):
    line_num = models.ForeignKey(
        Airplane, on_delete=models.CASCADE, related_name="ap_jobs")
    job_num = models.CharField(max_length=10, unique=True)
    description = models.CharField(max_length=200)
    status = models.CharField(max_length=30, choices=status_picker)
    category = models.CharField(max_length=30, choices=categories_picker)
    is_completed = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class meta:
        ordering = ["category", "status"]

    def __str__(self):
        return (f"{self.job_num}: {self.description} : {self.is_completed}")

Мое мнение:

def Ap_linup(request):
    context = {
        'ap_list': Airplane.objects.all().filter(is_completed=False),
        'open_jobs': Job.objects.all().filter(is_completed=False),
        'closed_jobs': Job.objects.all().filter(is_completed=True)
    }
    
    return render(request, 'airplane/airplane_list.html', context)

Шаблон:

{% extends 'base.html' %}

{% block title %} Airplane List {% endblock %}

{% block content %}
<center>
    <div class="row">
        {% for ap in ap_list %}
        <div class="col-md-3">
            <div class="card">
                <div class="card-body">
                    <h1>
                        <center>
                            <a href="{% url 'airplane:ap_detail' ap.id %}">{{ ap.line_num }}</a>
                        </center>
                    </h1>
                    <h3>
                        <p>Stall:<strong>{{ ap.stall }}</strong> VH:<strong>{{ ap.vh_num }}</strong> VZ:<strong>{{ap.vz_num }}</strong>
                        <p>MGR: {{ ap.owner }}</p>
                        <hr class="lead border border-dark">
                        <h1>{{ ap.id }}</h1>
                        {% if ap.status == "Avalible" %}
                        <p>Current Status:</p>
                        <p class="text-success">{{ ap.status }}</p>
                        {% else %}
                        <p>Current Status:</p>
                        <p class="text-danger">{{ ap.status }}</p>
                        {% endif %}
                    </h3>  
                    <!-- Open Job counts -->
                    <div> 
                        {% for open in open_jobs %}
                        {% if open.line_num_id == ap.id %}</p>
                            <p>Open Jobs: {{ open_jobs.count }}</p>
                        {% endif %}
                        {% endfor %}
                        {% for closed in closed_jobs %}
                        {% if closed.line_num_id == ap.id %}</p>
                            <p>Closed Jobs: {{ closed_jobs.count }}</p>
                        {% endif %}
                        {% endfor %}
                    </div>
                    <div class="lead border border-dark">
                        {% for comment in ap.ap_comments.all %}
                            {% if comment_id == ap_id %}
                                    <p><strong>{{ comment.author }}</strong>: {{ comment.text }} @ {{comment.created_at }}</p>
                            {% endif %}
                        {% endfor %}
                    </div>
                </div>
            </div>
        </div>
        {% endfor %}
        
    </div>
</center>



{% endblock %}

ВЫВОД:

Выход

Я хочу отображать количество открытых и закрытых заданий на каждом самолете. Количество открытых и закрытых заданий просто складывается с общим количеством заданий на самолете.

Как упоминает Куско в комментариях, вы можете передать это число в контекст. Это можно сделать следующим образом:

def Ap_linup(request):
    context = {
        'ap_list': Airplane.objects.all().filter(is_completed=False),
        'open_jobs': Job.objects.all().filter(is_completed=False),
        'closed_jobs': Job.objects.all().filter(is_completed=True),
        'open_jobs_count': Job.objects.filter(is_completed=False).count(),
        'closed_jobs_count': Job.objects.filter(is_completed=True).count()
    }

Кроме того, вам не нужно .all(), потому что фильтра достаточно.

и если вы хотите еще немного почистить код, чтобы не было много запросов, вы можете объявить переменные перед контекстом.

def Ap_linup(request):
    open_jobs = Job.objects.filter(is_completed=False)
    closed_jobs = Job.objects.filter(is_completed=True)

    context = {
        'ap_list': Airplane.objects.all().filter(is_completed=False),
        'open_jobs': open_jobs,
        'closed_jobs': closed_jobs,
        'open_jobs_count': open_jobs.count(),
        'closed_jobs_count': closed_jobs.count()
    }
    
    return render(request, 'airplane/airplane_list.html', context)
Вернуться на верх