2 回答
TA贡献1811条经验 获得超5个赞
我让它像这样工作:
models.py:
def save(self, *args, **kwargs):
super(Post, self).save(*args, **kwargs)
if self.postcover:
if not (self.postcover_tn and os.path.exists(self.postcover_tn.path)):
image = Image.open(self.postcover)
outputIoStream = BytesIO()
baseheight = 400
hpercent = baseheight / image.size[1]
wsize = int(image.size[0] * hpercent)
imageTemproaryResized = image.resize((wsize, baseheight))
imageTemproaryResized.save(outputIoStream, format='PNG')
outputIoStream.seek(0)
self.postcover = InMemoryUploadedFile(outputIoStream, 'ImageField',
"%s.png" % self.postcover.name.split('.')[0], 'image/png',
sys.getsizeof(outputIoStream), None)
image = Image.open(self.postcover)
outputIoStream = BytesIO()
baseheight = 175
hpercent = baseheight / image.size[1]
wsize = int(image.size[0] * hpercent)
imageTemproaryResized = image.resize((wsize, baseheight))
imageTemproaryResized.save(outputIoStream, format='PNG')
outputIoStream.seek(0)
self.postcover_tn = InMemoryUploadedFile(outputIoStream, 'ImageField',
"%s.png" % self.postcover.name.split('.')[0], 'image/png',
sys.getsizeof(outputIoStream), None)
elif self.postcover_tn:
self.postcover_tn.delete()
super(Post, self).save(*args, **kwargs)
signals.py
@receiver(models.signals.pre_save, sender=Post)
def post_auto_delete_files_on_change(sender, instance, **kwargs):
"""
Deletes old file from filesystem
when corresponding object is updated
with new file.
"""
if not instance.pk:
return False
try:
old_postcover = sender.objects.get(pk=instance.pk).postcover
old_postcover_tn = sender.objects.get(pk=instance.pk).postcover_tn
except sender.DoesNotExist:
return False
if not old_postcover:
return
new_postcover = instance.postcover
new_postcover_tn = instance.postcover_tn
if not old_postcover == new_postcover:
if os.path.isfile(old_postcover.path):
os.remove(old_postcover.path)
if old_postcover_tn == new_postcover_tn:
if os.path.isfile(old_postcover_tn.path):
os.remove(old_postcover_tn.path)
TA贡献1893条经验 获得超10个赞
这是问题所在
由于您正在处理保存后信号,因此在信号处理程序执行之前,实例上的数据已经插入到数据库中。
这意味着在你上面sender.objects.get(pk=instance.pk).postcover的instance.postcover代码中获取相同的东西——新保存的 postcover。
所以,你old_postcover在代码中命名的东西实际上是新的 postcover。真正的旧后封面已被永久覆盖,并且仍在您的文件系统中。
题外话
现在,这部分代码的主体......
if not old_postcover == new_postcover:
if os.path.isfile(old_postcover.path):
os.remove(old_postcover.path)
os.remove(old_postcover_tn.path)
...永远不会运行,因为old_postcover和new_postcover确实是一回事。
如何解决这个问题?
您可以使用预保存信号处理程序。
在处理程序中,您从数据库中获取旧的 postcoversender.objects.get(pk=instance.pk).postcover(在检查之后,就像您在代码中所做的那样,以确保实例确实有一个 pk)。
然后你删除这个旧的postcover,你就完成了。
此解决方案的问题
走这条路我可以立即看到的问题是,您正在删除旧数据而不知道新数据是否会被数据库首先接受。
但看好的一面
但是,如果您只通过ModelForms 更改 postcovers,则is_valid()对表单上的方法的调用会在实例上执行所有验证,因此您可以确信在处理程序执行时,实例上的新数据已经已验证并将被数据库接受。
添加回答
举报