57 lines
2.1 KiB
Python
57 lines
2.1 KiB
Python
"""Utils QuerySet Mixins"""
|
|
from django.db import models
|
|
from django.db.models import Q, Sum, F
|
|
from functools import reduce
|
|
from operator import add
|
|
from utils.methods import get_contenttype
|
|
|
|
|
|
class ContentTypeQuerySetMixin(models.QuerySet):
|
|
"""QuerySet for ContentType"""
|
|
|
|
def by_object_id(self, object_id: int):
|
|
"""Filter by object_id"""
|
|
return self.filter(object_id=object_id)
|
|
|
|
def by_content_type(self, app_label: str = 'favorites', model: str = 'favorites'):
|
|
"""Filter QuerySet by ContentType."""
|
|
return self.filter(content_type=get_contenttype(app_label=app_label,
|
|
model=model))
|
|
|
|
|
|
class RelatedObjectsCountMixin(models.QuerySet):
|
|
"""QuerySet for ManyToMany related count filter"""
|
|
|
|
def _get_related_objects_names(self):
|
|
"""Get all related objects (with reversed)"""
|
|
related_objects_names = []
|
|
|
|
for related_object in self.model._meta.related_objects:
|
|
if isinstance(related_object, models.ManyToManyRel):
|
|
related_objects_names.append(related_object.name)
|
|
|
|
return related_objects_names
|
|
|
|
def _annotate_related_objects_count(self):
|
|
"""Annotate all related objects to queryset"""
|
|
annotations = {}
|
|
for related_object in self._get_related_objects_names():
|
|
annotations[f"{related_object}_count"] = models.Count(f"{related_object}")
|
|
|
|
return self.annotate(**annotations)
|
|
|
|
def filter_related_gt(self, count):
|
|
"""QuerySet filter by related objects count"""
|
|
q_objects = Q()
|
|
for related_object in self._get_related_objects_names():
|
|
q_objects.add(Q(**{f"{related_object}_count__gt": count}), Q.OR)
|
|
|
|
return self._annotate_related_objects_count().filter(q_objects)
|
|
|
|
def filter_all_related_gt(self, count):
|
|
"""Queryset filter by all related objects count"""
|
|
exp =reduce(add, [F(f"{related_object}_count") for related_object in self._get_related_objects_names()])
|
|
return self._annotate_related_objects_count()\
|
|
.annotate(all_related_count=exp)\
|
|
.filter(all_related_count__gt=count)
|