1
+ from dataclasses import dataclass
1
2
from typing import Iterable
2
3
3
4
from django .conf import settings
4
5
from django .contrib .auth .mixins import AccessMixin
5
6
from django .core .exceptions import ImproperlyConfigured
7
+ from django .db .models import QuerySet
6
8
from django .urls import reverse
7
9
from django .urls .exceptions import NoReverseMatch
8
10
from django .utils .translation import gettext_lazy as _
12
14
from netbox .registry import registry
13
15
from utilities .relations import get_related_models
14
16
from utilities .request import safe_for_redirect
17
+ from utilities .string import title
15
18
from .permissions import resolve_permission
16
19
17
20
__all__ = (
@@ -177,8 +180,17 @@ class GetRelatedModelsMixin:
177
180
"""
178
181
Provides logic for collecting all related models for the currently viewed model.
179
182
"""
183
+ @dataclass
184
+ class RelatedObjectCount :
185
+ queryset : QuerySet
186
+ filter_param : str
187
+ label : str = ''
180
188
181
- def get_related_models (self , request , instance , omit = [], extra = []):
189
+ @property
190
+ def name (self ):
191
+ return self .label or title (_ (self .queryset .model ._meta .verbose_name_plural ))
192
+
193
+ def get_related_models (self , request , instance , omit = None , extra = None ):
182
194
"""
183
195
Get related models of the view's `queryset` model without those listed in `omit`. Will be sorted alphabetical.
184
196
@@ -191,14 +203,15 @@ def get_related_models(self, request, instance, omit=[], extra=[]):
191
203
extra: Add extra models to the list of automatically determined related models. Can be used to add indirect
192
204
relationships.
193
205
"""
206
+ omit = omit or []
194
207
model = self .queryset .model
195
208
related = filter (
196
209
lambda m : m [0 ] is not model and m [0 ] not in omit ,
197
210
get_related_models (model , False )
198
211
)
199
212
200
213
related_models = [
201
- (
214
+ self . RelatedObjectCount (
202
215
model .objects .restrict (request .user , 'view' ).filter (** (
203
216
{f'{ field } __in' : instance }
204
217
if isinstance (instance , Iterable )
@@ -208,11 +221,14 @@ def get_related_models(self, request, instance, omit=[], extra=[]):
208
221
)
209
222
for model , field in related
210
223
]
211
- related_models .extend (extra )
224
+ if extra is not None :
225
+ related_models .extend ([
226
+ self .RelatedObjectCount (* attrs ) for attrs in extra
227
+ ])
212
228
213
229
return sorted (
214
- filter (lambda qs : qs [ 0 ] .exists (), related_models ),
215
- key = lambda qs : qs [ 0 ]. model . _meta . verbose_name . lower () ,
230
+ filter (lambda roc : roc . queryset .exists (), related_models ),
231
+ key = lambda roc : roc . name ,
216
232
)
217
233
218
234
0 commit comments