17

I am trying to create a system which enables user to upload a zipfile, and then extract it using post_save signal.

class Project:
    ....
    file_zip=FileField(upload_to='projects/%Y/%m/%d')

@receiver(post_save, sender=Project)
def unzip_and_process(sender, **kwargs):
    #project_zip = FieldFile.open(file_zip, mode='rb')
    file_path = sender.instance.file_zip.path
    with zipfile.ZipFile(file_path, 'r') as project_zip:
        project_zip.extractall(re.search('[^\s]+(?=\.zip)', file_path).group(0))
        project_zip.close()

unzip_and_process method works fine when correct file paths are provided(in this case, i need to provide instance.file_zip.path. However, I couldn't get/set the instance with the signals. Django documentation about signals is not clear and have no examples. So, what do I do?

Umur Kontacı
  • 35,403
  • 8
  • 73
  • 96

2 Answers2

25

Actually, Django's documentation about signals is very clear and does contain examples.

In your case, the post_save signals sends the following arguments: sender (the model class), instance (the instance of class sender), created, raw, and using. If you need to access instance, you can access it using kwargs['instance'] in your example or, better, change your callback function to accept the argument:

@receiver(post_save, sender=Project)
def unzip_and_process(sender, instance, created, raw, using, **kwargs):
    # Now *instance* is the instance you want
    # ...
Ferdinand Beyer
  • 64,979
  • 15
  • 154
  • 145
  • 1
    I think it is about the `**kwargs` which I don't know yet. Your example works well, thank you. – Umur Kontacı Aug 09 '11 at 07:55
  • 1
    @Ferdinand There are no examples about post_save in django documentation. – Anuj Feb 28 '14 at 09:28
  • @Anuj - I never said there were any examples about `post_save`. There are examples on how to use signals in general, and these apply to `post_save` as well, as there is nothing special about this particular signal. – Ferdinand Beyer Feb 28 '14 at 09:57
  • I'm a green hand in django. I'm quite confused, do u mean that the argument `instance` is an instance of Project? – ray6080 Mar 13 '14 at 00:35
  • @ray6080 - Yes. It is the `Project` instance that has just been saved. – Ferdinand Beyer Mar 13 '14 at 23:11
  • @FerdinandBeyer Your statement about the Django documentation is not accurate. There is no such example there. I don't know where you find out how to create your code but it was not reading the page you provided. – Wilson Freitas Oct 26 '17 at 21:53
  • @WilsonFreitas you must be kidding, right? No "such example", are you expecting ready-made copy-and-paste examples for every particular problem a user might have? I claimed that the Django docs are very clear and contain example code, how exactly is that statement not accurate? What are you missing? – Ferdinand Beyer Oct 27 '17 at 04:41
  • @FerdinandBeyer I am expecting a single example with the instance parameter being used. Am I supposed to just guess I have to use it as the second param on the receiver callback? Maybe this is explained somewhere else on the documentation pages, but not on the signals documentation. So yes, the OP is right about the signals documentation not being clear about how to access the instance object from the receiver callback simply because there is no mention to the instance param anywhere to be seem. This question has 6,139 views so maybe the docs are not so obvious. – Wilson Freitas Oct 27 '17 at 17:53
  • @FerdinandBeyer BTW, thanks for your answer. I up voted because it helped me to solve the issue I couldn't by simply reading the signals documentation. – Wilson Freitas Oct 27 '17 at 17:55
  • @WilsonFreitas the arguments depend on the signal. Click on the post_save link I provided in this answer, it documents this particular signal. It clearly specifies the arguments and that the instance parameter is second. Sorry, but if you really think the docs are not clear then you are up for a surprise in your career. The Django docs are of an exceptional good quality. – Ferdinand Beyer Oct 27 '17 at 18:58
  • Making assumptions about someone you don't know will bring surprises to your career. I've been writing code for 20 years and I am pretty happy with my career. There are lots of reference docs, but they are not written in a way that is easy to read. The information is there, but not in the page you have posted. I've searched the entire page and didn't find a reference to the instance param. The info is in another page. So you should probably update your answer. Not everyone have the free time to dive into reference docs. Short guides are better for people who just need a quick answer. – Wilson Freitas Oct 30 '17 at 14:53
  • @WilsonFreitas I posted two links. General information on signals and specific documentation to the `post_save` signal. I quote from the second link: "Arguments sent with this signal: (...) instance The actual instance being saved." I really don't understand how you can claim that you did not find any reference to that. But you know what, let's just agree to disagree. – Ferdinand Beyer Oct 30 '17 at 15:49
2

This worked for me when connecting Django Signals:

Here is the models.py:

class MyModel(models.Model):
    name = models.CharField(max_length=100)

And the Signal that access it post_save:

@receiver(post_save, sender=MyModel)
def print_name(sender, instance, **kwargs):
    print '%s' % instance.name 
Aaron Lelevier
  • 19,850
  • 11
  • 76
  • 111