django-safedelete
django-safedelete copied to clipboard
Declaring a manager with a custom queryset does not work.
When following the SafeDelete documentation, it seems declaring a manager with a custom queryset should be done like this:
objects = SafeDeleteManager(MyCustomQuerySet)
Following this:
- The manager works as expected
- But the methods of my custom queryset are not visible! I got errors like:
AttributeError: 'SafeDeleteManager' object has no attribute 'my_custom_method_from_my_custom_queryset'
when I try to access it.
I found a workaround using from_queryset
method with safedelete?
objects = SafeDeleteManager.from_queryset(MyCustomQuerySet)()
This way, everything seems to work, but I'm worry I'm missing something. Could you please tell me if I did something wrong with the official method? Otherwise, the documentation should be updated.
Note : I'm using Django 1.11 Thanks a lot for this very useful lib by the way.
I think your solution should be the correct one. I see that we overwrite _queryset_class
in our __init__
method, but it is always better to keep the same api as Django.
I don't remember why it was done that way, we should try to remove the __init__
method and change the documentation accordingly if this works as intended.
Thanks for the report :+1: .
I don't think objects = SafeDeleteManager.from_queryset(MyCustomQuerySet)()
is a workaround as much as it is recommended way of using custom Managers and QuerySets, it's documented at https://docs.djangoproject.com/en/1.10/ref/models/querysets/#django.db.models.query.QuerySet.as_manager.
For advanced usage you might want both a custom Manager and a custom QuerySet. You can do that by calling Manager.from_queryset() which returns a subclass of your base Manager with a copy of the custom QuerySet methods
class BaseManager(models.Manager):
def manager_only_method(self):
return
class CustomQuerySet(models.QuerySet):
def manager_and_queryset_method(self):
return
class MyModel(models.Model):
objects = BaseManager.from_queryset(CustomQuerySet)()
CustomManager = BaseManager.from_queryset(CustomQuerySet)
class MyModel(models.Model):
objects = CustomManager()
I am getting the error while extending SafeDeleteQueryset
.
I have a queryset like
class MyQuerySet(SafeDeleteQueryset):
def active(self):
return self.filter(is_active=True)
and the manager be like
class MyManager(SafeDeleteManager):
def get_queryset(self):
return MyQuerySet(self.model, using=self._db)
def active(self):
return self.get_queryset().active()
and using the custom manager in model like
class MyModel(SafeDeleteModel):
objects = MyManager()
This is giving error
'MyQuerySet' object has no attribute '_safedelete_visibility'
Updated the manager with _safedelete_visibility = DELETED_INVISIBLE
but deleted objects are still showing in the filter queryset.
You are overriding the get_safedelete
method which set the _safedelete_visibility
attribute. See https://github.com/makinacorpus/django-safedelete/blob/master/safedelete/managers.py#L57-L62.
Set _queryset_class
on your manager to MyQuerySet
and remove your get_queryset
method.
You are overriding the get_queryset
method of the manager that is where _safedelete_visibility is set.
As. @Gagaro points you have two solitions:
class MyQuerySet(SafeDeleteQueryset):
def active(self):
return self.filter(is_active=True)
class MyManager(SafeDeleteManager):
_queryset_class = MyQuerySet
def active(self):
return self.get_queryset().active()
class MyModel(SafeDeleteModel):
objects = MyManager()
class MyQuerySet(SafeDeleteQueryset):
def active(self):
return self.filter(is_active=True)
class MyManager(SafeDeleteManager):
def active(self):
return self.get_queryset().active()
class MyModel(SafeDeleteModel):
objects = MyManager(MyQuerySet)
Both worked for me
class MyModel(SafeDeleteModel):
objects = SafeDeleteManager.from_queryset(MyQuerySet)(queryset_class=MyQuerySet)
Works pretty well too.