django-scopes
django-scopes copied to clipboard
Suggestion: ContentTypes framework/GenericForeignKey and support Q-objects for look up value?
Background: We have a few models that uses Django's ContentTypes framework and GenericForeignKey https://docs.djangoproject.com/en/5.0/ref/contrib/contenttypes/
As the typical example for ScopeManager is to passed in a fixed string (below), we have difficulty using this package.
objects = ScopedManager(site='post__site')
One idea is to extend django-scopes to support Q-objects, something along the lines of:
def ScopedManager(_manager_class=models.Manager, **scopes):
required_scopes = set(scopes.keys())
class Manager(_manager_class):
def __init__(self):
super().__init__()
def get_queryset(self):
current_scope = get_scope()
if not current_scope.get('_enabled', True):
return super().get_queryset()
missing_scopes = required_scopes - set(current_scope.keys())
if missing_scopes:
return DisabledQuerySet(self.model, using=self._db, missing_scopes=missing_scopes)
else:
filter_args = [] # <-----
filter_kwargs = {}
for dimension in required_scopes:
current_value = current_scope[dimension]
if isinstance(current_value, Q): # <-----
filter_args.append(current_value) # <-----
if isinstance(current_value, (list, tuple)):
filter_kwargs[scopes[dimension] + '__in'] = current_value
elif current_value is not None:
filter_kwargs[scopes[dimension]] = current_value
return super().get_queryset().filter(*filter_args, **filter_kwargs) # <-----
def all(self):
a = super().all()
if isinstance(a, DisabledQuerySet):
a = a.all()
return a
return Manager()
So that we can write something such as:
objects = ScopedManager(site=(Q(site=value) | Q(site=another_value))
Open to thoughts and comments, or other solutions. Thanks in advance! :)
I would not be opposed to this kind of feature, but I'd be very cautious of using it in production, it sounds like a possible performance hazard.