Deleted instances still appear in formfields (Heisenbug?)
See original GitHub issueI have a model for which I override Django Admin’s formfield_for_foreignkey()
like so:
class MyCustomAdmin(CustomSafeDeleteAdmin):
def get_queryset(self, request):
qs = super(MyCustomAdmin, self).get_queryset(request)
return qs.filter(user=request.user)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
user= request.user
if db_field.name == 'foo':
kwargs['queryset'] = Foo.objects.filter(user=user)
return super(MyCustomAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
The Foo
model inherits from SafeDeleteModel
, so its default objects manager should be handled by the default SafeDeleteManager.
Problem is I am still seeing deleted Foo
instances in formfield ForeignKey dropdowns, but not if I debug Foo.objects.filter(user=user)
or Foo.objects.all()
, and then if I step through, they don’t appear in the dropdown, hence Heisenbug 😦
Is this releated to the note here on ForeignKey visibility?
Django will stop me from saving the model with a deleted FK, it will give the error Select a valid choice. That choice is not one of the available choices
ATM the only way I can reliably ensure deleted instances don’t appear is to append .exclude(deleted__isnull=False)
to all querysets, but this is not desirable, the default manager should ensure they don’t exist?
Using safedelete 0.4.1 with queryset.py from PR #77, Django 1.11.1 and Python 3.6.1 (Note issue happens with or without PR 77 patch)
For extra ref I am overiding some django admin functions so I can split safedelete access in admin between su/staff and ‘lite’ admin users
from safedelete.admin import SafeDeleteAdmin, highlight_deleted
class CustomSafeDeleteAdmin(SafeDeleteAdmin):
"""
Overriding this convenience class from django-safedelete, as we want:
- Delete to work 'as in' for non su-staff i.e. User has no idea deleted model instances still exist
- Allow su/staff to see all instances, deleted or not, and recover them if needs be
Notes:
- If su/staff try deleting an already deleted instance, this is a noop
"""
# override django-safedelete method so deleted instances are hidden from non su/staff
def get_queryset(self, request):
qs = super(CustomSafeDeleteAdmin, self).get_queryset(request)
if request.user.profile.user_can_undelete():
return qs
else:
# assuming the model in question inherits SafeDeleteModel, this will exclude deleted model instances (the default)
return self.model._default_manager.all()
def get_list_display(self, request):
list_display = super(CustomSafeDeleteAdmin, self).get_list_display(request)
if request.user.profile.user_can_undelete():
# highlight_deleted overrides the default instance 'Name'
list_display = list(list_display)
if 'name' in list_display:
list_display.remove('name')
if 'Name' in list_display:
list_display.remove('Name')
return [highlight_deleted] + list_display
else:
return list_display
# hide undelete action from admin changelist page actions if user not su/staff
def get_actions(self, request):
actions = super(CustomSafeDeleteAdmin, self).get_actions(request)
if not request.user.profile.user_can_undelete():
if 'undelete_selected' in actions:
del actions['undelete_selected']
return actions
# hide deleted list_filter from admin changelist page if user not su/staff
def get_list_filter(self, request):
list_filter = super(CustomSafeDeleteAdmin, self).get_list_filter(request)
if request.user.profile.user_can_undelete():
if isinstance(list_filter, list):
list_filter = tuple(list_filter)
return SafeDeleteAdmin.list_filter + list_filter
else:
return list_filter
Issue Analytics
- State:
- Created 6 years ago
- Comments:5 (5 by maintainers)
Top GitHub Comments
Fixed, thanks for the report 👍 .
Ok I found it, we need to add
iterator
to the evaluation_methods.