我的Django应用程序中有这个模型:
class Image(models.Model):
image_file = models.ImageField(
upload_to='images/',
width_field='width',
height_field='height'
)
width = models.PositiveIntegerField(
blank = True, null = True,
editable = False
)
height = models.PositiveIntegerField(
blank = True, null = True,
editable = False
)
sha1 = models.CharField(max_length=32, blank=True, editable=False)
filesize = models.PositiveIntegerField(blank=True, null=True, editable=False)
我现在可以通过Django管理站点上传图片了。由于特殊的width
参数,height
和ImageField
属性会在上传时自动保存在数据库中。
但我也希望自动计算上传文件的尺寸和 SHA-1 摘要,并保存这些属性。我该怎么做?
答案 0 :(得分:3)
已经有一段时间了,但这样的事情应该有效:
import hashlib
class Image(models.Model):
#...
def save(self, *args, **kwargs):
super(Image, self).save(*args, **kwargs)
f = self.image_file.open('rb')
hash = hashlib.sha1()
if f.multiple_chunks():
for chunk in f.chunks():
hash.update(chunk)
else:
hash.update(f.read())
f.close()
self.sha1 = hash.hexdigest()
self.filesize = self.image_file.size
编辑: 添加了关于大块阅读的建议。默认块大小为64KB。
答案 1 :(得分:1)
我不确定你是否可以自动完成。但ImageField
也是FileField
,因此您始终可以使用hashlib.sha1
打开文件并计算校验和。您必须读取文件以计算校验和,以便您可以同时嗅探大小。
我使用Django的ORM已经有一段时间了,但我相信有一种方法可以编写一个方法,只要将模型实例保存到底层存储或从底层存储中读取,就会调用该方法。这是进行计算的好地方。
答案 2 :(得分:0)
尽管Burhan Khalid给出了答案,但我认为它仍是难题的部分解决方案。它仍然不能解决保存到数据库部分的问题。这是完整的解决方案,该解决方案还使用更新的with
子句来利用python和Django的文件context_manager
(因此不需要no和file.close(),它会自动发生):
import hashlib
class Image(models.Model):
#...
def save(self, *args, **kwargs):
with self.image_file.open('rb') as f:
hash = hashlib.sha1()
if f.multiple_chunks():
for chunk in f.chunks():
hash.update(chunk)
else:
hash.update(f.read())
self.sha1 = hash.hexdigest()
self.filesize = self.image_file.size
super(Image, self).save(*args, **kwargs)
请注意,在with子句中调用了super()。这一点很重要,否则您将得到一个错误:ValueError: I/O operation on closed file.
,因为Django尝试读取已关闭的文件,并在其关闭时以其为打开状态。这也是将我们已更新的所有内容保存到数据库的最后一条命令(这是上一个最佳答案所遗留的位置,您很可能必须再次调用save()才能真正保存这些详细信息)