14
14
from django_filters import (
15
15
ChoiceFilter ,
16
16
FilterSet ,
17
- ModelChoiceFilter ,
18
17
OrderingFilter ,
19
18
)
20
19
20
+ from readthedocs .core .filters import FilteredModelChoiceFilter
21
21
from readthedocs .organizations .constants import ACCESS_LEVELS
22
22
from readthedocs .organizations .models import Organization , Team
23
- from readthedocs .projects .models import Project
24
23
25
24
log = structlog .get_logger (__name__ )
26
25
27
26
27
+ class OrganizationFilterSet (FilterSet ):
28
+
29
+ """
30
+ Organization base filter set.
31
+
32
+ Adds some object attributes that are used for orgaization related queries
33
+ and common base querysets for filter fields.
34
+
35
+ Note, the querysets here are also found in the organization base views and
36
+ mixin classes. These are redefined here instead of passing in the querysets
37
+ from the view.
38
+
39
+ :param organization: Organization instance for current view
40
+ """
41
+
42
+ def __init__ (self , * args , ** kwargs ):
43
+ self .organization = kwargs .pop ("organization" , None )
44
+ super ().__init__ (* args , ** kwargs )
45
+
46
+ def get_organization_queryset (self ):
47
+ return Organization .objects .for_user (user = self .request .user )
48
+
49
+ def get_team_queryset (self ):
50
+ return Team .objects .member (
51
+ self .request .user ,
52
+ organization = self .organization ,
53
+ ).prefetch_related ("organization" )
54
+
55
+
28
56
class OrganizationSortOrderingFilter (OrderingFilter ):
29
57
30
58
"""Organization list sort ordering django_filters filter."""
@@ -69,16 +97,15 @@ def filter(self, qs, value):
69
97
return qs .order_by (* order_bys )
70
98
71
99
72
- class OrganizationListFilterSet (FilterSet ):
100
+ class OrganizationListFilterSet (OrganizationFilterSet ):
73
101
74
102
"""Filter and sorting for organization listing page."""
75
103
76
- slug = ModelChoiceFilter (
104
+ slug = FilteredModelChoiceFilter (
77
105
label = _ ("Organization" ),
78
106
empty_label = _ ("All organizations" ),
79
107
to_field_name = "slug" ,
80
- # Queryset is required, give an empty queryset from the correct model
81
- queryset = Organization .objects .none (),
108
+ queryset_method = "get_organization_queryset" ,
82
109
method = "get_organization" ,
83
110
)
84
111
@@ -87,26 +114,11 @@ class OrganizationListFilterSet(FilterSet):
87
114
label = _ ("Sort by" ),
88
115
)
89
116
90
- def __init__ (
91
- self ,
92
- data = None ,
93
- queryset = None ,
94
- * ,
95
- request = None ,
96
- prefix = None ,
97
- ):
98
- super ().__init__ (data , queryset , request = request , prefix = prefix )
99
- # Redefine the querysets used for the filter fields using the querysets
100
- # defined at view time. This populates the filter field with only the
101
- # correct related objects for the user. Otherwise, the default for model
102
- # choice filter fields is ``<Model>.objects.all()``.
103
- self .filters ["slug" ].field .queryset = self .queryset .all ()
104
-
105
117
def get_organization (self , queryset , field_name , organization ):
106
118
return queryset .filter (slug = organization .slug )
107
119
108
120
109
- class OrganizationProjectListFilterSet (FilterSet ):
121
+ class OrganizationProjectListFilterSet (OrganizationFilterSet ):
110
122
111
123
"""
112
124
Filter and sorting set for organization project listing page.
@@ -130,46 +142,30 @@ class OrganizationProjectListFilterSet(FilterSet):
130
142
:param team_queryset: Organization team list queryset
131
143
"""
132
144
133
- slug = ModelChoiceFilter (
145
+ slug = FilteredModelChoiceFilter (
134
146
label = _ ("Project" ),
135
147
empty_label = _ ("All projects" ),
136
148
to_field_name = "slug" ,
137
- # Queryset is required, give an empty queryset from the correct model
138
- queryset = Project .objects .none (),
149
+ queryset_method = "get_project_queryset" ,
139
150
method = "get_project" ,
140
151
)
141
152
142
- teams__slug = ModelChoiceFilter (
153
+ teams__slug = FilteredModelChoiceFilter (
143
154
label = _ ("Team" ),
144
155
empty_label = _ ("All teams" ),
145
156
field_name = "teams" ,
146
157
to_field_name = "slug" ,
147
- # Queryset is required, give an empty queryset from the correct model
148
- queryset = Team .objects .none (),
158
+ queryset_method = "get_team_queryset" ,
149
159
)
150
160
151
- def __init__ (
152
- self ,
153
- data = None ,
154
- queryset = None ,
155
- * ,
156
- request = None ,
157
- prefix = None ,
158
- teams_queryset = None ,
159
- ):
160
- super ().__init__ (data , queryset , request = request , prefix = prefix )
161
- # Redefine the querysets used for the filter fields using the querysets
162
- # defined at view time. This populates the filter field with only the
163
- # correct related objects for the user. Otherwise, the default for model
164
- # choice filter fields is ``<Model>.objects.all()``.
165
- self .filters ["slug" ].field .queryset = self .queryset .all ()
166
- self .filters ["teams__slug" ].field .queryset = teams_queryset .all ()
161
+ def get_project_queryset (self ):
162
+ return self .queryset
167
163
168
164
def get_project (self , queryset , field_name , project ):
169
165
return queryset .filter (slug = project .slug )
170
166
171
167
172
- class OrganizationTeamListFilterSet (FilterSet ):
168
+ class OrganizationTeamListFilterSet (OrganizationFilterSet ):
173
169
174
170
"""
175
171
Filter and sorting for organization team listing page.
@@ -184,37 +180,23 @@ class OrganizationTeamListFilterSet(FilterSet):
184
180
with the dropdown too.
185
181
"""
186
182
187
- slug = ModelChoiceFilter (
183
+ slug = FilteredModelChoiceFilter (
188
184
label = _ ("Team" ),
189
185
empty_label = _ ("All teams" ),
190
186
field_name = "teams" ,
191
187
to_field_name = "slug" ,
192
- # Queryset is required, give an empty queryset from the correct model
193
- queryset = Team .objects .none (),
188
+ queryset_method = "get_team_queryset" ,
194
189
method = "get_team" ,
195
190
)
196
191
197
- def __init__ (
198
- self ,
199
- data = None ,
200
- queryset = None ,
201
- * ,
202
- request = None ,
203
- prefix = None ,
204
- teams_queryset = None ,
205
- ):
206
- super ().__init__ (data , queryset , request = request , prefix = prefix )
207
- # Redefine the querysets used for the filter fields using the querysets
208
- # defined at view time. This populates the filter field with only the
209
- # correct related objects for the user/organization. Otherwise, the
210
- # default for model choice filter fields is ``<Model>.objects.all()``.
211
- self .filters ["slug" ].field .queryset = queryset .all ()
192
+ def get_team_queryset (self ):
193
+ return self .queryset
212
194
213
195
def get_team (self , queryset , field_name , team ):
214
196
return queryset .filter (slug = team .slug )
215
197
216
198
217
- class OrganizationTeamMemberListFilterSet (FilterSet ):
199
+ class OrganizationTeamMemberListFilterSet (OrganizationFilterSet ):
218
200
219
201
"""
220
202
Filter and sorting set for organization member listing page.
@@ -245,12 +227,12 @@ class OrganizationTeamMemberListFilterSet(FilterSet):
245
227
246
228
ACCESS_OWNER = "owner"
247
229
248
- teams__slug = ModelChoiceFilter (
230
+ teams__slug = FilteredModelChoiceFilter (
249
231
label = _ ("Team" ),
250
232
empty_label = _ ("All teams" ),
251
233
field_name = "teams" ,
252
234
to_field_name = "slug" ,
253
- queryset = Team . objects . none () ,
235
+ queryset_method = "get_team_queryset" ,
254
236
)
255
237
256
238
access = ChoiceFilter (
@@ -260,34 +242,6 @@ class OrganizationTeamMemberListFilterSet(FilterSet):
260
242
method = "get_access" ,
261
243
)
262
244
263
- def __init__ (
264
- self , data = None , queryset = None , * , request = None , prefix = None , organization = None
265
- ):
266
- """
267
- Organization members filter set.
268
-
269
- This filter set requires the following additional parameters:
270
-
271
- :param organization: Organization for field ``filter()`` and used to
272
- check for organization owner access.
273
- """
274
- super ().__init__ (data , queryset , request = request , prefix = prefix )
275
- self .organization = organization
276
- # Redefine the querysets used for the filter fields using the querysets
277
- # defined at view time. This populates the filter field with only the
278
- # correct related objects for the user/organization. Otherwise, the
279
- # default for model choice filter fields is ``<Model>.objects.all()``.
280
- filter_with_user_relationship = True
281
- team_queryset = self .organization .teams
282
- if filter_with_user_relationship :
283
- # XXX remove this conditional and decide which one of these is most
284
- # correct There are reasons for both showing all the teams here and
285
- # only the team that the user has access to.
286
- team_queryset = Team .objects .member (request .user ).filter (
287
- organization = self .organization ,
288
- )
289
- self .filters ["teams__slug" ].field .queryset = team_queryset .all ()
290
-
291
245
def get_access (self , queryset , field_name , value ):
292
246
# Note: the queryset here is effectively against the ``User`` model, and
293
247
# is from Organization.members, a union of TeamMember.user and
0 commit comments