Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#27340 closed New feature (needsinfo)

Model pre_init signal should provide an `instance` argument

Reported by: Ask Solem Hoel Owned by: nobody
Component: Database layer (models, ORM) Version: 1.10
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I struggle to find reasons as to why this argument is ommitted.

The current signature for pre_init is:

class Model(six.with_metaclass(ModelBase)):
    _deferred = False

    def __init__(self, *args, **kwargs):
        signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs)

I suggest that the signature should be:

class Model(six.with_metaclass(ModelBase)):
    _deferred = False

    def __init__(self, *args, **kwargs):
        signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs, instance=self)

Or alternatively, that the post_init signal contains the args and kwargs used to construct the model.

The reason for wanting access to the instance in pre_init is that I want to track changes
to the model since it was first retrieved from the database - This is currently not possible without subclassing Model,
and that is not a realistic option for us as we deal with third party models.

The current way we handle this is by using pre_save to fetch the row from the database again, but this is suboptimal
and this a simple change would allow us to do this.

Change History (4)

comment:1 by Ask Solem Hoel, 8 years ago

Component: UncategorizedDatabase layer (models, ORM)
Type: UncategorizedNew feature

comment:2 by Tim Graham, 8 years ago

Could you provide an example of your existing code and what it would look like after this change? I'll check that I don't see another way to accomplish your use case.

comment:3 by Tim Graham, 8 years ago

Resolution: needsinfo
Status: newclosed

comment:4 by Ask Solem Hoel, 8 years ago

lol, you want an example. Brace yourself, will probably be more difficult to understand, but here:

https://github.com/robinhood/thorn/blob/master/thorn/django/signals.py#L39-L44

we use the pre)save signal to store a snapshot of how the model looked like before it was changed

With the proposed change we'd be able to avoid doing two database queries for every Model.save by doing this:

@signals.pre_init.connect
def _track_changes(instance, args, kwargs, **kwargs):
    instance._original_args = args, kwargs

There's no other way as far as I can find, as we don't want to monkeypatch Model, and in any case it's very strange that the pre_init signal omits the instance being created.

Last edited 8 years ago by Ask Solem Hoel (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top