Как оптимизировать мой код и доступ к базе данных? - PullRequest
1 голос
/ 07 мая 2020
• 1000

Я хочу иметь эффективный и оптимизированный код, соблюдающий принцип DRY и меньшее количество возможных запросов к базе данных.

Пример объявления этого кода в моем views.py, он эффективен и оптимизирован?

def conto_economico(request):
    # Creazione tabella materie prime, sussidiarie, di consumo e merci
    defaults = list(0 for m in range(12))
    elements = dict()
    for conto_id, year, month, totale in(Materiale.objects.values_list('conto__nome', 'data__year', 'data__month').annotate(totale=ExpressionWrapper(Sum(F('quantita') * F('prezzo')),
        output_field=FloatField())).values_list('conto__nome', 'data__year', 'data__month', 'totale').order_by("conto_id")) :
        if conto_id not in elements.keys():
            elements[conto_id]=list(defaults)
        index=month-1
        elements[conto_id][index]=totale

    total_elements={'Per materie prime, sussidiarie, di consumo e di merci': [sum(t) for t in zip(*elements.values())],}

Я использую этот код для многих моделей для создания своих таблиц, но я думаю, что это неэффективно.

Это моя модель:

class MaterialeManager(models.Manager):
    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).annotate(
            iva_amount=ExpressionWrapper(F('quantita')*F('prezzo')*F('iva'),output_field=FloatField())
        ).annotate(totale_netto=ExpressionWrapper(F('quantita')*F('prezzo'),output_field=FloatField()))


class Materiale(models.Model):
    conto = models.ForeignKey(Conto, on_delete=models.CASCADE, null=True)
    tipologia = models.ForeignKey(Tipologia, on_delete=models.CASCADE, null=True)
    sottocategoria = models.ForeignKey(Sottocategoria, on_delete=models.CASCADE, null=True)
    um = models.CharField('U.M.', max_length=30, unique=False, blank=True, default="")
    quantita=models.DecimalField('Quantità',max_digits=5, decimal_places=2, default="")
    prezzo=models.DecimalField('Prezzo di acquisto', max_digits=5, decimal_places=2, default="")
    iva=models.DecimalField('I.V.A. in %', max_digits=5, decimal_places=2, default="0.22")
    data=models.DateField('Data di acquisto', default="GG/MM/YYYY")
    giorni_dilazione=models.IntegerField('Giorni dilazione pagamento', default="")
    objects=MaterialeManager()

Я хочу получить на основе данных регистрации ежемесячные таблицы, в которых суммируется вся сумма "quantita" для каждого отдельного "conto ".

1 Ответ

0 голосов
/ 07 мая 2020

Я не Django эксперт по орм, но я постараюсь дать свой ответ

contos = Conto.objects.prefetch_related('materiale_set').annotate(totale=Sum('materiale__quantita'))

Теперь, если вы хотите только январь / 2020 Contos, просто

january_contos = contos.filter(materiale__date__year=2020, materiale__date__month=1)

Я думаю, что таким образом вы перебираете не каждую Materiale запись, а только нужное количество месяцев, позволяя запросу sql вычислять суммы вместо кода python. Здесь важна предварительная выборка, иначе вы будете выполнять огромное количество подзапросов.

...