126 lines
4.2 KiB
Python
126 lines
4.2 KiB
Python
"""
|
|
pipeline_grouper.py
|
|
|
|
This module is used to make queryset by groups
|
|
"""
|
|
|
|
from datetime import datetime
|
|
|
|
from django.core.paginator import Paginator
|
|
from django.db import models
|
|
from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor
|
|
|
|
from horilla.horilla_middlewares import _thread_locals
|
|
|
|
|
|
def record_queryset_paginator(request, queryset, page_name, records_per_page=10):
|
|
"""
|
|
This method is used to return the paginator entries
|
|
"""
|
|
page = request.GET.get(page_name)
|
|
queryset = Paginator(queryset, records_per_page)
|
|
queryset = queryset.get_page(page)
|
|
return queryset
|
|
|
|
|
|
def generate_groups(request, groupers, queryset, page_name, group_field, is_fk_field):
|
|
"""
|
|
groups generating method
|
|
"""
|
|
groups = []
|
|
if is_fk_field:
|
|
for grouper in groupers:
|
|
group_queryset = queryset.filter(**{group_field: grouper.id})
|
|
# to avoid zero records groupings
|
|
if group_queryset.count():
|
|
group_info = {
|
|
"grouper": grouper,
|
|
"list": record_queryset_paginator(
|
|
request,
|
|
group_queryset,
|
|
f"dynamic_page_{page_name}{grouper.id}",
|
|
),
|
|
"dynamic_name": f"dynamic_page_{page_name}{grouper.id}",
|
|
}
|
|
groups.append(group_info)
|
|
else:
|
|
for grouper in groupers:
|
|
group_queryset = queryset.filter(**{group_field: grouper})
|
|
# to avoid zero records groupings
|
|
if group_queryset.count():
|
|
group = {
|
|
"grouper": grouper,
|
|
"list": record_queryset_paginator(
|
|
request,
|
|
group_queryset,
|
|
f"dynamic_page_{page_name}{grouper}".replace(" ", "_"),
|
|
),
|
|
"dynamic_name": f"dynamic_page_{page_name}{grouper}".replace(
|
|
" ", "_"
|
|
),
|
|
}
|
|
groups.append(group)
|
|
return groups
|
|
|
|
|
|
def group_by_queryset(
|
|
queryset, group_field, page=None, page_name="page", records_per_page=50
|
|
):
|
|
"""
|
|
This method is used to make group-by and split groups by nested pagination
|
|
"""
|
|
fields_split = group_field.split("__")
|
|
splited = len(fields_split) > 1
|
|
model = queryset.model
|
|
is_fk_field = isinstance(
|
|
getattr(model, group_field, None), ForwardManyToOneDescriptor
|
|
)
|
|
model_copy = model
|
|
field_obj = None
|
|
|
|
# geting request from the thread locals
|
|
request = getattr(_thread_locals, "request", None)
|
|
if splited or is_fk_field:
|
|
for field in fields_split:
|
|
field_obj = model_copy._meta.get_field(field)
|
|
model_copy = field_obj.related_model
|
|
if model_copy:
|
|
groupers = model_copy.objects.all()
|
|
groups = generate_groups(
|
|
request,
|
|
groupers,
|
|
queryset,
|
|
page_name,
|
|
group_field,
|
|
is_fk_field=True,
|
|
)
|
|
else:
|
|
groupers = [
|
|
item
|
|
for index, item in enumerate(
|
|
queryset.values_list(group_field, flat=True)
|
|
)
|
|
if item not in queryset.values_list(group_field, flat=True)[:index]
|
|
]
|
|
groups = generate_groups(
|
|
request, groupers, queryset, page_name, group_field, is_fk_field=False
|
|
)
|
|
|
|
else:
|
|
# making unique | not using set(groupers) due to ordering issue
|
|
groupers = [
|
|
item
|
|
for index, item in enumerate(queryset.values_list(group_field, flat=True))
|
|
if item not in queryset.values_list(group_field, flat=True)[:index]
|
|
]
|
|
related_model = queryset.model._meta.get_field(group_field).related_model
|
|
if related_model:
|
|
groupers = related_model.objects.filter(id__in=groupers)
|
|
groups = generate_groups(
|
|
request, groupers, queryset, page_name, group_field, is_fk_field=False
|
|
)
|
|
|
|
# getting related queryset
|
|
groups = Paginator(groups, records_per_page)
|
|
return groups.get_page(page)
|