2016-07-14 40 views
1

围绕这个主题有几个问题,但没有一个我发现适合我想要做的。我希望能够将文件上传到模型并使用模型实例属性(如pk)将该文件保存在一个不错的位置。我知道这个东西在model.save()之后被设置,所以我需要写一个自定义的保存来做到这一点,但我无法弄清楚。以下是我有:Django FileField在上传后移动文件

class UploadModel(models.Model): 
    image = models.ImageField(upload_to='uploads') 

    def save(self, *args, **kwargs): 

     # Call standard save 
     super(UploadModel, self).save(*args, **kwargs) 

     if 'uploads' in self.image.path: 

      initial_path = self.image.path 

      # New path in the form eg '/images/uploadmodel/1/image.jpg' 
      new_path = os.path.join(settings.MEDIA_ROOT, 'images', 
       self._meta.model_name, self.pk, os.path.basename(initial_path)) 

      # Create dir if necessary and move file 
      if not os.path.exists(os.path.dirname(new_path)): 
       makedirs(os.path.dirname(new_path)) 

      os.rename(initial_path, new_path) 

      # Do something here to save the new file to the image field 

      # Save changes 
      super(UploadModel, self).save(*args, **kwargs) 

我有什么做的image领域得到它引用这个新文件的位置,并设置都喜欢image.pathimage.nameimage.url等有用的属性呢?

docs说,以上是我应该需要做的,但这只是导致image字段指向一个不存在的文件。我查看了this相关问题,并尝试了其中一个答案中提到的snippet,但我还没有找到解决方案。

回答

0

经过大量的搜索找出this旧的文档票据,有一个很好的解释,我想通了。

class UploadModel(models.Model): 
    image = models.ImageField(upload_to='uploads') 

    def save(self, *args, **kwargs): 

     # Call standard save 
     super(UploadModel, self).save(*args, **kwargs) 

     if 'uploads' in self.image.path: 

      initial_path = self.image.path 

      # New path in the form eg '/images/uploadmodel/1/image.jpg' 
      new_name = '/'.join(['images', self._meta.model_name, str(self.id), 
       path.basename(initial_path)]) 
      new_path = os.path.join(settings.MEDIA_ROOT, 'images', 
      self._meta.model_name, self.pk, os.path.basename(initial_path)) 

      # Create dir if necessary and move file 
      if not os.path.exists(os.path.dirname(new_path)): 
       makedirs(os.path.dirname(new_path)) 

      os.rename(initial_path, new_path) 

      # Update the image_file field 
      self.image_file.name = new_name 

      # Save changes 
      super(UploadModel, self).save(*args, **kwargs) 

现在我读的docs for this它看起来完全明显:)但我觉得解释可以做更多的描述。希望这会节省一些时间!

+0

根据https://docs.djangoproject.com/en/2.0/ref/models/fields/#django.db.models.FileField.upload_to,您应该只传递一个可调用的'upload_to =' – janek37