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

Custom manager that excludes soft deleted records by default #2650

Open
kelvin-muchiri opened this issue Jul 24, 2024 · 1 comment · May be fixed by #2725
Open

Custom manager that excludes soft deleted records by default #2650

kelvin-muchiri opened this issue Jul 24, 2024 · 1 comment · May be fixed by #2725

Comments

@kelvin-muchiri
Copy link
Contributor

kelvin-muchiri commented Jul 24, 2024

Suggested Feature / Enhancement

When making queries, soft deleted items are included in the queryset unless explicitly filtered out e.g deleted_at__isnull=True. It is easy to forget to exclude soft deleted records. The side effect is accidental exposure of deleted records when returning API responses.

We should use a custom manager that excludes soft deleted items by default, but also provides an API for getting all records including soft deleted items.

Benefits of implementing the feature/enhancement

Prevents accidental exposure of soft deleted items.

Suggested implementation plan(Steps to be taken to implement feature)

  1. Create a custom queryset with methods to exclude soft-deleted records and to include all records.
class SoftDeleteQuerySet(models.QuerySet):
    def active(self):
        return self.filter(deleted_at__isnull=True)

    def all_with_deleted(self):
        return self
  1. Create a custom manager that makes use of the custom queryset
class SoftDeleteManager(models.Manager):
    def get_queryset(self):
        return SoftDeleteQuerySet(self.model, using=self._db).active()

    def all_with_deleted(self):
        return self.get_queryset().all_with_deleted()
  1. Update models to use the custom manager
class MyModel(models.Model):
    ...
    deleted_at = models.DateTimeField(null=True, blank=True)
    ...

    objects = SoftDeleteManager()

  1. To get active records
active_records = MyModel.objects.all()
  1. To get all records including soft deleted items
all_records = MyModel.objects.all_with_deleted()
@ukanga
Copy link
Member

ukanga commented Jul 26, 2024

Should this be added to our BaseModel? Which adds the other required fields.

@kelvin-muchiri kelvin-muchiri linked a pull request Oct 22, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants