From 6ed2e7b636ba2a91fbcf6cc34ac4e629620865fb Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 1 Mar 2021 17:24:30 -0500 Subject: [PATCH] Closes #5894: Use primary keys when filtering object lists by related objects in the UI --- docs/release-notes/version-2.11.md | 1 + netbox/circuits/forms.py | 53 ++--- netbox/dcim/forms.py | 356 ++++++++++++++--------------- netbox/extras/forms.py | 68 +++--- netbox/ipam/forms.py | 139 ++++++----- netbox/secrets/forms.py | 12 +- netbox/tenancy/forms.py | 27 +-- netbox/virtualization/forms.py | 91 ++++---- 8 files changed, 371 insertions(+), 376 deletions(-) diff --git a/docs/release-notes/version-2.11.md b/docs/release-notes/version-2.11.md index 7acc24cc5..b768e53a0 100644 --- a/docs/release-notes/version-2.11.md +++ b/docs/release-notes/version-2.11.md @@ -9,6 +9,7 @@ * [#5370](https://github.com/netbox-community/netbox/issues/5370) - Extend custom field support to organizational models * [#5401](https://github.com/netbox-community/netbox/issues/5401) - Extend custom field support to device component models * [#5451](https://github.com/netbox-community/netbox/issues/5451) - Add support for multiple-selection custom fields +* [#5894](https://github.com/netbox-community/netbox/issues/5894) - Use primary keys when filtering object lists by related objects in the UI * [#5901](https://github.com/netbox-community/netbox/issues/5901) - Add `created` and `last_updated` fields to device component models ### Other Changes diff --git a/netbox/circuits/forms.py b/netbox/circuits/forms.py index 2e66f99f1..458218468 100644 --- a/netbox/circuits/forms.py +++ b/netbox/circuits/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.utils.translation import gettext as _ from dcim.models import Region, Site from extras.forms import ( @@ -8,7 +9,7 @@ from extras.models import Tag from tenancy.forms import TenancyFilterForm, TenancyForm from tenancy.models import Tenant from utilities.forms import ( - add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, CSVModelChoiceField, CSVModelForm, DatePicker, + add_blank_choice, BootstrapMixin, CommentField, CSVChoiceField, CSVModelChoiceField, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SelectSpeedWidget, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, ) @@ -105,24 +106,24 @@ class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm): model = Provider q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) asn = forms.IntegerField( required=False, - label='ASN' + label=_('ASN') ) tag = TagFilterField(model) @@ -265,44 +266,44 @@ class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit class CircuitFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Circuit field_order = [ - 'q', 'type', 'provider', 'status', 'region', 'site', 'tenant_group', 'tenant', 'commit_rate', + 'q', 'type_id', 'provider_id', 'status', 'region_id', 'site_id', 'tenant_group_id', 'tenant_id', 'commit_rate', ] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - type = DynamicModelMultipleChoiceField( + type_id = DynamicModelMultipleChoiceField( queryset=CircuitType.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Type') ) - provider = DynamicModelMultipleChoiceField( + provider_id = DynamicModelMultipleChoiceField( queryset=Provider.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Provider') ) status = forms.MultipleChoiceField( choices=CircuitStatusChoices, required=False, widget=StaticSelect2Multiple() ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) commit_rate = forms.IntegerField( required=False, min_value=0, - label='Commit rate (Kbps)' + label=_('Commit rate (Kbps)') ) tag = TagFilterField(model) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 0d8f8eabc..4d2365454 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -6,6 +6,7 @@ from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.forms.array import SimpleArrayField from django.core.exceptions import ObjectDoesNotExist from django.utils.safestring import mark_safe +from django.utils.translation import gettext as _ from netaddr import EUI from netaddr.core import AddrFormatError from timezone_field import TimeZoneFormField @@ -19,7 +20,7 @@ from extras.models import Tag from ipam.constants import BGP_ASN_MAX, BGP_ASN_MIN from ipam.models import IPAddress, VLAN from tenancy.forms import TenancyFilterForm, TenancyForm -from tenancy.models import Tenant, TenantGroup +from tenancy.models import Tenant from utilities.forms import ( APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, DynamicModelChoiceField, @@ -59,32 +60,32 @@ def get_device_by_name_or_pk(name): class DeviceComponentFilterForm(BootstrapMixin, CustomFieldFilterForm): field_order = [ - 'q', 'region', 'site' + 'q', 'region_id', 'site_id' ] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - label='Device', query_params={ - 'site': '$site' - } + 'site_id': '$site_id' + }, + label=_('Device') ) @@ -203,7 +204,7 @@ class RegionFilterForm(BootstrapMixin, forms.Form): model = Site q = forms.CharField( required=False, - label='Search' + label=_('Search') ) @@ -337,20 +338,20 @@ class SiteBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor class SiteFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Site - field_order = ['q', 'status', 'region', 'tenant_group', 'tenant'] + field_order = ['q', 'status', 'region_id', 'tenant_group_id', 'tenant_id'] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) status = forms.MultipleChoiceField( choices=SiteStatusChoices, required=False, widget=StaticSelect2Multiple() ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) tag = TagFilterField(model) @@ -411,27 +412,27 @@ class RackGroupCSVForm(CustomFieldModelCSVForm): class RackGroupFilterForm(BootstrapMixin, forms.Form): - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) parent = DynamicModelMultipleChoiceField( queryset=RackGroup.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region', - 'site': '$site', - } + 'region_id': '$region_id', + 'site_id': '$site_id', + }, + label=_('Parent') ) @@ -666,32 +667,32 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Rack - field_order = ['q', 'region', 'site', 'group_id', 'status', 'role', 'tenant_group', 'tenant'] + field_order = ['q', 'region_id', 'site_id', 'group_id', 'status', 'role_id', 'tenant_group_id', 'tenant_id'] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) group_id = DynamicModelMultipleChoiceField( queryset=RackGroup.objects.all(), required=False, - label='Rack group', null_option='None', query_params={ - 'site': '$site' - } + 'site_id': '$site_id' + }, + label=_('Rack group') ) status = forms.MultipleChoiceField( choices=RackStatusChoices, @@ -708,11 +709,11 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): required=False, widget=StaticSelect2Multiple() ) - role = DynamicModelMultipleChoiceField( + role_id = DynamicModelMultipleChoiceField( queryset=RackRole.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Role') ) tag = TagFilterField(model) @@ -722,15 +723,15 @@ class RackFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): # class RackElevationFilterForm(RackFilterForm): - field_order = ['q', 'region', 'site', 'group_id', 'id', 'status', 'role', 'tenant_group', 'tenant'] + field_order = ['q', 'region_id', 'site_id', 'group_id', 'id', 'status', 'role_id', 'tenant_group_id', 'tenant_id'] id = DynamicModelMultipleChoiceField( queryset=Rack.objects.all(), - label='Rack', + label=_('Rack'), required=False, display_field='display_name', query_params={ - 'site': '$site', - 'group_id': '$group_id', + 'site_id': '$site_id', + 'group_id_id': '$group_id_id', } ) @@ -872,23 +873,23 @@ class RackReservationBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomField class RackReservationFilterForm(BootstrapMixin, TenancyFilterForm): model = RackReservation - field_order = ['q', 'region', 'site', 'group_id', 'user_id', 'tenant_group', 'tenant'] + field_order = ['q', 'region_id', 'site_id', 'group_id', 'user_id', 'tenant_group_id', 'tenant_id'] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Region') ) group_id = DynamicModelMultipleChoiceField( queryset=RackGroup.objects.prefetch_related('site'), @@ -1011,12 +1012,12 @@ class DeviceTypeFilterForm(BootstrapMixin, CustomFieldFilterForm): model = DeviceType q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - manufacturer = DynamicModelMultipleChoiceField( + manufacturer_id = DynamicModelMultipleChoiceField( queryset=Manufacturer.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Manufacturer') ) subdevice_role = forms.MultipleChoiceField( choices=add_blank_choice(SubdeviceRoleChoices), @@ -2133,69 +2134,66 @@ class DeviceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF class DeviceFilterForm(BootstrapMixin, LocalConfigContextFilterForm, TenancyFilterForm, CustomFieldFilterForm): model = Device field_order = [ - 'q', 'region', 'site', 'rack_group_id', 'rack_id', 'status', 'role', 'tenant_group', 'tenant', + 'q', 'region_id', 'site_id', 'rack_group_id', 'rack_id', 'status', 'role_id', 'tenant_group_id', 'tenant_id', 'manufacturer_id', 'device_type_id', 'mac_address', 'has_primary_ip', ] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', required=False ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' + 'region_id': '$region_id' } ) rack_group_id = DynamicModelMultipleChoiceField( queryset=RackGroup.objects.all(), required=False, - label='Rack group', + label=_('Rack group'), query_params={ - 'site': '$site' + 'site_id': '$site_id' } ) rack_id = DynamicModelMultipleChoiceField( queryset=Rack.objects.all(), required=False, - label='Rack', null_option='None', query_params={ - 'site': '$site', + 'site_id': '$site_id', 'group_id': '$rack_group_id', - } + }, + label=_('Rack') ) - role = DynamicModelMultipleChoiceField( + role_id = DynamicModelMultipleChoiceField( queryset=DeviceRole.objects.all(), - to_field_name='slug', - required=False - ) - manufacturer = DynamicModelMultipleChoiceField( - queryset=Manufacturer.objects.all(), - to_field_name='slug', required=False, - label='Manufacturer' + label=_('Role') + ) + manufacturer_id = DynamicModelMultipleChoiceField( + queryset=Manufacturer.objects.all(), + required=False, + label=_('Manufacturer') ) device_type_id = DynamicModelMultipleChoiceField( queryset=DeviceType.objects.all(), required=False, - label='Model', display_field='model', query_params={ - 'manufacturer': '$manufacturer' - } + 'manufacturer_id': '$manufacturer_id' + }, + label=_('Model') ) - platform = DynamicModelMultipleChoiceField( + platform_id = DynamicModelMultipleChoiceField( queryset=Platform.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Platform') ) status = forms.MultipleChoiceField( choices=DeviceStatusChoices, @@ -3540,10 +3538,10 @@ class InventoryItemBulkEditForm( class InventoryItemFilterForm(DeviceComponentFilterForm): model = InventoryItem - manufacturer = DynamicModelMultipleChoiceField( + manufacturer_id = DynamicModelMultipleChoiceField( queryset=Manufacturer.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Manufacturer') ) serial = forms.CharField( required=False @@ -3988,25 +3986,25 @@ class CableFilterForm(BootstrapMixin, forms.Form): model = Cable q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) - tenant = DynamicModelMultipleChoiceField( + tenant_id = DynamicModelMultipleChoiceField( queryset=Tenant.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Tenant') ) rack_id = DynamicModelMultipleChoiceField( queryset=Rack.objects.all(), @@ -4014,7 +4012,7 @@ class CableFilterForm(BootstrapMixin, forms.Form): label='Rack', null_option='None', query_params={ - 'site': '$site' + 'site_id': '$site_id' } ) type = forms.MultipleChoiceField( @@ -4035,12 +4033,12 @@ class CableFilterForm(BootstrapMixin, forms.Form): device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - label='Device', query_params={ - 'site': '$site', - 'tenant': '$tenant', + 'site_id': '$site_id', + 'tenant_id': '$tenant_id', 'rack_id': '$rack_id', - } + }, + label=_('Device') ) tag = TagFilterField(model) @@ -4050,74 +4048,74 @@ class CableFilterForm(BootstrapMixin, forms.Form): # class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form): - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - label='Device', query_params={ - 'site': '$site' - } + 'site_id': '$site_id' + }, + label=_('Device') ) class PowerConnectionFilterForm(BootstrapMixin, forms.Form): - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - label='Device', query_params={ - 'site': '$site' - } + 'site_id': '$site_id' + }, + label=_('Device') ) class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form): - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - label='Device', query_params={ - 'site': '$site' - } + 'site_id': '$site_id' + }, + label=_('Device') ) @@ -4344,39 +4342,25 @@ class VirtualChassisCSVForm(CustomFieldModelCSVForm): fields = VirtualChassis.csv_headers -class VirtualChassisFilterForm(BootstrapMixin, CustomFieldFilterForm): +class VirtualChassisFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = VirtualChassis + field_order = ['q', 'region_id', 'site_id', 'tenant_group_id', 'tenant_id'] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } - ) - tenant_group = DynamicModelMultipleChoiceField( - queryset=TenantGroup.objects.all(), - to_field_name='slug', - required=False, - null_option='None' - ) - tenant = DynamicModelMultipleChoiceField( - queryset=Tenant.objects.all(), - to_field_name='slug', - required=False, - null_option='None', - query_params={ - 'group': '$tenant_group' - } + 'region_id': '$region_id' + }, + label=_('Site') ) tag = TagFilterField(model) @@ -4482,29 +4466,29 @@ class PowerPanelFilterForm(BootstrapMixin, CustomFieldFilterForm): model = PowerPanel q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) rack_group_id = DynamicModelMultipleChoiceField( queryset=RackGroup.objects.all(), required=False, - label='Rack group (ID)', null_option='None', query_params={ - 'site': '$site' - } + 'site_id': '$site_id' + }, + label=_('Rack group') ) tag = TagFilterField(model) @@ -4701,38 +4685,38 @@ class PowerFeedFilterForm(BootstrapMixin, CustomFieldFilterForm): model = PowerFeed q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) power_panel_id = DynamicModelMultipleChoiceField( queryset=PowerPanel.objects.all(), required=False, - label='Power panel', null_option='None', query_params={ - 'site': '$site' - } + 'site_id': '$site_id' + }, + label=_('Power panel') ) rack_id = DynamicModelMultipleChoiceField( queryset=Rack.objects.all(), required=False, - label='Rack', null_option='None', query_params={ - 'site': '$site' - } + 'site_id': '$site_id' + }, + label=_('Rack') ) status = forms.MultipleChoiceField( choices=PowerFeedStatusChoices, diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index 4bb6bbfb3..ebb6ac5d4 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -2,6 +2,7 @@ from django import forms from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.utils.safestring import mark_safe +from django.utils.translation import gettext as _ from dcim.models import DeviceRole, Platform, Region, Site from tenancy.models import Tenant, TenantGroup @@ -177,7 +178,7 @@ class TagFilterForm(BootstrapMixin, forms.Form): model = Tag q = forms.CharField( required=False, - label='Search' + label=_('Search') ) @@ -278,54 +279,59 @@ class ConfigContextBulkEditForm(BootstrapMixin, BulkEditForm): class ConfigContextFilterForm(BootstrapMixin, forms.Form): + field_order = [ + 'q', 'region_id', 'site_id', 'role_id', 'platform_id', 'cluster_group_id', 'cluster_id', 'tenant_group_id', + 'tenant_id', + ] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Regions') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Sites') ) - role = DynamicModelMultipleChoiceField( + role_id = DynamicModelMultipleChoiceField( queryset=DeviceRole.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Roles') ) - platform = DynamicModelMultipleChoiceField( + platform_id = DynamicModelMultipleChoiceField( queryset=Platform.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Platforms') ) - cluster_group = DynamicModelMultipleChoiceField( + cluster_group_id = DynamicModelMultipleChoiceField( queryset=ClusterGroup.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Cluster groups') ) cluster_id = DynamicModelMultipleChoiceField( queryset=Cluster.objects.all(), required=False, - label='Cluster' + label=_('Clusters') ) - tenant_group = DynamicModelMultipleChoiceField( + tenant_group_id = DynamicModelMultipleChoiceField( queryset=TenantGroup.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Tenant groups') ) - tenant = DynamicModelMultipleChoiceField( + tenant_id = DynamicModelMultipleChoiceField( queryset=Tenant.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Tenant') ) tag = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), to_field_name='slug', - required=False + required=False, + label=_('Tags') ) @@ -336,7 +342,7 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form): class LocalConfigContextFilterForm(forms.Form): local_context_data = forms.NullBooleanField( required=False, - label='Has local config context data', + label=_('Has local config context data'), widget=StaticSelect2( choices=BOOLEAN_WITH_BLANK_CHOICES ) @@ -364,16 +370,16 @@ class ObjectChangeFilterForm(BootstrapMixin, forms.Form): model = ObjectChange q = forms.CharField( required=False, - label='Search' + label=_('Search') ) time_after = forms.DateTimeField( - label='After', required=False, + label=_('After'), widget=DateTimePicker() ) time_before = forms.DateTimeField( - label='Before', required=False, + label=_('Before'), widget=DateTimePicker() ) action = forms.ChoiceField( @@ -385,7 +391,7 @@ class ObjectChangeFilterForm(BootstrapMixin, forms.Form): queryset=User.objects.all(), required=False, display_field='username', - label='User', + label=_('User'), widget=APISelectMultiple( api_url='/api/users/users/', ) @@ -394,7 +400,7 @@ class ObjectChangeFilterForm(BootstrapMixin, forms.Form): queryset=ContentType.objects.all(), required=False, display_field='display_name', - label='Object Type', + label=_('Object Type'), widget=APISelectMultiple( api_url='/api/extras/content-types/', ) diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index bf3fd1491..664081010 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -1,4 +1,5 @@ from django import forms +from django.utils.translation import gettext as _ from dcim.models import Device, Interface, Rack, Region, Site from extras.forms import ( @@ -103,20 +104,20 @@ class VRFBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm class VRFFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = VRF - field_order = ['q', 'import_target', 'export_target', 'tenant_group', 'tenant'] + field_order = ['q', 'import_target_id', 'export_target_id', 'tenant_group_id', 'tenant_id'] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - import_target = DynamicModelMultipleChoiceField( + import_target_id = DynamicModelMultipleChoiceField( queryset=RouteTarget.objects.all(), - to_field_name='name', - required=False + required=False, + label=_('Import targets') ) - export_target = DynamicModelMultipleChoiceField( + export_target_id = DynamicModelMultipleChoiceField( queryset=RouteTarget.objects.all(), - to_field_name='name', - required=False + required=False, + label=_('Export targets') ) tag = TagFilterField(model) @@ -173,20 +174,20 @@ class RouteTargetBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulk class RouteTargetFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = RouteTarget - field_order = ['q', 'name', 'tenant_group', 'tenant', 'importing_vrfs', 'exporting_vrfs'] + field_order = ['q', 'name', 'tenant_group_id', 'tenant_id', 'importing_vrfs', 'exporting_vrfs'] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) importing_vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, - label='Imported by VRF' + label=_('Imported by VRF') ) exporting_vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, - label='Exported by VRF' + label=_('Exported by VRF') ) tag = TagFilterField(model) @@ -219,7 +220,7 @@ class RIRCSVForm(CustomFieldModelCSVForm): class RIRFilterForm(BootstrapMixin, forms.Form): is_private = forms.NullBooleanField( required=False, - label='Private', + label=_('Private'), widget=StaticSelect2( choices=BOOLEAN_WITH_BLANK_CHOICES ) @@ -309,21 +310,21 @@ class AggregateBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEd class AggregateFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Aggregate + field_order = ['q', 'family', 'rir', 'tenant_group_id', 'tenant_id'] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) family = forms.ChoiceField( required=False, choices=add_blank_choice(IPAddressFamilyChoices), - label='Address family', + label=_('Address family'), widget=StaticSelect2() ) - rir = DynamicModelMultipleChoiceField( + rir_id = DynamicModelMultipleChoiceField( queryset=RIR.objects.all(), - to_field_name='slug', required=False, - label='RIR' + label=_('RIR') ) tag = TagFilterField(model) @@ -494,14 +495,13 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF ) region = DynamicModelChoiceField( queryset=Region.objects.all(), - required=False, - to_field_name='slug' + required=False ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region': '$region' + 'region_id': '$region' } ) vrf = DynamicModelChoiceField( @@ -547,15 +547,15 @@ class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditF class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Prefix field_order = [ - 'q', 'within_include', 'family', 'mask_length', 'vrf_id', 'present_in_vrf_id', 'status', 'region', 'site', - 'role', 'tenant_group', 'tenant', 'is_pool', 'expand', + 'q', 'within_include', 'family', 'mask_length', 'vrf_id', 'present_in_vrf_id', 'status', 'region_id', 'site_id', + 'role_id', 'tenant_group_id', 'tenant_id', 'is_pool', ] mask_length__lte = forms.IntegerField( widget=forms.HiddenInput() ) q = forms.CharField( required=False, - label='Search' + label=_('Search') ) within_include = forms.CharField( required=False, @@ -564,59 +564,59 @@ class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm) 'placeholder': 'Prefix', } ), - label='Search within' + label=_('Search within') ) family = forms.ChoiceField( required=False, choices=add_blank_choice(IPAddressFamilyChoices), - label='Address family', + label=_('Address family'), widget=StaticSelect2() ) mask_length = forms.ChoiceField( required=False, choices=PREFIX_MASK_LENGTH_CHOICES, - label='Mask length', + label=_('Mask length'), widget=StaticSelect2() ) vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, - label='Assigned VRF', + label=_('Assigned VRF'), null_option='Global' ) present_in_vrf_id = DynamicModelChoiceField( queryset=VRF.objects.all(), required=False, - label='Present in VRF' + label=_('Present in VRF') ) status = forms.MultipleChoiceField( choices=PrefixStatusChoices, required=False, widget=StaticSelect2Multiple() ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, null_option='None', query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) - role = DynamicModelMultipleChoiceField( + role_id = DynamicModelMultipleChoiceField( queryset=Role.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Role') ) is_pool = forms.NullBooleanField( required=False, - label='Is a pool', + label=_('Is a pool'), widget=StaticSelect2( choices=BOOLEAN_WITH_BLANK_CHOICES ) @@ -1019,11 +1019,11 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo model = IPAddress field_order = [ 'q', 'parent', 'family', 'mask_length', 'vrf_id', 'present_in_vrf_id', 'status', 'role', - 'assigned_to_interface', 'tenant_group', 'tenant', + 'assigned_to_interface', 'tenant_group_id', 'tenant_id', ] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) parent = forms.CharField( required=False, @@ -1037,25 +1037,25 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo family = forms.ChoiceField( required=False, choices=add_blank_choice(IPAddressFamilyChoices), - label='Address family', + label=_('Address family'), widget=StaticSelect2() ) mask_length = forms.ChoiceField( required=False, choices=IPADDRESS_MASK_LENGTH_CHOICES, - label='Mask length', + label=_('Mask length'), widget=StaticSelect2() ) vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, - label='Assigned VRF', + label=_('Assigned VRF'), null_option='Global' ) present_in_vrf_id = DynamicModelChoiceField( queryset=VRF.objects.all(), required=False, - label='Present in VRF' + label=_('Present in VRF') ) status = forms.MultipleChoiceField( choices=IPAddressStatusChoices, @@ -1069,7 +1069,7 @@ class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterFo ) assigned_to_interface = forms.NullBooleanField( required=False, - label='Assigned to an interface', + label=_('Assigned to an interface'), widget=StaticSelect2( choices=BOOLEAN_WITH_BLANK_CHOICES ) @@ -1120,19 +1120,19 @@ class VLANGroupCSVForm(CustomFieldModelCSVForm): class VLANGroupFilterForm(BootstrapMixin, forms.Form): - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, null_option='None', query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) @@ -1250,14 +1250,13 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor ) region = DynamicModelChoiceField( queryset=Region.objects.all(), - required=False, - to_field_name='slug' + required=False ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region': '$region' + 'region_id': '$region' } ) group = DynamicModelChoiceField( @@ -1293,44 +1292,44 @@ class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor class VLANFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = VLAN - field_order = ['q', 'region', 'site', 'group_id', 'status', 'role', 'tenant_group', 'tenant'] + field_order = ['q', 'region_id', 'site_id', 'group_id', 'status', 'role_id', 'tenant_group_id', 'tenant_id'] q = forms.CharField( required=False, label='Search' ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, null_option='None', query_params={ 'region': '$region' - } + }, + label=_('Site') ) group_id = DynamicModelMultipleChoiceField( queryset=VLANGroup.objects.all(), required=False, - label='VLAN group', null_option='None', query_params={ 'region': '$region' - } + }, + label=_('VLAN group') ) status = forms.MultipleChoiceField( choices=VLANStatusChoices, required=False, widget=StaticSelect2Multiple() ) - role = DynamicModelMultipleChoiceField( + role_id = DynamicModelMultipleChoiceField( queryset=Role.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Role') ) tag = TagFilterField(model) @@ -1386,7 +1385,7 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm): model = Service q = forms.CharField( required=False, - label='Search' + label=_('Search') ) protocol = forms.ChoiceField( choices=add_blank_choice(ServiceProtocolChoices), diff --git a/netbox/secrets/forms.py b/netbox/secrets/forms.py index 2aa3243ee..9094d977c 100644 --- a/netbox/secrets/forms.py +++ b/netbox/secrets/forms.py @@ -1,7 +1,7 @@ from Crypto.Cipher import PKCS1_OAEP from Crypto.PublicKey import RSA from django import forms -from django.contrib.contenttypes.models import ContentType +from django.utils.translation import gettext as _ from dcim.models import Device from extras.forms import ( @@ -9,7 +9,7 @@ from extras.forms import ( ) from extras.models import Tag from utilities.forms import ( - BootstrapMixin, CSVModelChoiceField, CSVModelForm, DynamicModelChoiceField, DynamicModelMultipleChoiceField, + BootstrapMixin, CSVModelChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, TagFilterField, ) from virtualization.models import VirtualMachine @@ -221,12 +221,12 @@ class SecretFilterForm(BootstrapMixin, CustomFieldFilterForm): model = Secret q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - role = DynamicModelMultipleChoiceField( + role_id = DynamicModelMultipleChoiceField( queryset=SecretRole.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Role') ) tag = TagFilterField(model) diff --git a/netbox/tenancy/forms.py b/netbox/tenancy/forms.py index 1d57f5da8..43401baab 100644 --- a/netbox/tenancy/forms.py +++ b/netbox/tenancy/forms.py @@ -1,12 +1,13 @@ from django import forms +from django.utils.translation import gettext as _ from extras.forms import ( AddRemoveTagsForm, CustomFieldModelForm, CustomFieldBulkEditForm, CustomFieldFilterForm, CustomFieldModelCSVForm, ) from extras.models import Tag from utilities.forms import ( - BootstrapMixin, CommentField, CSVModelChoiceField, CSVModelForm, DynamicModelChoiceField, - DynamicModelMultipleChoiceField, SlugField, TagFilterField, + BootstrapMixin, CommentField, CSVModelChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, + SlugField, TagFilterField, ) from .models import Tenant, TenantGroup @@ -103,13 +104,13 @@ class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm): model = Tenant q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - group = DynamicModelMultipleChoiceField( + group_id = DynamicModelMultipleChoiceField( queryset=TenantGroup.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Group') ) tag = TagFilterField(model) @@ -137,18 +138,18 @@ class TenancyForm(forms.Form): class TenancyFilterForm(forms.Form): - tenant_group = DynamicModelMultipleChoiceField( + tenant_group_id = DynamicModelMultipleChoiceField( queryset=TenantGroup.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Tenant group') ) - tenant = DynamicModelMultipleChoiceField( + tenant_id = DynamicModelMultipleChoiceField( queryset=Tenant.objects.all(), - to_field_name='slug', required=False, null_option='None', query_params={ - 'group': '$tenant_group' - } + 'group_id': '$tenant_group_id' + }, + label=_('Tenant') ) diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index c68f2db44..65c2e45d4 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -1,6 +1,7 @@ from django import forms from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError +from django.utils.translation import gettext as _ from dcim.choices import InterfaceModeChoices from dcim.constants import INTERFACE_MTU_MAX, INTERFACE_MTU_MIN @@ -160,13 +161,12 @@ class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit region = DynamicModelChoiceField( queryset=Region.objects.all(), required=False, - to_field_name='slug' ) site = DynamicModelChoiceField( queryset=Site.objects.all(), required=False, query_params={ - 'region': '$region' + 'region_id': '$region' } ) comments = CommentField( @@ -183,33 +183,36 @@ class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEdit class ClusterFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Cluster field_order = [ - 'q', 'type', 'region', 'site', 'group', 'tenant_group', 'tenant' + 'q', 'type_id', 'region_id', 'site_id', 'group_id', 'tenant_group_id', 'tenant_id', ] - q = forms.CharField(required=False, label='Search') - type = DynamicModelMultipleChoiceField( + q = forms.CharField( + required=False, + label=_('Search') + ) + type_id = DynamicModelMultipleChoiceField( queryset=ClusterType.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Type') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, null_option='None', query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Site') ) - group = DynamicModelMultipleChoiceField( + group_id = DynamicModelMultipleChoiceField( queryset=ClusterGroup.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Group') ) tag = TagFilterField(model) @@ -478,63 +481,63 @@ class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldB class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = VirtualMachine field_order = [ - 'q', 'cluster_group', 'cluster_type', 'cluster_id', 'status', 'role', 'region', 'site', 'tenant_group', - 'tenant', 'platform', 'mac_address', + 'q', 'cluster_group_id', 'cluster_type_id', 'cluster_id', 'status', 'role_id', 'region_id', 'site_id', + 'tenant_group_id', 'tenant_id', 'platform_id', 'mac_address', ] q = forms.CharField( required=False, - label='Search' + label=_('Search') ) - cluster_group = DynamicModelMultipleChoiceField( + cluster_group_id = DynamicModelMultipleChoiceField( queryset=ClusterGroup.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Cluster group') ) - cluster_type = DynamicModelMultipleChoiceField( + cluster_type_id = DynamicModelMultipleChoiceField( queryset=ClusterType.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Cluster type') ) cluster_id = DynamicModelMultipleChoiceField( queryset=Cluster.objects.all(), required=False, - label='Cluster' + label=_('Cluster') ) - region = DynamicModelMultipleChoiceField( + region_id = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), - to_field_name='slug', - required=False + required=False, + label=_('Region') ) - site = DynamicModelMultipleChoiceField( + site_id = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), - to_field_name='slug', required=False, null_option='None', query_params={ - 'region': '$region' - } + 'region_id': '$region_id' + }, + label=_('Cluster') ) - role = DynamicModelMultipleChoiceField( - queryset=DeviceRole.objects.filter(vm_role=True), - to_field_name='slug', + role_id = DynamicModelMultipleChoiceField( + queryset=DeviceRole.objects.all(), required=False, null_option='None', query_params={ 'vm_role': "True" - } + }, + label=_('Role') ) status = forms.MultipleChoiceField( choices=VirtualMachineStatusChoices, required=False, widget=StaticSelect2Multiple() ) - platform = DynamicModelMultipleChoiceField( + platform_id = DynamicModelMultipleChoiceField( queryset=Platform.objects.all(), - to_field_name='slug', required=False, - null_option='None' + null_option='None', + label=_('Platform') ) mac_address = forms.CharField( required=False, @@ -781,15 +784,15 @@ class VMInterfaceFilterForm(forms.Form): cluster_id = DynamicModelMultipleChoiceField( queryset=Cluster.objects.all(), required=False, - label='Cluster' + label=_('Cluster') ) virtual_machine_id = DynamicModelMultipleChoiceField( queryset=VirtualMachine.objects.all(), required=False, - label='Virtual machine', query_params={ 'cluster_id': '$cluster_id' - } + }, + label=_('Virtual machine') ) enabled = forms.NullBooleanField( required=False,