Coverage for extras/filtersets.py: 63%

344 statements  

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

1import django_filters 

2from django.contrib.contenttypes.models import ContentType 

3from django.db.models import Q 

4from django.utils.translation import gettext as _ 

5 

6from core.models import DataSource, ObjectType 

7from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup 

8from netbox.event_rules import get_event_rule_action_choices, get_event_rule_action_slugs 

9from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet, PrimaryModelFilterSet 

10from tenancy.models import Tenant, TenantGroup 

11from users.filterset_mixins import OwnerFilterMixin 

12from users.models import Group, User 

13from utilities.filters import MultiValueCharFilter, MultiValueContentTypeFilter, MultiValueNumberFilter 

14from utilities.filtersets import register_filterset 

15from virtualization.models import Cluster, ClusterGroup, ClusterType 

16 

17from .choices import * 

18from .filters import TagFilter, TagIDFilter 

19from .models import * 

20 

21__all__ = ( 

22 'BookmarkFilterSet', 

23 'ConfigContextFilterSet', 

24 'ConfigContextProfileFilterSet', 

25 'ConfigTemplateFilterSet', 

26 'CustomFieldChoiceSetFilterSet', 

27 'CustomFieldFilterSet', 

28 'CustomLinkFilterSet', 

29 'EventRuleFilterSet', 

30 'ExportTemplateFilterSet', 

31 'ImageAttachmentFilterSet', 

32 'JournalEntryFilterSet', 

33 'LocalConfigContextFilterSet', 

34 'NotificationGroupFilterSet', 

35 'SavedFilterFilterSet', 

36 'ScriptFilterSet', 

37 'TableConfigFilterSet', 

38 'TagFilterSet', 

39 'TaggedItemFilterSet', 

40 'WebhookFilterSet', 

41) 

42 

43 

44@register_filterset 

45class ScriptFilterSet(BaseFilterSet): 

46 q = django_filters.CharFilter( 

47 method='search', 

48 label=_('Search'), 

49 ) 

50 module_id = django_filters.ModelMultipleChoiceFilter( 

51 queryset=ScriptModule.objects.all(), 

52 distinct=False, 

53 label=_('Script module (ID)'), 

54 ) 

55 

56 class Meta: 

57 model = Script 

58 fields = ('id', 'name', 'is_executable') 

59 

60 def search(self, queryset, name, value): 

61 if not value.strip(): 

62 return queryset 

63 return queryset.filter( 

64 Q(name__icontains=value) 

65 ) 

66 

67 

68@register_filterset 

69class WebhookFilterSet(OwnerFilterMixin, NetBoxModelFilterSet): 

70 q = django_filters.CharFilter( 

71 method='search', 

72 label=_('Search'), 

73 ) 

74 http_method = django_filters.MultipleChoiceFilter( 

75 choices=WebhookHttpMethodChoices, 

76 distinct=False, 

77 ) 

78 payload_url = MultiValueCharFilter( 

79 lookup_expr='icontains' 

80 ) 

81 

82 class Meta: 

83 model = Webhook 

84 fields = ( 

85 'id', 'name', 'payload_url', 'http_method', 'http_content_type', 'secret', 'ssl_verification', 

86 'ca_file_path', 'timeout', 'description', 

87 ) 

88 

89 def search(self, queryset, name, value): 

90 if not value.strip(): 

91 return queryset 

92 return queryset.filter( 

93 Q(name__icontains=value) | 

94 Q(description__icontains=value) | 

95 Q(payload_url__icontains=value) 

96 ) 

97 

98 

99@register_filterset 

100class EventRuleFilterSet(OwnerFilterMixin, NetBoxModelFilterSet): 

101 q = django_filters.CharFilter( 

102 method='search', 

103 label=_('Search'), 

104 ) 

105 object_type_id = django_filters.ModelMultipleChoiceFilter( 

106 queryset=ObjectType.objects.all(), 

107 field_name='object_types' 

108 ) 

109 object_type = MultiValueContentTypeFilter( 

110 field_name='object_types' 

111 ) 

112 event_type = MultiValueCharFilter( 

113 method='filter_event_type' 

114 ) 

115 action_type = django_filters.MultipleChoiceFilter( 

116 choices=get_event_rule_action_choices, 

117 distinct=False, 

118 ) 

119 action_is_available = django_filters.BooleanFilter( 

120 method='filter_action_is_available', 

121 label=_('Action available'), 

122 ) 

123 action_object_type = MultiValueContentTypeFilter() 

124 action_object_id = MultiValueNumberFilter() 

125 

126 class Meta: 

127 model = EventRule 

128 fields = ( 

129 'id', 'name', 'enabled', 'action_type', 'description', 

130 ) 

131 

132 def search(self, queryset, name, value): 

133 if not value.strip(): 

134 return queryset 

135 return queryset.filter( 

136 Q(name__icontains=value) | 

137 Q(description__icontains=value) | 

138 Q(comments__icontains=value) 

139 ) 

140 

141 def filter_event_type(self, queryset, name, value): 

142 return queryset.filter(event_types__overlap=value) 

143 

144 def filter_action_is_available(self, queryset, name, value): 

145 registered_slugs = get_event_rule_action_slugs() 

146 if value: 

147 return queryset.filter(action_type__in=registered_slugs) 

148 return queryset.exclude(action_type__in=registered_slugs) 

149 

150 

151@register_filterset 

152class CustomFieldFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): 

153 q = django_filters.CharFilter( 

154 method='search', 

155 label=_('Search'), 

156 ) 

157 type = django_filters.MultipleChoiceFilter( 

158 choices=CustomFieldTypeChoices, 

159 distinct=False, 

160 ) 

161 object_type_id = django_filters.ModelMultipleChoiceFilter( 

162 queryset=ObjectType.objects.all(), 

163 field_name='object_types' 

164 ) 

165 object_type = MultiValueContentTypeFilter( 

166 field_name='object_types' 

167 ) 

168 related_object_type_id = django_filters.ModelMultipleChoiceFilter( 

169 queryset=ObjectType.objects.all(), 

170 distinct=False, 

171 field_name='related_object_type' 

172 ) 

173 related_object_type = MultiValueContentTypeFilter() 

174 choice_set_id = django_filters.ModelMultipleChoiceFilter( 

175 queryset=CustomFieldChoiceSet.objects.all(), 

176 distinct=False, 

177 ) 

178 choice_set = django_filters.ModelMultipleChoiceFilter( 

179 field_name='choice_set__name', 

180 queryset=CustomFieldChoiceSet.objects.all(), 

181 distinct=False, 

182 to_field_name='name' 

183 ) 

184 

185 class Meta: 

186 model = CustomField 

187 fields = ( 

188 'id', 'name', 'label', 'group_name', 'required', 'unique', 'search_weight', 'filter_logic', 'ui_visible', 

189 'ui_editable', 'weight', 'is_cloneable', 'nulls_first', 'description', 'validation_minimum', 

190 'validation_maximum', 'validation_regex', 'status', 

191 ) 

192 

193 def search(self, queryset, name, value): 

194 if not value.strip(): 194 ↛ 195line 194 didn't jump to line 195 because the condition on line 194 was never true

195 return queryset 

196 return queryset.filter( 

197 Q(name__icontains=value) | 

198 Q(label__icontains=value) | 

199 Q(group_name__icontains=value) | 

200 Q(description__icontains=value) | 

201 Q(comments__icontains=value) 

202 ) 

203 

204 

205@register_filterset 

206class CustomFieldChoiceSetFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): 

207 q = django_filters.CharFilter( 

208 method='search', 

209 label=_('Search'), 

210 ) 

211 choice = MultiValueCharFilter( 

212 method='filter_by_choice' 

213 ) 

214 choice_colors = django_filters.MultipleChoiceFilter( 

215 choices=CustomFieldChoiceColorChoices, 

216 method='filter_by_choice_colors', 

217 label=_('Choice colors'), 

218 distinct=False, 

219 ) 

220 

221 class Meta: 

222 model = CustomFieldChoiceSet 

223 fields = ( 

224 'id', 'name', 'description', 'base_choices', 'order_alphabetically', 

225 ) 

226 

227 def search(self, queryset, name, value): 

228 if not value.strip(): 

229 return queryset 

230 return queryset.filter( 

231 Q(name__icontains=value) | 

232 Q(description__icontains=value) 

233 ) 

234 

235 def filter_by_choice(self, queryset, name, value): 

236 # TODO: Support case-insensitive matching 

237 return queryset.filter(extra_choices__overlap=value) 

238 

239 def filter_by_choice_colors(self, queryset, name, value): 

240 if not value: 

241 return queryset 

242 

243 choice_color_keys = set() 

244 for choice_colors in queryset.values_list('choice_colors', flat=True): 

245 if isinstance(choice_colors, dict): 

246 choice_color_keys.update(choice_colors.keys()) 

247 

248 if not choice_color_keys: 

249 return queryset.none() 

250 

251 params = Q() 

252 for key in choice_color_keys: 

253 for color in value: 

254 params |= Q(choice_colors__contains={key: color}) 

255 

256 return queryset.filter(params) 

257 

258 

259@register_filterset 

260class CustomLinkFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): 

261 q = django_filters.CharFilter( 

262 method='search', 

263 label=_('Search'), 

264 ) 

265 object_type_id = django_filters.ModelMultipleChoiceFilter( 

266 queryset=ObjectType.objects.all(), 

267 field_name='object_types' 

268 ) 

269 object_type = MultiValueContentTypeFilter( 

270 field_name='object_types' 

271 ) 

272 

273 class Meta: 

274 model = CustomLink 

275 fields = ( 

276 'id', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', 'new_window', 'button_class', 

277 ) 

278 

279 def search(self, queryset, name, value): 

280 if not value.strip(): 

281 return queryset 

282 return queryset.filter( 

283 Q(name__icontains=value) | 

284 Q(link_text__icontains=value) | 

285 Q(link_url__icontains=value) | 

286 Q(group_name__icontains=value) 

287 ) 

288 

289 

290@register_filterset 

291class ExportTemplateFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): 

292 q = django_filters.CharFilter( 

293 method='search', 

294 label=_('Search'), 

295 ) 

296 object_type_id = django_filters.ModelMultipleChoiceFilter( 

297 queryset=ObjectType.objects.all(), 

298 field_name='object_types' 

299 ) 

300 object_type = MultiValueContentTypeFilter( 

301 field_name='object_types' 

302 ) 

303 data_source_id = django_filters.ModelMultipleChoiceFilter( 

304 queryset=DataSource.objects.all(), 

305 distinct=False, 

306 label=_('Data source (ID)'), 

307 ) 

308 data_file_id = django_filters.ModelMultipleChoiceFilter( 

309 queryset=DataSource.objects.all(), 

310 distinct=False, 

311 label=_('Data file (ID)'), 

312 ) 

313 

314 class Meta: 

315 model = ExportTemplate 

316 fields = ( 

317 'id', 'name', 'description', 'mime_type', 'file_name', 'file_extension', 'as_attachment', 

318 'auto_sync_enabled', 'data_synced', 

319 ) 

320 

321 def search(self, queryset, name, value): 

322 if not value.strip(): 

323 return queryset 

324 return queryset.filter( 

325 Q(name__icontains=value) | 

326 Q(description__icontains=value) | 

327 Q(file_name__icontains=value) 

328 ) 

329 

330 

331@register_filterset 

332class SavedFilterFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): 

333 q = django_filters.CharFilter( 

334 method='search', 

335 label=_('Search'), 

336 ) 

337 object_type_id = django_filters.ModelMultipleChoiceFilter( 

338 queryset=ObjectType.objects.all(), 

339 field_name='object_types' 

340 ) 

341 object_type = MultiValueContentTypeFilter( 

342 field_name='object_types' 

343 ) 

344 user_id = django_filters.ModelMultipleChoiceFilter( 

345 queryset=User.objects.all(), 

346 distinct=False, 

347 label=_('User (ID)'), 

348 ) 

349 user = django_filters.ModelMultipleChoiceFilter( 

350 field_name='user__username', 

351 queryset=User.objects.all(), 

352 distinct=False, 

353 to_field_name='username', 

354 label=_('User (name)'), 

355 ) 

356 usable = django_filters.BooleanFilter( 

357 method='_usable' 

358 ) 

359 

360 class Meta: 

361 model = SavedFilter 

362 fields = ('id', 'name', 'slug', 'description', 'enabled', 'shared', 'weight') 

363 

364 def search(self, queryset, name, value): 

365 if not value.strip(): 

366 return queryset 

367 return queryset.filter( 

368 Q(name__icontains=value) | 

369 Q(description__icontains=value) 

370 ) 

371 

372 def _usable(self, queryset, name, value): 

373 """ 

374 Return only SavedFilters that are both enabled and are shared (or belong to the current user). 

375 """ 

376 user = self.request.user if self.request else None 

377 if not user or user.is_anonymous: 

378 if value: 

379 return queryset.filter(enabled=True, shared=True) 

380 return queryset.filter(Q(enabled=False) | Q(shared=False)) 

381 if value: 

382 return queryset.filter(enabled=True).filter(Q(shared=True) | Q(user=user)) 

383 return queryset.filter(Q(enabled=False) | Q(Q(shared=False) & ~Q(user=user))) 

384 

385 

386@register_filterset 

387class TableConfigFilterSet(ChangeLoggedModelFilterSet): 

388 q = django_filters.CharFilter( 

389 method='search', 

390 label=_('Search'), 

391 ) 

392 object_type_id = django_filters.ModelMultipleChoiceFilter( 

393 queryset=ObjectType.objects.all(), 

394 distinct=False, 

395 field_name='object_type' 

396 ) 

397 object_type = MultiValueContentTypeFilter( 

398 field_name='object_type' 

399 ) 

400 user_id = django_filters.ModelMultipleChoiceFilter( 

401 queryset=User.objects.all(), 

402 distinct=False, 

403 label=_('User (ID)'), 

404 ) 

405 user = django_filters.ModelMultipleChoiceFilter( 

406 field_name='user__username', 

407 queryset=User.objects.all(), 

408 distinct=False, 

409 to_field_name='username', 

410 label=_('User (name)'), 

411 ) 

412 usable = django_filters.BooleanFilter( 

413 method='_usable' 

414 ) 

415 

416 class Meta: 

417 model = TableConfig 

418 fields = ('id', 'name', 'description', 'table', 'enabled', 'shared', 'weight') 

419 

420 def search(self, queryset, name, value): 

421 if not value.strip(): 

422 return queryset 

423 return queryset.filter( 

424 Q(name__icontains=value) | 

425 Q(description__icontains=value) | 

426 Q(table__icontains=value) 

427 ) 

428 

429 def _usable(self, queryset, name, value): 

430 """ 

431 Return only TableConfigs that are both enabled and are shared (or belong to the current user). 

432 """ 

433 user = self.request.user if self.request else None 

434 if not user or user.is_anonymous: 

435 if value: 

436 return queryset.filter(enabled=True, shared=True) 

437 return queryset.filter(Q(enabled=False) | Q(shared=False)) 

438 if value: 

439 return queryset.filter(enabled=True).filter(Q(shared=True) | Q(user=user)) 

440 return queryset.filter(Q(enabled=False) | Q(Q(shared=False) & ~Q(user=user))) 

441 

442 

443@register_filterset 

444class BookmarkFilterSet(BaseFilterSet): 

445 created = django_filters.DateTimeFilter() 

446 object_type_id = MultiValueNumberFilter() 

447 object_type = MultiValueContentTypeFilter() 

448 user_id = django_filters.ModelMultipleChoiceFilter( 

449 queryset=User.objects.all(), 

450 distinct=False, 

451 label=_('User (ID)'), 

452 ) 

453 user = django_filters.ModelMultipleChoiceFilter( 

454 field_name='user__username', 

455 queryset=User.objects.all(), 

456 distinct=False, 

457 to_field_name='username', 

458 label=_('User (name)'), 

459 ) 

460 

461 class Meta: 

462 model = Bookmark 

463 fields = ('id', 'object_id') 

464 

465 

466@register_filterset 

467class NotificationGroupFilterSet(ChangeLoggedModelFilterSet): 

468 q = django_filters.CharFilter( 

469 method='search', 

470 label=_('Search'), 

471 ) 

472 user_id = django_filters.ModelMultipleChoiceFilter( 

473 field_name='users', 

474 queryset=User.objects.all(), 

475 label=_('User (ID)'), 

476 ) 

477 user = django_filters.ModelMultipleChoiceFilter( 

478 field_name='users__username', 

479 queryset=User.objects.all(), 

480 to_field_name='username', 

481 label=_('User (name)'), 

482 ) 

483 group_id = django_filters.ModelMultipleChoiceFilter( 

484 field_name='groups', 

485 queryset=Group.objects.all(), 

486 label=_('Group (ID)'), 

487 ) 

488 group = django_filters.ModelMultipleChoiceFilter( 

489 field_name='groups__name', 

490 queryset=Group.objects.all(), 

491 to_field_name='name', 

492 label=_('Group (name)'), 

493 ) 

494 

495 class Meta: 

496 model = NotificationGroup 

497 fields = ( 

498 'id', 'name', 'description', 

499 ) 

500 

501 def search(self, queryset, name, value): 

502 if not value.strip(): 

503 return queryset 

504 return queryset.filter( 

505 Q(name__icontains=value) | 

506 Q(description__icontains=value) 

507 ) 

508 

509 

510@register_filterset 

511class ImageAttachmentFilterSet(ChangeLoggedModelFilterSet): 

512 q = django_filters.CharFilter( 

513 method='search', 

514 label=_('Search'), 

515 ) 

516 object_type = MultiValueContentTypeFilter() 

517 

518 class Meta: 

519 model = ImageAttachment 

520 fields = ( 

521 'id', 'object_type_id', 'object_id', 'name', 'description', 'image_width', 'image_height', 'image_size', 

522 ) 

523 

524 def search(self, queryset, name, value): 

525 if not value.strip(): 

526 return queryset 

527 return queryset.filter( 

528 Q(name__icontains=value) | 

529 Q(image__icontains=value) | 

530 Q(description__icontains=value) 

531 ) 

532 

533 

534@register_filterset 

535class JournalEntryFilterSet(NetBoxModelFilterSet): 

536 created = django_filters.DateTimeFromToRangeFilter() 

537 assigned_object_type = MultiValueContentTypeFilter() 

538 assigned_object_type_id = django_filters.ModelMultipleChoiceFilter( 

539 queryset=ContentType.objects.all(), 

540 distinct=False, 

541 ) 

542 created_by_id = django_filters.ModelMultipleChoiceFilter( 

543 queryset=User.objects.all(), 

544 distinct=False, 

545 label=_('User (ID)'), 

546 ) 

547 created_by = django_filters.ModelMultipleChoiceFilter( 

548 field_name='created_by__username', 

549 queryset=User.objects.all(), 

550 distinct=False, 

551 to_field_name='username', 

552 label=_('User (name)'), 

553 ) 

554 kind = django_filters.MultipleChoiceFilter( 

555 choices=JournalEntryKindChoices, 

556 distinct=False, 

557 ) 

558 

559 class Meta: 

560 model = JournalEntry 

561 fields = ('id', 'assigned_object_type_id', 'assigned_object_id', 'created', 'kind') 

562 

563 def search(self, queryset, name, value): 

564 if not value.strip(): 

565 return queryset 

566 return queryset.filter(comments__icontains=value) 

567 

568 

569@register_filterset 

570class TagFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): 

571 q = django_filters.CharFilter( 

572 method='search', 

573 label=_('Search'), 

574 ) 

575 content_type = MultiValueCharFilter( 

576 method='_content_type' 

577 ) 

578 content_type_id = MultiValueNumberFilter( 

579 method='_content_type_id' 

580 ) 

581 for_object_type_id = MultiValueNumberFilter( 

582 method='_for_object_type' 

583 ) 

584 

585 class Meta: 

586 model = Tag 

587 fields = ('id', 'name', 'slug', 'color', 'weight', 'description', 'object_types') 

588 

589 def search(self, queryset, name, value): 

590 if not value.strip(): 

591 return queryset 

592 return queryset.filter( 

593 Q(name__icontains=value) | 

594 Q(slug__icontains=value) | 

595 Q(description__icontains=value) 

596 ) 

597 

598 def _content_type(self, queryset, name, values): 

599 ct_filter = Q() 

600 

601 # Compile list of app_label & model pairings 

602 for value in values: 

603 try: 

604 app_label, model = value.lower().split('.') 

605 ct_filter |= Q( 

606 app_label=app_label, 

607 model=model 

608 ) 

609 except ValueError: 

610 pass 

611 

612 # Get ContentType instances 

613 content_types = ContentType.objects.filter(ct_filter) 

614 

615 return queryset.filter(extras_taggeditem_items__content_type__in=content_types).distinct() 

616 

617 def _content_type_id(self, queryset, name, values): 

618 

619 # Get ContentType instances 

620 content_types = ContentType.objects.filter(pk__in=values) 

621 

622 return queryset.filter(extras_taggeditem_items__content_type__in=content_types).distinct() 

623 

624 def _for_object_type(self, queryset, name, values): 

625 return queryset.filter( 

626 Q(object_types__id__in=values) | Q(object_types__isnull=True) 

627 ) 

628 

629 

630@register_filterset 

631class TaggedItemFilterSet(BaseFilterSet): 

632 q = django_filters.CharFilter( 

633 method='search', 

634 label=_('Search'), 

635 ) 

636 object_type = MultiValueContentTypeFilter( 

637 field_name='content_type' 

638 ) 

639 object_type_id = django_filters.ModelMultipleChoiceFilter( 

640 queryset=ContentType.objects.all(), 

641 distinct=False, 

642 field_name='content_type_id' 

643 ) 

644 tag_id = django_filters.ModelMultipleChoiceFilter( 

645 queryset=Tag.objects.all(), 

646 distinct=False, 

647 ) 

648 tag = django_filters.ModelMultipleChoiceFilter( 

649 field_name='tag__slug', 

650 queryset=Tag.objects.all(), 

651 distinct=False, 

652 to_field_name='slug', 

653 ) 

654 

655 class Meta: 

656 model = TaggedItem 

657 fields = ('id', 'object_id') 

658 

659 def search(self, queryset, name, value): 

660 if not value.strip(): 

661 return queryset 

662 return queryset.filter( 

663 Q(tag__name__icontains=value) | 

664 Q(tag__slug__icontains=value) | 

665 Q(tag__description__icontains=value) 

666 ) 

667 

668 

669@register_filterset 

670class ConfigContextProfileFilterSet(PrimaryModelFilterSet): 

671 q = django_filters.CharFilter( 

672 method='search', 

673 label=_('Search'), 

674 ) 

675 data_source_id = django_filters.ModelMultipleChoiceFilter( 

676 queryset=DataSource.objects.all(), 

677 distinct=False, 

678 label=_('Data source (ID)'), 

679 ) 

680 data_file_id = django_filters.ModelMultipleChoiceFilter( 

681 queryset=DataSource.objects.all(), 

682 distinct=False, 

683 label=_('Data file (ID)'), 

684 ) 

685 

686 class Meta: 

687 model = ConfigContextProfile 

688 fields = ( 

689 'id', 'name', 'description', 'auto_sync_enabled', 'data_synced', 

690 ) 

691 

692 def search(self, queryset, name, value): 

693 if not value.strip(): 

694 return queryset 

695 return queryset.filter( 

696 Q(name__icontains=value) | 

697 Q(description__icontains=value) | 

698 Q(comments__icontains=value) 

699 ) 

700 

701 

702@register_filterset 

703class ConfigContextFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): 

704 q = django_filters.CharFilter( 

705 method='search', 

706 label=_('Search'), 

707 ) 

708 profile_id = django_filters.ModelMultipleChoiceFilter( 

709 queryset=ConfigContextProfile.objects.all(), 

710 distinct=False, 

711 label=_('Profile (ID)'), 

712 ) 

713 profile = django_filters.ModelMultipleChoiceFilter( 

714 field_name='profile__name', 

715 queryset=ConfigContextProfile.objects.all(), 

716 distinct=False, 

717 to_field_name='name', 

718 label=_('Profile (name)'), 

719 ) 

720 region_id = django_filters.ModelMultipleChoiceFilter( 

721 field_name='regions', 

722 queryset=Region.objects.all(), 

723 label=_('Region'), 

724 ) 

725 region = django_filters.ModelMultipleChoiceFilter( 

726 field_name='regions__slug', 

727 queryset=Region.objects.all(), 

728 to_field_name='slug', 

729 label=_('Region (slug)'), 

730 ) 

731 site_group = django_filters.ModelMultipleChoiceFilter( 

732 field_name='site_groups__slug', 

733 queryset=SiteGroup.objects.all(), 

734 to_field_name='slug', 

735 label=_('Site group (slug)'), 

736 ) 

737 site_group_id = django_filters.ModelMultipleChoiceFilter( 

738 field_name='site_groups', 

739 queryset=SiteGroup.objects.all(), 

740 label=_('Site group'), 

741 ) 

742 site_id = django_filters.ModelMultipleChoiceFilter( 

743 field_name='sites', 

744 queryset=Site.objects.all(), 

745 label=_('Site'), 

746 ) 

747 site = django_filters.ModelMultipleChoiceFilter( 

748 field_name='sites__slug', 

749 queryset=Site.objects.all(), 

750 to_field_name='slug', 

751 label=_('Site (slug)'), 

752 ) 

753 location_id = django_filters.ModelMultipleChoiceFilter( 

754 field_name='locations', 

755 queryset=Location.objects.all(), 

756 label=_('Location'), 

757 ) 

758 location = django_filters.ModelMultipleChoiceFilter( 

759 field_name='locations__slug', 

760 queryset=Location.objects.all(), 

761 to_field_name='slug', 

762 label=_('Location (slug)'), 

763 ) 

764 device_type_id = django_filters.ModelMultipleChoiceFilter( 

765 field_name='device_types', 

766 queryset=DeviceType.objects.all(), 

767 label=_('Device type'), 

768 ) 

769 device_role_id = django_filters.ModelMultipleChoiceFilter( 

770 field_name='roles', 

771 queryset=DeviceRole.objects.all(), 

772 label=_('Role'), 

773 ) 

774 device_role = django_filters.ModelMultipleChoiceFilter( 

775 field_name='roles__slug', 

776 queryset=DeviceRole.objects.all(), 

777 to_field_name='slug', 

778 label=_('Role (slug)'), 

779 ) 

780 platform_id = django_filters.ModelMultipleChoiceFilter( 

781 field_name='platforms', 

782 queryset=Platform.objects.all(), 

783 label=_('Platform'), 

784 ) 

785 platform = django_filters.ModelMultipleChoiceFilter( 

786 field_name='platforms__slug', 

787 queryset=Platform.objects.all(), 

788 to_field_name='slug', 

789 label=_('Platform (slug)'), 

790 ) 

791 cluster_type_id = django_filters.ModelMultipleChoiceFilter( 

792 field_name='cluster_types', 

793 queryset=ClusterType.objects.all(), 

794 label=_('Cluster type'), 

795 ) 

796 cluster_type = django_filters.ModelMultipleChoiceFilter( 

797 field_name='cluster_types__slug', 

798 queryset=ClusterType.objects.all(), 

799 to_field_name='slug', 

800 label=_('Cluster type (slug)'), 

801 ) 

802 cluster_group_id = django_filters.ModelMultipleChoiceFilter( 

803 field_name='cluster_groups', 

804 queryset=ClusterGroup.objects.all(), 

805 label=_('Cluster group'), 

806 ) 

807 cluster_group = django_filters.ModelMultipleChoiceFilter( 

808 field_name='cluster_groups__slug', 

809 queryset=ClusterGroup.objects.all(), 

810 to_field_name='slug', 

811 label=_('Cluster group (slug)'), 

812 ) 

813 cluster_id = django_filters.ModelMultipleChoiceFilter( 

814 field_name='clusters', 

815 queryset=Cluster.objects.all(), 

816 label=_('Cluster'), 

817 ) 

818 tenant_group_id = django_filters.ModelMultipleChoiceFilter( 

819 field_name='tenant_groups', 

820 queryset=TenantGroup.objects.all(), 

821 label=_('Tenant group'), 

822 ) 

823 tenant_group = django_filters.ModelMultipleChoiceFilter( 

824 field_name='tenant_groups__slug', 

825 queryset=TenantGroup.objects.all(), 

826 to_field_name='slug', 

827 label=_('Tenant group (slug)'), 

828 ) 

829 tenant_id = django_filters.ModelMultipleChoiceFilter( 

830 field_name='tenants', 

831 queryset=Tenant.objects.all(), 

832 label=_('Tenant'), 

833 ) 

834 tenant = django_filters.ModelMultipleChoiceFilter( 

835 field_name='tenants__slug', 

836 queryset=Tenant.objects.all(), 

837 to_field_name='slug', 

838 label=_('Tenant (slug)'), 

839 ) 

840 tag_id = django_filters.ModelMultipleChoiceFilter( 

841 field_name='tags', 

842 queryset=Tag.objects.all(), 

843 label=_('Tag'), 

844 ) 

845 tag = django_filters.ModelMultipleChoiceFilter( 

846 field_name='tags__slug', 

847 queryset=Tag.objects.all(), 

848 to_field_name='slug', 

849 label=_('Tag (slug)'), 

850 ) 

851 data_source_id = django_filters.ModelMultipleChoiceFilter( 

852 queryset=DataSource.objects.all(), 

853 distinct=False, 

854 label=_('Data source (ID)'), 

855 ) 

856 data_file_id = django_filters.ModelMultipleChoiceFilter( 

857 queryset=DataSource.objects.all(), 

858 distinct=False, 

859 label=_('Data file (ID)'), 

860 ) 

861 

862 class Meta: 

863 model = ConfigContext 

864 fields = ('id', 'name', 'is_active', 'description', 'weight', 'auto_sync_enabled', 'data_synced') 

865 

866 def search(self, queryset, name, value): 

867 if not value.strip(): 

868 return queryset 

869 return queryset.filter( 

870 Q(name__icontains=value) | 

871 Q(description__icontains=value) | 

872 Q(data__icontains=value) 

873 ) 

874 

875 

876@register_filterset 

877class ConfigTemplateFilterSet(OwnerFilterMixin, ChangeLoggedModelFilterSet): 

878 q = django_filters.CharFilter( 

879 method='search', 

880 label=_('Search'), 

881 ) 

882 data_source_id = django_filters.ModelMultipleChoiceFilter( 

883 queryset=DataSource.objects.all(), 

884 distinct=False, 

885 label=_('Data source (ID)'), 

886 ) 

887 data_file_id = django_filters.ModelMultipleChoiceFilter( 

888 queryset=DataSource.objects.all(), 

889 distinct=False, 

890 label=_('Data file (ID)'), 

891 ) 

892 tag = TagFilter() 

893 tag_id = TagIDFilter() 

894 

895 class Meta: 

896 model = ConfigTemplate 

897 fields = ( 

898 'id', 'name', 'description', 'mime_type', 'file_name', 'file_extension', 'as_attachment', 'debug', 

899 'auto_sync_enabled', 'data_synced' 

900 ) 

901 

902 def search(self, queryset, name, value): 

903 if not value.strip(): 

904 return queryset 

905 return queryset.filter( 

906 Q(name__icontains=value) | 

907 Q(description__icontains=value) 

908 ) 

909 

910 

911# 

912# Filter for Local Config Context Data 

913# 

914 

915class LocalConfigContextFilterSet(django_filters.FilterSet): 

916 local_context_data = django_filters.BooleanFilter( 

917 method='_local_context_data', 

918 label=_('Has local config context data'), 

919 ) 

920 

921 def _local_context_data(self, queryset, name, value): 

922 return queryset.exclude(local_context_data__isnull=value)