对QuerySet的注释应用修改

时间:2019-05-14 10:33:49

标签: django

具有以下模型,我需要在每个记录的image_url上应用一些功能(使用到期令牌对其进行预签名)。

class Item(models.Model):
    name = models.CharField()
    image_url = models.CharField()
    # other fields omitted

和查询集

qs = Item.objects.filter(q).annotate(name=F('name'), image_url=F('image_url)).values('name', 'image_url').annotate(count=Count('name'))

我通过将函数映射到结果列表来解决它,如下所示:

    def update_url(x):
        x['image_url'] = create_presigned_url(x['image_url'])
        return x
    sale_items = map(lambda x: update_url(x), list(qs)) 

有没有更好的方法,可以将它应用于list()评估之前的查询集吗?

1 个答案:

答案 0 :(得分:0)

您可以通过编写如下代码来使转换更加有效和紧凑:

qs = Item.objects.filter(q).values('name', 'image_url').annotate(count=Count('name'))
sale_items = map(update_url, qs)

一个查询集中不需要.annotate(..)个字段,尽管这对查询性能没有太大影响。

因为QuerySet是可迭代的,因此我们避免了第二次将其包装在列表中,并且与对该函数的lambda表达式相比,使用函数引用将节省一些周期,但不会导致显着改善。

除非您知道create_presigned_url函数的实现,否则可以通过使用Concat [Django-doc]Lower [Django-doc]等各种函数将其转换为表达式。

您无法在数据库级别进行处理。您不能在查询中传递“黑盒”函数,并且希望以某种方式希望您的数据库理解Python,或者希望有某种层可以转换SQL表达式中的函数。此外,数据库本身并不具有评估所有功能的全部方法,例如,如果您的create_presigned_url需要与网络服务器联系,那么(可能)在数据库系统中是不可能的。