Repository: netbox-community/netbox
Pull request: Closes #8998: Add site group filter to racks
<!--
    Thank you for your interest in contributing to NetBox! Please note
    that our contribution policy requires that a feature request or bug
    report be opened for approval prior to filing a pull request. This
    helps avoid wasting time and effort on something that we might not
    be able to accept.

    Please indicate the relevant feature request or bug report below.
    IF YOUR PULL REQUEST DOES NOT REFERENCE AN ACCEPTED BUG REPORT OR
    FEATURE REQUEST, IT WILL BE MARKED AS INVALID AND CLOSED.
-->
### Fixes: #8998 
<!--
    Please include a summary of the proposed changes below.
-->


Problem statement:
Add site_group filter everywhere region is set
### NetBox version

v3.1.10

### Feature type

Change to existing functionality

### Proposed functionality

Anywhere region currently exists as a filter, site group should exist as an option.

### Use case

Let's say I want to filter racks in datacenters, I cannot do that today.

### Database changes

N/A

### External dependencies

N/A

Hints from issue discussion:

Commit message: Closes #8998: Add site group filter to racks

Patch to review:
diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py
index 0f4e7cf7e3a..4910e794d49 100644
--- a/netbox/dcim/filtersets.py
+++ b/netbox/dcim/filtersets.py
@@ -346,6 +346,19 @@ class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
         to_field_name='slug',
         label='Site (slug)',
     )
+    site_group_id = TreeNodeMultipleChoiceFilter(
+        queryset=SiteGroup.objects.all(),
+        field_name='rack__site__group',
+        lookup_expr='in',
+        label='Site group (ID)',
+    )
+    site_group = TreeNodeMultipleChoiceFilter(
+        queryset=SiteGroup.objects.all(),
+        field_name='rack__site__group',
+        lookup_expr='in',
+        to_field_name='slug',
+        label='Site group (slug)',
+    )
     location_id = TreeNodeMultipleChoiceFilter(
         queryset=Location.objects.all(),
         field_name='rack__location',
diff --git a/netbox/dcim/forms/filtersets.py b/netbox/dcim/forms/filtersets.py
index d5335947a85..079927ea35e 100644
--- a/netbox/dcim/forms/filtersets.py
+++ b/netbox/dcim/forms/filtersets.py
@@ -210,7 +210,7 @@ class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte
     model = Rack
     fieldsets = (
         (None, ('q', 'tag')),
-        ('Location', ('region_id', 'site_id', 'location_id')),
+        ('Location', ('region_id', 'site_id', 'site_group_id', 'location_id')),
         ('Function', ('status', 'role_id')),
         ('Hardware', ('type', 'width', 'serial', 'asset_tag')),
         ('Tenant', ('tenant_group_id', 'tenant_id')),
@@ -229,6 +229,11 @@ class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte
         },
         label=_('Site')
     )
+    site_group_id = DynamicModelMultipleChoiceField(
+        queryset=SiteGroup.objects.all(),
+        required=False,
+        label=_('Site group')
+    )
     location_id = DynamicModelMultipleChoiceField(
         queryset=Location.objects.all(),
         required=False,
@@ -282,7 +287,7 @@ class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
     fieldsets = (
         (None, ('q', 'tag')),
         ('User', ('user_id',)),
-        ('Rack', ('region_id', 'site_id', 'location_id')),
+        ('Rack', ('region_id', 'site_id', 'site_group_id', 'location_id')),
         ('Tenant', ('tenant_group_id', 'tenant_id')),
     )
     region_id = DynamicModelMultipleChoiceField(
@@ -298,6 +303,11 @@ class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
         },
         label=_('Site')
     )
+    site_group_id = DynamicModelMultipleChoiceField(
+        queryset=SiteGroup.objects.all(),
+        required=False,
+        label=_('Site group')
+    )
     location_id = DynamicModelMultipleChoiceField(
         queryset=Location.objects.prefetch_related('site'),
         required=False,


Code review comments:
diff_hunk: @@ -282,7 +287,7 @@ class RackReservationFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
     fieldsets = (
         (None, ('q', 'tag')),
         ('User', ('user_id',)),
-        ('Rack', ('region_id', 'site_id', 'location_id')),
+        ('Rack', ('region_id', 'site_id', 'site_group_id', 'location_id')),
path: netbox/dcim/forms/filtersets.py
text: @user1:
```suggestion
        ('Rack', ('region_id', 'site_group_id', 'site_id', 'location_id')),
```

diff_hunk: @@ -210,7 +210,7 @@ class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilte
     model = Rack
     fieldsets = (
         (None, ('q', 'tag')),
-        ('Location', ('region_id', 'site_id', 'location_id')),
+        ('Location', ('region_id', 'site_id', 'site_group_id', 'location_id')),
path: netbox/dcim/forms/filtersets.py
text: @user1:
Let's move site group before site to maintain hierarchical order.

```suggestion
        ('Location', ('region_id', 'site_group_id', 'site_id', 'location_id')),
```