Coverage for extras/forms/bulk_edit.py: 100%

124 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 extras.choices import * 

5from extras.models import * 

6from netbox.events import get_event_type_choices 

7from netbox.forms import NetBoxModelBulkEditForm, PrimaryModelBulkEditForm 

8from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin 

9from utilities.forms import BulkEditForm, add_blank_choice 

10from utilities.forms.fields import ChoiceField, ColorField, CommentField, DynamicModelChoiceField, JSONField 

11from utilities.forms.rendering import FieldSet 

12from utilities.forms.widgets import BulkEditNullBooleanSelect 

13 

14__all__ = ( 

15 'ConfigContextBulkEditForm', 

16 'ConfigContextProfileBulkEditForm', 

17 'ConfigTemplateBulkEditForm', 

18 'CustomFieldBulkEditForm', 

19 'CustomFieldChoiceSetBulkEditForm', 

20 'CustomLinkBulkEditForm', 

21 'EventRuleBulkEditForm', 

22 'ExportTemplateBulkEditForm', 

23 'ImageAttachmentBulkEditForm', 

24 'JournalEntryBulkEditForm', 

25 'NotificationGroupBulkEditForm', 

26 'SavedFilterBulkEditForm', 

27 'TableConfigBulkEditForm', 

28 'TagBulkEditForm', 

29 'WebhookBulkEditForm', 

30) 

31 

32 

33class CustomFieldBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm): 

34 pk = forms.ModelMultipleChoiceField( 

35 queryset=CustomField.objects.all(), 

36 widget=forms.MultipleHiddenInput 

37 ) 

38 group_name = forms.CharField( 

39 label=_('Group name'), 

40 required=False 

41 ) 

42 description = forms.CharField( 

43 label=_('Description'), 

44 required=False 

45 ) 

46 required = forms.NullBooleanField( 

47 label=_('Required'), 

48 required=False, 

49 widget=BulkEditNullBooleanSelect() 

50 ) 

51 unique = forms.NullBooleanField( 

52 label=_('Must be unique'), 

53 required=False, 

54 widget=BulkEditNullBooleanSelect() 

55 ) 

56 weight = forms.IntegerField( 

57 label=_('Weight'), 

58 required=False 

59 ) 

60 choice_set = DynamicModelChoiceField( 

61 queryset=CustomFieldChoiceSet.objects.all(), 

62 required=False 

63 ) 

64 ui_visible = ChoiceField( 

65 label=_("UI visible"), 

66 choices=add_blank_choice(CustomFieldUIVisibleChoices), 

67 required=False 

68 ) 

69 ui_editable = ChoiceField( 

70 label=_("UI editable"), 

71 choices=add_blank_choice(CustomFieldUIEditableChoices), 

72 required=False 

73 ) 

74 is_cloneable = forms.NullBooleanField( 

75 label=_('Is cloneable'), 

76 required=False, 

77 widget=BulkEditNullBooleanSelect() 

78 ) 

79 nulls_first = forms.NullBooleanField( 

80 label=_('Nulls first'), 

81 required=False, 

82 widget=BulkEditNullBooleanSelect() 

83 ) 

84 validation_minimum = forms.DecimalField( 

85 label=_('Minimum value'), 

86 required=False, 

87 ) 

88 validation_maximum = forms.DecimalField( 

89 label=_('Maximum value'), 

90 required=False, 

91 ) 

92 validation_regex = forms.CharField( 

93 label=_('Validation regex'), 

94 required=False 

95 ) 

96 validation_schema = JSONField( 

97 label=_('Validation schema'), 

98 required=False 

99 ) 

100 comments = CommentField() 

101 

102 fieldsets = ( 

103 FieldSet('group_name', 'description', 'weight', 'required', 'unique', 'choice_set', name=_('Attributes')), 

104 FieldSet('ui_visible', 'ui_editable', 'is_cloneable', 'nulls_first', name=_('Behavior')), 

105 FieldSet( 

106 'validation_minimum', 'validation_maximum', 'validation_regex', 'validation_schema', 

107 name=_('Validation') 

108 ), 

109 ) 

110 nullable_fields = ('group_name', 'description', 'choice_set', 'validation_schema', 'owner', 'comments') 

111 

112 

113class CustomFieldChoiceSetBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm): 

114 pk = forms.ModelMultipleChoiceField( 

115 queryset=CustomFieldChoiceSet.objects.all(), 

116 widget=forms.MultipleHiddenInput 

117 ) 

118 base_choices = ChoiceField( 

119 choices=add_blank_choice(CustomFieldChoiceSetBaseChoices), 

120 required=False 

121 ) 

122 description = forms.CharField( 

123 required=False 

124 ) 

125 order_alphabetically = forms.NullBooleanField( 

126 required=False, 

127 widget=BulkEditNullBooleanSelect() 

128 ) 

129 

130 nullable_fields = ('base_choices', 'description') 

131 

132 

133class CustomLinkBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm): 

134 pk = forms.ModelMultipleChoiceField( 

135 queryset=CustomLink.objects.all(), 

136 widget=forms.MultipleHiddenInput 

137 ) 

138 enabled = forms.NullBooleanField( 

139 label=_('Enabled'), 

140 required=False, 

141 widget=BulkEditNullBooleanSelect() 

142 ) 

143 new_window = forms.NullBooleanField( 

144 label=_('New window'), 

145 required=False, 

146 widget=BulkEditNullBooleanSelect() 

147 ) 

148 weight = forms.IntegerField( 

149 label=_('Weight'), 

150 required=False 

151 ) 

152 button_class = ChoiceField( 

153 label=_('Button class'), 

154 choices=add_blank_choice(CustomLinkButtonClassChoices), 

155 required=False 

156 ) 

157 

158 

159class ExportTemplateBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm): 

160 pk = forms.ModelMultipleChoiceField( 

161 queryset=ExportTemplate.objects.all(), 

162 widget=forms.MultipleHiddenInput 

163 ) 

164 description = forms.CharField( 

165 label=_('Description'), 

166 max_length=200, 

167 required=False 

168 ) 

169 mime_type = forms.CharField( 

170 label=_('MIME type'), 

171 max_length=50, 

172 required=False 

173 ) 

174 file_name = forms.CharField( 

175 label=_('File name'), 

176 required=False 

177 ) 

178 file_extension = forms.CharField( 

179 label=_('File extension'), 

180 max_length=15, 

181 required=False 

182 ) 

183 as_attachment = forms.NullBooleanField( 

184 label=_('As attachment'), 

185 required=False, 

186 widget=BulkEditNullBooleanSelect() 

187 ) 

188 

189 nullable_fields = ('description', 'mime_type', 'file_name', 'file_extension') 

190 

191 

192class SavedFilterBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm): 

193 pk = forms.ModelMultipleChoiceField( 

194 queryset=SavedFilter.objects.all(), 

195 widget=forms.MultipleHiddenInput 

196 ) 

197 description = forms.CharField( 

198 label=_('Description'), 

199 max_length=200, 

200 required=False 

201 ) 

202 weight = forms.IntegerField( 

203 label=_('Weight'), 

204 required=False 

205 ) 

206 enabled = forms.NullBooleanField( 

207 label=_('Enabled'), 

208 required=False, 

209 widget=BulkEditNullBooleanSelect() 

210 ) 

211 shared = forms.NullBooleanField( 

212 label=_('Shared'), 

213 required=False, 

214 widget=BulkEditNullBooleanSelect() 

215 ) 

216 

217 nullable_fields = ('description',) 

218 

219 

220class TableConfigBulkEditForm(ChangelogMessageMixin, BulkEditForm): 

221 pk = forms.ModelMultipleChoiceField( 

222 queryset=TableConfig.objects.all(), 

223 widget=forms.MultipleHiddenInput 

224 ) 

225 description = forms.CharField( 

226 label=_('Description'), 

227 max_length=200, 

228 required=False 

229 ) 

230 weight = forms.IntegerField( 

231 label=_('Weight'), 

232 required=False 

233 ) 

234 enabled = forms.NullBooleanField( 

235 label=_('Enabled'), 

236 required=False, 

237 widget=BulkEditNullBooleanSelect() 

238 ) 

239 shared = forms.NullBooleanField( 

240 label=_('Shared'), 

241 required=False, 

242 widget=BulkEditNullBooleanSelect() 

243 ) 

244 

245 nullable_fields = ('description',) 

246 

247 

248class WebhookBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): 

249 model = Webhook 

250 

251 pk = forms.ModelMultipleChoiceField( 

252 queryset=Webhook.objects.all(), 

253 widget=forms.MultipleHiddenInput 

254 ) 

255 description = forms.CharField( 

256 label=_('Description'), 

257 max_length=200, 

258 required=False 

259 ) 

260 http_method = ChoiceField( 

261 choices=add_blank_choice(WebhookHttpMethodChoices), 

262 required=False, 

263 label=_('HTTP method') 

264 ) 

265 payload_url = forms.CharField( 

266 required=False, 

267 label=_('Payload URL') 

268 ) 

269 ssl_verification = forms.NullBooleanField( 

270 required=False, 

271 widget=BulkEditNullBooleanSelect(), 

272 label=_('SSL verification') 

273 ) 

274 secret = forms.CharField( 

275 label=_('Secret'), 

276 required=False 

277 ) 

278 ca_file_path = forms.CharField( 

279 required=False, 

280 label=_('CA file path') 

281 ) 

282 timeout = forms.IntegerField( 

283 required=False, 

284 min_value=1, 

285 max_value=3600, 

286 label=_('Timeout') 

287 ) 

288 

289 nullable_fields = ('secret', 'ca_file_path', 'timeout') 

290 

291 

292class EventRuleBulkEditForm(OwnerMixin, NetBoxModelBulkEditForm): 

293 model = EventRule 

294 

295 pk = forms.ModelMultipleChoiceField( 

296 queryset=EventRule.objects.all(), 

297 widget=forms.MultipleHiddenInput 

298 ) 

299 enabled = forms.NullBooleanField( 

300 label=_('Enabled'), 

301 required=False, 

302 widget=BulkEditNullBooleanSelect() 

303 ) 

304 event_types = forms.MultipleChoiceField( 

305 choices=get_event_type_choices(), 

306 required=False, 

307 label=_('Event types') 

308 ) 

309 description = forms.CharField( 

310 label=_('Description'), 

311 max_length=200, 

312 required=False 

313 ) 

314 conditions = JSONField( 

315 label=_('Conditions'), 

316 required=False, 

317 help_text=_('Enter conditions in <a href="https://json.org/">JSON</a> format.') 

318 ) 

319 

320 nullable_fields = ('description', 'conditions') 

321 

322 

323class TagBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm): 

324 pk = forms.ModelMultipleChoiceField( 

325 queryset=Tag.objects.all(), 

326 widget=forms.MultipleHiddenInput 

327 ) 

328 color = ColorField( 

329 label=_('Color'), 

330 required=False 

331 ) 

332 description = forms.CharField( 

333 label=_('Description'), 

334 max_length=200, 

335 required=False 

336 ) 

337 weight = forms.IntegerField( 

338 label=_('Weight'), 

339 required=False 

340 ) 

341 

342 nullable_fields = ('description',) 

343 

344 

345class ConfigContextProfileBulkEditForm(PrimaryModelBulkEditForm): 

346 pk = forms.ModelMultipleChoiceField( 

347 queryset=ConfigContextProfile.objects.all(), 

348 widget=forms.MultipleHiddenInput 

349 ) 

350 

351 model = ConfigContextProfile 

352 fieldsets = ( 

353 FieldSet('description',), 

354 ) 

355 nullable_fields = ('description',) 

356 

357 

358class ConfigContextBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm): 

359 pk = forms.ModelMultipleChoiceField( 

360 queryset=ConfigContext.objects.all(), 

361 widget=forms.MultipleHiddenInput 

362 ) 

363 weight = forms.IntegerField( 

364 label=_('Weight'), 

365 required=False, 

366 min_value=0 

367 ) 

368 profile = DynamicModelChoiceField( 

369 queryset=ConfigContextProfile.objects.all(), 

370 required=False 

371 ) 

372 is_active = forms.NullBooleanField( 

373 label=_('Is active'), 

374 required=False, 

375 widget=BulkEditNullBooleanSelect() 

376 ) 

377 description = forms.CharField( 

378 label=_('Description'), 

379 required=False, 

380 max_length=100 

381 ) 

382 

383 fieldsets = ( 

384 FieldSet('weight', 'profile', 'is_active', 'description'), 

385 ) 

386 nullable_fields = ('profile', 'description', 'owner') 

387 

388 

389class ConfigTemplateBulkEditForm(ChangelogMessageMixin, OwnerMixin, BulkEditForm): 

390 pk = forms.ModelMultipleChoiceField( 

391 queryset=ConfigTemplate.objects.all(), 

392 widget=forms.MultipleHiddenInput 

393 ) 

394 description = forms.CharField( 

395 label=_('Description'), 

396 max_length=200, 

397 required=False 

398 ) 

399 mime_type = forms.CharField( 

400 label=_('MIME type'), 

401 max_length=50, 

402 required=False 

403 ) 

404 file_name = forms.CharField( 

405 label=_('File name'), 

406 required=False 

407 ) 

408 file_extension = forms.CharField( 

409 label=_('File extension'), 

410 max_length=15, 

411 required=False 

412 ) 

413 as_attachment = forms.NullBooleanField( 

414 label=_('As attachment'), 

415 required=False, 

416 widget=BulkEditNullBooleanSelect() 

417 ) 

418 debug = forms.NullBooleanField( 

419 label=_('Debug'), 

420 required=False, 

421 widget=BulkEditNullBooleanSelect() 

422 ) 

423 auto_sync_enabled = forms.NullBooleanField( 

424 label=_('Auto sync enabled'), 

425 required=False, 

426 widget=BulkEditNullBooleanSelect() 

427 ) 

428 nullable_fields = ('description', 'mime_type', 'file_name', 'file_extension', 'auto_sync_enabled',) 

429 

430 

431class ImageAttachmentBulkEditForm(ChangelogMessageMixin, BulkEditForm): 

432 pk = forms.ModelMultipleChoiceField( 

433 queryset=ImageAttachment.objects.all(), 

434 widget=forms.MultipleHiddenInput 

435 ) 

436 description = forms.CharField( 

437 label=_('Description'), 

438 max_length=200, 

439 required=False 

440 ) 

441 

442 

443class JournalEntryBulkEditForm(ChangelogMessageMixin, BulkEditForm): 

444 pk = forms.ModelMultipleChoiceField( 

445 queryset=JournalEntry.objects.all(), 

446 widget=forms.MultipleHiddenInput 

447 ) 

448 kind = ChoiceField( 

449 label=_('Kind'), 

450 choices=add_blank_choice(JournalEntryKindChoices), 

451 required=False 

452 ) 

453 comments = CommentField() 

454 

455 

456class NotificationGroupBulkEditForm(ChangelogMessageMixin, BulkEditForm): 

457 pk = forms.ModelMultipleChoiceField( 

458 queryset=NotificationGroup.objects.all(), 

459 widget=forms.MultipleHiddenInput 

460 ) 

461 description = forms.CharField( 

462 label=_('Description'), 

463 max_length=200, 

464 required=False 

465 ) 

466 

467 nullable_fields = ('description',)