How to add element in Django QuerySet?
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?
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()
)
)
)
)