当模型有多个 file.fields 时,上传新版本时从特定模型字段中删除文件,而不删除所有 Django 内容



我的问题是关于孤立文件以及我的模型使用多个文件字段的事实。我有一个用户的模型,它有一个个人资料图像字段和一个 cv 字段。用户可以更新这些工作正常的字段,但旧文件仍然存在。现在我已经在网上查看了各种解决方案,创建了自己的解决方案等,但它不能正常工作。我的解决方案(见下文(的问题在于,即使我只更改了一个值,它也会删除当时与该实例关联的所有旧媒体文件。此外,每个字段都有自己的目录路径,因此不会因共享相同的目录路径而导致递归删除。当我更改两个字段时都很好,因为更改和以前的文件都被删除了,但通常人们只更改一个值,所以我该如何解决这个问题?出于各种原因,我不想使用 django-cleanup。

models.py

def teacher_avatar_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    return 'teachers/avatar/{0}/{1}'.format(instance.user.email.replace(" ", "_").lower(), filename)
def teacher_cv_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    return 'teachers/cv/{0}/{1}'.format(instance.user.email.replace(" ", "_").lower(), filename)

#Teacher
class ProfileTeacher(models.Model):
    created = models.DateTimeField(auto_now=False, auto_now_add=True, blank = False, null = False, verbose_name = 'Creation Date')
    user = models.OneToOneField(app_settings.USER_MODEL,blank=True, null=False)
    first_name = models.CharField(max_length = 400, null=True, blank = True, verbose_name = 'First Name')
    last_name = models.CharField(max_length = 400, null=True, blank = True, verbose_name = 'Surname')
    phone_number = models.CharField(max_length = 15, null=True, blank = True, verbose_name = 'Phone Number')
    cvv = models.FileField(upload_to=teacher_cv_directory_path, null=True, blank = True, verbose_name="CV")
    profile_image = models.ImageField(upload_to=teacher_avatar_directory_path,
                                      null = True,
                                      blank=True,
                                      default='/perfil.png',
                                      )

#-------Model image and files clean up ----------------------------------
@receiver(post_init, sender= ProfileTeacher)
def backup_image_and_cv_paths(sender, instance, **kwargs):
    instance._current_image_file = instance.profile_image
    instance._current_cvv_file = instance.cvv
@receiver(post_save, sender= ProfileTeacher)
def delete_old_image(sender, instance, **kwargs):
    if hasattr(instance, '_current_image_file'):
        if instance._current_image_file != instance.profile_image.path:
            instance._current_image_file.delete(save=False)   
    if hasattr(instance, '_current_cvv_file'):
        if instance._current_cvv_file != instance.cvv.path:
            instance._current_cvv_file.delete(save=False)

您可以为模型创建自定义保存方法。文档在这里

class YourModel(models.Model):
   field_1 = ...
   field_2 = ...  
   def save(self, *args, **kw):
      if self.id:
         # Check that instance that you are sending for update have files in it
         # Get corresponding file field(s) and manually remove old file(s) according to the path
         # Store new file(s) to the file field(s)
         # Update other fields if required
         super().save(*args, **kwargs)

最新更新