覆盖Django中只有一个字段的保存

时间:2013-12-19 05:29:12

标签: python django model django-models

这是我的models.py:

class College(models.Model):
  name = models.CharField(unique=True, max_length=50, 
    help_text='Name of the college.'
  )
  slug = models.SlugField(unique=True)
  description = models.TextField(blank = True)
  image = models.ImageField(upload_to='site-media/media/college_images/', 
    default = 'site-media/media/college_images/default.jpeg' 
  )
  user = models.ForeignKey(User)


  def get_absolute_url(self):
    return "/%s/" % self.slug

  def create_thumbnail(self):
    if not self.image:
        return

    THUMBNAIL_SIZE = (250,193)

    image = Image.open(StringIO(self.image.read()))
    thumb = ImageOps.fit(image, THUMBNAIL_SIZE, Image.ANTIALIAS)
    temp_handle = StringIO()
    thumb.convert('RGB').save(temp_handle, 'jpeg')
    temp_handle.seek(0)

    suf = SimpleUploadedFile(os.path.split(self.image.name)[-1],
            temp_handle.read(), content_type='image/jpeg')
    self.image.save('%s_college_.%s'%(os.path.splitext(suf.name)[0],'jpeg'), suf, save=False)

  def save(self, *args, **kwargs):
    self.slug = slugify(self.name)
    self.create_thumbnail()

    super(College, self).save(*args, **kwargs)

我向用户提供了一个表单来编辑描述。当描述'POST'时,调用上面的'save()'方法。这个问题是缩略图是每次都用一个更大的名字一遍又一遍地创建的。而且,以前的缩略图也不会从硬盘中删除。是否有可能,每次编辑“描述”时都不会反复调用这种“缩略图”方法。

3 个答案:

答案 0 :(得分:3)

您可以检查您是否在请求帖子中发送图像文件。为此,您需要使用一个参数请求在视图中调用save,例如:college.save(request)

def save(self, request=False, *args, **kwargs):
    self.slug = slugify(self.name)

    if request and request.FILES.get('image',False):
        self.create_thumbnail()

    super(College, self).save(*args, **kwargs)

OR 您可以使用

区分保存和编辑
if self.pk is not None 

但如果您编辑图像,则可能会产生问题。

所以它是你的选择你想如何去做它。

答案 1 :(得分:1)

我认为有两条合理的路径可以解决这个问题。两者都不理想,所以我很想知道是否有人有更好的选择。

一种方法是将您创建缩略图的最新图像的文件名保存为模型字段。然后在您的保存方法中,您可以检查image字段的文件名,并创建一个新的Thumbmail(如果已更改)。这样做的缺点是需要一个新的模型领域,但在其应用中更为普遍。

另一种方法是覆盖表单类的save方法。然后,您可以查看self.instance.image并将其与self.cleaned_data['image']进行比较,以检查旧图片文件名。这样做的缺点是只影响使用该表单类的视图,但不需要更改数据模型。您可以将自定义表单传递给管理员,如果您正在使用它,或者覆盖管理类的save_model方法。

答案 2 :(得分:0)

简单的解决方案是不要尝试在此阶段创建缩略图,但仅在需要时才创建缩略图,即(伪代码示例):

class Whatever(models.Model):
    image = models.ImageField(...)

    @property
    def thumbnail(self):
       thumb = do_i_have_a_thumbnail_yet(self.image)
       if not thumb:
           thumb = ok_then_make_me_a_thumbnail_and_store_it_please(self.image)
       return thumb

实施do_i_have_a_thumbnail_yet()ok_then_make_me_a_thumbnail_and_store_it_please()是留给读者的练习,但有提供此类服务的librairies或django应用程序。

另一个 - 甚至更好的imho - 解决方案是将缩略图处理委托给模板标签或模板过滤器。为什么?因为

  1. 缩略图主要是演示内容,不属于模型
  2. 大多数情况下,您需要来自同一图片的不同缩略图尺寸
  3. 前端开发人员可能希望可以自由更改缩略图的大小,而无需要求您更改后端代码并编写迁移脚本以重新计算所有现有缩略图。