Запрос к модели django для поиска лучшей продажи компании за месяц

У меня есть две модели django одна "компания", а другая "MonthlyReport" компании. Я хочу выяснить, продажи какой компании в текущем месяце превысили 20% от продаж предыдущего месяца

class Company(models.Model):
name = models.CharField(max_length=50)


class MonthlyReport(models.Model):
    company = models.ForeignKey(Company,on_delete=models.CASCADE)
    sale = models.IntegerField()
    date = models.DateField()

Как мне решить этот вопрос, чтобы найти компанию, у которой продажи больше 20% по сравнению с предыдущим месяцем

Возможно, есть способ сделать это с помощью ORM, но я бы просто пошел по пути python:

Сначала добавьте связанное имя к MonthlyReport

class Company(models.Model):
    name = models.CharField(max_length=50)


class MonthlyReport(models.Model):
    company = models.ForeignKey(Company, related_name="monthly_reports", on_delete=models.CASCADE)
    sale = models.IntegerField()
    date = models.DateField()

Тогда

best_companies = []

companies = Company.objects.all()
for company in companies:
    two_last_monthly_reports = company.monthly_reports.order_by("date")[:2]
    previous_report = two_last_monthly_reports[0]
    current_report = two_last_monthly_reports[1]

    if current_report.sale / previous_report.sale > 1.2:
        best_companies.append(company)

Вы, конечно, можете сделать это с помощью ORM. Вам нужно будет объединить Max (или SUM в зависимости от вашего случая использования) с фильтром выражений Q() и аннотировать процентное увеличение к набору запросов перед его фильтрацией.

Вы могли бы сделать это в одном куске кода, но я разделил его, потому что получение дат и выражения запроса довольно длинные. Я также поместил значение увеличения в отдельную переменную, вместо того чтобы жестко кодировать его.

from datetime import datetime, timedelta
from django.db.models import Max, Q

SALES_INCREASE = 1.2

# Get the start dates of this month and last month
this_month = datetime.now().date().replace(day=1)
last_month = (this_month - timedelta(days=15)).replace(day=1)

# Get the maximum sale this month
amount_this_month = Max('monthlyreport__sale', 
    filter=Q(monthlyreport__date__gte=this_month))

# Get the maximum sale last month, but before this month
amount_last_month = Max('monthlyreport__sale', 
    filter=Q(monthlyreport__date__gte=last_month) & \
        Q(monthlyreport__date__lt=this_month))

Company.objects.annotate(
    percentage_increase=amount_this_month/amount_last_month
    ).filter(percentage_increase__gte=SALES_INCREASE)

что если мы удалим модель компании и будем использовать только monthlReport как :

class MonthlyReport(models.Model):
    company = models.CharField(max_length=50)
    sale = models.IntegerField()
    date = models.DateField()
Вернуться на верх