Django - Фильтр менеджеров - PullRequest
0 голосов
/ 28 мая 2020

Я застрял в этом уже несколько недель, и я считаю, что ответ очень прост, но почему-то я не могу найти его нигде в Интернете. Что заставляет меня думать, что я поступаю совершенно неправильно.

Все, что я хочу сделать, это иметь возможность фильтровать свою статистику, такую ​​как функция get_largest_winning_trade, на основе пакета django -filter . Где я ошибаюсь? В качестве побочного примечания get_largest_winning_trade показывает самую крупную прибыльную сделку в торговой модели, но она не фильтруется по моим критериям. Например, «пользователь».

manager.py

from django.db import models

class TradeQuerySet(models.QuerySet):

    def get_users_trades(self, username):
        return self.filter(user__username=username)

class TradeManager(models.Manager):

    def get_queryset(self):
        return TradeQuerySet(self.model, using=self._db)

    def get_users_trades(self, username):
        return self.get_queryset().get_users_trades(username)

    def get_largest_winning_trade(self):
        return max([t.profit_loss_value_fees for t in self.all()])

views.py

class StatsView1(LoginRequiredMixin, ListView):
    model = Trade
    template_name = 'dashboard/stats1.html'

    def get_context_data(self, **kwargs):
        filter = StatsFilter1(self.request.GET, queryset=self.get_queryset())
        context = super().get_context_data(**kwargs)
        context['filter'] = filter
        context['get_largest_winning_trade'] = Trade.objects.get_largest_winning_trade
        return context

stats. html (тестирование)

        filter.qs.get_largest_winning_trade: {{ filter.qs.get_largest_winning_trade }} <br>
        Trade.get_largest_winning_trade: {{ Trade.get_largest_winning_trade }} <br>
        trade.get_largest_winning_trade: {{ trade.get_largest_winning_trade }} <br>
        get_largest_winning_trade: {{ get_largest_winning_trade }} <br>  # works but not with filter

Дополнительная запрошенная информация

Разделил класс, он довольно длинный, поэтому я попытался сократить его до наиболее полезного. Пожалуйста, дайте мне знать, если есть что-нибудь еще.

models.py

class Trade(models.Model):
    class Meta:
        verbose_name = "Trade"
        verbose_name_plural = "Trades"
     ...

     user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
     status = models.CharField(max_length=2, choices=STATUS_CHOICES, default='cl')
     type = models.CharField(max_length=5, choices=TYPE_CHOICES, default=LONG)
     broker = models.ForeignKey(Broker, on_delete=models.CASCADE, blank=True, null=True)
     asset = models.ForeignKey(Asset, default=DEFAULT_ASSET_ID, on_delete=models.CASCADE, null=True)
     #AUTOMATED FIELDS
     profit_loss_value_fees = models.FloatField(null=True)
     objects = TradeManager()
     ...

     def save(self):
         ...
         self.profit_loss_value_fees = self.get_profit_loss_value_fees()
         return super(Trade, self).save()

     ...

1 Ответ

1 голос
/ 28 мая 2020

Вероятно, вы можете сделать что-то подобное, используя свойство qs:

def get_context_data(self, **kwargs):
    filter = StatsFilter1(self.request.GET, queryset=self.get_queryset())
    context = super().get_context_data(**kwargs)
    context['filter'] = filter
    context['get_largest_winning_trade'] = filter.qs.get_largest_winning_trade
    return context

Update

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

from django.db.models import Max
...

context['get_largest_winning_trade'] = filter.qs.aggregate(max_value=Max('profit_loss_value_fees'))['max_value']

Причина использования агрегации состоит в том, чтобы уменьшить количество обращений к базе данных, потому что ваш метод менеджера будет обращаться к базе данных несколько раз в течение l oop итерации.

...