You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When we override the get_queryset method it works for base models but not for related models is_deleated filter is not applied. here is the initial proposal for it [its not optimized code just an idea]
please let me if there are any concerning points
from django.db import models
from django.db.models import sql
from django.db.models.query_utils import Q
from django.db.models.sql.compiler import SQLCompiler
from django.db.models.fields.related import RelatedField
from django.db.models.query import Collector
class ObjectStatus:
DELETED = "deleted"
ACTIVE = "active"
class Query(sql.Query):
pass
class SoftDeleteQuerySet(models.query.QuerySet):
def __init__(self, model=None, query=None, using=None, hints=None):
super(SoftDeleteQuerySet, self).__init__(
model=model, query=query, using=using, hints=hints
)
self.query: Query = query or Query(self.model)
def delete(self):
for obj in self.all():
obj.delete()
def filter(self, *args, **kwargs):
queryset = self._clone()
obj = super(SoftDeleteQuerySet, queryset).filter(*args, **kwargs)
filters = obj.related_fields()
print(filters)
return obj._filter_or_exclude(False, args, filters)
def related_field_soft_delete(
self, model, visited: set, path: list, target_table: str
):
if target_table == model._meta.db_table:
if path:
delete_filter_path = "__".join(["__".join(path), "status"])
else:
delete_filter_path = "status"
return True, delete_filter_path
visited.add(model)
forward_fields = list(
filter(lambda f: isinstance(f, RelatedField), model._meta.get_fields())
)
for field in forward_fields:
_model, _on_delete, _name = (
field.remote_field.model,
field.remote_field.on_delete,
field.name,
)
if not _model in visited:
path.append(_name)
is_table_found, delete_filter_path = self.related_field_soft_delete(
_model, visited, path, target_table
)
if is_table_found:
return True, delete_filter_path
path.pop()
reversed_fields = model._meta.related_objects
for field in reversed_fields:
_model, _on_delete, _name = (
field.remote_field.model,
field.remote_field.on_delete,
field.name,
)
if not _model in visited:
path.append(_name)
is_table_found, delete_filter_path = self.related_field_soft_delete(
_model, visited, path, target_table
)
if is_table_found:
return True, delete_filter_path
path.pop()
return False, ""
def related_fields(self):
used_aliases = self.query.used_aliases
table_map = self.query.table_map
table_alias_map = dict()
joined_tables = set()
for table_name, aliases in table_map.items():
for alias in aliases:
table_alias_map[alias] = table_name
for alias in used_aliases:
joined_tables.add(table_alias_map[alias])
filters = {}
for target_table in joined_tables:
target_table_path = []
is_table_found, delete_filter_path = self.related_field_soft_delete(
self.model, set(), target_table_path, target_table
)
if is_table_found:
filters[delete_filter_path] = ObjectStatus.ACTIVE
return filters
class BaseModelManager(models.Manager):
def get_queryset(self):
return SoftDeleteQuerySet(self.model, self._db)
class BaseModel(models.Model):
status = models.CharField(max_length=100, default=ObjectStatus.ACTIVE)
class Meta:
abstract = True
class Author(BaseModel):
name = models.CharField(max_length=100)
objects = BaseModelManager()
class Children(BaseModel):
name = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
objects = BaseModelManager()
class Book(BaseModel):
name = models.CharField(max_length=100)
children = models.ForeignKey(
Children, related_name="related_name_children", on_delete=models.CASCADE
)
objects = BaseModelManager()
The text was updated successfully, but these errors were encountered:
When we override the get_queryset method it works for base models but not for related models is_deleated filter is not applied. here is the initial proposal for it [its not optimized code just an idea]
please let me if there are any concerning points
The text was updated successfully, but these errors were encountered: