Использование функции класса в качестве переменной в Django

У меня есть этот файл models.py в моем проекте Django

from django.db import models
from django.urls import reverse
from django.utils.timezone import now

class Campaign(models.Model):
    class Meta:
        db_table = 'campaign'

    campaign_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255, default='')
    topic = models.CharField(max_length=255, default='')
    sender = models.CharField(max_length=255, default='')
    start_date = models.DateTimeField(default=now)
    is_active = models.BooleanField(default=False)
    draft = models.BooleanField(default=True)
    content = models.TextField(default='')
    footer = models.CharField(max_length=255, default='')
    unsubscribe_message = models.CharField(max_length=255, default='')

    @property
    def get_completion_percent(self):
        return 70

И я пытаюсь использовать функцию get_completion_percent в моем views.py в качестве фильтра прямо здесь

def finished_ads_view(request):
    queryset = Campaign.objects.filter(get_completion_percent=100)

    context = {
        'object_list': queryset,
    }

    return render(request, 'campaigns_in_progress.html', context)

Но ошибка, которую я получаю, выглядит следующим образом:

FieldError at /finished_campaigns/ Невозможно преобразовать ключевое слово 'get_completion_percent' в поле. Варианты: campaign_id, content, draft, footer, is_active, name, sender, start_date, topic, unsubscribe_message

Может ли кто-нибудь помочь мне заставить это работать?

Вы не можете фильтровать свойство.

Если вам нужен процент, вы можете использовать .annotate() и отфильтровать поле.

Campaign.objects.annotate(percentage=70).filter(percentage=100)

Если вам нужно выполнить операцию над полями одной записи, вы можете получить значения с помощью выражения F()

Я попытаюсь дать решение. Оно не проверено, поэтому вы должны попробовать его и сообщить мне, если оно работает. Я пытаюсь понять, что является вашей конечной целью, и, насколько я понимаю, это отобразить что-то, если процент завершения достигнет 100. Я бы добавил еще одну модель, например, такую:

class Percentage(models.Model):
    campaign= models.ForeignKey(
        Campaign, on_delete=models.CASCADE, null=True, blank=True)
    percentage= models.IntegerField(default=0, blank=True, null=True) #I don't know if you need integer or float

Теперь, используя этот внешний ключ, вы можете выполнить вычисления (в представлении, я полагаю), чтобы получить процент. Примером может быть:

from django.db.models import Sum # remember this import

def finished_ads_view(request, pk):
    campaign = Campaign.objects.filter(campaign_id=pk)
    percentages = Percentage.objects.filter(campaign=campaign).aggregate(Sum(percentage))
    if percentages == 100:
         context = {
             'object_list': percentages,
         } #this context is idented inside the if statement
    else:
         percentages = 'Not completed' # or whatever you want display if the percentage is not 100
         context = {
                 'object_list': percentages,
             }
        

    return render(request, 'campaigns_in_progress.html', context)

Это просто попытка, дайте мне знать, если это сработает. Я не тестировал код, так что могут быть ошибки, но я бы сделал что-то вроде этого

Вернуться на верх