Django. Override save for model

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.

2

7 Answers

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).

4

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
2

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!

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.

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

I have found one another simple way to store the data into the database

models.py

class LinkModel(models.Model): link = models.CharField(max_length=500) shortLink = models.CharField(max_length=30,unique=True)

In database I have only 2 variables

views.py

class HomeView(TemplateView): def post(self,request, *args, **kwargs): form = LinkForm(request.POST) if form.is_valid(): text = form.cleaned_data['link'] # text for link dbobj = LinkModel() dbobj.link = text self.no = self.gen.generateShortLink() # no for shortLink dbobj.shortLink = str(self.no) dbobj.save() # Saving from views.py

In this I have created the instance of model in views.py only and putting/saving data into 2 variables from views only.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like