我有一个自定义照片/图像服务应用程序。我们的优化之一是图像的数据基于图像数据的 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 对象复制到另一个自身的 DB 对象的最佳方法吗?我不确定是否copy()
甚至deepcopy()
会起作用,或者它是否是处理这种情况的正确方法。