forked from aboutcode-org/dejacode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfilters.py
More file actions
131 lines (110 loc) · 4.3 KB
/
filters.py
File metadata and controls
131 lines (110 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# DejaCode is a trademark of nexB Inc.
# SPDX-License-Identifier: AGPL-3.0-only
# See https://github.com/aboutcode-org/dejacode for support or download.
# See https://aboutcode.org for more information about AboutCode FOSS projects.
#
from django.contrib import admin
from django.contrib import messages
from django.contrib.admin.views.main import ORDER_VAR
from django.shortcuts import get_object_or_404
from django.utils.text import capfirst
from django.utils.translation import gettext_lazy as _
from dje.filters import DataspacedFilterSet
from dje.filters import DataspaceFilter
from dje.filters import DefaultOrderingFilter
from dje.filters import SearchFilter
from dje.widgets import DropDownAsListWidget
from reporting.models import Query
from reporting.models import Report
class ReportingQueryListFilter(admin.SimpleListFilter):
"""
Allows to filter a changelist given a reporting.Query instance
This can only be used on a ModelAdmin for which the Model is supported by
the reporting app.
Only available on the user dataspace objects for security reason.
If `order_fields` are available on this Query, the ordering will be added in
the filter parameters.
"""
title = _("reporting query")
parameter_name = "reporting_query"
def lookups(self, request, model_admin):
# Limit the availability of this filter to current user dataspace objects
if DataspaceFilter.parameter_name in request.GET:
return
query_qs = (
Query.objects.scope(request.user.dataspace)
.get_for_model(model_admin.model)
.prefetch_related("order_fields")
)
lookups = []
for query in query_qs:
param_dict = {
self.parameter_name: query._get_pk_val(),
}
ordering_from_query = query.get_order_list_for_url(request, model_admin)
if ordering_from_query:
param_dict[ORDER_VAR] = ".".join(ordering_from_query)
lookups.append((query.name, param_dict))
return lookups
def choices(self, changelist):
yield {
"selected": self.value() is None,
"query_string": changelist.get_query_string({}, [self.parameter_name, ORDER_VAR]),
"display": _("All"),
}
for title, param_dict in self.lookup_choices:
yield {
"selected": str(param_dict.get(self.parameter_name)) == str(self.value()),
"query_string": changelist.get_query_string(param_dict, [ORDER_VAR]),
"display": title,
}
def queryset(self, request, queryset):
if not self.value():
return queryset
# This filter is only available on the user dataspace objects
query_instance = get_object_or_404(
Query,
pk=self.value(),
dataspace=request.user.dataspace,
)
try:
qs = query_instance.get_qs(user=request.user)
except Exception as e: # Broad exception as get_qs is fairly unstable
messages.error(request, f"{self.title} filter error: {e}")
return
msg = f"{capfirst(self.title)} filter active. Other filters may be ignored."
messages.warning(request, msg)
return qs
class ReportFilterSet(DataspacedFilterSet):
q = SearchFilter(
label=_("Search"),
search_fields=[
"name",
"description",
],
)
sort = DefaultOrderingFilter(
label=_("Sort"),
fields=["name", "query__content_type"],
field_labels={
"query__content_type": "Object type",
},
empty_label="Default",
widget=DropDownAsListWidget,
)
class Meta:
model = Report
fields = (
"q",
"query__content_type",
"sort",
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
content_type_filter = self.filters["query__content_type"]
content_type_filter.label = _("Object type")
content_type_filter.extra["to_field_name"] = "model"
content_type_filter.extra["widget"] = DropDownAsListWidget(label="Object type")
content_type_filter.field.label_from_instance = lambda obj: obj.model