mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-25 01:48:38 -06:00
commit
5c07b6dc1d
@ -1,3 +1,12 @@
|
|||||||
|
# v2.6.11 (2020-01-03)
|
||||||
|
|
||||||
|
## Bug Fixes
|
||||||
|
|
||||||
|
* [#3831](https://github.com/netbox-community/netbox/issues/3831) - Fix API-driven filter field rendering (#3812 regression)
|
||||||
|
* [#3833](https://github.com/netbox-community/netbox/issues/3833) - Add missing region filters for multiple objects
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
# v2.6.10 (2020-01-02)
|
# v2.6.10 (2020-01-02)
|
||||||
|
|
||||||
## Enhancements
|
## Enhancements
|
||||||
|
@ -18,6 +18,17 @@ class ProviderFilter(CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='circuits__terminations__site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='circuits__terminations__site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
field_name='circuits__terminations__site',
|
field_name='circuits__terminations__site',
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
|
@ -104,6 +104,18 @@ class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False,
|
required=False,
|
||||||
label='Search'
|
label='Search'
|
||||||
)
|
)
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -302,6 +314,9 @@ class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm
|
|||||||
widget=APISelectMultiple(
|
widget=APISelectMultiple(
|
||||||
api_url="/api/dcim/regions/",
|
api_url="/api/dcim/regions/",
|
||||||
value_field="slug",
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
|
@ -93,6 +93,17 @@ class SiteFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet
|
|||||||
|
|
||||||
|
|
||||||
class RackGroupFilter(NameSlugSearchFilterSet):
|
class RackGroupFilter(NameSlugSearchFilterSet):
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
label='Site (ID)',
|
label='Site (ID)',
|
||||||
@ -125,6 +136,17 @@ class RackFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
label='Site (ID)',
|
label='Site (ID)',
|
||||||
@ -831,6 +853,28 @@ class InventoryItemFilter(DeviceComponentFilterSet):
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='device__site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='device__site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
|
field_name='device__site',
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
label='Site (ID)',
|
||||||
|
)
|
||||||
|
site = django_filters.ModelMultipleChoiceFilter(
|
||||||
|
field_name='device__site__slug',
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Site name (slug)',
|
||||||
|
)
|
||||||
device_id = django_filters.ModelChoiceFilter(
|
device_id = django_filters.ModelChoiceFilter(
|
||||||
queryset=Device.objects.all(),
|
queryset=Device.objects.all(),
|
||||||
label='Device (ID)',
|
label='Device (ID)',
|
||||||
@ -880,6 +924,17 @@ class VirtualChassisFilter(django_filters.FilterSet):
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='master__site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='master__site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
field_name='master__site',
|
field_name='master__site',
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
@ -1078,6 +1133,17 @@ class PowerPanelFilter(django_filters.FilterSet):
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
label='Site (ID)',
|
label='Site (ID)',
|
||||||
@ -1116,6 +1182,17 @@ class PowerFeedFilter(CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='power_panel__site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='power_panel__site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
field_name='power_panel__site',
|
field_name='power_panel__site',
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
|
@ -364,6 +364,18 @@ class RackGroupCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class RackGroupFilterForm(BootstrapMixin, forms.Form):
|
class RackGroupFilterForm(BootstrapMixin, forms.Form):
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -635,11 +647,23 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
|
|||||||
|
|
||||||
class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
||||||
model = Rack
|
model = Rack
|
||||||
field_order = ['q', 'site', 'group_id', 'status', 'role', 'tenant_group', 'tenant']
|
field_order = ['q', 'region', 'site', 'group_id', 'status', 'role', 'tenant_group', 'tenant']
|
||||||
q = forms.CharField(
|
q = forms.CharField(
|
||||||
required=False,
|
required=False,
|
||||||
label='Search'
|
label='Search'
|
||||||
)
|
)
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -651,16 +675,15 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
group_id = ChainedModelChoiceField(
|
group_id = FilterChoiceField(
|
||||||
label='Rack group',
|
queryset=RackGroup.objects.prefetch_related(
|
||||||
queryset=RackGroup.objects.prefetch_related('site'),
|
'site'
|
||||||
chains=(
|
|
||||||
('site', 'site'),
|
|
||||||
),
|
),
|
||||||
required=False,
|
label='Rack group',
|
||||||
|
null_label='-- None --',
|
||||||
widget=APISelectMultiple(
|
widget=APISelectMultiple(
|
||||||
api_url="/api/dcim/rack-groups/",
|
api_url="/api/dcim/rack-groups/",
|
||||||
null_option=True,
|
null_option=True
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
@ -3387,6 +3410,29 @@ class InventoryItemFilterForm(BootstrapMixin, forms.Form):
|
|||||||
required=False,
|
required=False,
|
||||||
label='Search'
|
label='Search'
|
||||||
)
|
)
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
site = FilterChoiceField(
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/sites/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'device_id': 'site'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
device_id = FilterChoiceField(
|
device_id = FilterChoiceField(
|
||||||
queryset=Device.objects.all(),
|
queryset=Device.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@ -3552,6 +3598,18 @@ class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False,
|
required=False,
|
||||||
label='Search'
|
label='Search'
|
||||||
)
|
)
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -3657,6 +3715,18 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False,
|
required=False,
|
||||||
label='Search'
|
label='Search'
|
||||||
)
|
)
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -3877,6 +3947,18 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False,
|
required=False,
|
||||||
label='Search'
|
label='Search'
|
||||||
)
|
)
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
|
@ -4,10 +4,10 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from netaddr.core import AddrFormatError
|
from netaddr.core import AddrFormatError
|
||||||
|
|
||||||
from dcim.models import Site, Device, Interface
|
from dcim.models import Device, Interface, Region, Site
|
||||||
from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet
|
from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet
|
||||||
from tenancy.filtersets import TenancyFilterSet
|
from tenancy.filtersets import TenancyFilterSet
|
||||||
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
|
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
from .constants import *
|
from .constants import *
|
||||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||||
@ -149,6 +149,17 @@ class PrefixFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterS
|
|||||||
to_field_name='rd',
|
to_field_name='rd',
|
||||||
label='VRF (RD)',
|
label='VRF (RD)',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
label='Site (ID)',
|
label='Site (ID)',
|
||||||
@ -375,6 +386,17 @@ class IPAddressFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilt
|
|||||||
|
|
||||||
|
|
||||||
class VLANGroupFilter(NameSlugSearchFilterSet):
|
class VLANGroupFilter(NameSlugSearchFilterSet):
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
label='Site (ID)',
|
label='Site (ID)',
|
||||||
@ -400,6 +422,17 @@ class VLANFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
label='Site (ID)',
|
label='Site (ID)',
|
||||||
|
@ -3,7 +3,7 @@ from django.core.exceptions import MultipleObjectsReturned
|
|||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from taggit.forms import TagField
|
from taggit.forms import TagField
|
||||||
|
|
||||||
from dcim.models import Site, Rack, Device, Interface
|
from dcim.models import Device, Interface, Rack, Region, Site
|
||||||
from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
|
from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
|
||||||
from tenancy.forms import TenancyFilterForm, TenancyForm
|
from tenancy.forms import TenancyFilterForm, TenancyForm
|
||||||
from tenancy.models import Tenant
|
from tenancy.models import Tenant
|
||||||
@ -492,8 +492,8 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
|
|||||||
class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
||||||
model = Prefix
|
model = Prefix
|
||||||
field_order = [
|
field_order = [
|
||||||
'q', 'within_include', 'family', 'mask_length', 'vrf_id', 'status', 'site', 'role', 'tenant_group', 'tenant',
|
'q', 'within_include', 'family', 'mask_length', 'vrf_id', 'status', 'region', 'site', 'role', 'tenant_group',
|
||||||
'is_pool', 'expand',
|
'tenant', 'is_pool', 'expand',
|
||||||
]
|
]
|
||||||
q = forms.CharField(
|
q = forms.CharField(
|
||||||
required=False,
|
required=False,
|
||||||
@ -534,6 +534,18 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm)
|
|||||||
required=False,
|
required=False,
|
||||||
widget=StaticSelect2Multiple()
|
widget=StaticSelect2Multiple()
|
||||||
)
|
)
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -1034,6 +1046,18 @@ class VLANGroupCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class VLANGroupFilterForm(BootstrapMixin, forms.Form):
|
class VLANGroupFilterForm(BootstrapMixin, forms.Form):
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -1215,11 +1239,24 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
|
|||||||
|
|
||||||
class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
|
||||||
model = VLAN
|
model = VLAN
|
||||||
field_order = ['q', 'site', 'group_id', 'status', 'role', 'tenant_group', 'tenant']
|
field_order = ['q', 'region', 'site', 'group_id', 'status', 'role', 'tenant_group', 'tenant']
|
||||||
q = forms.CharField(
|
q = forms.CharField(
|
||||||
required=False,
|
required=False,
|
||||||
label='Search'
|
label='Search'
|
||||||
)
|
)
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region',
|
||||||
|
'group_id': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
|
@ -12,7 +12,7 @@ from django.core.exceptions import ImproperlyConfigured
|
|||||||
# Environment setup
|
# Environment setup
|
||||||
#
|
#
|
||||||
|
|
||||||
VERSION = '2.6.10'
|
VERSION = '2.6.11'
|
||||||
|
|
||||||
# Hostname
|
# Hostname
|
||||||
HOSTNAME = platform.node()
|
HOSTNAME = platform.node()
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
<select name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>{% for group_name, group_choices, group_index in widget.optgroups %}{% if group_name %}
|
<select name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
|
||||||
<optgroup label="{{ group_name }}">{% endif %}{% for widget in group_choices %}{% if widget.attrs.selected %}
|
{% for group_name, group_choices, group_index in widget.optgroups %}
|
||||||
{% include widget.template_name %}{% endif %}{% endfor %}{% if group_name %}
|
{% if group_name %}<optgroup label="{{ group_name }}">{% endif %}
|
||||||
</optgroup>{% endif %}{% endfor %}
|
{% for option in group_choices %}
|
||||||
|
{% if option.attrs.selected or option.value == "null" %}{% include option.template_name with widget=option %}{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% if group_name %}</optgroup>{% endif %}
|
||||||
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
@ -36,6 +36,27 @@ class ClusterFilter(CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
label='Region (ID)',
|
||||||
|
)
|
||||||
|
region = TreeNodeMultipleChoiceFilter(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
field_name='site__region__in',
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Region (slug)',
|
||||||
|
)
|
||||||
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
label='Site (ID)',
|
||||||
|
)
|
||||||
|
site = django_filters.ModelMultipleChoiceFilter(
|
||||||
|
field_name='site__slug',
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
label='Site (slug)',
|
||||||
|
)
|
||||||
group_id = django_filters.ModelMultipleChoiceFilter(
|
group_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=ClusterGroup.objects.all(),
|
queryset=ClusterGroup.objects.all(),
|
||||||
label='Parent group (ID)',
|
label='Parent group (ID)',
|
||||||
@ -56,16 +77,6 @@ class ClusterFilter(CustomFieldFilterSet, CreatedUpdatedFilterSet):
|
|||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
label='Cluster type (slug)',
|
label='Cluster type (slug)',
|
||||||
)
|
)
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
|
||||||
queryset=Site.objects.all(),
|
|
||||||
label='Site (ID)',
|
|
||||||
)
|
|
||||||
site = django_filters.ModelMultipleChoiceFilter(
|
|
||||||
field_name='site__slug',
|
|
||||||
queryset=Site.objects.all(),
|
|
||||||
to_field_name='slug',
|
|
||||||
label='Site (slug)',
|
|
||||||
)
|
|
||||||
tag = TagFilter()
|
tag = TagFilter()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -173,6 +173,29 @@ class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
|
|||||||
class ClusterFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class ClusterFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = Cluster
|
model = Cluster
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(required=False, label='Search')
|
||||||
|
region = FilterChoiceField(
|
||||||
|
queryset=Region.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/regions/",
|
||||||
|
value_field="slug",
|
||||||
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
site = FilterChoiceField(
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
to_field_name='slug',
|
||||||
|
null_label='-- None --',
|
||||||
|
required=False,
|
||||||
|
widget=APISelectMultiple(
|
||||||
|
api_url="/api/dcim/sites/",
|
||||||
|
value_field='slug',
|
||||||
|
null_option=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
type = FilterChoiceField(
|
type = FilterChoiceField(
|
||||||
queryset=ClusterType.objects.all(),
|
queryset=ClusterType.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -193,17 +216,6 @@ class ClusterFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
null_option=True,
|
null_option=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
site = FilterChoiceField(
|
|
||||||
queryset=Site.objects.all(),
|
|
||||||
to_field_name='slug',
|
|
||||||
null_label='-- None --',
|
|
||||||
required=False,
|
|
||||||
widget=APISelectMultiple(
|
|
||||||
api_url="/api/dcim/sites/",
|
|
||||||
value_field='slug',
|
|
||||||
null_option=True,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
||||||
@ -563,7 +575,9 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
|
|||||||
widget=APISelectMultiple(
|
widget=APISelectMultiple(
|
||||||
api_url='/api/dcim/regions/',
|
api_url='/api/dcim/regions/',
|
||||||
value_field="slug",
|
value_field="slug",
|
||||||
null_option=True,
|
filter_for={
|
||||||
|
'site': 'region'
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
|
Loading…
Reference in New Issue
Block a user