On Sunday, March 4, 2012 12:31:50 PM UTC+2, Nikhil Verma wrote:
>
> Hi all 
>
> I am using Django-1.2.5 and i want to use post_save signal in the 
> following problem/task.
>
> I have :- 
> models.py
>
> image = models.ImageField(.....)
> remove_image = models.BooleanField()
>
> Now i want  :-
>
> 1) When the user uploads the file , the file path appears on the 
> imageField like this.
>
> Currently: 
> images/testimonial-bottom_1.png<http://localhost:8000/media/images/testimonial-bottom_1.png>
>  
>
> Change: 
>
> I want to give the option to delete the file .So i made a field called 
> remove image which is a checkbox . Now when the user clicks that 
> remove_image checkbox and press save the image should get deleted. I was 
> going through the documentation and believe that this problem could be 
> solved by using post_save signal
>
>
> I have not used signals so need help , 
>
>
> def delete_old_image(sender, instance, using=None,*args, **kwargs):
>     try:
>         old_record = sender.objects.get(pk=instance.pk)
>         old_record.delete()
>     except sender.DoesNotExist:
>         pass
> signals.post_save.connect(delete_old_image, sender=Trip)
>
> How can i achieve this task by using signals or without signals.
>
> Any help will be appreciated.
>
> You have a misunderstanding in your code: when you fetch the old_record 
from sender.objects you are actually refetching the instance being saved. 
Then you do on to delete the instance. Is this really what you want?

Now, if you want to delete the file in a signal, you should use pre_save 
signal, where you delete the image using instance.image.delete(save=False) 
or better jet set instance.image = None (see later for details). You should 
probably also clear the "save" flag, as otherwise that gets saved into the 
DB.

Still, it is much better to handle the clearing of the image field by using 
a custom form, and then do the clearing of the image in some hook of the 
form or in the view directly (for ModelForm that would be overridden 
.save()). The checkbox remove_image isn't really part of your data model, 
so it should not be a field in you model class, just a user input element.

Last, for some technicalities about file handling in transactional setting: 
To do file handling properly when using transactional databases you should 
actually do the file delete post-commit. The reason is this sequence of 
events:
  - delete file
  - do save
  - for some reason the transaction is rolled back. (network error, 
integrity error in DB, electricity lost and so on).

Now you have a model in the DB whose file field points to the now deleted 
file. The delete can't be rolled back.

So, to be technically correct, you should do the .delete() in post-commit 
hook. Now the worst case is that the transaction gets committed, but for 
some reason the file can't be deleted (crash of the server at the wrong 
moment). But, this results just in a leftover file in the storage. That is 
easy to clean up and in most cases doesn't matter at all.

As said, this is just a technicality. Django doesn't even provide that 
post-commit hook. I think I am going to suggest a pre/post commit signal, 
that could have other uses, too... However: there is a lesson here: are you 
sure you want to actually delete the actual file? You could just remove the 
link from the instance to that file, but leave the file in the file system.

 - Anssi

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/django-users/-/j3k9QXOZkYcJ.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to