Coverage for netbox/forms/bulk_edit.py: 72%

36 statements  

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

1from django import forms 

2from django.utils.translation import gettext_lazy as _ 

3 

4from core.models import ObjectType 

5from extras.choices import * 

6from extras.models import Tag 

7from utilities.forms import BulkEditForm 

8from utilities.forms.fields import CommentField, DynamicModelMultipleChoiceField 

9 

10from .mixins import ChangelogMessageMixin, CustomFieldsMixin, OwnerMixin 

11 

12__all__ = ( 

13 'NestedGroupModelBulkEditForm', 

14 'NetBoxModelBulkEditForm', 

15 'OrganizationalModelBulkEditForm', 

16 'PrimaryModelBulkEditForm', 

17) 

18 

19 

20class NetBoxModelBulkEditForm(ChangelogMessageMixin, CustomFieldsMixin, BulkEditForm): 

21 """ 

22 Base form for modifying multiple NetBox objects (of the same type) in bulk via the UI. Adds support for custom 

23 fields and adding/removing tags. 

24 

25 Attributes: 

26 fieldsets: An iterable of two-tuples which define a heading and field set to display per section of 

27 the rendered form (optional). If not defined, the all fields will be rendered as a single section. 

28 """ 

29 fieldsets = None 

30 

31 pk = forms.ModelMultipleChoiceField( 

32 queryset=None, # Set from self.model on init 

33 widget=forms.MultipleHiddenInput 

34 ) 

35 add_tags = DynamicModelMultipleChoiceField( 

36 label=_('Add tags'), 

37 queryset=Tag.objects.all(), 

38 required=False 

39 ) 

40 remove_tags = DynamicModelMultipleChoiceField( 

41 label=_('Remove tags'), 

42 queryset=Tag.objects.all(), 

43 required=False 

44 ) 

45 

46 def __init__(self, *args, **kwargs): 

47 super().__init__(*args, **kwargs) 

48 

49 self.fields['pk'].queryset = self.model.objects.all() 

50 

51 # Restrict tag fields by model 

52 object_type = ObjectType.objects.get_for_model(self.model) 

53 self.fields['add_tags'].widget.add_query_param('for_object_type_id', object_type.pk) 

54 self.fields['remove_tags'].widget.add_query_param('for_object_type_id', object_type.pk) 

55 

56 self._extend_nullable_fields() 

57 

58 def _get_form_field(self, customfield): 

59 return customfield.to_form_field(set_initial=False, enforce_required=False) 

60 

61 def _extend_nullable_fields(self): 

62 # The bulk edit template always renders a Set Null control for these 

63 nullable_common_fields = [ 

64 name for name in ('owner', 'comments') 

65 if name in self.fields and name not in self.nullable_fields 

66 ] 

67 nullable_custom_fields = [ 

68 name for name, customfield in self.custom_fields.items() 

69 if (not customfield.required and customfield.ui_editable == CustomFieldUIEditableChoices.YES) 

70 ] 

71 self.nullable_fields = ( 

72 *self.nullable_fields, 

73 *nullable_common_fields, 

74 *nullable_custom_fields, 

75 ) 

76 

77 

78class PrimaryModelBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): 

79 """ 

80 Bulk edit form for models which inherit from PrimaryModel. 

81 """ 

82 description = forms.CharField( 

83 label=_('Description'), 

84 max_length=100, 

85 required=False 

86 ) 

87 comments = CommentField() 

88 

89 

90class OrganizationalModelBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): 

91 """ 

92 Bulk edit form for models which inherit from OrganizationalModel. 

93 """ 

94 description = forms.CharField( 

95 label=_('Description'), 

96 max_length=200, 

97 required=False 

98 ) 

99 comments = CommentField() 

100 

101 

102class NestedGroupModelBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): 

103 """ 

104 Bulk edit form for models which inherit from NestedGroupModel. 

105 """ 

106 description = forms.CharField( 

107 label=_('Description'), 

108 max_length=200, 

109 required=False 

110 ) 

111 comments = CommentField()