Reputation: 1736
I want to update one field of my model after post save. For that I am using post_save signal but when I try to save the model it always get trapped in some kind of infinite loop and in the end I am getting max, recursion depth error
My code is as follows :
class UserProfile(models.Model):
.
.
.
def profile_thumbanil(sender, created, instance , **kwargs):
profile = UserProfile.objects.get(id = instance.id)
thumb = handlers.create_thumbanil(profile.image, profile.user_id)
profile.thumbnail_image = thumb
profile.save()
post_save.connect(profile_thumbanil, sender=UserProfile)
I don't know what's the error here. If anyone can tell me another way of saving the data after post_save then that will be also fine.
Thanks
Edit :
save() will not work in my case because I am creating the thumbnail of images and the script which I using resize the images which are already exist on server and thus untill the save() finished its work image will not be saved on server and thus I cannot resize it that's why I can only run my function after save() finished its work so that image will be saved on server and I can resize it.
I can use Update() when user try to save images via UI and in that case my function works because Image is already saved into db but when admin (django-admin) try to upload an image then issue comes. So I need to call my function in such a way that whenever django admin save/edit profile images I can call my function but as I said my function only works after actual save() finished its work.
Upvotes: 3
Views: 4595
Reputation: 3215
We need to be super careful when using save() inside post_save, they can lead to a recursive call. Here is one solution.
def profile_thumbanil(sender, created, instance , update_fields=["thumbnail_image"], **kwargs):
profile = UserProfile.objects.get(id = instance.id)
thumb = handlers.create_thumbanil(profile.image, profile.user_id)
profile.save(update_fields=["thumbnail_image"])
post_save.connect(profile_thumbanil, sender=UserProfile)
Internally this would use an update SQL command instead of insert.
UPDATE row
SET "thumbnail_image" = 'your image'
WHERE "row"."id" = pk
This will work for sure, however, the best practice would be to use save() method instead.
Upvotes: 0
Reputation: 3168
You can get the object using filter and then use the update method to save the corresponding field.
def profile_thumbanil(sender, created, instance , update_fields=["thumbnail_image"], **kwargs):
profile = UserProfile.objects.get(id = instance.id)
thumb = handlers.create_thumbanil(profile.image, profile.user_id)
profile.update(thumbnail_image = thumb)
post_save.connect(profile_thumbanil, sender=UserProfile)
An alternative method is to disconnect the post save signal, save relevant fields then reconnect the post save method.
Upvotes: 0
Reputation: 10135
You can redefine save method of the model. It is more appropriate in your case than using signals because you modify the same instance.
Maybe this would be helpful: http://www.martin-geber.com/thought/2007/10/29/django-signals-vs-custom-save-method/
Upvotes: 2