2010-11-24 15 views
83

モデルを保存する前に画像のサイズを変更しています。しかし、新しい画像が追加されたのか、単に説明が更新されたのかを確認するにはどうすればいいのですか?モデルが保存されるたびに再スケーリングをスキップできますか?Django。モデルの保存をオーバーライド

class Model(model.Model): 
    image=models.ImageField(upload_to='folder') 
    thumb=models.ImageField(upload_to='folder') 
    description=models.CharField() 


    def save(self, *args, **kwargs): 
     if self.image: 
      small=rescale_image(self.image,width=100,height=100) 
      self.image_small=SimpleUploadedFile(name,small_pic) 
     super(Model, self).save(*args, **kwargs) 

新しい画像が読み込まれた場合や画像が更新された場合にのみ再スケーリングしたいのですが、説明が更新された場合は再スケーリングしません。

+0

あなたは100×100の固定サイズにリサイズされていますか? – bdd

+1

U [django-imagekit](http://bitbucket.org/jdriscoll/django-imagekit/wiki/Home)が役に立ちます – vikingosegundo

答えて

91

いくつかの考え:それならば

class Model(model.Model): 
    _image=models.ImageField(upload_to='folder') 
    thumb=models.ImageField(upload_to='folder') 
    description=models.CharField() 

    def set_image(self, val): 
     self._image = val 
     self._image_changed = True 

     # Or put whole logic in here 
     small = rescale_image(self.image,width=100,height=100) 
     self.image_small=SimpleUploadedFile(name,small_pic) 

    def get_image(self): 
     return self._image 

    image = property(get_image, set_image) 

    # this is not needed if small_image is created at set_image 
    def save(self, *args, **kwargs): 
     if getattr(self, '_image_changed', True): 
      small=rescale_image(self.image,width=100,height=100) 
      self.image_small=SimpleUploadedFile(name,small_pic) 
     super(Model, self).save(*args, **kwargs) 

わかりませんすべての擬似自動車のdjangoツールでうまくいくでしょう(例:ModelForm、contrib.adminなど)。

+1

いいね。しかし、画像の名前を_imageに変更することはできません。それは重要ですか? – Pol

+0

Becouse私はすでにデータベースにフィールド画像を持っています。 – Pol

+0

私はそれをdb_column = 'image'で解決しました。しかし、それは動作しませんスチール! – Pol

1

データベースに同じPKを持つ既存のレコードを照会します。新しい画像と既存の画像のファイルサイズとチェックサムを比較して、同じかどうかを確認します。

5

新しい画像が投稿されたことを確認するために、追加の引数を指定することができます。私はこれらが単に呼び出されたときに、あなたの保存破る文句を言わないと思います

def save(self, new_image=False, *args, **kwargs): 
    if new_image: 
     small=rescale_image(self.image,width=100,height=100) 
     self.image_small=SimpleUploadedFile(name,small_pic) 
    super(Model, self).save(*args, **kwargs) 

やリクエスト変数

def save(self, request=False, *args, **kwargs): 
    if request and request.FILES.get('image',False): 
     small=rescale_image(self.image,width=100,height=100) 
     self.image_small=SimpleUploadedFile(name,small_pic) 
    super(Model, self).save(*args, **kwargs) 

を渡しますよう
何か。

あなたadmin.pyでこれを置くことができるように(上記の解決策の第二のために)あまりにadminサイトでこの作品:

class ModelAdmin(admin.ModelAdmin): 

    .... 
    def save_model(self, request, obj, form, change): 
     instance = form.save(commit=False) 
     instance.save(request=request) 
     return instance 
+0

'WSGIRequest'オブジェクトに 'FILE'属性がありません – Pol

+0

あなたが言ったように管理者... – Pol

+0

FILEの代わりにFILESを実行し、request.FILES ['image']の代わりにrequest.FILES.get( 'image'、False)に更新すると、例外が発生しなくなります。 – crodjer

11

モデルのpkフィールドを確認します。 Noneの場合、それは新しいオブジェクトです。

class Model(model.Model): 
    image=models.ImageField(upload_to='folder') 
    thumb=models.ImageField(upload_to='folder') 
    description=models.CharField() 


    def save(self, *args, **kwargs): 
     if 'form' in kwargs: 
      form=kwargs['form'] 
     else: 
      form=None 

     if self.pk is None and form is not None and 'image' in form.changed_data: 
      small=rescale_image(self.image,width=100,height=100) 
      self.image_small=SimpleUploadedFile(name,small_pic) 
     super(Model, self).save(*args, **kwargs) 

編集:form.changed_dataに「画像」のチェックを追加しました。これは、管理サイトを使用して画像を更新していることを前提としています。以下に示すように、デフォルトのsave_modelメソッドをオーバーライドする必要もあります。私は目標を達成するためにやった

class ModelAdmin(admin.ModelAdmin): 
    def save_model(self, request, obj, form, change): 
     obj.save(form=form) 
+0

adminサイトを使用していると仮定すると、AdminModelのsave_modelをオーバーライドしてフォームを保存し、 'image'が入っているかどうかを確認できますform.changed_data。私は時間を取るとすぐに更新します。 – dgraves

+0

これは、あなたが言うようにオブジェクトが新しい場合にのみ機能します。新しい画像をアップロードすると、再スケーリングはトリガーされません。 – Jonathan

+1

"self.pk is None"はidを指定すると機能しません:Model.objects.get_or_create(id = 234、...)はこのソリューションでは動作しません – nuts

2

はこれを作ることだった。..

# I added an extra_command argument that defaults to blank 
def save(self, extra_command="", *args, **kwargs): 

およびsave()メソッド以下

これを..ですので

# override the save method to create an image thumbnail 
if self.image and extra_command != "skip creating photo thumbnail": 
    # your logic here 

私はいくつかの編集しますフィールドを編集するのではなく、画像を編集します。

Model.save("skip creating photo thumbnail") 

"skip creating photo thumbnail""im just editing the description"またはより正式なテキストに置き換えることができます。

願っています。新バージョンで

0

それはこのようなものです:

def validate(self, attrs): 
    has_unknown_fields = set(self.initial_data) - set(self.fields.keys()) 
    if has_unknown_fields: 
     raise serializers.ValidationError("Do not send extra fields") 
    return attrs 
関連する問題