-
-
Notifications
You must be signed in to change notification settings - Fork 259
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
Fix flush with reverse m2m changed signal #386
Fix flush with reverse m2m changed signal #386
Conversation
waffle/signals.py
Outdated
try: | ||
instance.flush() | ||
except AttributeError: | ||
for flag in get_waffle_flag_model().objects.filter(pk__in=kwargs['pk_set']): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why this is necessary, please? Is there anyway to do this without a database call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Clinton, first of all thx for the review on this patch.
The problem here is m2m_changed
handling from Django.
If i execute the following code
from my_app.models import MyUserModel
from waffle.models import Flag
flag = Flag.objects.first()
user = MyUserModel.objects.first()
flag.users.add(user) # all fine, cache is flushed without errors
user.flag_set.add(flag) # crash
the last line will crash because the instance
received by flag_membership_changed
is a MyUserModel
instance instead of a Flag
instance.
The only solution that i can see when instance
is of type user/group is to retrieve all the flag involved and flush them like i do here
The reason why i query the db is that is not possible to guarantee that the flag involved are still accessible from instance
when flag_membership_changed
is executed.
Let me know if you want some of this explanation in the code.
I have added 2 tests to ensure that the m2m_changed
signal is tested when the change are performed from the User/Group
instance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed the code to use reverse
instead of try/except
to be more explicit of what is happening here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation. Would you mind adding a comment with a version of this explanation, too?
Also, instead of checking for a kwarg
, what if you checked: if isinstance(instance, get_waffle_flag_model())
? That seems a bit safer than relying on the kwarg
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have applied the required changes.
0fcf22c
to
917f573
Compare
waffle/signals.py
Outdated
try: | ||
instance.flush() | ||
except AttributeError: | ||
for flag in get_waffle_flag_model().objects.filter(pk__in=kwargs['pk_set']): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation. Would you mind adding a comment with a version of this explanation, too?
Also, instead of checking for a kwarg
, what if you checked: if isinstance(instance, get_waffle_flag_model())
? That seems a bit safer than relying on the kwarg
.
598992a
to
da67d2e
Compare
Thx @clintonb for the merge. What are the policy for this repository to have a new release? Unfortunately this bug impact my production code and i would avoid if possible to install django-waffle from github. |
@k4rl85 new release is out. |
Fix issue #377