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

Many to many fields #120

Closed
danialb007 opened this issue Nov 20, 2022 · 2 comments
Closed

Many to many fields #120

danialb007 opened this issue Nov 20, 2022 · 2 comments

Comments

@danialb007
Copy link

Greetings.
I've been working on a project and i wanted to fire a hook after an object is created and immediately use its m2m field's value and process some stuff.
AFTER_CREATE and AFTER_SAVE hooks are not working as expected in this case. (even with on_commit=True)
so if field (X) is a ManyToManyField you would write code like this:

@hook(AFTER_CREATE)
    def my_hook(self):
        print(self.X.all())

and this results in an empty queryset.

Django has a built-in signal called m2m_changed and it works as i expected but the syntax is messy and thats the main reason i preferred this package.

@EnriqueSoria
Copy link
Collaborator

tl;dr

AFAIK this is not possible with django-lifecycle, for this use case stick to the signal or create a function that handle the whole behaviour (creating object, adding m2m and doing the "after create" thing.

Explanation

A m2m relation what it does is creating another table that contains a foreing key to both tables:

class Person(models.Model):
    ...

class Group(models.Model):
    members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)

(If you don't specify this through model explicitly, it's created automatically)
So... in order to add a Membership you need before to have a Person and a Group saved (because you need their ids)

So, if we add a hook to either side of the M2M, it will be called before the through instance are created:

class Person(LifecycleModel):
    
    @hook(AFTER_CREATE)
    def my_hook(self):
        print(self.X.all())

class Group(models.Model):
    members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)

When you add or remove items for a M2M relationship, the save method is not called, but signals do.

@danialb007
Copy link
Author

Thanks.
Actually makes sense and i kind of knew that, just thought it's somehow possible and i didn't know.
Closing this issue.

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

2 participants