nautobot 2.3.12__py3-none-any.whl → 2.3.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/circuits/tables.py +2 -1
- nautobot/core/api/serializers.py +1 -0
- nautobot/core/celery/log.py +4 -4
- nautobot/core/filters.py +2 -0
- nautobot/core/jobs/cleanup.py +47 -11
- nautobot/core/models/tree_queries.py +5 -2
- nautobot/core/settings.py +1 -1
- nautobot/core/tables.py +60 -10
- nautobot/core/templates/search.html +7 -0
- nautobot/core/templatetags/helpers.py +7 -1
- nautobot/core/testing/api.py +5 -1
- nautobot/core/testing/filters.py +20 -5
- nautobot/core/tests/test_api.py +20 -0
- nautobot/core/tests/test_csv.py +25 -3
- nautobot/core/tests/test_utils.py +8 -0
- nautobot/core/utils/lookup.py +11 -8
- nautobot/dcim/api/views.py +3 -0
- nautobot/dcim/filters/__init__.py +26 -1
- nautobot/dcim/forms.py +10 -5
- nautobot/dcim/models/devices.py +1 -0
- nautobot/dcim/tests/test_filters.py +33 -0
- nautobot/dcim/tests/test_forms.py +51 -2
- nautobot/dcim/tests/test_views.py +6 -0
- nautobot/extras/api/serializers.py +1 -0
- nautobot/extras/api/views.py +2 -0
- nautobot/extras/forms/forms.py +2 -0
- nautobot/extras/forms/mixins.py +10 -2
- nautobot/extras/group_sync.py +3 -3
- nautobot/extras/jobs.py +6 -4
- nautobot/extras/plugins/__init__.py +13 -2
- nautobot/extras/tests/test_views.py +2 -0
- nautobot/ipam/lookups.py +101 -62
- nautobot/ipam/models.py +62 -11
- nautobot/ipam/tables.py +20 -6
- nautobot/ipam/tests/test_api.py +68 -1
- nautobot/ipam/tests/test_models.py +41 -0
- nautobot/ipam/tests/test_querysets.py +49 -1
- nautobot/ipam/utils/__init__.py +24 -0
- nautobot/ipam/views.py +61 -68
- nautobot/project-static/docs/404.html +1 -1
- nautobot/project-static/docs/apps/index.html +1 -1
- nautobot/project-static/docs/apps/nautobot-apps.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +7 -5
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +197 -5
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +16 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1 -1
- nautobot/project-static/docs/development/apps/api/configuration-view.html +1 -1
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +1 -1
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +1 -1
- nautobot/project-static/docs/development/apps/api/models/global-search.html +1 -1
- nautobot/project-static/docs/development/apps/api/models/graphql.html +1 -1
- nautobot/project-static/docs/development/apps/api/models/index.html +1 -1
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +1 -1
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +23 -4
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +1 -1
- nautobot/project-static/docs/development/apps/api/prometheus.html +1 -1
- nautobot/project-static/docs/development/apps/api/setup.html +1 -1
- nautobot/project-static/docs/development/apps/api/testing.html +1 -1
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +1 -1
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +1 -1
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +1 -1
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +1 -1
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/base-template.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/index.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/notes.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +1 -1
- nautobot/project-static/docs/development/apps/api/views/urls.html +1 -1
- nautobot/project-static/docs/development/apps/index.html +1 -1
- nautobot/project-static/docs/development/apps/migration/code-updates.html +1 -1
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +1 -1
- nautobot/project-static/docs/development/apps/migration/from-v1.html +1 -1
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +1 -1
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +1 -1
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +1 -1
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +1 -1
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +1 -1
- nautobot/project-static/docs/development/core/application-registry.html +1 -1
- nautobot/project-static/docs/development/core/best-practices.html +1 -1
- nautobot/project-static/docs/development/core/bootstrap-ui.html +1 -1
- nautobot/project-static/docs/development/core/caching.html +1 -1
- nautobot/project-static/docs/development/core/controllers.html +1 -1
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +1 -1
- nautobot/project-static/docs/development/core/generic-views.html +1 -1
- nautobot/project-static/docs/development/core/getting-started.html +154 -140
- nautobot/project-static/docs/development/core/homepage.html +1 -1
- nautobot/project-static/docs/development/core/index.html +1 -1
- nautobot/project-static/docs/development/core/model-checklist.html +1 -1
- nautobot/project-static/docs/development/core/model-features.html +1 -1
- nautobot/project-static/docs/development/core/natural-keys.html +1 -1
- nautobot/project-static/docs/development/core/navigation-menu.html +1 -1
- nautobot/project-static/docs/development/core/release-checklist.html +1 -1
- nautobot/project-static/docs/development/core/role-internals.html +1 -1
- nautobot/project-static/docs/development/core/settings.html +1 -1
- nautobot/project-static/docs/development/core/style-guide.html +1 -1
- nautobot/project-static/docs/development/core/templates.html +1 -1
- nautobot/project-static/docs/development/core/testing.html +1 -1
- nautobot/project-static/docs/development/core/user-preferences.html +1 -1
- nautobot/project-static/docs/development/index.html +1 -1
- nautobot/project-static/docs/development/jobs/index.html +142 -118
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +1 -1
- nautobot/project-static/docs/index.html +1 -1
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +1 -1
- nautobot/project-static/docs/overview/design_philosophy.html +1 -1
- nautobot/project-static/docs/release-notes/index.html +1 -1
- nautobot/project-static/docs/release-notes/version-1.0.html +1 -1
- nautobot/project-static/docs/release-notes/version-1.1.html +1 -1
- nautobot/project-static/docs/release-notes/version-1.2.html +1 -1
- nautobot/project-static/docs/release-notes/version-1.3.html +1 -1
- nautobot/project-static/docs/release-notes/version-1.4.html +1 -1
- nautobot/project-static/docs/release-notes/version-1.5.html +1 -1
- nautobot/project-static/docs/release-notes/version-1.6.html +614 -179
- nautobot/project-static/docs/release-notes/version-2.0.html +1 -1
- nautobot/project-static/docs/release-notes/version-2.1.html +1 -1
- nautobot/project-static/docs/release-notes/version-2.2.html +1 -1
- nautobot/project-static/docs/release-notes/version-2.3.html +553 -200
- nautobot/project-static/docs/requirements.txt +1 -1
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +270 -270
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +1 -1
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +1 -1
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +3 -3
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +1 -1
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +1 -1
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +1 -1
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +1 -1
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +1 -1
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +1 -1
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +1 -1
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +1 -1
- nautobot/project-static/docs/user-guide/administration/installation/index.html +1 -1
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +1 -1
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +1 -1
- nautobot/project-static/docs/user-guide/administration/installation/services.html +1 -1
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +1 -1
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +1 -1
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +1 -1
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +1 -1
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +1 -1
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +1 -1
- nautobot/project-static/docs/user-guide/index.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +1 -1
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +1 -1
- nautobot/users/api/serializers.py +1 -0
- nautobot/virtualization/filters.py +19 -2
- nautobot/virtualization/tests/test_filters.py +9 -0
- {nautobot-2.3.12.dist-info → nautobot-2.3.14.dist-info}/METADATA +3 -3
- {nautobot-2.3.12.dist-info → nautobot-2.3.14.dist-info}/RECORD +324 -324
- {nautobot-2.3.12.dist-info → nautobot-2.3.14.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.12.dist-info → nautobot-2.3.14.dist-info}/NOTICE +0 -0
- {nautobot-2.3.12.dist-info → nautobot-2.3.14.dist-info}/WHEEL +0 -0
- {nautobot-2.3.12.dist-info → nautobot-2.3.14.dist-info}/entry_points.txt +0 -0
nautobot/dcim/forms.py
CHANGED
|
@@ -792,7 +792,7 @@ class DeviceFamilyFilterForm(NautobotFilterForm):
|
|
|
792
792
|
tags = TagFilterField(model)
|
|
793
793
|
|
|
794
794
|
|
|
795
|
-
class DeviceFamilyBulkEditForm(
|
|
795
|
+
class DeviceFamilyBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
796
796
|
pk = forms.ModelMultipleChoiceField(queryset=DeviceFamily.objects.all(), widget=forms.MultipleHiddenInput())
|
|
797
797
|
description = forms.CharField(required=False)
|
|
798
798
|
|
|
@@ -2123,6 +2123,8 @@ class DeviceBulkEditForm(
|
|
|
2123
2123
|
rack_group = DynamicModelChoiceField(
|
|
2124
2124
|
queryset=RackGroup.objects.all(), required=False, query_params={"location": "$location"}
|
|
2125
2125
|
)
|
|
2126
|
+
cluster = DynamicModelChoiceField(queryset=Cluster.objects.all(), required=False)
|
|
2127
|
+
comments = CommentField(widget=SmallTextarea, label="Comments")
|
|
2126
2128
|
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
|
2127
2129
|
platform = DynamicModelChoiceField(queryset=Platform.objects.all(), required=False)
|
|
2128
2130
|
serial = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False, label="Serial Number")
|
|
@@ -2146,6 +2148,8 @@ class DeviceBulkEditForm(
|
|
|
2146
2148
|
"position",
|
|
2147
2149
|
"face",
|
|
2148
2150
|
"rack_group",
|
|
2151
|
+
"cluster",
|
|
2152
|
+
"comments",
|
|
2149
2153
|
"secrets_group",
|
|
2150
2154
|
"device_redundancy_group",
|
|
2151
2155
|
"device_redundancy_group_priority",
|
|
@@ -3179,9 +3183,6 @@ class InterfaceBulkEditForm(
|
|
|
3179
3183
|
untagged_vlan = DynamicModelChoiceField(
|
|
3180
3184
|
queryset=VLAN.objects.all(),
|
|
3181
3185
|
required=False,
|
|
3182
|
-
query_params={
|
|
3183
|
-
"locations": "null",
|
|
3184
|
-
},
|
|
3185
3186
|
)
|
|
3186
3187
|
tagged_vlans = DynamicModelMultipleChoiceField(
|
|
3187
3188
|
queryset=VLAN.objects.all(),
|
|
@@ -3231,8 +3232,12 @@ class InterfaceBulkEditForm(
|
|
|
3231
3232
|
# Limit VLAN choices by Location
|
|
3232
3233
|
if locations.count() == 1:
|
|
3233
3234
|
location = locations.first()
|
|
3234
|
-
|
|
3235
|
+
# In the case of a single location, use the available_on_device query param to limit untagged VLAN choices
|
|
3236
|
+
# to those available on the devices in that location and in the ancestors of the location.
|
|
3237
|
+
self.fields["untagged_vlan"].widget.add_query_param("available_on_device", device.pk)
|
|
3235
3238
|
self.fields["tagged_vlans"].widget.add_query_param("locations", location.pk)
|
|
3239
|
+
else:
|
|
3240
|
+
self.fields["tagged_vlans"].widget.add_query_param("locations", "null")
|
|
3236
3241
|
|
|
3237
3242
|
# Restrict parent/bridge/LAG interface assignment by device (or VC master)
|
|
3238
3243
|
if device_count == 1:
|
nautobot/dcim/models/devices.py
CHANGED
|
@@ -1701,6 +1701,7 @@ class DeviceTestCase(
|
|
|
1701
1701
|
("front_ports", "front_ports__id"),
|
|
1702
1702
|
("interfaces", "interfaces__id"),
|
|
1703
1703
|
("interfaces", "interfaces__name"),
|
|
1704
|
+
("ip_addresses", "interfaces__ip_addresses__id"),
|
|
1704
1705
|
("mac_address", "interfaces__mac_address"),
|
|
1705
1706
|
("manufacturer", "device_type__manufacturer__id"),
|
|
1706
1707
|
("manufacturer", "device_type__manufacturer__name"),
|
|
@@ -1874,6 +1875,14 @@ class DeviceTestCase(
|
|
|
1874
1875
|
Device.objects.filter(primary_ip4__isnull=True, primary_ip6__isnull=True),
|
|
1875
1876
|
)
|
|
1876
1877
|
|
|
1878
|
+
def test_ip_addresses(self):
|
|
1879
|
+
addresses = list(IPAddress.objects.filter(interfaces__isnull=False)[:2])
|
|
1880
|
+
params = {"ip_addresses": [addresses[0].address, addresses[1].id]}
|
|
1881
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
1882
|
+
self.filterset(params, self.queryset).qs,
|
|
1883
|
+
self.queryset.filter(interfaces__ip_addresses__in=addresses).distinct(),
|
|
1884
|
+
)
|
|
1885
|
+
|
|
1877
1886
|
def test_virtual_chassis_member(self):
|
|
1878
1887
|
# TODO: Not a generic_filter_test because this is a boolean filter but not a RelatedMembershipBooleanFilter
|
|
1879
1888
|
with self.subTest():
|
|
@@ -2168,6 +2177,7 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
|
|
|
2168
2177
|
("child_interfaces", "child_interfaces__name"),
|
|
2169
2178
|
("description",),
|
|
2170
2179
|
# ("device", "device__id"), # TODO - InterfaceFilterSet overrides device as a MultiValueCharFilter on name only
|
|
2180
|
+
("ip_addresses", "ip_addresses__id"),
|
|
2171
2181
|
("label",),
|
|
2172
2182
|
("lag", "lag__id"),
|
|
2173
2183
|
("lag", "lag__name"),
|
|
@@ -2413,6 +2423,21 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
|
|
|
2413
2423
|
status=interface_statuses[3],
|
|
2414
2424
|
)
|
|
2415
2425
|
|
|
2426
|
+
ipaddr_status = Status.objects.get_for_model(IPAddress).first()
|
|
2427
|
+
prefix_status = Status.objects.get_for_model(Prefix).first()
|
|
2428
|
+
namespace = Namespace.objects.first()
|
|
2429
|
+
Prefix.objects.create(prefix="192.0.2.0/24", namespace=namespace, status=prefix_status)
|
|
2430
|
+
Prefix.objects.create(prefix="2600::/64", namespace=namespace, status=prefix_status)
|
|
2431
|
+
ipaddresses = (
|
|
2432
|
+
IPAddress.objects.create(address="192.0.2.1/24", namespace=namespace, status=ipaddr_status),
|
|
2433
|
+
IPAddress.objects.create(address="192.0.2.2/24", namespace=namespace, status=ipaddr_status),
|
|
2434
|
+
IPAddress.objects.create(address="2600::1/120", namespace=namespace, status=ipaddr_status),
|
|
2435
|
+
IPAddress.objects.create(address="2600::0100/120", namespace=namespace, status=ipaddr_status),
|
|
2436
|
+
)
|
|
2437
|
+
|
|
2438
|
+
cabled_interfaces[0].add_ip_addresses([ipaddresses[0], ipaddresses[2]])
|
|
2439
|
+
cabled_interfaces[1].add_ip_addresses([ipaddresses[1], ipaddresses[3]])
|
|
2440
|
+
|
|
2416
2441
|
def test_enabled(self):
|
|
2417
2442
|
# TODO: Not a generic_filter_test because this is a boolean filter but not a RelatedMembershipBooleanFilter
|
|
2418
2443
|
with self.subTest():
|
|
@@ -2646,6 +2671,14 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
|
|
|
2646
2671
|
with self.subTest("device (pk) filter with an invalid uuid"):
|
|
2647
2672
|
self.assertFalse(self.filterset({"device": [uuid.uuid4()]}, self.queryset).is_valid())
|
|
2648
2673
|
|
|
2674
|
+
def test_ip_addresses(self):
|
|
2675
|
+
addresses = list(IPAddress.objects.filter(interfaces__isnull=False)[:2])
|
|
2676
|
+
params = {"ip_addresses": [addresses[0].address, addresses[1].id]}
|
|
2677
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
2678
|
+
self.filterset(params, self.queryset).qs,
|
|
2679
|
+
self.queryset.filter(ip_addresses__in=addresses).distinct(),
|
|
2680
|
+
)
|
|
2681
|
+
|
|
2649
2682
|
def test_kind(self):
|
|
2650
2683
|
# TODO: Not a generic_filter_test because this is a single-value filter
|
|
2651
2684
|
# 2.0 TODO: Support filtering for multiple values
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
from django.test import TestCase
|
|
2
2
|
|
|
3
3
|
from nautobot.core.testing.forms import FormTestCases
|
|
4
|
+
from nautobot.core.testing.mixins import NautobotTestCaseMixin
|
|
4
5
|
from nautobot.dcim.choices import DeviceFaceChoices, InterfaceModeChoices, InterfaceTypeChoices, RackWidthChoices
|
|
5
|
-
from nautobot.dcim.forms import
|
|
6
|
+
from nautobot.dcim.forms import (
|
|
7
|
+
DeviceFilterForm,
|
|
8
|
+
DeviceForm,
|
|
9
|
+
InterfaceBulkEditForm,
|
|
10
|
+
InterfaceCreateForm,
|
|
11
|
+
InterfaceForm,
|
|
12
|
+
RackForm,
|
|
13
|
+
)
|
|
6
14
|
from nautobot.dcim.models import (
|
|
7
15
|
Device,
|
|
8
16
|
DeviceType,
|
|
@@ -320,7 +328,7 @@ class RackTestCase(TestCase):
|
|
|
320
328
|
self.assertTrue(form.is_valid())
|
|
321
329
|
|
|
322
330
|
|
|
323
|
-
class InterfaceTestCase(TestCase):
|
|
331
|
+
class InterfaceTestCase(NautobotTestCaseMixin, TestCase):
|
|
324
332
|
@classmethod
|
|
325
333
|
def setUpTestData(cls):
|
|
326
334
|
cls.device = Device.objects.first()
|
|
@@ -380,3 +388,44 @@ class InterfaceTestCase(TestCase):
|
|
|
380
388
|
self.vlan.locations.clear()
|
|
381
389
|
form = InterfaceForm(data=self.data, instance=self.interface)
|
|
382
390
|
self.assertTrue(form.is_valid())
|
|
391
|
+
|
|
392
|
+
def test_untagged_vlans_dropdown_options_align_in_interface_edit_form_and_bulk_edit_form(self):
|
|
393
|
+
"""
|
|
394
|
+
Assert that untagged_vlans field dropdown are populated correctly in InterfaceForm and InterfaceBulkEditForm,
|
|
395
|
+
and that the queryset is the same for both forms.
|
|
396
|
+
"""
|
|
397
|
+
status = Status.objects.get_for_model(Interface).first()
|
|
398
|
+
location = Location.objects.filter(location_type=LocationType.objects.get(name="Campus")).first()
|
|
399
|
+
devices = Device.objects.all()[:3]
|
|
400
|
+
for device in devices:
|
|
401
|
+
device.location = location
|
|
402
|
+
device.save()
|
|
403
|
+
interfaces = (
|
|
404
|
+
Interface.objects.create(
|
|
405
|
+
device=devices[0],
|
|
406
|
+
name="Test Interface 1",
|
|
407
|
+
type=InterfaceTypeChoices.TYPE_2GFC_SFP,
|
|
408
|
+
status=status,
|
|
409
|
+
),
|
|
410
|
+
Interface.objects.create(
|
|
411
|
+
device=devices[1],
|
|
412
|
+
name="Test Interface 2",
|
|
413
|
+
type=InterfaceTypeChoices.TYPE_LAG,
|
|
414
|
+
status=status,
|
|
415
|
+
),
|
|
416
|
+
Interface.objects.create(
|
|
417
|
+
device=devices[2],
|
|
418
|
+
name="Test Interface 3",
|
|
419
|
+
type=InterfaceTypeChoices.TYPE_100ME_FIXED,
|
|
420
|
+
status=status,
|
|
421
|
+
),
|
|
422
|
+
)
|
|
423
|
+
edit_form = InterfaceForm(data=self.data, instance=interfaces[0])
|
|
424
|
+
bulk_edit_form = InterfaceBulkEditForm(
|
|
425
|
+
model=Interface,
|
|
426
|
+
data={"pks": [interface.pk for interface in interfaces]},
|
|
427
|
+
)
|
|
428
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
429
|
+
edit_form.fields["untagged_vlan"].queryset,
|
|
430
|
+
bulk_edit_form.fields["untagged_vlan"].queryset,
|
|
431
|
+
)
|
|
@@ -130,6 +130,7 @@ from nautobot.ipam.choices import IPAddressTypeChoices
|
|
|
130
130
|
from nautobot.ipam.models import IPAddress, Namespace, Prefix, VLAN, VLANGroup, VRF
|
|
131
131
|
from nautobot.tenancy.models import Tenant
|
|
132
132
|
from nautobot.users.models import ObjectPermission
|
|
133
|
+
from nautobot.virtualization.models import Cluster, ClusterType
|
|
133
134
|
|
|
134
135
|
# Use the proper swappable User model
|
|
135
136
|
User = get_user_model()
|
|
@@ -2047,6 +2048,9 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
2047
2048
|
|
|
2048
2049
|
rack_group = RackGroup.objects.create(location=locations[0], name="Rack Group 1")
|
|
2049
2050
|
|
|
2051
|
+
cluster_type = ClusterType.objects.create(name="Cluster Type 1")
|
|
2052
|
+
cluster = Cluster.objects.create(name="Cluster 1", cluster_type=cluster_type)
|
|
2053
|
+
|
|
2050
2054
|
rack_status = Status.objects.get_for_model(Rack).first()
|
|
2051
2055
|
racks = (
|
|
2052
2056
|
Rack.objects.create(
|
|
@@ -2218,6 +2222,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
2218
2222
|
"status": statuses[2].pk,
|
|
2219
2223
|
"location": locations[1].pk,
|
|
2220
2224
|
"rack": racks[1].pk,
|
|
2225
|
+
"cluster": cluster.pk,
|
|
2226
|
+
"comments": "An older device",
|
|
2221
2227
|
"position": None,
|
|
2222
2228
|
"face": DeviceFaceChoices.FACE_FRONT,
|
|
2223
2229
|
"secrets_group": secrets_groups[1].pk,
|
|
@@ -270,6 +270,7 @@ class ContactAssociationSerializer(NautobotModelSerializer):
|
|
|
270
270
|
|
|
271
271
|
|
|
272
272
|
class ContentTypeSerializer(BaseModelSerializer):
|
|
273
|
+
id = serializers.IntegerField(read_only=True)
|
|
273
274
|
url = serializers.HyperlinkedIdentityField(view_name="extras-api:contenttype-detail")
|
|
274
275
|
display = serializers.SerializerMethodField()
|
|
275
276
|
|
nautobot/extras/api/views.py
CHANGED
|
@@ -17,6 +17,7 @@ from rest_framework.permissions import IsAuthenticated
|
|
|
17
17
|
from rest_framework.response import Response
|
|
18
18
|
|
|
19
19
|
from nautobot.core.api.authentication import TokenPermissions
|
|
20
|
+
from nautobot.core.api.parsers import NautobotCSVParser
|
|
20
21
|
from nautobot.core.api.utils import get_serializer_for_model
|
|
21
22
|
from nautobot.core.api.views import (
|
|
22
23
|
BulkDestroyModelMixin,
|
|
@@ -484,6 +485,7 @@ class ImageAttachmentViewSet(ModelViewSet):
|
|
|
484
485
|
queryset = ImageAttachment.objects.all()
|
|
485
486
|
serializer_class = serializers.ImageAttachmentSerializer
|
|
486
487
|
filterset_class = filters.ImageAttachmentFilterSet
|
|
488
|
+
parser_classes = [JSONParser, NautobotCSVParser, MultiPartParser]
|
|
487
489
|
|
|
488
490
|
|
|
489
491
|
#
|
nautobot/extras/forms/forms.py
CHANGED
|
@@ -1682,6 +1682,8 @@ class RoleBulkEditForm(NautobotBulkEditForm):
|
|
|
1682
1682
|
|
|
1683
1683
|
pk = forms.ModelMultipleChoiceField(queryset=Role.objects.all(), widget=forms.MultipleHiddenInput)
|
|
1684
1684
|
color = forms.CharField(max_length=6, required=False, widget=ColorSelect())
|
|
1685
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
1686
|
+
weight = forms.IntegerField(required=False)
|
|
1685
1687
|
content_types = MultipleContentTypeField(
|
|
1686
1688
|
queryset=RoleModelsQuery().as_queryset(), required=False, label="Content Type(s)"
|
|
1687
1689
|
)
|
nautobot/extras/forms/mixins.py
CHANGED
|
@@ -842,8 +842,16 @@ class TagsBulkEditFormMixin(forms.Form):
|
|
|
842
842
|
super().__init__(*args, **kwargs)
|
|
843
843
|
|
|
844
844
|
# Add add/remove tags fields
|
|
845
|
-
self.fields["add_tags"] = DynamicModelMultipleChoiceField(
|
|
846
|
-
|
|
845
|
+
self.fields["add_tags"] = DynamicModelMultipleChoiceField(
|
|
846
|
+
queryset=Tag.objects.all(),
|
|
847
|
+
query_params={"content_types": self.model._meta.label_lower},
|
|
848
|
+
required=False,
|
|
849
|
+
)
|
|
850
|
+
self.fields["remove_tags"] = DynamicModelMultipleChoiceField(
|
|
851
|
+
queryset=Tag.objects.all(),
|
|
852
|
+
query_params={"content_types": self.model._meta.label_lower},
|
|
853
|
+
required=False,
|
|
854
|
+
)
|
|
847
855
|
|
|
848
856
|
|
|
849
857
|
# 2.2 TODO: Names below are only for backward compatibility with Nautobot 1.3 and earlier. Remove in 2.2
|
nautobot/extras/group_sync.py
CHANGED
|
@@ -8,15 +8,15 @@ from django.contrib.auth.models import Group
|
|
|
8
8
|
logger = logging.getLogger(__name__)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
CLAIMS_GROUP_NAME = getattr(settings, "
|
|
11
|
+
CLAIMS_GROUP_NAME = getattr(settings, "SSO_CLAIMS_GROUP", "groups")
|
|
12
12
|
""" Which claim to look at in the OAuth2/OIDC response
|
|
13
13
|
|
|
14
14
|
For Okta you can look at `Okta -> Authorization Servers -> Claims`. And a reasonable
|
|
15
15
|
default is "groups". For Azure a reasonable default is "roles".
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
SUPERUSER_GROUPS = getattr(settings, "
|
|
19
|
-
STAFF_GROUPS = getattr(settings, "
|
|
18
|
+
SUPERUSER_GROUPS = getattr(settings, "SSO_SUPERUSER_GROUPS", [])
|
|
19
|
+
STAFF_GROUPS = getattr(settings, "SSO_STAFF_GROUPS", [])
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def group_sync(uid, user=None, response=None, *args, **kwargs):
|
nautobot/extras/jobs.py
CHANGED
|
@@ -98,13 +98,15 @@ class BaseJob:
|
|
|
98
98
|
|
|
99
99
|
- name (str)
|
|
100
100
|
- description (str)
|
|
101
|
-
- hidden (bool)
|
|
102
|
-
- field_order (list)
|
|
103
101
|
- approval_required (bool)
|
|
104
|
-
-
|
|
105
|
-
-
|
|
102
|
+
- dryrun_default (bool)
|
|
103
|
+
- field_order (list)
|
|
106
104
|
- has_sensitive_variables (bool)
|
|
105
|
+
- hidden (bool)
|
|
106
|
+
- soft_time_limit (int)
|
|
107
107
|
- task_queues (list)
|
|
108
|
+
- template_name (str)
|
|
109
|
+
- time_limit (int)
|
|
108
110
|
"""
|
|
109
111
|
|
|
110
112
|
def __init__(self):
|
|
@@ -519,6 +519,7 @@ class TableExtension:
|
|
|
519
519
|
"""
|
|
520
520
|
|
|
521
521
|
model = None
|
|
522
|
+
suffix = None
|
|
522
523
|
table_columns = {}
|
|
523
524
|
add_to_default_columns = ()
|
|
524
525
|
remove_from_default_columns = ()
|
|
@@ -594,7 +595,7 @@ def _add_columns_into_model_table(table_extension, app_name):
|
|
|
594
595
|
logger.error(error)
|
|
595
596
|
return
|
|
596
597
|
|
|
597
|
-
table = get_table_for_model(table_extension.model)
|
|
598
|
+
table = get_table_for_model(table_extension.model, suffix=table_extension.suffix)
|
|
598
599
|
for name, column in table_extension.table_columns.items():
|
|
599
600
|
_validate_table_column_name_is_prefixed_with_app_name(name, app_name)
|
|
600
601
|
_add_column_to_table_base_columns(table, name, column, app_name)
|
|
@@ -629,18 +630,28 @@ def _modify_default_table_columns(table_extension, app_name):
|
|
|
629
630
|
"""Add or remove columns from the table default columns."""
|
|
630
631
|
from nautobot.core.utils.lookup import get_table_for_model
|
|
631
632
|
|
|
632
|
-
table = get_table_for_model(table_extension.model)
|
|
633
|
+
table = get_table_for_model(table_extension.model, suffix=table_extension.suffix)
|
|
633
634
|
message = (
|
|
634
635
|
f"{app_name}: Cannot {{action}} column `{{column_name}}` {{preposition}} the default columns for `{table}`."
|
|
635
636
|
)
|
|
636
637
|
|
|
637
638
|
for column_name in table_extension.add_to_default_columns:
|
|
639
|
+
if not getattr(table.Meta, "default_columns", None):
|
|
640
|
+
logger.warning(
|
|
641
|
+
f"{app_name}: Table `{table}` does not have a `default_columns` attribute. Cannot add column: {column_name}."
|
|
642
|
+
)
|
|
643
|
+
continue
|
|
638
644
|
if column_name in table.base_columns:
|
|
639
645
|
table.Meta.default_columns = (*table.Meta.default_columns, column_name)
|
|
640
646
|
else:
|
|
641
647
|
logger.debug(message.format(action="add", column_name=column_name, preposition="to"))
|
|
642
648
|
|
|
643
649
|
for column_name in table_extension.remove_from_default_columns:
|
|
650
|
+
if not getattr(table.Meta, "default_columns", None):
|
|
651
|
+
logger.warning(
|
|
652
|
+
f"{app_name}: Table `{table}` does not have a `default_columns` attribute. Cannot remove column: {column_name}."
|
|
653
|
+
)
|
|
654
|
+
continue
|
|
644
655
|
if column_name in table.Meta.default_columns:
|
|
645
656
|
table.Meta.default_columns = tuple(name for name in table.Meta.default_columns if name != column_name)
|
|
646
657
|
else:
|
|
@@ -3607,6 +3607,8 @@ class RoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
|
|
3607
3607
|
|
|
3608
3608
|
cls.bulk_edit_data = {
|
|
3609
3609
|
"color": "000000",
|
|
3610
|
+
"description": "I used to be a new role object.",
|
|
3611
|
+
"weight": 255,
|
|
3610
3612
|
}
|
|
3611
3613
|
|
|
3612
3614
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|