Django最佳实践用文件上传替换旧文件

时间:2011-01-27 14:00:57

标签: django django-forms

总之,我在这里要完成的是:

  • 为了组织和安全起见,对上传文件的名称进行转换
  • 不要将旧文件永久保存在存储中

假设您有一个带有徽标的Company型号。像

这样的东西
class Company(models.Model):
  name = ...
  logo = models.FileField(blank=True, null=True)

现在,因为我有点偏执,我不喜欢上传文件得到(可能是邪恶的)用户给出的名字这一事实,我添加一个upload_to参数指向一个函数这就像

def logo_getfilename(instance, filename):
  extension = ... # get just the original extension from the file
  return 'logos/' + str(uuid.uuid4()) + extension

好的,现在只缺少视图了!

def company_edit(request, ...):
  company = ... # get the company and stuff

  if request.method == 'POST':
    form = CompanyAdminForm(request.POST, request.FILES, instance=company)
    last_file_path = None
    if not company.logo is None:
      last_file_path = company.logo.path
    # ^^ after calling is_valid(), file_path gets changed to
    # the would-be-default-behavior
    if form.is_valid():
      # first we write the new file
      form.save()
      # now we remove the old one
      os.unlink(last_file_path)

虽然目前正在使用,但我对此并不满意,因为

  • 我正在使用os.unlink()代替FieldFile.delete()似乎错了
  • 我假设一个本地文件系统存储
  • 我仍然没有采取任何措施来防止命名冲突(它们可能仍会发生)
  • 我忽略了多个块并假设form.save()将处理所有内容
  • 我没有考虑事务行为(只有在.save()模型更改提交到数据库后才应删除以前的文件
  • 我觉得那里有一些我甚至不知道的问题

为了实现这些简单(而不是那种不常见)的目标,您的建议是什么?

1 个答案:

答案 0 :(得分:0)

为什么不使用公司的主键,而不是随机用户名?当他们上传新文件时,只需覆盖现有文件(我认为只要您在保存之前更改文件名,它就会自动执行)。这样就无需执行os.unlink和(可能)停止您的交易担忧。

相关问题