Python 聚合查询集以获取文件字段大小之和

Python 聚合查询集以获取文件字段大小之和,python,django,mongodb,gridfs,Python,Django,Mongodb,Gridfs,我使用django Nonl,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 而且工作正

我使用django Nonl,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
而且工作正常

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
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/Users/zoidberg/dev/backus/lib/python2.6/site packages/django/db/models/query.py”,第321行,总计
is_summary=True)
文件“/Users/zoidberg/dev/backus/lib/python2.6/site packages/django/db/models/sql/query.py”,第974行,在add_聚合中
字段\列表,选项,self.get\初始\别名(),False)
文件“/Users/zoidberg/dev/backus/lib/python2.6/site packages/django/db/models/sql/query.py”,第1417行,在setup_中
raise FIELDRERROR(“不允许加入字段%r。查找类型是否拼写错误%r?”%(名称,名称[pos+1]))
FieldError:不允许加入字段“文件”。查找类型是否拼错了“大小”?
在这里输入代码

你知道使用ORM是可行的还是我必须自己迭代文件?

使用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'))

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

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

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

只是一个想法?

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

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

只是一个想法?

在我使用
sum([f.file.size for f in Doc.objects.all()])的同时,你的解决方案听起来更合理。非常感谢。就在那时,我使用了
sum([f.file.size for f in Doc.objects.all()])
,但您的解决方案听起来更合理。非常感谢。是的,在hcalves提出他的解决方案之前,我一直回过头来,只是不觉得“django”的方式:)项目离生产还有很长的路要走,所以我可以改变我的模型。将总额转移到数据库可能比在app Side上做更明智。是的,在hcalves提出他的解决方案之前,我一直回过头来,只是没有感觉到“django”方法:)这个项目离生产还很远,所以我可以改变我的模型。把总数转移到数据库中可能比在应用程序端进行更明智