signal
A signal is a mechanism that triggers your code (function/method) whenever an event of a given type occurs in ormar.
To do this, you need to register the receiver for the given type of signal of the selected model.
Define receiver
The following example model is given:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
For example, you can define a trigger that sets the album.is_best_seller state if the album has been played more than 50 times.
Import the\pre_update decorator and see the list of currently available decorators/signals below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
Define your function.
Please note that each receiver function:
- Must be callable
- Must accept the first sender parameter of the receive sender class
- must accept the**kwargs parameter as a parameter sent in each ormar. Signals can change at any time, so your function must serve them.
- Must be asynchronous because callbacks are collected and waiting.
pre_update Currently only one parameter is sent besides the sender, and it is instance one.
Notice how the\pre_update decorator accepts the senders parameter, which can be a single model or a list of models for which you want to run the signal receiver.
Currently, signals cannot be set for all models immediately without explicitly passing them all into the receiver's registry.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
!!!note Note that the sink is defined at class level->, so even if you connect/disconnect the function through an instance, it will run/stop all operations on that ormar.Model class.
Note that our newly created function has classes of instances and instances, so you can easily run database queries inside the sink if you like.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
You can define the same receiver for multiple models at once by passing a list of models to the signal decorator.
1 2 3 4 | |
Of course, you can also create multiple functions for the same signal and model. Each of them runs on each signal.
1 2 3 4 5 6 7 | |
Note that ormar decorators are syntactic sugar, you can directly connect functions or methods of a given signal of a given model. Connect accepts only one parameter-your receiver function/method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Note that the signal retains references to the receiver (not weak references), so keep this in mind to avoid circular references.
Disconnect the receiver
To disconnect a receiver and stop it from running a given model, you need to disconnect it.
1 2 3 4 5 6 7 8 9 10 | |
available signal
!!!Warning Please note that no signal will be sent:
1 2 3 4 | |
pre save
pre_save(sender: Type["Model"], instance: "Model")
Send the Model.save () and Model.objects.create() methods.
sender is an ormar.Model class and instance is the model to save.
after saving
post_save(sender: Type["Model"], instance: "Model")
Send Model.save () and Model.objects.create() methods.
sender is an ormar.Model class and instance is the saved model.
pre-update
pre_update(sender: Type["Model"], instance: "Model")
Send to Model.update() method.
sender is an ormar.Model class and instance is the model to update.
updated
post_update(sender: Type["Model"], instance: "Model")
Send to Model.update() method.
sender is an ormar.Model class and instance is an updated model.
predeleted
pre_delete(sender: Type["Model"], instance: "Model")
Send the Model.save () and Model.objects.create() methods.
sender is an ormar.Model class and instance is the model to delete.
after deletion
post_delete(sender: Type["Model"], instance: "Model")
Send to Model.update() method.
sender is an ormar.Model class and instance is the model to be deleted.
Pre-relationship addition
pre_relation_add(sender: Type["Model"], instance: "Model", child: "Model", relation_name: str, passed_args: Dict)
Send Model.relation_name.add() method of many-to-many relationship and inverse of foreign key relationship.
sender -sender class, instance -add instance of related model, child -model being added, relation_name -name of relation to which child is added, also passed for add signal_kwargs -dictionary of kwargs passed to add()
Post-relationship addition
post_relation_add(sender: Type["Model"], instance: "Model", child: "Model", relation_name: str, passed_args: Dict)
Send Model.relation_name.add() method of many-to-many relationship and inverse of foreign key relationship.
sender -sender class, instance -add instance of related model, child -model being added, relation_name -name of relation to which child is added, also passed for add signal_kwargs -dictionary of kwargs passed to add()
Pre-relationship deletion
pre_relation_remove(sender: Type["Model"], instance: "Model", child: "Model", relation_name: str)
Send the Model.relation_name.remove() method of the many-to-many relationship and the inverse of the foreign key relationship.
sender -sender class, instance -add instance of related model, child -model being added, relation_name -name of relation to which child is added.
After deleting the relationship
post_relation_remove(sender: Type["Model"], instance: "Model", child: "Model", relation_name: str, passed_args: Dict)
Send the Model.relation_name.remove() method of the many-to-many relationship and the inverse of the foreign key relationship.
sender -sender class, instance -add instance of related model, child -model being added, relation_name -name of relation to which child is added.
After batch update
post_bulk_update(sender: Type["Model"], instances: List["Model"], **kwargs), sent to Model.objects.bulk_update(List[objects]) method.
Define your own signals
Note that you can create your own signals, although you have to send them manually in code or subclass ormar.Model and trigger signals there.
Creating a new signal is easy. The following example sets up a new signal named your_custom_signal.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
In fact, the bottom layer of a signal is a SignalEmitter instance that holds a dictionary of known signals and allows you to access them as attributes. SignalEmitter creates a signal for you when you try to access a signal that doesn't exist.
So the example above can be simplified to. The signal will be created for you.
1 | |
Now to trigger this signal, you need to call the send method of the signal.
1 | |
Note that sender is the only required parameter, which should be the ormar Model class.
Additional parameters must be passed as keyword parameters.
1 | |