如何查询SoftDeletableModel含软删除对象?替代自制方案遇阻
all_with_deleted to django-model-utils SoftDeletableModel Alright, let's break down how to solve this. You're right that the default SoftDeletableManagerMixin in django-model-utils only filters out soft-deleted objects in its get_queryset method—there's no built-in all_with_deleted functionality. But since you need access to those deleted records for cross-node notifications in your decentralized architecture, here are a couple of clean, maintainable solutions:
1. Custom Manager with all_with_deleted and deleted Methods
The simplest approach is to extend the existing SoftDeletableManagerMixin to add the methods you need. This preserves the default behavior of hiding soft-deleted objects while giving you explicit access when you need it.
from django.db import models from model_utils.managers import SoftDeletableManagerMixin, SoftDeletableManager class CustomSoftDeletableManager(SoftDeletableManagerMixin, models.Manager): def all_with_deleted(self): # Bypass the soft-delete filter by calling the parent of SoftDeletableManagerMixin return super(SoftDeletableManagerMixin, self).get_queryset() def deleted(self): # Optional: Convenience method to fetch only soft-deleted objects return self.all_with_deleted().filter(is_removed=True) # Use this manager in your model from model_utils.models import SoftDeletableModel class YourDecentralizedModel(SoftDeletableModel): # Your model fields go here (e.g., name, created_at, etc.) name = models.CharField(max_length=100) # Replace the default manager with your custom one objects = CustomSoftDeletableManager()
How to Use It:
- For normal operations (where you don't want soft-deleted objects), use
YourDecentralizedModel.objects.all()as usual—it will still exclude deleted records. - When you need to process soft-deleted objects for cross-node notifications, call
YourDecentralizedModel.objects.deleted()to get only the deleted entries, orall_with_deleted()to get every record (deleted and active).
2. Abstract Base Class for Reusability
If you have multiple models that need this functionality, create an abstract base model so you don't repeat code across your project:
class BaseSoftDeletableModel(SoftDeletableModel): objects = CustomSoftDeletableManager() class Meta: abstract = True # Now inherit from this base model for all your decentralized models class UserData(BaseSoftDeletableModel): # Your fields email = models.EmailField(unique=True) class DeviceRecord(BaseSoftDeletableModel): # Your fields device_id = models.CharField(max_length=50)
Key Notes for Your Decentralized Setup
- Avoid Overusing
all_with_deleted: Keep the default manager's behavior intact for most business logic to prevent accidental exposure of deleted data. Only usedeleted()orall_with_deleted()specifically in your cross-node notification workflows. - Track Processed Deletions: Consider adding a
notification_sentboolean field to your models (or a separate audit log) to mark when you've already sent a deletion notification to other nodes. This prevents duplicate notifications. - Test Edge Cases: Make sure to write tests that verify:
- Normal queries exclude soft-deleted objects
all_with_deleted()returns all recordsdeleted()returns only soft-deleted records
内容的提问来源于stack exchange,提问作者Csaba Toth

