【问题标题】:How to most compactly implement the code on DRF ORM如何最紧凑地在 DRF ORM 上实现代码
【发布时间】:2020-05-23 02:32:58
【问题描述】:
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上实现代码,其中queryset会返回'cur id'、'last rate'和'average volume in the last 10 days'

型号

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'])

【问题讨论】:

  • 嗨,迈克,您能否为“Rate”模型发布您的models.py 文件……或者这不是在您的应用程序中建模的(即,您是否连接到外部数据库源?)
  • 忽略我,你有!

标签: python django orm django-rest-framework django-orm


【解决方案1】:

所以,看起来您的基本查询集设置略有偏差。

我不确定您是否需要按 ID 进行排序,因为您只使用一个 ID 进行过滤。因此,重新过滤后的 QuerySet<> 对象中的每个 ID 都是相同的 - 所以从技术上讲,它已经被排序了。

values() 方法是一种提取 QuerySet<> 以进行迭代操作的方法......因此您需要首先过滤 cur__id 等于 self.kwargs['id']

接下来,只提取您想要的值 - 在我看来,这些值类似于 idratevolume(后续注释需要)。

然后,如图所示使用 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() 对象 - 我会在此级别上执行的唯一过滤是非常基本的过滤,例如视图是否用于显示所有 @987654333 @Users(无论出于何种原因)...所以 User.objects.filter(gender='female') 作为您构建的基本查询是有意义的。

DB 评估它的点是在最后的values() 调用上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 2019-06-29
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 2021-12-02
    相关资源
    最近更新 更多