6. Interview Questions- Events and Internals
Source: https://docs.sqlalchemy.org/en/20/orm/extending.html
1. What is the purpose of extending the SQLAlchemy ORM?
Answer: To customize behavior such as object instantiation, attribute access, change tracking, or mapping configuration beyond default behavior.
2. What are ORM events in SQLAlchemy?
Answer: Hooks that let you intercept and respond to changes in ORM objects or sessions—e.g., object load, insert, update, delete, etc.
3. How do you register an event for when a class is loaded from the database?
Answer:
from sqlalchemy import event
@event.listens_for(MyClass, "load")
def receive_load(instance, context):
print(f"{instance} was loaded")4. What does the @event.listens_for(..., 'init') decorator do?
@event.listens_for(..., 'init') decorator do?Answer: It intercepts when a new instance of a class is created (before it's added to a session or persisted).
5. What’s the difference between load and refresh events?
load and refresh events?Answer:
load: Triggered when the object is loaded from the DB the first time.refresh: Triggered when an existing instance is reloaded from the DB (e.g., viarefresh()).
6. How can you track changes to a particular attribute?
Answer:
7. What event is used to intercept before insert or update in ORM?
Answer:
8. Can you intercept attribute-level access (e.g., __get__, __set__) using ORM tools?
__get__, __set__) using ORM tools?Answer:
Yes, using attribute instrumentation events like "set" and "init_scalar".
9. What does the "append" event on a relationship do?
"append" event on a relationship do?Answer: It triggers when a new item is added to a collection-based relationship.
10. How can you perform actions when an object is added to a relationship?
Answer:
11. What is the use of __init__() vs. @event.listens_for(..., 'init')?
__init__() vs. @event.listens_for(..., 'init')?Answer:
__init__() is Python-native object creation. The init event allows SQLAlchemy to instrument or wrap creation dynamically.
12. How do you extend a mapped class with mixins in SQLAlchemy?
Answer:
Define shared logic (columns, methods, relationships) in a base class without __tablename__, and inherit it in ORM classes.
13. What is the difference between a mixin and an abstract base in SQLAlchemy ORM?
Answer:
Mixin: Reusable logic; not mapped by itself.
Abstract base: May be mapped, but marked with
__abstract__ = True.
14. Can attribute-level events be registered after class definition?
Answer:
Yes, via the event.listen() API or using @event.listens_for() decorator.
15. How do you track when a relationship collection is cleared?
Answer:
16. How do you prevent a certain value from being assigned to a field?
Answer:
Use the "set" attribute event and raise an exception based on the value.
17. What is a class manager in SQLAlchemy ORM internals?
Answer: It’s an internal object that manages instrumentation, lifecycle events, and tracking for ORM-mapped classes.
18. How does SQLAlchemy know which attributes are mapped and instrumented?
Answer:
Through the class’s mapper and the instrumentation system via DeclarativeBase or registry().
19. Can you define global listeners that affect all ORM classes?
Answer:
Yes, by targeting the base Mapper or InstanceEvents on all mapped classes.
20. What’s the difference between instance-level and class-level event listeners?
Answer:
Instance-level: React to changes on specific instances (e.g., attribute set).
Class-level: Affect all instances of the class during lifecycle phases like insert, load, etc.
21. How do you intercept an object being marked as deleted?
Answer:
22. What event can you use to automatically populate a timestamp on insert?
Answer:
23. How do you instrument a class without using declarative?
Answer:
You can use registry().map_imperatively() and still attach class- or attribute-level listeners.
24. What’s the use of @event.listens_for(Mapper, 'after_configured')?
@event.listens_for(Mapper, 'after_configured')?Answer: It lets you execute logic after all ORM mappings have been configured (e.g., apply validations or constraints globally).
25. What does the "append" event emit in terms of arguments?
"append" event emit in terms of arguments?Answer:
It passes the target (the parent), value (the new child), and initiator (instrumentation metadata).
26. Can you listen to events on unmapped classes?
Answer: No, ORM-specific events only apply to mapped classes or instrumented attributes.
27. What’s the difference between "set" and "modified" events on an attribute?
"set" and "modified" events on an attribute?Answer:
"set": Triggers when a value is assigned."modified": Triggers when a value changes meaningfully (often used for dirty tracking).
28. How do you dynamically add a listener at runtime?
Answer:
29. What is the init_scalar event used for?
init_scalar event used for?Answer:
It fires when a new instance is constructed and scalar attributes are initialized (typically None or default values).
30. How can you track whether a particular column was changed during a session?
Answer:
Use attribute-level "set" event or use sqlalchemy.inspect(obj).attrs.column_name.history.
31. How do you mark a mixin as declarative-safe?
Answer:
Use the @declarative_mixin decorator:
32. What does @declarative_mixin offer over a plain class?
@declarative_mixin offer over a plain class?Answer: It signals SQLAlchemy that the class is intended as a mixin for mapping and avoids accidental mapping of the mixin itself.
33. Can @event.listens_for be used on hybrid properties?
@event.listens_for be used on hybrid properties?Answer: Yes, but it should be attached to the underlying attribute, not the property method.
34. How do you register an event on all mappers globally?
Answer:
35. What is the initiator argument in attribute events?
Answer: It carries metadata about the operation, including the key name, parent object, and whether the event is user-triggered.
36. Can listeners be removed once added?
Answer:
Yes, using event.remove() with the same signature used to register.
37. What’s the purpose of dispatch on ORM classes or attributes?
dispatch on ORM classes or attributes?Answer: It exposes the event registry for that target, allowing inspection or programmatic listener attachment.
38. How can you use ORM events to implement soft deletes?
Answer:
Intercept the before_delete event, cancel the actual delete, and instead set a deleted flag:
39. How can you override attribute access behavior in an ORM-mapped class?
Answer:
Use descriptors or attribute-level instrumentation with events like "set" and "get".
40. What is the role of the MapperEvents class in SQLAlchemy?
MapperEvents class in SQLAlchemy?Answer:
It defines the set of ORM-level event names like before_insert, after_update, before_flush, etc., for mapped classes.
41. What is the purpose of __declare_last__() in a mapped class?
__declare_last__() in a mapped class?Answer: It is a class method that SQLAlchemy calls after all mappings are configured. It’s often used to register class-specific events or constraints.
42. Can you override default behavior of an attribute (e.g., validation) using events?
Answer:
Yes. Use the "set" event to intercept assignment and apply validation logic.
43. What’s the role of MapperExtension in SQLAlchemy?
MapperExtension in SQLAlchemy?Answer:
MapperExtension was a legacy system used to hook into ORM behavior. It is now replaced by the modern event system (e.g., before_insert, after_update).
44. Can @event.listens_for be applied to both attributes and relationships?
@event.listens_for be applied to both attributes and relationships?Answer:
Yes. It can listen to scalar fields ("set", "modified") and collection-based relationships ("append", "remove", "bulk_replace").
45. What event should you use to modify values coming from the database during object load?
Answer:
The "load" event on the mapped class:
46. How do you make a declarative mixin class that contributes indexes or constraints?
Answer:
Use __table_args__ in the mixin:
47. How can you use events to inject behavior across multiple ORM classes?
Answer:
Attach listeners to the base Mapper class or apply the same mixin with __declare_last__() in child classes.
48. What’s the purpose of the bulk_replace event on relationships?
bulk_replace event on relationships?Answer: It fires when a full list of items is replaced on a collection-based relationship, allowing inspection or intervention.
49. Can you attach listeners to hybrid or computed properties?
Answer:
Direct event listening is not available on @hybrid_property, but you can hook into the underlying columns or override the property logic.
50. How does SQLAlchemy handle multiple mixins with overlapping attributes?
Answer: The last mixin in the MRO (method resolution order) overrides earlier ones. Conflicts should be resolved manually to avoid ambiguous behavior.
Last updated