#29557: add on_commit decorator -------------------------------------+------------------------------------- Reporter: obayemi | Owner: nobody Type: New feature | Status: new Component: Database layer | Version: master (models, ORM) | Severity: Normal | Resolution: Keywords: transaction | Triage Stage: on_commit decorator | Unreviewed Has patch: 1 | Needs documentation: 1 Needs tests: 1 | Patch needs improvement: 0 Easy pickings: 1 | UI/UX: 0 -------------------------------------+-------------------------------------
Comment (by obayemi): Replying to [comment:4 Carlton Gibson]: > I think you need to explain the usage more fully here. > > I'm expecting this sort of thing: > > {{{ > def send_mail() > ... > > with transaction.atomic(): > Thing.objects.create(...) > transaction.on_commit(send_mail) > }}} > > You need to explain how the decorator would work. > > From the docs: > > > If you call on_commit() while there isn’t an active transaction, the callback will be executed immediately. > > So you can't just decorate `send_mail()` at the point of declaration here. So what would your code look like? The decorator don't run the function at the declaration, it only makes every usage run at transaction commit, and it would be completely transparent for the user as even if no transaction is active it would onlybe run synchronously as you stated from the doc Manually calling on_commit(function) can work, but it adds some boilerplate if your function should always be run at the end of transaction, and it is easy to forget The decorator would be usefull in two cases 1) when you have to automatically add every invocation of the function to the commit hook instead of running it instantly 2) when your function is ran by django e.g. post_save on creation when you did not finshed filling all the items in a m2m field for example, one my actual use case is that I have callbacks that get called in post_save in a complex objects that needs a lot of data in related objects that with foreignkeys to the objects that was created like if you wanted to send a message at every user in a group at creation with a post_save signal {{{ with transaction.atomic(): group = Group.objects.create() group.users.add(Users.objects.all() }}} You would have to do {{{ @receiver(post_save, sender=Group) def notify_users(sender, instance, created, *args, **kwargs): def _notify_users(): # defining inner function to remove the need to pass parameters from context since they can't be used in on_commit hook if created: for user in group.users.all(): user.notify_group_creation(group) # without on_commit, there wouldn't be any users in the group yet on_commit(_notify_users) }}} where the goal of my decorator is to remove the need to declare an inner function and call it in the on_commit hook explicitely which is useless boilerplate and indent the whole function one step more if the whole function should be ran after the commit using this decorator would allow only writing the receiver as {{{ @receiver(post_save, sender=Group) @call_on_commit def notify_users(sender, instance, created, *args, **kwargs): if created: for user in group.users.all(): user.notify_group_creation(group) }}} -- Ticket URL: <https://code.djangoproject.com/ticket/29557#comment:5> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/065.ed458d60f94d393305b5e2f0fa6ae46b%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.