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()對表單上的方法的調用會在實例上執行所有驗證,因此您可以確信在處理程序執行時,實例上的新數據已經已驗證并將被數據庫接受。
添加回答
舉報