Coverage for extras/models/search.py: 62%

36 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1import uuid 

2 

3from django.db import models 

4from django.utils.translation import gettext_lazy as _ 

5 

6from netbox.search.utils import get_indexer 

7from utilities.fields import RestrictedGenericForeignKey 

8 

9from ..fields import CachedValueField 

10 

11__all__ = ( 

12 'CachedValue', 

13) 

14 

15 

16class CachedValue(models.Model): 

17 id = models.UUIDField( 

18 primary_key=True, 

19 default=uuid.uuid4, 

20 editable=False 

21 ) 

22 timestamp = models.DateTimeField( 

23 verbose_name=_('timestamp'), 

24 auto_now_add=True, 

25 editable=False 

26 ) 

27 object_type = models.ForeignKey( 

28 to='contenttypes.ContentType', 

29 on_delete=models.CASCADE, 

30 related_name='+' 

31 ) 

32 object_id = models.PositiveBigIntegerField() 

33 object = RestrictedGenericForeignKey( 

34 ct_field='object_type', 

35 fk_field='object_id' 

36 ) 

37 field = models.CharField( 

38 verbose_name=_('field'), 

39 max_length=200 

40 ) 

41 type = models.CharField( 

42 verbose_name=_('type'), 

43 max_length=30 

44 ) 

45 value = CachedValueField( 

46 verbose_name=_('value'), 

47 ) 

48 weight = models.PositiveSmallIntegerField( 

49 verbose_name=_('weight'), 

50 default=1000 

51 ) 

52 

53 _netbox_private = True 

54 

55 class Meta: 

56 ordering = ('weight', 'object_type', 'value', 'object_id') 

57 verbose_name = _('cached value') 

58 verbose_name_plural = _('cached values') 

59 indexes = ( 

60 models.Index(fields=('object_type', 'object_id'), name='extras_cachedvalue_object'), 

61 ) 

62 

63 def __str__(self): 

64 return f'{self.object_type} {self.object_id}: {self.field}={self.value}' 

65 

66 @property 

67 def display_attrs(self): 

68 """ 

69 Render any display attributes associated with this search result. 

70 """ 

71 indexer = get_indexer(self.object_type) 

72 attrs = {} 

73 for attr in indexer.display_attrs: 

74 name = self.object._meta.get_field(attr).verbose_name 

75 if value := getattr(self.object, attr): 

76 if display_func := getattr(self.object, f'get_{attr}_display', None): 

77 attrs[name] = display_func() 

78 else: 

79 attrs[name] = value 

80 return attrs