I desperately need to be able to get some information from the request array on post_save() for a certain model. Is it possible to do that somehow?
I think your best bet would be to override the save() method on that model and emit the post save signal along with the specific data you need to send. See Sending Signals to learn how.
An alternative (albeit a very dirty hackish way) would be to have an additional column in the model which saves the data you need to send out (although you would still have to override the save() method on the model).
Related
Let's say I have a model Message. In admin, I need to add a message by submitting/uploading a message file, not by posting message fields as normally would. The process is, I get the file uploaded, send it to a processing program which parse the file, do some further processing and then add an entry into database.
So I create a custom form for ModelAdmin(assign form = CustomForm) with one FileField and override save_model() to not to save anything. However, this isn't a proper way as the doc clearly mention ModelAdmin's save_model() method is not for veto purpose. So what would be the proper way for this?
Some suggest an extra button pointed to a custom view, while it's surelly possible but logically I'm still adding a message so an extra view doesn't seem nature.
Simple use case:
After a user updates a record, I want to get the changed fields and save them in a history table. I'm using django-ditryfields to grab this history. So my thought process was to use the pre_save signal to grab all the 'dirty' fields and them store them in my history table.
Problem there is that I can't get request.user while using signals. I need this to see which user has made the change to the record. My other thought was just to override the save method of my model but then I also can't get request.user from a model directly either. I would have to send a **kwarg['user'] with the user info from the view to get this info. This is fine but I am going to be making save calls from a bunch of different places around the code. I don't want to have to keep passing request.user every time I edit an object. This is why I'd love to have one spot, like a signal, to handle all of this. Perhaps some middleware I'm not familiar with?
Is there a better way to achieve such a thing?
You cannot access the user object from a signal.
You can consider using this third party package: django-requestprovider to access the request object in the signal.
The other way would be to overriding the models' save method.
What is the recommend approach when extending some sort of save behavior in Django, such as saving calculated values?
I've seen people overriding the save method and I've seen people using signals.
What is the correct/most used/better approach for this?
save(), delete() do not get called on bulk actions, signals are your only option then.
I use simple approach. If need to update some fields on object itself - redefine save(). If need to work with other objects or querysets somehow - connect signals.
Goal: On submission of a form to add/update/delete objects an email is sent out with the current contents of the DB object and the new contents of the DB object in html.
Example
Object Title was oldTitle and has been changed to newTitle
Object Date was oldDate and has been changed to newDate
My assumption this can be done two different ways. Directly through send_mail or via signals. My gut leans towards using signals to make sure I can grab previous content and the new content but I am not quite sure if this is the right way to go. Any advice you can give would be much appreciated. I couldn't find very much on this subject online.
Queue up the message to be sent in the pre_save signal, and send (or reap) them in the post_save signal.
Try overriding save() in your model objects, and grabbing the fields in question before calling super().
Here's a database email queue I wrote, which may help you with the actual sending of the mail:
http://gist.github.com/629663
I am working on a Django project and I want to send a signal when something gets added to some model's related set. E.g. we have an owner who has a set of collectables, and each time the method owner.collectable_set.add(something) is getting called, I want a signal like collectable_added or something. Signals are clear to me, but I don't know which manager(?) contains the "add" method that I want to override.
Edit for Xavier's request to provide more details: you can easily override a model’s save method, by simply defining it and calling the "super-save" so it gets properly saved with some extra functionality. But I wonder where to override a related set's add method.
Gosh, I think I haven't brought in any further details, but I think it should be clear what I want to do even from the first paragraph.
Edit 2: This is the method I want to override. Is it recommended to do so, or do you suggest another way to place the sending of the signal?
This is the solution I found, the m2m_changed signal. Took me quite some searching and reading. Furthermore, I found out that it is not trivial to extend the ManyRelatedManager class, which would have been the other option. But with the m2m_changed signal I can rely on built-in functions which is the preferred way most of the time.
I think you're looking for the RelatedManager Class.
After much searching (thanks to this Paul's hint), I came across this snippet that helped to explain the m2m_changed implementation to intercept not override the add method on the ManyRelatedManager. It appears that the manager on a many-to-many relationship happens on the fly, so it's not trivial to override the method.