-1

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())
                )
            )
        )
4
  • So this is a APIView or ViewSet, or something similar? Commented Dec 11, 2024 at 18:57
  • Can you share the vieset? Does it do any extra filtering/searching/whatever? Commented Dec 11, 2024 at 19:23
  • @willeM_VanOnsem, Its's ViewSet. Post updated Commented Dec 12, 2024 at 6:15
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Commented Dec 15, 2024 at 23:57

1 Answer 1

0

I added "total group" in database and set all reports to it. Queryset fixed:

def _get_accessible_reports(self, perms: str | List[str]) -> QuerySet[Report]:
  """
  Method for obtaining a list of reports available to the user.

  :param perms: list of rights in a standard name, for example: 'add', 'change', 'delete', 'view'.
                You can check the available actions in Meta[default_permissions, permissions]: Report | ReportGroup.
  :return: Complete list of reports that the user has access to directly or through reporting groups.
  """
  if self.request.user.is_superuser:
      return Report.actived_objects.all()

  if isinstance(perms, str):
      perms = [perms]

  reports = get_objects_for_user(
      user=self.request.user,
      perms=[f'{perm}_report' for perm in perms],
      klass=Report.actived_objects,
      any_perm=True,
      accept_global_perms=False
  )
  groups = get_objects_for_user(
      user=self.request.user,
      perms=[f'{perm}_reportgroup' for perm in perms],
      klass=ReportGroup.actived_objects,
      any_perm=True,
      accept_global_perms=False
  )

  return Report.actived_objects.filter(
      Q(id__in=reports) | Q(groups__in=groups)
  ).distinct()


def get_queryset(self):
  """
  Generating a list of objects.

  return: List of ReportGroup objects.
  """
  total_reports = self._get_accessible_reports('view')
        return ReportGroup.actived_objects.filter(reports__in=total_reports).distinct().prefetch_related(
            Prefetch(
                'reports',
                queryset=Report.actived_objects.filter(id__in=total_reports).prefetch_related(
                    Prefetch(
                        'storage',
                        queryset=super().get_queryset()
                    )
                )
            )
        )

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.