Receive a collection 'bulk replace' event. This event is invoked for a sequence of values as they are incoming to a bulk collection set operation, which can be modified in place before the values are treated as ORM objects. This is an "early hook" that runs before th
(
self,
target: _O,
values: Iterable[_T],
initiator: Event,
*,
keys: Optional[Iterable[EventConstants]] = None,
)
| 2644 | """ |
| 2645 | |
| 2646 | def bulk_replace( |
| 2647 | self, |
| 2648 | target: _O, |
| 2649 | values: Iterable[_T], |
| 2650 | initiator: Event, |
| 2651 | *, |
| 2652 | keys: Optional[Iterable[EventConstants]] = None, |
| 2653 | ) -> None: |
| 2654 | """Receive a collection 'bulk replace' event. |
| 2655 | |
| 2656 | This event is invoked for a sequence of values as they are incoming |
| 2657 | to a bulk collection set operation, which can be |
| 2658 | modified in place before the values are treated as ORM objects. |
| 2659 | This is an "early hook" that runs before the bulk replace routine |
| 2660 | attempts to reconcile which objects are already present in the |
| 2661 | collection and which are being removed by the net replace operation. |
| 2662 | |
| 2663 | It is typical that this method be combined with use of the |
| 2664 | :meth:`.AttributeEvents.append` event. When using both of these |
| 2665 | events, note that a bulk replace operation will invoke |
| 2666 | the :meth:`.AttributeEvents.append` event for all new items, |
| 2667 | even after :meth:`.AttributeEvents.bulk_replace` has been invoked |
| 2668 | for the collection as a whole. In order to determine if an |
| 2669 | :meth:`.AttributeEvents.append` event is part of a bulk replace, |
| 2670 | use the symbol :attr:`~.attributes.OP_BULK_REPLACE` to test the |
| 2671 | incoming initiator:: |
| 2672 | |
| 2673 | from sqlalchemy.orm.attributes import OP_BULK_REPLACE |
| 2674 | |
| 2675 | |
| 2676 | @event.listens_for(SomeObject.collection, "bulk_replace") |
| 2677 | def process_collection(target, values, initiator): |
| 2678 | values[:] = [_make_value(value) for value in values] |
| 2679 | |
| 2680 | |
| 2681 | @event.listens_for(SomeObject.collection, "append", retval=True) |
| 2682 | def process_collection(target, value, initiator): |
| 2683 | # make sure bulk_replace didn't already do it |
| 2684 | if initiator is None or initiator.op is not OP_BULK_REPLACE: |
| 2685 | return _make_value(value) |
| 2686 | else: |
| 2687 | return value |
| 2688 | |
| 2689 | :param target: the object instance receiving the event. |
| 2690 | If the listener is registered with ``raw=True``, this will |
| 2691 | be the :class:`.InstanceState` object. |
| 2692 | :param value: a sequence (e.g. a list) of the values being set. The |
| 2693 | handler can modify this list in place. |
| 2694 | :param initiator: An instance of :class:`.attributes.Event` |
| 2695 | representing the initiation of the event. |
| 2696 | :param keys: When the event is established using the |
| 2697 | :paramref:`.AttributeEvents.include_key` parameter set to |
| 2698 | True, this will be the sequence of keys used in the operation, |
| 2699 | typically only for a dictionary update. The parameter is not passed |
| 2700 | to the event at all if the the |
| 2701 | :paramref:`.AttributeEvents.include_key` |
| 2702 | was not used to set up the event; this is to allow backwards |
| 2703 | compatibility with existing event handlers that don't include the |