【问题标题】:Aggregating a QuerySet to get Sum of FileFields size聚合 QuerySet 以获取 FileFields 大小的总和
【发布时间】:2012-06-20 19:37:06
【问题描述】:

我使用 django-nonrel,Postgre 作为数据库,Mongo 作为文件存储。

我的模型看起来像这样并且工作正常

class Doc(models.Model):
    created_on = models.DateTimeField(auto_now_add=True)
    file = models.FileField(storage=gridfs_storage, upload_to='/')

并且工作正常

Doc.objects.all()[0].file.size
108776

现在我正在尝试聚合大小以获得查询集的总大小。

我试过了

Doc.objects.all().aggregate(Sum('file__size'))

但是这个抛出

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Users/zoidberg/dev/backus/lib/python2.6/site-packages/django/db/models/query.py", line 321, in aggregate
    is_summary=True)
  File "/Users/zoidberg/dev/backus/lib/python2.6/site-packages/django/db/models/sql/query.py", line 974, in add_aggregate
    field_list, opts, self.get_initial_alias(), False)
  File "/Users/zoidberg/dev/backus/lib/python2.6/site-packages/django/db/models/sql/query.py", line 1417, in setup_joins
    raise FieldError("Join on field %r not permitted. Did you misspell %r for the lookup type?" % (name, names[pos + 1]))
FieldError: Join on field 'file' not permitted. Did you misspell 'size' for the lookup type?
    enter code here

知道是否可以使用 ORM 或者我必须自己迭代文件?

【问题讨论】:

    标签: python django mongodb gridfs


    【解决方案1】:

    A hcalves 指出使用直接 ORM 是不可能的。我假设您的数据库已经完成并设置,那么您为什么不能这样做呢?

    total_size = sum([ x.file.size for x in Doc.objects.all() ])
    

    只是一个想法?

    【讨论】:

    • 是的,直到 hcalves 提出他的解决方案,我才回过头来,只是没有感觉到“django”的方式:) 项目离生产还很远,所以我可以改变我的模型
    • 将总和卸载到数据库可能比在应用程序端进行更明智
    【解决方案2】:

    使用 ORM 无法做到这一点,因为它只能针对数据库字段生成聚合,而 file.size 是存储后端提供的动态属性。

    也就是说,您最好在上传时将此信息保存在您的实际数据库中,这样您就可以避免遍历所有文件的开销。

    class Doc(models.Model):
        created_on = models.DateTimeField(auto_now_add=True)
        file = models.FileField(storage=gridfs_storage, upload_to='/')
        file_size = models.PositiveIntegerField()
    
        def save(self, *args, **kwargs):
            self.file_size = self.file.size
            super(Doc, self).save(*args, **kwargs)
    

    现在聚合按预期工作,因为您正在处理数据库字段:

    Doc.objects.all().aggregate(Sum('file_size'))
    

    【讨论】:

    • 就在我使用sum([f.file.size for f in Doc.objects.all()]) 的同时,但您的解决方案听起来更合理。谢谢!
    猜你喜欢
    • 2019-08-03
    • 1970-01-01
    • 2018-06-03
    • 2017-10-08
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多