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

[Feature] Pass origin object to signals #876

Open
2 tasks done
dacotagh opened this issue Apr 3, 2024 · 2 comments
Open
2 tasks done

[Feature] Pass origin object to signals #876

dacotagh opened this issue Apr 3, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@dacotagh
Copy link

dacotagh commented Apr 3, 2024

Is this feature missing in the latest version?

  • I'm using the latest release

Is your feature request related to a problem? Please describe.

Some copied objects have links to data out of the data base, linked by id or uuid.
When object cloned, it has new id/uuid.
To copy external data user need access to origin id/uuid of object.

Describe the solution you'd like?

I suppose to add origin parameter to pre_clone_save/post_clone_save signals.

To do this, in function make_clone in mixin.py we need to make these changes:

    -pre_clone_save.send(sender=self.__class__, instance=duplicate)
    +pre_clone_save.send(sender=self.__class__, instance=duplicate, origin=self)

...

    -post_clone_save.send(sender=self.__class__, instance=duplicate)
    +post_clone_save.send(sender=self.__class__, instance=duplicate, origin=self)

Describe alternatives you've considered?

No response

Anything else?

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct
@dacotagh dacotagh added the enhancement New feature or request label Apr 3, 2024
Copy link
Contributor

github-actions bot commented Apr 3, 2024

Thanks for reporting this issue, don't forget to star this project if you haven't already to help us reach a wider audience.

@mfoulds
Copy link

mfoulds commented Sep 3, 2024

I found that I also need origin. I also need to know whether the new clone instance is a result of cloning the origin object directly, or if it resulted from cloning a o2o, o2m, m2o or m2m relationship by origin's parent (a kind of "cascade clone"). I couldn't see an obvious way to achieve this (except by inspecting the stack (eg inspect.stack()[1][3]).

My approach (see mixin.py in the _pass_kwargs_from_make_clone branch of my fork) is:

  1. Include **kwargs in method signature of make_clone()
  2. From each of the __duplicate_* methods that calls make_clone:
    1. Add the name of the parent_instance (ie self) and the name of the method as calling_function to kwargs
    2. Make sure to pass **kwargs to each call to make_clone
  3. In make_clone add kwargs['origin'] = self (to achieve @dacotagh 's objective)
  4. Pass the kwargs to the pre_clone_* signals (eg pre_clone_save.send(sender=self.__class__, instance=duplicate, **kwargs)

The project that's using this fork of django-clone sets instance._state variables in the pre_clone_save signal (and unsets them in the post_clone_save signal), like this:

@receiver(pre_clone_save)
def set_new_clone_state_true(sender, instance, **kwargs):
    instance._state.new_clone = True
    instance._state.origin = kwargs.get("origin")
    instance._state.calling_function = kwargs.get("calling_function", None)
    instance._state.parent_instance = kwargs.get("parent_instance", None)
    instance._state.cascade_clone = (
        instance._state.parent_instance is not None and instance._state.calling_function is not None
    )

These can then be picked up in the relevant save() methods of the models that need them.

Another possible benefit of having **kwargs in the make_clone method signature and also passing them to the ???_clone_save methods is that users of the library could then possibly override make_clone and add additional kwargs before calling super().make_clone which would then propagate through signals.

I don't know if any of this is generally needed by anyone else, but it seemed pretty close to @dacotagh 's requirement here. I thought maybe using **kwargs would meet the immediate objective and also provide room for future needs.

PS Thanks @jackton1 very much for this terrific library!

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

No branches or pull requests

2 participants