Django. Override save for model

匿名 (未验证) 提交于 2019-12-03 01:54:01

问题:

Before saving model I'm re-size a picture. But how can I check if new picture added or just description updated, so I can skip rescaling every time the model is saved?

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) 

I want to rescale only if new image loaded or image updated, but not when description updated.

回答1:

Some thoughts:

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) 

Not sure if it would play nice with all pseudo-auto django tools (Example: ModelForm, contrib.admin etc).



回答2:

Check the model's pk field. If it is None, then it is a new object.

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) 

Edit: I've added a check for 'image' in form.changed_data. This assumes that you're using the admin site to update your images. You'll also have to override the default save_model method as indicated below.

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


回答3:

You may supply extra argument for confirming a new image is posted.
Something like:

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) 

or pass request variable

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) 

I think these wont break your save when called simply.

You may put this in your admin.py so that this work with admin site too (for second of above solutions):

class ModelAdmin(admin.ModelAdmin):      ....     def save_model(self, request, obj, form, change):          instance = form.save(commit=False)         instance.save(request=request)         return instance 


回答4:

What I did to achieve the goal was to make this..

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

and below the save() method is this..

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

so when i edit some fields but not editing the image, I put this..

Model.save("skip creating photo thumbnail") 

you can replace the "skip creating photo thumbnail" with "im just editing the description" or a more formal text.

Hope this one helps!



回答5:

Query the database for an existing record with the same PK. Compare the file sizes and checksums of the new and existing images to see if they're the same.



回答6:

In new version it is like this:

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 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!