Skip to content

skip_hooks context manager #135

@TonisPiip

Description

@TonisPiip

Due to the current way skip_hooks works, you need to pass it into save(), you can not suppress hooks in the case of using model.objects.get_or_create. You can't just pass in skip_hooks to that method as it's used when initing the new model, and in inital get request.

For create() it would be possible to eaisly fix by popping out skip_hooks from init's kwags

    def create(self, **kwargs):
        """
        Create a new object with the given kwargs, saving it to the database
        and returning the created object.
        """
        obj = self.model(**kwargs)
        self._for_write = True
        obj.save(force_insert=True, using=self.db)
        return obj
class LifecycleModelMixin(object):
    def __init__(self, *args, **kwargs):
        self._skip_hooks = kwargs.pop("skip_hooks", None) #newline
        super().__init__(*args, **kwargs)
        self._initial_state = self._snapshot_state()

and then in save also check the non_null sate of self._get_hooks

    @transaction.atomic
    def save(self, *args, **kwargs):
        skip_hooks = kwargs.pop("skip_hooks", False) or self._skip_hooks

But that doesn't fix that skip_hooks=True will be passed to the queryset filter.
So in that case, the only solution would be some global var/instance which is set using enter and exit

class SkipHooks() :
    skip_hooks = False
    def __enter__(self):
         self.skip_hooks = True
    def __exit__(self):
         self.skip_hooks = False

skip_hooks = SkipHooks()

with skip_hooks:
    foo.save()
    @transaction.atomic
    def save(self, *args, **kwargs):
        skip_hooks = kwargs.pop("skip_hooks", False) or self._skip_hooks or skip_hooks.skip_hooks

Does anyone have any comments on this?

And if I were to make the proposed changes, would they PR be accepted?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions