Новое поле в аннотации уничтожает все типы полей django - PullRequest
0 голосов
/ 11 июля 2019

Мне нужно загрузить всю статистику по одному для каждой учетной записи пользователя.

Я использовал annotate () для соединения и вычисления полей других связанных моделей, но одно из полей, при добавлении, уничтожает все типы и умножает целое число на 10 в предыдущих полях в наборе запросов.

У меня есть 3 модели: AdvertisingAccount, Campaign, UserProfile.Я пробовал приводить для всех полей, но это не изменило картинку:

Мне нужно, чтобы целые числа были целыми числами, а десятичные дроби были десятичными с двумя десятичными знаками (как установлено в моделях).

ожидается:

ads_direct
313
303
31.12
2165.18

но получено:

ads_direct
3443
3333
342.320000000000
8441.80000000000

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

accounts = user.userprofile.advertising_accounts.annotate(
        clicks=Cast(Sum('campaigns__clicks', filter = Q(campaigns__userprofile = userprofile)), IntegerField()),
        views=Cast(Sum('campaigns__views', filter = Q(campaigns__userprofile = userprofile)),IntegerField()),
        ad_spent=Cast(Sum('campaigns__ad_spent', filter = Q(campaigns__userprofile = userprofile)),DecimalField(decimal_places=2)),
        money_left = Sum('budgetings__deposited', filter = Q(budgetings__userprofile = userprofile)) - (Sum('campaigns__ad_spent', filter = Q(campaigns__userprofile = userprofile))),
)

Примечание Если я закомментирую money_left, все аннотации вычисляются и отображаются в порядке (кроме десятичного знака: оно занимает12 мест вместо 2).

Я пробовал это, но это не изменило ситуацию:

accounts = user.userprofile.advertising_accounts.annotate(
        clicks=Cast(Sum('campaigns__clicks', filter = Q(campaigns__userprofile = userprofile)), IntegerField()),
        views=Cast(Sum('campaigns__views', filter = Q(campaigns__userprofile = userprofile)),IntegerField()),
        ad_spent=Cast(Sum('campaigns__ad_spent', filter = Q(campaigns__userprofile = userprofile)),DecimalField(decimal_places=2)),
money_left = Cast((Sum('budgetings__deposited', filter = Q(budgetings__userprofile = userprofile)) - (Sum('campaigns__ad_spent', filter = Q(campaigns__userprofile = userprofile)))),DecimalField(decimal_places=2)),
        )

шаблон

{% for i in accounts %}
  {{i.foreign_system_name}}<p></p>
  {{i.clicks}}<p></p>
  {{i.views}}<p></p>
  {{i.ad_spent}}<p></p>
  {{i.money_left}}<p></p>
  <p></p>
{% endfor %}

модели:

1

from django.db import models
from payments.models import Trade
# from users.models import UserProfile

# Create your models here.

class AdvertisingAccount(models.Model):
    balance = models.DecimalField(max_digits=12, decimal_places=2, default=0, blank=True, null=True)
    # eg yandex_direct or google_adwords
    foreign_system_name = models.CharField(max_length=30, blank=True, default=None)
    foreign_system_id = models.IntegerField(default=None, blank=True, null=True)
    def __str__(self):
        return self.foreign_system_name + '--' + str(self.foreign_system_id)


class Campaign(models.Model):
    userprofile = models.ForeignKey('users.UserProfile', on_delete=models.PROTECT, related_name='campaigns')
    # needs to open access to audience
    trade = models.ForeignKey('payments.Trade', on_delete=models.PROTECT, related_name='campaigns')
    ad_account = models.ForeignKey('AdvertisingAccount', on_delete=models.PROTECT, related_name='campaigns')
    views = models.IntegerField(default=0, blank=True, null=True)
    clicks = models.IntegerField(default=0, blank=True, null=True)
    ad_spent = models.DecimalField(max_digits=12, decimal_places=2, default=0, blank=True, null=True)

    def __str__(self):
        return str(self.userprofile) + '--' + str(self.ad_account.foreign_system_name) + '--' + str(self.trade.ad_budget)

2

class AdAccountsBudgeting(models.Model):
    userprofile = models.ForeignKey(UserProfile, on_delete=models.PROTECT)
    ad_account = models.ForeignKey('advertiser.AdvertisingAccount', on_delete=models.PROTECT, related_name='budgetings')
    deposited = models.DecimalField(max_digits=12, decimal_places=2, default=0, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    def __str__(self):
        return str(self.userprofile) + '--' + str(self.ad_account) + '--' + str(self.deposited)

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.PROTECT)
    role = models.CharField(max_length=15, default=None)
    balance = models.DecimalField(max_digits=12, decimal_places=2, default=0, blank=True, null=True)
    deposits = models.DecimalField(max_digits=12, decimal_places=2, default=0, blank=True, null=True)
    advertising_accounts = models.ManyToManyField('advertiser.AdvertisingAccount', through='AdAccountsRelations', related_name='userprofiles' )
    advertising_accounts_deposited = models.ManyToManyField('advertiser.AdvertisingAccount', through='AdAccountsBudgeting')

    def __str__(self):
        return self.user.username

Что может пойти не так при аннотировании?Что я должен сделать, чтобы соответствовать ожидаемому поведению?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...