Как добавить элемент в Django QuerySet?

У меня есть модель Report и GroupReport. Они имеют отношение «многие-ко-многим». Я могу легко получить QuerySet[GroupReport] для всех экземпляров GroupReport:

  Group Name 1:
    Report Name 1
    Report Name 2
  Group Name 2:
    Report Name 2
    Report Name 10
  ... and etc.

Но мне нужно добавить запись «Total Reports» в QuerySet[GroupReport]:

  Group All reports:
    Report Name 1
    Report Name 2
    Report Name 5
  ... and another reports from QuerySet[Report]

Я не могу сохранить группу «Total Reports» в базе данных, так как использую объектные разрешения для QuerySets. Необходимо сгенерировать группу динамически. Мой Serializer ожидает корректный набор запросов. Как я могу это сделать?

Я пытался сделать это примерно так:

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()
        )
      )
    )
  )

Но получил ожидаемую ошибку: «требуется значение для поля 'id' bla-bla...» для total.reports.set. Я также думал о том, чтобы добавить ReportStorage в groups._result_cache. Но я не понимаю, как это должно выглядеть. Может быть, есть более правильные способы, такие как пользовательский SQL, преобразование QuerySet в List?

Я добавил в базу данных «общую группу» и установил на нее все отчеты. Набор запросов исправлен:

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()
                    )
                )
            )
        )

Вернуться на верх