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.
Related
I'm using odooV10.
I want to know every model's methods without searching it manually, but I couldn't find anywhere to achieve this. Is anyone have any idea?
well you can simply dir(model)
ie.
any_method_on_your_model(self):
print dir(self)
you will see all the properties included in the object.
Activate the Developer Mode in OdooV10.
Then go Setting(odoo Main Settings)--> Technical -->Models.
Here you can find all models, fields, views and constraints. I hope this will work for you.
if not explain what you want trying to do.?
In python you can get method of class
get methods of class
but the problem here odoo inherits mechanism prevent you from doing
this. when you call a method a very complicated operation to create
an object with that method from the inherited classes
I have a model, on which I need to edit objects given certain states.
Using post_save signals I can identify the given state, and from there run the specified method(s).
My issue now is that in these methods I need to save the object after editing, causing end endless save-loop. Is there a 'correct way' to handling this kind of situation, or are there only bad or worse kinds of workarounds?
In order to avoid this kind of loop, you need to disconnect at the beginning of your custom method, and then reconnect to signal afterwards :
Inside your method connected to signal :
signals.post_save.disconnect(YourModel.your_custom_method, sender=YourModel)
# Do your stuff
instance.save()
signals.post_save.connect(YourModel.your_custom_method, sender=YourModel)
Note : I'm using "YourModel.your_custom_method because I tend to place it inside the model, this is obviously not mandatory.
EDIT :
This SO question brings the use of update() instead of save() as a cleaner way, it might be what you're looking for.
Django post_save preventing recursion without overriding model save()
Although it might be cleaner I wouldn't think of it as a perfect solution unless properly managed with caching, since you'll be forced to hit the database to retrieve the queryset while you already have the instance in your hands as argument of the signal...
The idea of save_without_signal seems interesting but I wonder how it could be done without the above caveats.
Hope this helps,
Regards,
On Google AppEngine, we have .put() and put_async(), which are called to save an model object. ().
Being new to GAE, it is not clear to me how I can ensure that some functionality gets executed every time I same an object.
In vanilla Django, I can use signals, or override the .save() method.
How would I achieve similar results on GAE, considering I can actually rely on .put() being called when an object is saved?
There are several ways you could accomplish this. You could override the put method with your own code. Just be sure to call the models super put().
However, the route I would choose would be to implement a post put hook (assuming you're using NDB). See the hook method documentation here: https://developers.google.com/appengine/docs/python/ndb/modelclass
I've coded myself into a corner sort of with my data abstraction scheme and it's resulted in my needing editorOpened(QModelIndex) and editorClosed(QmodelIndex) signals in my views (QTableView almost exclusively).
The reason being that my data classes have automatic behavior that needs to be block/disabled during editing, then re-enabled afterwards.
At first I thought to try to do it with custom delegates but ran into problems for a couple reasons: one being just that it seems a bit excessive to use a custom delegate providing the same behavior for every single item, in other words it seems like it ought to be done for all items by the view itself. The second problem being that the delegates seem to be const which prevents me from setting an internal handle to the data object within the delegate.
Looking at the view methods, I found QAbstractItemView::edit and QAbstractItemView::closeEditor which would be perfect candidates for re-implementing with opened() and closed() signals, however I need an index/handle to the specific item being edited, which I don't think I can obtain from within those methods...
At this point I have no idea what else I could do. I'd appreciate any tips or pointers in the right direction! Thanks for reading
I solved it on my own...
I found QAbstractItemDelegate::editorEvent which is non-const (I must have not been looking as closely as I thought when reading the docs before).
I was able to set an internal handle in the custom delegate within this method, which allowed me to simply create a slot to do what I needed upon closing, and connect the closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint) signal to it.
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.