Merge pull request #2931 from DanSheps/2813-addtenantgroupfilter

Closes #2813: Add Filter and View on Lists for TenantGroup
This commit is contained in:
Jeremy Stretch 2019-05-09 13:48:46 -04:00 committed by GitHub
commit 7895ccfae1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 122 additions and 283 deletions

View File

@ -3,7 +3,7 @@ from django.db.models import Q
from dcim.models import Site from dcim.models import Site
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from tenancy.models import Tenant from tenancy.filterset import TenancyFilterSet
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
from .constants import CIRCUIT_STATUS_CHOICES from .constants import CIRCUIT_STATUS_CHOICES
from .models import Provider, Circuit, CircuitTermination, CircuitType from .models import Provider, Circuit, CircuitTermination, CircuitType
@ -54,7 +54,7 @@ class CircuitTypeFilter(NameSlugSearchFilterSet):
fields = ['name', 'slug'] fields = ['name', 'slug']
class CircuitFilter(CustomFieldFilterSet, django_filters.FilterSet): class CircuitFilter(CustomFieldFilterSet, TenancyFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -87,16 +87,6 @@ class CircuitFilter(CustomFieldFilterSet, django_filters.FilterSet):
choices=CIRCUIT_STATUS_CHOICES, choices=CIRCUIT_STATUS_CHOICES,
null_value=None null_value=None
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
site_id = django_filters.ModelMultipleChoiceFilter( site_id = django_filters.ModelMultipleChoiceFilter(
field_name='terminations__site', field_name='terminations__site',
queryset=Site.objects.all(), queryset=Site.objects.all(),

View File

@ -4,6 +4,7 @@ from taggit.forms import TagField
from dcim.models import Site from dcim.models import Site
from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from tenancy.formset import TenancyFilterForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField,
@ -265,8 +266,10 @@ class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit
] ]
class CircuitFilterForm(BootstrapMixin, CustomFieldFilterForm): class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = Circuit model = Circuit
# Order the form fields, fields not listed are appended
field_order = ['q', 'type', 'provider', 'status']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -292,16 +295,6 @@ class CircuitFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
site = FilterChoiceField( site = FilterChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
to_field_name='slug', to_field_name='slug',

View File

@ -7,7 +7,7 @@ from netaddr import EUI
from netaddr.core import AddrFormatError from netaddr.core import AddrFormatError
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from tenancy.models import Tenant from tenancy.filterset import TenancyFilterSet
from utilities.constants import COLOR_CHOICES from utilities.constants import COLOR_CHOICES
from utilities.filters import ( from utilities.filters import (
NameSlugSearchFilterSet, NullableCharFieldFilter, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter NameSlugSearchFilterSet, NullableCharFieldFilter, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter
@ -39,7 +39,7 @@ class RegionFilter(NameSlugSearchFilterSet):
fields = ['name', 'slug'] fields = ['name', 'slug']
class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet): class SiteFilter(TenancyFilterSet, CustomFieldFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -63,16 +63,6 @@ class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
to_field_name='slug', to_field_name='slug',
label='Region (slug)', label='Region (slug)',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
tag = TagFilter() tag = TagFilter()
class Meta: class Meta:
@ -124,7 +114,7 @@ class RackRoleFilter(NameSlugSearchFilterSet):
fields = ['name', 'slug', 'color'] fields = ['name', 'slug', 'color']
class RackFilter(CustomFieldFilterSet, django_filters.FilterSet): class RackFilter(TenancyFilterSet, CustomFieldFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -154,16 +144,6 @@ class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
to_field_name='slug', to_field_name='slug',
label='Group', label='Group',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
status = django_filters.MultipleChoiceFilter( status = django_filters.MultipleChoiceFilter(
choices=RACK_STATUS_CHOICES, choices=RACK_STATUS_CHOICES,
null_value=None null_value=None
@ -200,7 +180,7 @@ class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
) )
class RackReservationFilter(django_filters.FilterSet): class RackReservationFilter(TenancyFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -235,16 +215,6 @@ class RackReservationFilter(django_filters.FilterSet):
to_field_name='slug', to_field_name='slug',
label='Group', label='Group',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
user_id = django_filters.ModelMultipleChoiceFilter( user_id = django_filters.ModelMultipleChoiceFilter(
queryset=User.objects.all(), queryset=User.objects.all(),
label='User (ID)', label='User (ID)',
@ -450,7 +420,7 @@ class PlatformFilter(NameSlugSearchFilterSet):
fields = ['name', 'slug'] fields = ['name', 'slug']
class DeviceFilter(CustomFieldFilterSet): class DeviceFilter(TenancyFilterSet, CustomFieldFilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -485,16 +455,6 @@ class DeviceFilter(CustomFieldFilterSet):
to_field_name='slug', to_field_name='slug',
label='Role (slug)', label='Role (slug)',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
platform_id = django_filters.ModelMultipleChoiceFilter( platform_id = django_filters.ModelMultipleChoiceFilter(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
label='Platform (ID)', label='Platform (ID)',
@ -915,7 +875,7 @@ class InventoryItemFilter(DeviceComponentFilterSet):
return queryset.filter(qs_filter) return queryset.filter(qs_filter)
class VirtualChassisFilter(django_filters.FilterSet): class VirtualChassisFilter(TenancyFilterSet, django_filters.FilterSet):
q = django_filters.CharFilter( q = django_filters.CharFilter(
method='search', method='search',
label='Search', label='Search',
@ -931,17 +891,6 @@ class VirtualChassisFilter(django_filters.FilterSet):
to_field_name='slug', to_field_name='slug',
label='Site name (slug)', label='Site name (slug)',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
field_name='master__tenant',
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='master__tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
tag = TagFilter() tag = TagFilter()
class Meta: class Meta:

View File

@ -13,6 +13,7 @@ from timezone_field import TimeZoneFormField
from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from ipam.models import IPAddress, VLAN, VLANGroup from ipam.models import IPAddress, VLAN, VLANGroup
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from tenancy.formset import TenancyFilterForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm, APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm,
@ -256,8 +257,10 @@ class SiteBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
] ]
class SiteFilterForm(BootstrapMixin, CustomFieldFilterForm): class SiteFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = Site model = Site
# Order the form fields, fields not listed are appended
field_order = ['q', 'status', 'region']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -276,16 +279,6 @@ class SiteFilterForm(BootstrapMixin, CustomFieldFilterForm):
value_field="slug", value_field="slug",
) )
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
# #
@ -596,8 +589,10 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
] ]
class RackFilterForm(BootstrapMixin, CustomFieldFilterForm): class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = Rack model = Rack
# Order the form fields, fields not listed are appended
field_order = ['q', 'site', 'group_id']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -619,16 +614,6 @@ class RackFilterForm(BootstrapMixin, CustomFieldFilterForm):
null_option=True, null_option=True,
) )
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
status = forms.MultipleChoiceField( status = forms.MultipleChoiceField(
choices=RACK_STATUS_CHOICES, choices=RACK_STATUS_CHOICES,
required=False, required=False,
@ -689,7 +674,9 @@ class RackReservationForm(BootstrapMixin, TenancyForm, forms.ModelForm):
return unit_choices return unit_choices
class RackReservationFilterForm(BootstrapMixin, forms.Form): class RackReservationFilterForm(BootstrapMixin, TenancyFilterForm, forms.Form):
# Order the form fields, fields not listed are appended
field_order = ['q', 'site', 'group_id']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -711,16 +698,6 @@ class RackReservationFilterForm(BootstrapMixin, forms.Form):
null_option=True, null_option=True,
) )
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
class RackReservationBulkEditForm(BootstrapMixin, BulkEditForm): class RackReservationBulkEditForm(BootstrapMixin, BulkEditForm):
@ -1643,8 +1620,10 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
] ]
class DeviceFilterForm(BootstrapMixin, CustomFieldFilterForm): class DeviceFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = Device model = Device
# Order the form fields, fields not listed are appended
field_order = ['q', 'region', 'site', 'rack_group_id', 'rack_id', 'role']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -1702,16 +1681,6 @@ class DeviceFilterForm(BootstrapMixin, CustomFieldFilterForm):
value_field="slug", value_field="slug",
) )
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
manufacturer_id = FilterChoiceField( manufacturer_id = FilterChoiceField(
queryset=Manufacturer.objects.all(), queryset=Manufacturer.objects.all(),
label='Manufacturer', label='Manufacturer',

View File

@ -305,7 +305,7 @@ class RackDetailTable(RackTable):
class RackReservationTable(BaseTable): class RackReservationTable(BaseTable):
pk = ToggleColumn() pk = ToggleColumn()
tenant = tables.LinkColumn('tenancy:tenant', args=[Accessor('tenant.slug')]) tenant = tables.TemplateColumn(template_code=COL_TENANT)
rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')]) rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
unit_list = tables.Column(orderable=False, verbose_name='Units') unit_list = tables.Column(orderable=False, verbose_name='Units')
actions = tables.TemplateColumn( actions = tables.TemplateColumn(

View File

@ -4,7 +4,7 @@ from django.db.models import Q
from taggit.models import Tag from taggit.models import Tag
from dcim.models import DeviceRole, Platform, Region, Site from dcim.models import DeviceRole, Platform, Region, Site
from tenancy.models import Tenant, TenantGroup from tenancy.filterset import TenancyFilterSet
from .constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_TYPE_BOOLEAN, CF_TYPE_SELECT from .constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_TYPE_BOOLEAN, CF_TYPE_SELECT
from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, TopologyMap from .models import ConfigContext, CustomField, Graph, ExportTemplate, ObjectChange, TopologyMap
@ -122,7 +122,7 @@ class TopologyMapFilter(django_filters.FilterSet):
fields = ['name', 'slug'] fields = ['name', 'slug']
class ConfigContextFilter(django_filters.FilterSet): class ConfigContextFilter(TenancyFilterSet, django_filters.FilterSet):
q = django_filters.CharFilter( q = django_filters.CharFilter(
method='search', method='search',
label='Search', label='Search',
@ -171,28 +171,6 @@ class ConfigContextFilter(django_filters.FilterSet):
to_field_name='slug', to_field_name='slug',
label='Platform (slug)', label='Platform (slug)',
) )
tenant_group_id = django_filters.ModelMultipleChoiceFilter(
field_name='tenant_groups',
queryset=TenantGroup.objects.all(),
label='Tenant group',
)
tenant_group = django_filters.ModelMultipleChoiceFilter(
field_name='tenant_groups__slug',
queryset=TenantGroup.objects.all(),
to_field_name='slug',
label='Tenant group (slug)',
)
tenant_id = django_filters.ModelMultipleChoiceFilter(
field_name='tenants',
queryset=Tenant.objects.all(),
label='Tenant',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenants__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
class Meta: class Meta:
model = ConfigContext model = ConfigContext

View File

@ -8,7 +8,7 @@ from taggit.forms import TagField
from taggit.models import Tag from taggit.models import Tag
from dcim.models import DeviceRole, Platform, Region, Site from dcim.models import DeviceRole, Platform, Region, Site
from tenancy.models import Tenant, TenantGroup from tenancy.formset import TenancyFilterForm
from utilities.forms import ( from utilities.forms import (
add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ContentTypeSelect, add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ContentTypeSelect,
FilterChoiceField, LaxURLField, JSONField, SlugField, FilterChoiceField, LaxURLField, JSONField, SlugField,
@ -274,7 +274,7 @@ class ConfigContextBulkEditForm(BootstrapMixin, BulkEditForm):
] ]
class ConfigContextFilterForm(BootstrapMixin, forms.Form): class ConfigContextFilterForm(TenancyFilterForm, BootstrapMixin, forms.Form):
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -311,22 +311,10 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
value_field="slug", value_field="slug",
) )
) )
tenant_group = FilterChoiceField(
queryset=TenantGroup.objects.all(), class Meta:
to_field_name='slug', # Order the form fields, fields not listed are appended
widget=APISelectMultiple( field_order = ['q', 'type', 'provider', 'status']
api_url="/api/tenancy/tenant-groups/",
value_field="slug",
)
)
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
)
)
# #

View File

@ -6,14 +6,14 @@ from netaddr.core import AddrFormatError
from dcim.models import Site, Device, Interface from dcim.models import Site, Device, Interface
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from tenancy.models import Tenant from tenancy.filterset import TenancyFilterSet
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from .constants import IPADDRESS_ROLE_CHOICES, IPADDRESS_STATUS_CHOICES, PREFIX_STATUS_CHOICES, VLAN_STATUS_CHOICES from .constants import IPADDRESS_ROLE_CHOICES, IPADDRESS_STATUS_CHOICES, PREFIX_STATUS_CHOICES, VLAN_STATUS_CHOICES
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
class VRFFilter(CustomFieldFilterSet, django_filters.FilterSet): class VRFFilter(TenancyFilterSet, CustomFieldFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -22,16 +22,6 @@ class VRFFilter(CustomFieldFilterSet, django_filters.FilterSet):
method='search', method='search',
label='Search', label='Search',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
tag = TagFilter() tag = TagFilter()
def search(self, queryset, name, value): def search(self, queryset, name, value):
@ -107,7 +97,7 @@ class RoleFilter(NameSlugSearchFilterSet):
fields = ['name', 'slug'] fields = ['name', 'slug']
class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet): class PrefixFilter(TenancyFilterSet, CustomFieldFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -146,16 +136,6 @@ class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet):
to_field_name='rd', to_field_name='rd',
label='VRF (RD)', label='VRF (RD)',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (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)',
@ -254,7 +234,7 @@ class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet):
return queryset.filter(prefix__net_mask_length=value) return queryset.filter(prefix__net_mask_length=value)
class IPAddressFilter(CustomFieldFilterSet, django_filters.FilterSet): class IPAddressFilter(TenancyFilterSet, CustomFieldFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -285,16 +265,6 @@ class IPAddressFilter(CustomFieldFilterSet, django_filters.FilterSet):
to_field_name='rd', to_field_name='rd',
label='VRF (RD)', label='VRF (RD)',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
device = django_filters.CharFilter( device = django_filters.CharFilter(
method='filter_device', method='filter_device',
field_name='name', field_name='name',
@ -394,7 +364,7 @@ class VLANGroupFilter(NameSlugSearchFilterSet):
fields = ['name', 'slug'] fields = ['name', 'slug']
class VLANFilter(CustomFieldFilterSet, django_filters.FilterSet): class VLANFilter(TenancyFilterSet, CustomFieldFilterSet, django_filters.FilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -423,16 +393,6 @@ class VLANFilter(CustomFieldFilterSet, django_filters.FilterSet):
to_field_name='slug', to_field_name='slug',
label='Group', label='Group',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
role_id = django_filters.ModelMultipleChoiceFilter( role_id = django_filters.ModelMultipleChoiceFilter(
queryset=Role.objects.all(), queryset=Role.objects.all(),
label='Role (ID)', label='Role (ID)',

View File

@ -6,6 +6,7 @@ from taggit.forms import TagField
from dcim.models import Site, Rack, Device, Interface from dcim.models import Site, Rack, Device, Interface
from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from tenancy.formset import TenancyFilterForm
from tenancy.models import Tenant from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField, add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField,
@ -97,22 +98,14 @@ class VRFBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm
] ]
class VRFFilterForm(BootstrapMixin, CustomFieldFilterForm): class VRFFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = VRF model = VRF
# Order the form fields, fields not listed are appended
field_order = ['q']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
# #
@ -497,8 +490,10 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF
] ]
class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm): class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = Prefix model = Prefix
# Order the form fields, fields not listed are appended
field_order = ['q', 'within_include', 'family', 'mask_length', 'vrf']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -533,16 +528,6 @@ class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm):
null_option=True, null_option=True,
) )
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
status = forms.MultipleChoiceField( status = forms.MultipleChoiceField(
choices=PREFIX_STATUS_CHOICES, choices=PREFIX_STATUS_CHOICES,
required=False, required=False,
@ -944,8 +929,10 @@ class IPAddressAssignForm(BootstrapMixin, forms.Form):
) )
class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm): class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = IPAddress model = IPAddress
# Order the form fields, fields not listed are appended
field_order = ['q', 'parent', 'family', 'mask_length', 'vrf']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -980,16 +967,6 @@ class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm):
null_option=True, null_option=True,
) )
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
status = forms.MultipleChoiceField( status = forms.MultipleChoiceField(
choices=IPADDRESS_STATUS_CHOICES, choices=IPADDRESS_STATUS_CHOICES,
required=False, required=False,
@ -1221,8 +1198,10 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
] ]
class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm): class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = VLAN model = VLAN
# Order the form fields, fields not listed are appended
field_order = ['q', 'site', 'group_id']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -1246,16 +1225,6 @@ class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm):
null_option=True, null_option=True,
) )
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)
status = forms.MultipleChoiceField( status = forms.MultipleChoiceField(
choices=VLAN_STATUS_CHOICES, choices=VLAN_STATUS_CHOICES,
required=False, required=False,

View File

@ -319,6 +319,7 @@ class PrefixTable(BaseTable):
class PrefixDetailTable(PrefixTable): class PrefixDetailTable(PrefixTable):
utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False) utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False)
tenant = tables.TemplateColumn(template_code=COL_TENANT)
class Meta(PrefixTable.Meta): class Meta(PrefixTable.Meta):
fields = ('pk', 'prefix', 'status', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role', 'description') fields = ('pk', 'prefix', 'status', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role', 'description')
@ -349,6 +350,7 @@ class IPAddressDetailTable(IPAddressTable):
nat_inside = tables.LinkColumn( nat_inside = tables.LinkColumn(
'ipam:ipaddress', args=[Accessor('nat_inside.pk')], orderable=False, verbose_name='NAT (Inside)' 'ipam:ipaddress', args=[Accessor('nat_inside.pk')], orderable=False, verbose_name='NAT (Inside)'
) )
tenant = tables.TemplateColumn(template_code=COL_TENANT)
class Meta(IPAddressTable.Meta): class Meta(IPAddressTable.Meta):
fields = ( fields = (
@ -423,6 +425,7 @@ class VLANTable(BaseTable):
class VLANDetailTable(VLANTable): class VLANDetailTable(VLANTable):
prefixes = tables.TemplateColumn(VLAN_PREFIXES, orderable=False, verbose_name='Prefixes') prefixes = tables.TemplateColumn(VLAN_PREFIXES, orderable=False, verbose_name='Prefixes')
tenant = tables.TemplateColumn(template_code=COL_TENANT)
class Meta(VLANTable.Meta): class Meta(VLANTable.Meta):
fields = ('pk', 'vid', 'site', 'group', 'name', 'prefixes', 'tenant', 'status', 'role', 'description') fields = ('pk', 'vid', 'site', 'group', 'name', 'prefixes', 'tenant', 'status', 'role', 'description')

View File

@ -0,0 +1,27 @@
import django_filters
from .models import Tenant, TenantGroup
class TenancyFilterSet(django_filters.FilterSet):
tenant_group_id = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__group__id',
queryset=TenantGroup.objects.all(),
to_field_name='id',
label='Tenant Group (ID)',
)
tenant_group = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__group__slug',
queryset=TenantGroup.objects.all(),
to_field_name='slug',
label='Tenant Group (slug)',
)
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)

View File

@ -1,5 +1,4 @@
from django import forms from django import forms
from django.db.models import Count
from taggit.forms import TagField from taggit.forms import TagField
from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm from extras.forms import AddRemoveTagsForm, CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
@ -119,7 +118,6 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
# #
# Tenancy form extension # Tenancy form extension
# #
class TenancyForm(ChainedFieldsMixin, forms.Form): class TenancyForm(ChainedFieldsMixin, forms.Form):
tenant_group = forms.ModelChoiceField( tenant_group = forms.ModelChoiceField(
queryset=TenantGroup.objects.all(), queryset=TenantGroup.objects.all(),

32
netbox/tenancy/formset.py Normal file
View File

@ -0,0 +1,32 @@
from django import forms
from utilities.forms import APISelectMultiple, FilterChoiceField
from .models import Tenant, TenantGroup
#
# Tenancy filtering form extension
#
class TenancyFilterForm(forms.Form):
tenant_group = FilterChoiceField(
queryset=TenantGroup.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenant-groups/",
value_field="slug",
null_option=True,
filter_for={
'tenant': 'group'
}
)
)
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url="/api/tenancy/tenants/",
value_field="slug",
null_option=True,
)
)

View File

@ -6,7 +6,7 @@ from netaddr.core import AddrFormatError
from dcim.models import DeviceRole, Interface, Platform, Region, Site from dcim.models import DeviceRole, Interface, Platform, Region, Site
from extras.filters import CustomFieldFilterSet from extras.filters import CustomFieldFilterSet
from tenancy.models import Tenant from tenancy.filterset import TenancyFilterSet
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter
from .constants import VM_STATUS_CHOICES from .constants import VM_STATUS_CHOICES
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
@ -80,7 +80,7 @@ class ClusterFilter(CustomFieldFilterSet):
) )
class VirtualMachineFilter(CustomFieldFilterSet): class VirtualMachineFilter(TenancyFilterSet, CustomFieldFilterSet):
id__in = NumericInFilter( id__in = NumericInFilter(
field_name='id', field_name='id',
lookup_expr='in' lookup_expr='in'
@ -151,16 +151,6 @@ class VirtualMachineFilter(CustomFieldFilterSet):
to_field_name='slug', to_field_name='slug',
label='Role (slug)', label='Role (slug)',
) )
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
label='Tenant (ID)',
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
label='Tenant (slug)',
)
platform_id = django_filters.ModelMultipleChoiceFilter( platform_id = django_filters.ModelMultipleChoiceFilter(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
label='Platform (ID)', label='Platform (ID)',

View File

@ -8,7 +8,8 @@ from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, S
from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
from ipam.models import IPAddress from ipam.models import IPAddress
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from tenancy.models import Tenant from tenancy.formset import TenancyFilterForm
from tenancy.models import Tenant, TenantGroup
from utilities.forms import ( from utilities.forms import (
add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, add_blank_choice, APISelect, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
ChainedFieldsMixin, ChainedModelChoiceField, ChainedModelMultipleChoiceField, CommentField, ComponentForm, ChainedFieldsMixin, ChainedModelChoiceField, ChainedModelMultipleChoiceField, CommentField, ComponentForm,
@ -336,7 +337,7 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
class Meta: class Meta:
model = VirtualMachine model = VirtualMachine
fields = [ fields = [
'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant_group', 'tenant', 'platform', 'primary_ip4', 'primary_ip6',
'vcpus', 'memory', 'disk', 'comments', 'tags', 'local_context_data', 'vcpus', 'memory', 'disk', 'comments', 'tags', 'local_context_data',
] ]
help_texts = { help_texts = {
@ -520,8 +521,10 @@ class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldB
] ]
class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm): class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm):
model = VirtualMachine model = VirtualMachine
# Order the form fields, fields not listed are appended
field_order = ['q', 'cluster_group', 'cluster_type', 'cluster_id', 'region', 'site']
q = forms.CharField( q = forms.CharField(
required=False, required=False,
label='Search' label='Search'
@ -591,16 +594,6 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
required=False, required=False,
widget=StaticSelect2Multiple() widget=StaticSelect2Multiple()
) )
tenant = FilterChoiceField(
queryset=Tenant.objects.all(),
to_field_name='slug',
null_label='-- None --',
widget=APISelectMultiple(
api_url='/api/tenancy/tenants/',
value_field="slug",
null_option=True,
)
)
platform = FilterChoiceField( platform = FilterChoiceField(
queryset=Platform.objects.all(), queryset=Platform.objects.all(),
to_field_name='slug', to_field_name='slug',