Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model inheritance: CRUDEvent object_json_repr doesn't include parent model fields #255

Open
marko90b opened this issue Jun 27, 2023 · 1 comment

Comments

@marko90b
Copy link

This is due to django's Serializer includes only local fields: Django #7350

It could be handled in one of these ways:

@marko90b
Copy link
Author

Solved with an ugly callback:
(not tested on instances with multiple inheritance, but it should work)

from django.db.models import signals

def create_crud_for_parent_class(
    instance, object_json_repr, created, raw, using, update_fields, **kwargs
):
    #* Callback must return True, otherwise CRUDEvent for instance is not logged
    # If not child class instance, exit
    if not type(instance)._meta.parents:
        return True
    # Determine if this is post_save or pre_save signal
    signal_type = 'post_save' if 'created' in kwargs['signal'].providing_args else 'pre_save'
    # On pre_save, not created CRUDevents are logged -> exit if opposite
    if signal_type == 'pre_save' and created:
        return True
    # On post_save, created CRUDevents are logged -> exit if opposite
    if signal_type == 'post_save' and not created:
        return True
    
    # If CRUDEvent should be logged, loop through instance's parents (if it has them)
    for parent_model, parent_field in type(instance)._meta.parents.items():
        # get parent instance
        parent_instance = getattr(instance, parent_field.name, None)
        if parent_instance:
            # if parent instance exists, send appropriate signal
            # NOTE: pre_save doesn't accept 'created' arg, post_save does
            signal = getattr(signals, signal_type)
            kwargs = {'raw': raw, 'using': using, 'update_fields': update_fields}
            if signal_type == 'post_save':
                kwargs['created'] = created
            signal.send(parent_instance.__class__, instance=parent_instance, **kwargs)
    return True

BTW: Does anyone know if there is a leaner approach how to determine if callback was called from pre_save or post_save signal?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant