mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Fixes #2781: Fixes filter by regions on site and device list
* Add Device filter
This commit is contained in:
parent
8683efe54a
commit
b4d7f9ea43
@ -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, TenantGroup
|
from tenancy.filters 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,28 +87,6 @@ class CircuitFilter(CustomFieldFilterSet, django_filters.FilterSet):
|
|||||||
choices=CIRCUIT_STATUS_CHOICES,
|
choices=CIRCUIT_STATUS_CHOICES,
|
||||||
null_value=None
|
null_value=None
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
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(),
|
||||||
|
@ -3,8 +3,8 @@ 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, TenancyFilterForm
|
||||||
from tenancy.models import Tenant, TenantGroup
|
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,
|
||||||
FilterChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple
|
FilterChoiceField, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple
|
||||||
@ -265,8 +265,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,29 +294,6 @@ class CircuitFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False,
|
required=False,
|
||||||
widget=StaticSelect2Multiple()
|
widget=StaticSelect2Multiple()
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
|||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from tenancy.tables import COL_TENANTGROUP_TENANT
|
from tenancy.tables import COL_TENANT
|
||||||
from utilities.tables import BaseTable, ToggleColumn
|
from utilities.tables import BaseTable, ToggleColumn
|
||||||
from .models import Circuit, CircuitType, Provider
|
from .models import Circuit, CircuitType, Provider
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ class CircuitTable(BaseTable):
|
|||||||
cid = tables.LinkColumn(verbose_name='ID')
|
cid = tables.LinkColumn(verbose_name='ID')
|
||||||
provider = tables.LinkColumn('circuits:provider', args=[Accessor('provider.slug')])
|
provider = tables.LinkColumn('circuits:provider', args=[Accessor('provider.slug')])
|
||||||
status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
|
status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
|
||||||
tenant = tables.TemplateColumn(template_code=COL_TENANTGROUP_TENANT)
|
tenant = tables.TemplateColumn(template_code=COL_TENANT)
|
||||||
termination_a = CircuitTerminationColumn(orderable=False, verbose_name='A Side')
|
termination_a = CircuitTerminationColumn(orderable=False, verbose_name='A Side')
|
||||||
termination_z = CircuitTerminationColumn(orderable=False, verbose_name='Z Side')
|
termination_z = CircuitTerminationColumn(orderable=False, verbose_name='Z Side')
|
||||||
|
|
||||||
|
@ -6,7 +6,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, TenantGroup
|
from tenancy.filters import TenancyFilterSet
|
||||||
from utilities.constants import COLOR_CHOICES
|
from utilities.constants import COLOR_CHOICES
|
||||||
from utilities.filters import NameSlugSearchFilterSet, NullableCharFieldFilter, NumericInFilter, TagFilter
|
from utilities.filters import NameSlugSearchFilterSet, NullableCharFieldFilter, NumericInFilter, TagFilter
|
||||||
from virtualization.models import Cluster
|
from virtualization.models import Cluster
|
||||||
@ -36,7 +36,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'
|
||||||
@ -59,28 +59,6 @@ class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
|
|||||||
field_name='slug',
|
field_name='slug',
|
||||||
label='Region (slug)',
|
label='Region (slug)',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
tag = TagFilter()
|
tag = TagFilter()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -142,7 +120,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'
|
||||||
@ -172,28 +150,6 @@ class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
|
|||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
label='Group',
|
label='Group',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
status = django_filters.MultipleChoiceFilter(
|
status = django_filters.MultipleChoiceFilter(
|
||||||
choices=RACK_STATUS_CHOICES,
|
choices=RACK_STATUS_CHOICES,
|
||||||
null_value=None
|
null_value=None
|
||||||
@ -230,7 +186,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'
|
||||||
@ -265,28 +221,6 @@ class RackReservationFilter(django_filters.FilterSet):
|
|||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
label='Group',
|
label='Group',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
user_id = django_filters.ModelMultipleChoiceFilter(
|
user_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=User.objects.all(),
|
queryset=User.objects.all(),
|
||||||
label='User (ID)',
|
label='User (ID)',
|
||||||
@ -492,7 +426,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'
|
||||||
@ -527,28 +461,6 @@ class DeviceFilter(CustomFieldFilterSet):
|
|||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
label='Role (slug)',
|
label='Role (slug)',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
platform_id = django_filters.ModelMultipleChoiceFilter(
|
platform_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Platform.objects.all(),
|
queryset=Platform.objects.all(),
|
||||||
label='Platform (ID)',
|
label='Platform (ID)',
|
||||||
@ -978,7 +890,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',
|
||||||
@ -994,17 +906,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:
|
||||||
|
@ -12,8 +12,8 @@ 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, TenancyFilterForm
|
||||||
from tenancy.models import Tenant, TenantGroup
|
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,
|
||||||
BulkEditNullBooleanSelect, ChainedFieldsMixin, ChainedModelChoiceField, ColorSelect, CommentField,
|
BulkEditNullBooleanSelect, ChainedFieldsMixin, ChainedModelChoiceField, ColorSelect, CommentField,
|
||||||
@ -256,8 +256,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,29 +278,6 @@ class SiteFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
value_field="slug",
|
value_field="slug",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -609,8 +588,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'
|
||||||
@ -632,29 +613,6 @@ class RackFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
null_option=True,
|
null_option=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=RACK_STATUS_CHOICES,
|
choices=RACK_STATUS_CHOICES,
|
||||||
required=False,
|
required=False,
|
||||||
@ -715,7 +673,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'
|
||||||
@ -737,29 +697,6 @@ class RackReservationFilterForm(BootstrapMixin, forms.Form):
|
|||||||
null_option=True,
|
null_option=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class RackReservationBulkEditForm(BootstrapMixin, BulkEditForm):
|
class RackReservationBulkEditForm(BootstrapMixin, BulkEditForm):
|
||||||
@ -1682,8 +1619,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'
|
||||||
@ -1742,29 +1681,6 @@ class DeviceFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
null_option=True,
|
null_option=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
manufacturer_id = FilterChoiceField(
|
manufacturer_id = FilterChoiceField(
|
||||||
queryset=Manufacturer.objects.all(),
|
queryset=Manufacturer.objects.all(),
|
||||||
label='Manufacturer',
|
label='Manufacturer',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from tenancy.tables import COL_TENANT, COL_TENANTGROUP_TENANT
|
from tenancy.tables import COL_TENANT
|
||||||
from utilities.tables import BaseTable, BooleanColumn, ColorColumn, ToggleColumn
|
from utilities.tables import BaseTable, BooleanColumn, ColorColumn, ToggleColumn
|
||||||
from .models import (
|
from .models import (
|
||||||
Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
|
Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
|
||||||
@ -214,7 +214,7 @@ class SiteTable(BaseTable):
|
|||||||
name = tables.LinkColumn(order_by=('_nat1', '_nat2', '_nat3'))
|
name = tables.LinkColumn(order_by=('_nat1', '_nat2', '_nat3'))
|
||||||
status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
|
status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
|
||||||
region = tables.TemplateColumn(template_code=SITE_REGION_LINK)
|
region = tables.TemplateColumn(template_code=SITE_REGION_LINK)
|
||||||
tenant = tables.TemplateColumn(template_code=COL_TENANTGROUP_TENANT)
|
tenant = tables.TemplateColumn(template_code=COL_TENANT)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = Site
|
model = Site
|
||||||
@ -275,7 +275,7 @@ class RackTable(BaseTable):
|
|||||||
name = tables.LinkColumn(order_by=('_nat1', '_nat2', '_nat3'))
|
name = tables.LinkColumn(order_by=('_nat1', '_nat2', '_nat3'))
|
||||||
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
|
group = tables.Column(accessor=Accessor('group.name'), verbose_name='Group')
|
||||||
tenant = tables.TemplateColumn(template_code=COL_TENANTGROUP_TENANT)
|
tenant = tables.TemplateColumn(template_code=COL_TENANT)
|
||||||
status = tables.TemplateColumn(STATUS_LABEL)
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
role = tables.TemplateColumn(RACK_ROLE)
|
role = tables.TemplateColumn(RACK_ROLE)
|
||||||
u_height = tables.TemplateColumn("{{ record.u_height }}U", verbose_name='Height')
|
u_height = tables.TemplateColumn("{{ record.u_height }}U", verbose_name='Height')
|
||||||
@ -305,7 +305,7 @@ class RackDetailTable(RackTable):
|
|||||||
|
|
||||||
class RackReservationTable(BaseTable):
|
class RackReservationTable(BaseTable):
|
||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
tenant = tables.TemplateColumn(template_code=COL_TENANTGROUP_TENANT)
|
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(
|
||||||
@ -512,7 +512,7 @@ class DeviceTable(BaseTable):
|
|||||||
template_code=DEVICE_LINK
|
template_code=DEVICE_LINK
|
||||||
)
|
)
|
||||||
status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
|
status = tables.TemplateColumn(template_code=STATUS_LABEL, verbose_name='Status')
|
||||||
tenant = tables.TemplateColumn(template_code=COL_TENANTGROUP_TENANT)
|
tenant = tables.TemplateColumn(template_code=COL_TENANT)
|
||||||
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
|
rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')])
|
||||||
device_role = tables.TemplateColumn(DEVICE_ROLE, verbose_name='Role')
|
device_role = tables.TemplateColumn(DEVICE_ROLE, verbose_name='Role')
|
||||||
|
@ -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, TenantGroup
|
from tenancy.filters 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,28 +22,6 @@ class VRFFilter(CustomFieldFilterSet, django_filters.FilterSet):
|
|||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
tag = TagFilter()
|
tag = TagFilter()
|
||||||
|
|
||||||
def search(self, queryset, name, value):
|
def search(self, queryset, name, value):
|
||||||
@ -119,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'
|
||||||
@ -158,28 +136,6 @@ class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet):
|
|||||||
to_field_name='rd',
|
to_field_name='rd',
|
||||||
label='VRF (RD)',
|
label='VRF (RD)',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
site_id = django_filters.ModelMultipleChoiceFilter(
|
site_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
label='Site (ID)',
|
label='Site (ID)',
|
||||||
@ -278,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'
|
||||||
@ -309,28 +265,6 @@ class IPAddressFilter(CustomFieldFilterSet, django_filters.FilterSet):
|
|||||||
to_field_name='rd',
|
to_field_name='rd',
|
||||||
label='VRF (RD)',
|
label='VRF (RD)',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
device = django_filters.CharFilter(
|
device = django_filters.CharFilter(
|
||||||
method='filter_device',
|
method='filter_device',
|
||||||
field_name='name',
|
field_name='name',
|
||||||
@ -430,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'
|
||||||
@ -459,28 +393,6 @@ class VLANFilter(CustomFieldFilterSet, django_filters.FilterSet):
|
|||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
label='Group',
|
label='Group',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
role_id = django_filters.ModelMultipleChoiceFilter(
|
role_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Role.objects.all(),
|
queryset=Role.objects.all(),
|
||||||
label='Role (ID)',
|
label='Role (ID)',
|
||||||
|
@ -5,8 +5,8 @@ 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, TenancyFilterForm
|
||||||
from tenancy.models import Tenant, TenantGroup
|
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,
|
||||||
CSVChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, ReturnURLForm, SlugField,
|
CSVChoiceField, ExpandableIPAddressField, FilterChoiceField, FlexibleModelChoiceField, ReturnURLForm, SlugField,
|
||||||
@ -97,35 +97,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_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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -510,8 +489,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'
|
||||||
@ -548,29 +529,6 @@ class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
null_option=True,
|
null_option=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=PREFIX_STATUS_CHOICES,
|
choices=PREFIX_STATUS_CHOICES,
|
||||||
required=False,
|
required=False,
|
||||||
@ -972,8 +930,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'
|
||||||
@ -1010,29 +970,6 @@ class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
null_option=True,
|
null_option=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=IPADDRESS_STATUS_CHOICES,
|
choices=IPADDRESS_STATUS_CHOICES,
|
||||||
required=False,
|
required=False,
|
||||||
@ -1264,8 +1201,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'
|
||||||
@ -1289,29 +1228,6 @@ class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
null_option=True,
|
null_option=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
status = forms.MultipleChoiceField(
|
status = forms.MultipleChoiceField(
|
||||||
choices=VLAN_STATUS_CHOICES,
|
choices=VLAN_STATUS_CHOICES,
|
||||||
required=False,
|
required=False,
|
||||||
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
|||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from dcim.models import Interface
|
from dcim.models import Interface
|
||||||
from tenancy.tables import COL_TENANT,COL_TENANTGROUP_TENANT
|
from tenancy.tables import COL_TENANT
|
||||||
from utilities.tables import BaseTable, BooleanColumn, ToggleColumn
|
from utilities.tables import BaseTable, BooleanColumn, ToggleColumn
|
||||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
from .models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ class VRFTable(BaseTable):
|
|||||||
pk = ToggleColumn()
|
pk = ToggleColumn()
|
||||||
name = tables.LinkColumn()
|
name = tables.LinkColumn()
|
||||||
rd = tables.Column(verbose_name='RD')
|
rd = tables.Column(verbose_name='RD')
|
||||||
tenant = tables.TemplateColumn(template_code=COL_TENANTGROUP_TENANT)
|
tenant = tables.TemplateColumn(template_code=COL_TENANT)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = VRF
|
model = VRF
|
||||||
@ -323,7 +323,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_TENANTGROUP_TENANT)
|
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')
|
||||||
@ -354,7 +354,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_TENANTGROUP_TENANT)
|
tenant = tables.TemplateColumn(template_code=COL_TENANT)
|
||||||
|
|
||||||
class Meta(IPAddressTable.Meta):
|
class Meta(IPAddressTable.Meta):
|
||||||
fields = (
|
fields = (
|
||||||
@ -415,7 +415,7 @@ class VLANTable(BaseTable):
|
|||||||
vid = tables.TemplateColumn(VLAN_LINK, verbose_name='ID')
|
vid = tables.TemplateColumn(VLAN_LINK, verbose_name='ID')
|
||||||
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')])
|
||||||
group = tables.LinkColumn('ipam:vlangroup_vlans', args=[Accessor('group.pk')], verbose_name='Group')
|
group = tables.LinkColumn('ipam:vlangroup_vlans', args=[Accessor('group.pk')], verbose_name='Group')
|
||||||
tenant = tables.TemplateColumn(template_code=COL_TENANTGROUP_TENANT)
|
tenant = tables.TemplateColumn(template_code=COL_TENANT)
|
||||||
status = tables.TemplateColumn(STATUS_LABEL)
|
status = tables.TemplateColumn(STATUS_LABEL)
|
||||||
role = tables.TemplateColumn(VLAN_ROLE_LINK)
|
role = tables.TemplateColumn(VLAN_ROLE_LINK)
|
||||||
|
|
||||||
@ -429,7 +429,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_TENANTGROUP_TENANT)
|
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')
|
||||||
|
@ -46,3 +46,28 @@ class TenantFilter(CustomFieldFilterSet, django_filters.FilterSet):
|
|||||||
Q(description__icontains=value) |
|
Q(description__icontains=value) |
|
||||||
Q(comments__icontains=value)
|
Q(comments__icontains=value)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
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)',
|
||||||
|
)
|
||||||
|
@ -115,6 +115,34 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Tenancy form extension
|
# Tenancy form extension
|
||||||
|
@ -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, TenantGroup
|
from tenancy.filters import TenancyFilterSet
|
||||||
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
|
from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter
|
||||||
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'
|
||||||
@ -150,28 +150,6 @@ class VirtualMachineFilter(CustomFieldFilterSet):
|
|||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
label='Role (slug)',
|
label='Role (slug)',
|
||||||
)
|
)
|
||||||
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)',
|
|
||||||
)
|
|
||||||
platform_id = django_filters.ModelMultipleChoiceFilter(
|
platform_id = django_filters.ModelMultipleChoiceFilter(
|
||||||
queryset=Platform.objects.all(),
|
queryset=Platform.objects.all(),
|
||||||
label='Platform (ID)',
|
label='Platform (ID)',
|
||||||
|
@ -7,7 +7,7 @@ from dcim.forms import INTERFACE_MODE_HELP_TEXT
|
|||||||
from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
|
from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
|
||||||
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, TenancyFilterForm
|
||||||
from tenancy.models import Tenant, TenantGroup
|
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,
|
||||||
@ -336,7 +336,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 +520,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,29 +593,6 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False,
|
required=False,
|
||||||
widget=StaticSelect2Multiple()
|
widget=StaticSelect2Multiple()
|
||||||
)
|
)
|
||||||
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,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
platform = FilterChoiceField(
|
platform = FilterChoiceField(
|
||||||
queryset=Platform.objects.all(),
|
queryset=Platform.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
|||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
|
|
||||||
from dcim.models import Interface
|
from dcim.models import Interface
|
||||||
from tenancy.tables import COL_TENANTGROUP_TENANT
|
from tenancy.tables import COL_TENANT
|
||||||
from utilities.tables import BaseTable, ToggleColumn
|
from utilities.tables import BaseTable, ToggleColumn
|
||||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
|
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ class VirtualMachineTable(BaseTable):
|
|||||||
status = tables.TemplateColumn(template_code=VIRTUALMACHINE_STATUS)
|
status = tables.TemplateColumn(template_code=VIRTUALMACHINE_STATUS)
|
||||||
cluster = tables.LinkColumn('virtualization:cluster', args=[Accessor('cluster.pk')])
|
cluster = tables.LinkColumn('virtualization:cluster', args=[Accessor('cluster.pk')])
|
||||||
role = tables.TemplateColumn(VIRTUALMACHINE_ROLE)
|
role = tables.TemplateColumn(VIRTUALMACHINE_ROLE)
|
||||||
tenant = tables.TemplateColumn(template_code=COL_TENANTGROUP_TENANT)
|
tenant = tables.TemplateColumn(template_code=COL_TENANT)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = VirtualMachine
|
model = VirtualMachine
|
||||||
|
Loading…
Reference in New Issue
Block a user