Как максимально компактно реализовать код на DRF ORM - PullRequest
1 голос
/ 07 февраля 2020
def read_rate(self, id):

    cursor = self.db.cursor()

    cursor.execute('SELECT volume FROM rate WHERE cur_id = ' + str(id) + ' ORDER BY id DESC LIMIT 10')
    volume = cursor.fetchall()

    cursor.execute('SELECT rate FROM rate WHERE cur_id = ' + str(id) + 'ORDER BY id DESC LIMIT 1')
    (get,) = cursor.fetchone()
    rate = str(get)
    average = str(sum([float(x[0]) for x in volume])/len(volume))

    cursor.close()
    return {'rate': rate, 'average_volume': average}

Необходимо реализовать код в DRF ORM, где набор запросов будет возвращать 'cur id', 'last rate' и 'средний объем за последние 10 дней'

Модель

class Rate(models.Model):
    cur = models.ForeignKey(Cur, on_delete=models.CASCADE)
    date = models.DateField(auto_now=True)
    rate = models.FloatField()
    volume = models.FloatField()

    def __str__(self):
        return self.cur

    class Meta:
        ordering = ['-id']

и как я пытался реализовать

class RateView(ListAPIView):


    serializer_class = RateSerializer

    def get_queryset(self):
        return Rate.objects.values(
            cur__id__in=[self.kwargs['id']]).order_by(
                '-id')[:10].annotate(Avg('volume'), 'rate', self.kwargs['id'])

1 Ответ

0 голосов
/ 07 февраля 2020

Итак, похоже, у вас немного отключены настройки базового набора запросов.

Я не уверен, что вам нужно заказывать по идентификатору, потому что вы фильтруете по одному идентификатору. Таким образом, все идентификаторы в отфильтрованном фильтрованном объекте QuerySet<> будут одинаковыми - так что технически он уже упорядочен.

Метод values() - это способ извлечь QuerySet<> для итеративной манипуляции ... так сначала вам нужно будет выполнить фильтрацию на cur__id, равном self.kwargs['id'].

Далее, извлечь только те значения, которые вы хотите - что выглядит как id, rate и volume ( необходимо для последующей аннотации).

Затем используйте агрегатор Avg, как показано.

Тогда предел? (Я думаю - я не уверен, что это работает для менее чем 10 записей от руки).

Итак, в общем, я бы реализовал это следующим образом:

class RateView(ListAPIView):

    serializer_class = RateSerializer

    def get_queryset(self):
        return Rate.objects.all()

    def list(self):
        queryset = self.get_queryset().filter(
            cur__id=self.kwargs['id']
        )

        queryset = queryset.values(
            'id',
            'rate', 
            'volume'
        ).annotate(
            average_volume=Avg('volume'),
        )[:10]

        ...

Я также изменил ваш метод базового класса "get_queryset()" для возврата all() объектов - единственная фильтрация, которую я бы сделал на этом уровне, это очень базовая c фильтрация, например, если бы представление отображало всех female пользователей (по какой-либо причине) ... так и User.objects.filter (пол = ' female ') будет иметь смысл в качестве базового запроса для построения.

Точка, в которой он оценивается БД, находится на последнем вызове values().

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