我有一个自定义照片/图像服务应用程序。我们的一个优化是基于图像数据的MD5将图像的数据存储在磁盘上。我编写了一个自定义save()
方法来处理从File
对象获取数据并创建创建实际数据库对象所需的所有零碎和字段。
问题是在几乎同时上传相同图像时发生的竞争条件。 save()
方法很可能会被两个不同的线程同时调用。
如果第二个线程发现文件存在,我们会忽略该事实并继续处理。虽然我们测试在写入之前检查文件是否存在但是如果两个进程写入图像数据则不是错误。它将浪费一些周期,但数据将与md5哈希相同。我们只是测试以避免浪费那些周期。
现在是时候将实际对象写入数据库了。如果我们成功,那么一切都很好,我们的对象已根据需要由django的ORM更新。
如果我们因完整性错误而失败,则意味着该对象在我们开始之间就已存在。
如果发生这种情况,我们希望将实际保存的对象的内容复制到self
,以便来电者留下save()
工作的印象。
try:
super(Photo,self).save(*args, **kwargs) # the "real" save()
except IntegrityError:
#
# Looks like we were in a race condition. We'll pull the
# record and copy it.
photo = Photo.objects.get(hash=self.hash)
# that fetch darn well should have worked. If it didn't let the
# error propagate so we can find and fix it.
#
# N.B. dangerious copy of fields from db object.
#
for field in photo._meta.get_all_field_names:
exec('self.%s=photo.%s' % (field, field))
所以问题是:这是将字段从django数据库对象复制到另一个自我的DB对象的最佳方法吗?我不确定copy()
或deepcopy()
是否可行,或者是否是处理这种情况的正确方法。
答案 0 :(得分:0)
我相信deepcopy()
会对此有用。但肯定有比exec()
更好的方法。像这样可能:
for field in photo._meta.get_all_field_names:
setattr(self, field, getattr(photo, field))