Skip to content

Hooks not effecting rows when called using create_or_update in django 4.2 #136

@TonisPiip

Description

@TonisPiip
from dataclasses import dataclass
from typing import List, Optional

from django_lifecycle import BEFORE_CREATE, BEFORE_SAVE, BEFORE_UPDATE, LifecycleModel
from django_lifecycle.decorators import HookConfig


@dataclass(order=False)
class UpdateFieldsHookConfig(HookConfig):
    # Is only required for a single hook,
    update_fields: Optional[List[str]] = None


update_fields_hook = UpdateFieldsHookConfig


class UpdateFieldsLifecycleModel(LifecycleModel):
    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        skip_hooks = kwargs.pop("skip_hooks", False)
        save = super().save

        if skip_hooks:
            save(*args, **kwargs)
            return

        # unsure about next line, if running twice is OK, but ought to be...
        self._clear_watched_fk_model_cache()
        is_new = self._state.adding

        if "update_fields" in kwargs:

            if is_new:
                methods = self._get_hooked_methods(BEFORE_CREATE, **kwargs)
            else:
                methods = self._get_hooked_methods(BEFORE_UPDATE, **kwargs)

            methods += self._get_hooked_methods(BEFORE_SAVE, **kwargs)
            fields = set()
            for hooked_method in methods:
                for hook in hooked_method.method._hooked:
                    if hook.update_fields:
                        fields = fields.union(set(hook.update_fields))
            kwargs["update_fields"] = list(set(kwargs["update_fields"]).union(fields))

        save(*args, **kwargs)

usage: same as before but you gotta swtich to our mixin and hook decorator, just add update_fields to the hook params
@update_fields_hook(BEFORE_CREATE, update_fields=["anchor_status"])


My basic fix for it. caused by this change in django https://docs.djangoproject.com/en/4.2/releases/4.2/#setting-update-fields-in-model-save-may-now-be-required which makes it so only fields which are being passed into the update kwags, so if you're updating a field based on an updated field the code will run, but not change in the db. This code above works, but maybe there's better solutions, if I'm able to get a PR approved.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingquestionFurther information is requested

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions