2016-03-21 36 views
1

我正在尋找一種在保存ImageField時調整,壓縮和優化上傳圖像的方法。Django如何在使用ImageField保存模型時檢查用戶是否上傳了圖像文件?

class Image(models.Model): 
    name = models.CharField(max_length=254, blank=True) 
    caption = models.TextField(max_length=1000, blank=True) 
    height = models.IntegerField() 
    width = models.IntegerField() 
    image = models.ImageField(upload_to='', height_field='height', width_field='width', storage=S3MediaStorage()) 

我首先想到的是覆蓋模型的save()和實現這個邏輯,但我不想,如果用戶不更新圖像文件的大小調整/壓縮/優化再次運行(即,如果他只更新現有對象上的namecaption並將其保存)。

  1. 什麼是正確的方法來檢查時,一個新的圖像文件被上傳到的ImageField,但不是當用戶只在模型中,如改變另一個領域。用戶更新caption,但保持原樣?

  2. 如何在代碼中訪問上傳的圖像文件?即包含可傳遞給Pillow的實際圖像文件的變量是什麼?

編輯:這是從the suspected duplicate獨特。我並不是問該領域是否發生了變化,因爲這總是會導致誤報。我詢問用戶是否上傳了一個圖像文件,我將立即更改(調整大小/優化/壓縮),因此如果用戶立即下載他上傳的圖像,他會發現它具有與隨機生成的文件名不同的二進制文件,以及因此比較文件名或二進制文件不是有效的方法來確定用戶是否正在上傳不同的圖像。

+0

可能重複[Django:保存時,如何檢查字段是否已更改?](http://stackoverflow.com/questions/1355150/django-when-saving-how-can-you-check- if-a-field-has-changed) – rnevius

+0

@rnevius我已經添加了信息來區分這個問題,謝謝 – dtgq

回答

1

您的模型可以使用不同的名稱。

不過,你可以嘗試通過post_save信號(https://docs.djangoproject.com/en/1.9/ref/signals/#post-save

from PIL import Image 
from django.db.models.signals import post_save 

@receiver(post_save, sender=Image) 
def crop_image(sender, instance, **kwargs): 
    img = instance.image 
    original = Image.open(img.src.path) 
    # ... your code here... 

編輯處理圖像:道歉。跳了一下槍。你的一個實際問題是如果相同,不要操縱圖像。你可以做它在save()像這樣(未經):

def save(self, **kwargs): 
    try: 
     related_img = Image.objects.get(id=self.id) 
     if related_img.image != self.image: 
      crop_me(self.image) 
    except Image.DoesNotExist: 
     # object doesn't exist. Passing... 
     pass 

    return super(Image, self).save(**kwargs) 

def crop_me(img): 
    original_img = Image.open(img.src.path) 
    # ... your code here... 

編輯2:如果名字改變,你可以保存原文件名中的幫手場

class Image(models.Model): 
    image = models.ImageField(upload_to='', height_field='height', width_field='width', storage=S3MediaStorage()) 

    __original_image_filename = None 

    def __init__(self, *args, **kwargs): 
     super(Image, self).__init__(*args, **kwargs) 
     self.__original_image_filename = self.image.name 

    def save(self, force_insert=False, force_update=False, *args, **kwargs): 
     if self.image.name != self.__original_image_filename: 
     # name changed - do something here 

     super(Image, self).save(force_insert, force_update, *args, **kwargs) 
     self.__original_image_filename = self.image.name 

我修改的另一個答案飛,所以可能會有一兩個錯誤。請檢查the original answer。在這個問題上還有其他方法可以幫助你。

+1

你寫了'if not self.id',然後在'if'塊中,你正在做'id = self .id'。可能想解決這個問題。它應該是'如果self.id'。 – xyres

+0

固定。感謝您指出了這一點!這也是反模式(EAFP)http://docs.quantifiedcode.com/python-code-patterns/readability/asking_for_permission_instead_of_forgiveness_when_working_with_files.html –

+0

'if related_img.image!= self.image:'這可能工作,如果我保留副本原始文件上傳到'related_img.image'中,但是如果我只保存原始文件的副本,該文件已被重命名爲隨機字符串,並且圖像已被調整大小和壓縮,它看起來不會有用。是否有可能只檢查用戶上傳的圖像文件? – dtgq

相關問題