具有以下模型,我需要在每个记录的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()评估之前的查询集吗?
答案 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
需要与网络服务器联系,那么(可能)在数据库系统中是不可能的。