I have model Report and GroupReport. They have many-to-many relation. I can easily get QuerySet[GroupReport] for all GroupReport instance:
Group Name 1:
Report Name 1
Report Name 2
Group Name 2:
Report Name 2
Report Name 10
... and etc.
But i need to add entry "Total Reports" to QuerySet[GroupReport]:
Group All reports:
Report Name 1
Report Name 2
Report Name 5
... and another reports from QuerySet[Report]
I can't store group "Total Reports" in database because using object permissions for QuerySets. It is necessary to generate the group dynamically. My Serializer expect correct queryset. How can i do this?
I tried to do it something like this:
def get_queryset(self):
groups = get_objects_for_user(
user=self.request.user,
perms=view_reportgroup,
klass=ReportGroup.actived_objects,
accept_global_perms=False
)
reports = get_objects_for_user(
user=self.request.user,
perms=view_report,
klass=Report.actived_objects,
accept_global_perms=False
)
total = ReportStorage(id=None, name='Total Reports')
total.reports.set(
Report.actived_objects.filter(
Q(id__in=reports) | Q(groups__in=groups)
).distinct()
)
return (groups | total).prefetch_related(
Prefetch(
'reports',
queryset=ReportStorage.prefetch_related(
Prefetch(
'reportstorage',
queryset=super().get_queryset()
)
)
)
)
But got expected error: "needs to have a value for field 'id' bla-bla..." for total.reports.set. I was also thinking about adding ReportStorage to groups._result_cache. But I don't understand how it should look. Maybe there are more correct ways such as custom SQL, converting QuerySet to List?
ViewSets:
class ReportStorageGenericViewSet(GenericViewSet):
"""
Basic view for filtering file storage objects.
Fields
-------
queryset: QuerySet[ReportStorage]
Basic set of objects.
query_params_validator: QueryParamValidator
Class for processing the correctness of the specified date from query_param.
"""
queryset = ReportStorage.objects
query_params_validator = QueryParamsValidator() # getattr(settings, 'DATE_INPUT_FORMATS', None))
permission_classes = [PortalRDjangoObjectPermissions]
def _get_date(self) -> date:
"""
Getting date from query_params.
:return: Valid date, if the value is not specified, the reporting day is used.
"""
date_str = self.request.query_params.get('date')
self.query_params_validator(date_str)
if date_str:
return parse_date(date_str)
return (timezone.now() - timedelta(days=1)).date()
def get_queryset(self) -> QuerySet[ReportStorage]:
"""
Generating a list of objects.
It is guaranteed that the list of files is filtered by date.
:return: A set of ReportStorage objects.
"""
return super().get_queryset().filter(validity_period__contains=self._get_date())
def get_serializer_context(self) -> Dict[str, Any]:
"""
Adding a queryset to the context during the List operation to further check for the presence of loaded help at the current time.
:return: Context for the serializer.
"""
context = super().get_serializer_context()
if self.action == 'list':
context['queryset'] = self.get_queryset()
return context
def handle_exception(self, exc: APIException) -> Response:
"""
Handling request execution errors.
:param exc: Query execution exception.
:return: If an error occurs, returns a standard {"detail": "message"} JSON response.
"""
if isinstance(exc, ValidationError):
return Response({"detail": exc.detail}, status=exc.status_code)
return super().handle_exception(exc=exc)
class ReportGroupViewSet(ListModelMixin, ReportStorageGenericViewSet):
"""
View to get a list of reporting groups with enabled reports and file uploads.
Fields
-------
serializer_class: ReportGroupSerializer
Basic view object serializer.
"""
serializer_class = ReportGroupSerializer
def get_queryset(self) -> QuerySet[ReportGroup]:
"""
Generating a list of objects.
:return: List of ReportGroup objects.
"""
#### Override queryset here ####
return ReportGroup.actived_objects.prefetch_related(
Prefetch(
'reports',
queryset=Report.actived_objects.prefetch_related(
Prefetch('storage', queryset=super().get_queryset())
)
)
)
APIVieworViewSet, or something similar?