nautobot 2.3.10__py3-none-any.whl → 2.3.12__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/apps/utils.py +2 -0
- nautobot/cloud/tables.py +1 -0
- nautobot/core/forms/forms.py +5 -1
- nautobot/core/settings.py +26 -0
- nautobot/core/settings.yaml +31 -0
- nautobot/core/tables.py +88 -22
- nautobot/core/templates/generic/object_bulk_destroy.html +12 -3
- nautobot/core/templates/generic/object_bulk_update.html +4 -2
- nautobot/core/templates/generic/object_create.html +1 -1
- nautobot/core/templates/generic/object_notes.html +1 -1
- nautobot/core/templates/generic/object_retrieve.html +1 -1
- nautobot/core/templates/rest_framework/api.html +3 -0
- nautobot/core/testing/api.py +3 -1
- nautobot/core/testing/integration.py +64 -0
- nautobot/core/testing/views.py +48 -31
- nautobot/core/tests/integration/test_app_navbar.py +3 -3
- nautobot/core/tests/integration/test_navbar.py +1 -1
- nautobot/core/tests/test_csv.py +3 -0
- nautobot/core/tests/test_utils.py +25 -5
- nautobot/core/utils/lookup.py +35 -0
- nautobot/core/views/generic.py +50 -39
- nautobot/core/views/mixins.py +97 -43
- nautobot/core/views/renderers.py +8 -5
- nautobot/dcim/choices.py +6 -0
- nautobot/dcim/tables/devices.py +5 -6
- nautobot/dcim/templates/dcim/controller_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/device/base.html +1 -1
- nautobot/dcim/templates/dcim/device_component_add.html +8 -8
- nautobot/dcim/templates/dcim/virtualchassis_add_member.html +2 -2
- nautobot/dcim/templates/dcim/virtualchassis_edit.html +2 -2
- nautobot/dcim/tests/integration/test_create_device.py +86 -0
- nautobot/extras/group_sync.py +42 -0
- nautobot/extras/models/metadata.py +1 -0
- nautobot/extras/models/models.py +1 -1
- nautobot/extras/plugins/__init__.py +2 -1
- nautobot/extras/tables.py +1 -0
- nautobot/extras/templates/extras/inc/job_table.html +1 -1
- nautobot/extras/tests/test_relationships.py +1 -0
- nautobot/extras/tests/test_views.py +0 -2
- nautobot/extras/views.py +1 -2
- nautobot/ipam/factory.py +3 -0
- nautobot/ipam/filters.py +5 -0
- nautobot/ipam/forms.py +17 -0
- nautobot/ipam/models.py +2 -1
- nautobot/ipam/signals.py +2 -2
- nautobot/ipam/tables.py +6 -13
- nautobot/ipam/templates/ipam/ipaddress_assign.html +2 -2
- nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -1
- nautobot/ipam/tests/test_models.py +113 -1
- nautobot/ipam/tests/test_views.py +39 -5
- nautobot/project-static/docs/404.html +10 -10
- nautobot/project-static/docs/additional-features/caching.html +1 -2
- nautobot/project-static/docs/additional-features/change-logging.html +1 -2
- nautobot/project-static/docs/additional-features/config-contexts.html +1 -2
- nautobot/project-static/docs/additional-features/healthcheck.html +1 -2
- nautobot/project-static/docs/additional-features/jobs.html +1 -2
- nautobot/project-static/docs/additional-features/prometheus-metrics.html +1 -2
- nautobot/project-static/docs/administration/celery-queues.html +1 -2
- nautobot/project-static/docs/administration/nautobot-server.html +1 -2
- nautobot/project-static/docs/administration/nautobot-shell.html +1 -2
- nautobot/project-static/docs/administration/permissions.html +1 -2
- nautobot/project-static/docs/administration/replicating-nautobot.html +1 -2
- nautobot/project-static/docs/apps/index.html +10 -10
- nautobot/project-static/docs/apps/migrating-jobs-from-nautobot-v1.html +1 -2
- nautobot/project-static/docs/apps/nautobot-apps.html +10 -10
- nautobot/project-static/docs/assets/stylesheets/main.6f8fc17f.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.6f8fc17f.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +141 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +185 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +10 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +104 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +14 -14
- nautobot/project-static/docs/configuration/authentication/ldap.html +1 -2
- nautobot/project-static/docs/configuration/authentication/remote.html +1 -2
- nautobot/project-static/docs/configuration/authentication/sso.html +1 -2
- nautobot/project-static/docs/configuration/index.html +1 -2
- nautobot/project-static/docs/configuration/optional-settings.html +1 -2
- nautobot/project-static/docs/configuration/required-settings.html +1 -2
- nautobot/project-static/docs/core-functionality/circuits.html +1 -2
- nautobot/project-static/docs/core-functionality/device-types.html +1 -2
- nautobot/project-static/docs/core-functionality/devices.html +1 -2
- nautobot/project-static/docs/core-functionality/ipam.html +1 -2
- nautobot/project-static/docs/core-functionality/power.html +1 -2
- nautobot/project-static/docs/core-functionality/secrets.html +1 -2
- nautobot/project-static/docs/core-functionality/services.html +1 -2
- nautobot/project-static/docs/core-functionality/sites-and-racks.html +1 -2
- nautobot/project-static/docs/core-functionality/tenancy.html +1 -2
- nautobot/project-static/docs/core-functionality/virtualization.html +1 -2
- nautobot/project-static/docs/core-functionality/vlans.html +1 -2
- nautobot/project-static/docs/development/application-registry.html +1 -2
- nautobot/project-static/docs/development/apps/api/configuration-view.html +10 -10
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +10 -10
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +10 -10
- nautobot/project-static/docs/development/apps/api/models/global-search.html +10 -10
- nautobot/project-static/docs/development/apps/api/models/graphql.html +10 -10
- nautobot/project-static/docs/development/apps/api/models/index.html +10 -10
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +10 -10
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +10 -10
- nautobot/project-static/docs/development/apps/api/prometheus.html +10 -10
- nautobot/project-static/docs/development/apps/api/setup.html +10 -10
- nautobot/project-static/docs/development/apps/api/testing.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-detail-views.html +1 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +10 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/tabs.html +1 -2
- nautobot/project-static/docs/development/apps/api/views/base-template.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/index.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/notes.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/urls.html +10 -10
- nautobot/project-static/docs/development/apps/api/views/view-overrides.html +1 -2
- nautobot/project-static/docs/development/apps/index.html +10 -10
- nautobot/project-static/docs/development/apps/migration/code-updates.html +10 -10
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +10 -10
- nautobot/project-static/docs/development/apps/migration/from-v1.html +10 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +10 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +10 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +10 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +10 -10
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +10 -10
- nautobot/project-static/docs/development/best-practices.html +1 -2
- nautobot/project-static/docs/development/core/application-registry.html +10 -10
- nautobot/project-static/docs/development/core/best-practices.html +10 -10
- nautobot/project-static/docs/development/core/bootstrap-ui.html +10 -10
- nautobot/project-static/docs/development/core/caching.html +10 -10
- nautobot/project-static/docs/development/core/controllers.html +10 -10
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +10 -10
- nautobot/project-static/docs/development/core/extending-models.html +1 -2
- nautobot/project-static/docs/development/core/generic-views.html +10 -10
- nautobot/project-static/docs/development/core/getting-started.html +10 -10
- nautobot/project-static/docs/development/core/homepage.html +10 -10
- nautobot/project-static/docs/development/core/index.html +10 -10
- nautobot/project-static/docs/development/core/model-checklist.html +10 -10
- nautobot/project-static/docs/development/core/model-features.html +10 -10
- nautobot/project-static/docs/development/core/natural-keys.html +10 -10
- nautobot/project-static/docs/development/core/navigation-menu.html +10 -10
- nautobot/project-static/docs/development/core/react-ui.html +1 -2
- nautobot/project-static/docs/development/core/release-checklist.html +10 -10
- nautobot/project-static/docs/development/core/role-internals.html +10 -10
- nautobot/project-static/docs/development/core/settings.html +10 -10
- nautobot/project-static/docs/development/core/style-guide.html +10 -10
- nautobot/project-static/docs/development/core/templates.html +10 -10
- nautobot/project-static/docs/development/core/testing.html +12 -12
- nautobot/project-static/docs/development/core/user-preferences.html +10 -10
- nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1 -2
- nautobot/project-static/docs/development/extending-models.html +1 -2
- nautobot/project-static/docs/development/generic-views.html +1 -2
- nautobot/project-static/docs/development/getting-started.html +1 -2
- nautobot/project-static/docs/development/homepage.html +1 -2
- nautobot/project-static/docs/development/index.html +10 -10
- nautobot/project-static/docs/development/jobs/index.html +10 -10
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +10 -10
- nautobot/project-static/docs/development/model-features.html +1 -2
- nautobot/project-static/docs/development/natural-keys.html +1 -2
- nautobot/project-static/docs/development/navigation-menu.html +1 -2
- nautobot/project-static/docs/development/react-ui.html +1 -2
- nautobot/project-static/docs/development/release-checklist.html +1 -2
- nautobot/project-static/docs/development/role-internals.html +1 -2
- nautobot/project-static/docs/development/style-guide.html +1 -2
- nautobot/project-static/docs/development/templates.html +1 -2
- nautobot/project-static/docs/development/testing.html +1 -2
- nautobot/project-static/docs/development/user-preferences.html +1 -2
- nautobot/project-static/docs/docker/index.html +1 -2
- nautobot/project-static/docs/index.html +10 -10
- nautobot/project-static/docs/installation/centos.html +1 -2
- nautobot/project-static/docs/installation/external-authentication.html +1 -2
- nautobot/project-static/docs/installation/http-server.html +1 -2
- nautobot/project-static/docs/installation/index.html +1 -2
- nautobot/project-static/docs/installation/migrating-from-netbox.html +1 -2
- nautobot/project-static/docs/installation/migrating-from-postgresql.html +1 -2
- nautobot/project-static/docs/installation/nautobot.html +1 -2
- nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1 -2
- nautobot/project-static/docs/installation/selinux-troubleshooting.html +1 -2
- nautobot/project-static/docs/installation/services.html +1 -2
- nautobot/project-static/docs/installation/ubuntu.html +1 -2
- nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +1 -2
- nautobot/project-static/docs/installation/upgrading.html +1 -2
- nautobot/project-static/docs/models/circuits/circuit.html +1 -2
- nautobot/project-static/docs/models/circuits/circuittermination.html +1 -2
- nautobot/project-static/docs/models/circuits/circuittype.html +1 -2
- nautobot/project-static/docs/models/circuits/provider.html +1 -2
- nautobot/project-static/docs/models/circuits/providernetwork.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudaccount.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudnetwork.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudresourcetype.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudservice.html +1 -2
- nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +1 -2
- nautobot/project-static/docs/models/dcim/cable.html +1 -2
- nautobot/project-static/docs/models/dcim/consoleport.html +1 -2
- nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/consoleserverport.html +1 -2
- nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/controller.html +1 -2
- nautobot/project-static/docs/models/dcim/controllermanageddevicegroup.html +1 -2
- nautobot/project-static/docs/models/dcim/device.html +1 -2
- nautobot/project-static/docs/models/dcim/devicebay.html +1 -2
- nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/devicefamily.html +1 -2
- nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1 -2
- nautobot/project-static/docs/models/dcim/devicetype.html +1 -2
- nautobot/project-static/docs/models/dcim/frontport.html +1 -2
- nautobot/project-static/docs/models/dcim/frontporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/interface.html +1 -2
- nautobot/project-static/docs/models/dcim/interfacetemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/inventoryitem.html +1 -2
- nautobot/project-static/docs/models/dcim/location.html +1 -2
- nautobot/project-static/docs/models/dcim/locationtype.html +1 -2
- nautobot/project-static/docs/models/dcim/manufacturer.html +1 -2
- nautobot/project-static/docs/models/dcim/module.html +1 -2
- nautobot/project-static/docs/models/dcim/modulebay.html +1 -2
- nautobot/project-static/docs/models/dcim/modulebaytemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/moduletype.html +1 -2
- nautobot/project-static/docs/models/dcim/platform.html +1 -2
- nautobot/project-static/docs/models/dcim/powerfeed.html +1 -2
- nautobot/project-static/docs/models/dcim/poweroutlet.html +1 -2
- nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/powerpanel.html +1 -2
- nautobot/project-static/docs/models/dcim/powerport.html +1 -2
- nautobot/project-static/docs/models/dcim/powerporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/rack.html +1 -2
- nautobot/project-static/docs/models/dcim/rackgroup.html +1 -2
- nautobot/project-static/docs/models/dcim/rackreservation.html +1 -2
- nautobot/project-static/docs/models/dcim/rearport.html +1 -2
- nautobot/project-static/docs/models/dcim/rearporttemplate.html +1 -2
- nautobot/project-static/docs/models/dcim/softwareimagefile.html +1 -2
- nautobot/project-static/docs/models/dcim/softwareversion.html +1 -2
- nautobot/project-static/docs/models/dcim/virtualchassis.html +1 -2
- nautobot/project-static/docs/models/extras/computedfield.html +1 -2
- nautobot/project-static/docs/models/extras/configcontext.html +1 -2
- nautobot/project-static/docs/models/extras/configcontextschema.html +1 -2
- nautobot/project-static/docs/models/extras/contact.html +1 -2
- nautobot/project-static/docs/models/extras/customfield.html +1 -2
- nautobot/project-static/docs/models/extras/customlink.html +1 -2
- nautobot/project-static/docs/models/extras/dynamicgroup.html +1 -2
- nautobot/project-static/docs/models/extras/exporttemplate.html +1 -2
- nautobot/project-static/docs/models/extras/gitrepository.html +1 -2
- nautobot/project-static/docs/models/extras/jobhook.html +1 -2
- nautobot/project-static/docs/models/extras/joblogentry.html +1 -2
- nautobot/project-static/docs/models/extras/jobresult.html +1 -2
- nautobot/project-static/docs/models/extras/metadatachoice.html +1 -2
- nautobot/project-static/docs/models/extras/metadatatype.html +1 -2
- nautobot/project-static/docs/models/extras/objectmetadata.html +1 -2
- nautobot/project-static/docs/models/extras/role.html +1 -2
- nautobot/project-static/docs/models/extras/savedview.html +1 -2
- nautobot/project-static/docs/models/extras/secret.html +1 -2
- nautobot/project-static/docs/models/extras/secretsgroup.html +1 -2
- nautobot/project-static/docs/models/extras/staticgroupassociation.html +1 -2
- nautobot/project-static/docs/models/extras/status.html +1 -2
- nautobot/project-static/docs/models/extras/team.html +1 -2
- nautobot/project-static/docs/models/ipam/ipaddress.html +1 -2
- nautobot/project-static/docs/models/ipam/prefix.html +1 -2
- nautobot/project-static/docs/models/ipam/rir.html +1 -2
- nautobot/project-static/docs/models/ipam/routetarget.html +1 -2
- nautobot/project-static/docs/models/ipam/service.html +1 -2
- nautobot/project-static/docs/models/ipam/vlan.html +1 -2
- nautobot/project-static/docs/models/ipam/vlangroup.html +1 -2
- nautobot/project-static/docs/models/ipam/vrf.html +1 -2
- nautobot/project-static/docs/models/tenancy/tenant.html +1 -2
- nautobot/project-static/docs/models/tenancy/tenantgroup.html +1 -2
- nautobot/project-static/docs/models/virtualization/cluster.html +1 -2
- nautobot/project-static/docs/models/virtualization/clustergroup.html +1 -2
- nautobot/project-static/docs/models/virtualization/clustertype.html +1 -2
- nautobot/project-static/docs/models/virtualization/virtualmachine.html +1 -2
- nautobot/project-static/docs/models/virtualization/vminterface.html +1 -2
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +10 -10
- nautobot/project-static/docs/overview/design_philosophy.html +10 -10
- nautobot/project-static/docs/overview/index.html +1 -2
- nautobot/project-static/docs/plugins/development.html +1 -2
- nautobot/project-static/docs/plugins/index.html +1 -2
- nautobot/project-static/docs/plugins/porting-from-netbox.html +1 -2
- nautobot/project-static/docs/release-notes/index.html +15 -15
- nautobot/project-static/docs/release-notes/version-1.0.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.1.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.2.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.3.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.4.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.5.html +10 -10
- nautobot/project-static/docs/release-notes/version-1.6.html +10 -10
- nautobot/project-static/docs/release-notes/version-2.0.html +10 -10
- nautobot/project-static/docs/release-notes/version-2.1.html +10 -10
- nautobot/project-static/docs/release-notes/version-2.2.html +10 -10
- nautobot/project-static/docs/release-notes/version-2.3.html +491 -182
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/rest-api/overview.html +1 -2
- 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 +10 -10
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +10 -10
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +65 -12
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +10 -10
- nautobot/project-static/docs/user-guide/administration/configuration/node-configuration.html +1 -2
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +1 -2
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +10 -10
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +1 -2
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +122 -10
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +1 -2
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +1 -2
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +49 -10
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +10 -10
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/docker.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/index.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation/services.html +10 -10
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +1 -2
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +1 -2
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +10 -10
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +10 -10
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +10 -10
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +10 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +10 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +10 -10
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +10 -10
- nautobot/project-static/docs/user-guide/index.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +10 -10
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +10 -10
- nautobot/project-static/docs/user-guides/custom-fields.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/index.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/ipam.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/platforms.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/tenants.html +1 -2
- nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1 -2
- nautobot/project-static/docs/user-guides/git-data-source.html +1 -2
- nautobot/project-static/docs/user-guides/graphql.html +1 -2
- nautobot/project-static/docs/user-guides/ip-address-merge-tool.html +1 -2
- nautobot/project-static/docs/user-guides/relationships.html +1 -2
- nautobot/project-static/docs/user-guides/s3-django-storage.html +1 -2
- nautobot/project-static/js/forms.js +10 -0
- nautobot/virtualization/forms.py +24 -0
- nautobot/virtualization/templates/virtualization/vminterface.html +4 -0
- nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
- nautobot/virtualization/tests/test_views.py +7 -2
- {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/METADATA +2 -2
- {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/RECORD +522 -520
- nautobot/project-static/docs/assets/stylesheets/main.0253249f.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.0253249f.min.css.map +0 -1
- {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/NOTICE +0 -0
- {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/WHEEL +0 -0
- {nautobot-2.3.10.dist-info → nautobot-2.3.12.dist-info}/entry_points.txt +0 -0
nautobot/core/views/mixins.py
CHANGED
|
@@ -414,7 +414,7 @@ class NautobotViewSetMixin(GenericViewSet, AccessMixin, GetReturnURLMixin, FormV
|
|
|
414
414
|
else:
|
|
415
415
|
# render the form with the error message.
|
|
416
416
|
data = {}
|
|
417
|
-
if self.action in ["bulk_update", "bulk_destroy"]:
|
|
417
|
+
if not request.POST.get("_all") and self.action in ["bulk_update", "bulk_destroy"]:
|
|
418
418
|
pk_list = self.pk_list
|
|
419
419
|
table_class = self.get_table_class()
|
|
420
420
|
table = table_class(queryset.filter(pk__in=pk_list), orderable=False)
|
|
@@ -578,6 +578,9 @@ class NautobotViewSetMixin(GenericViewSet, AccessMixin, GetReturnURLMixin, FormV
|
|
|
578
578
|
if not form_class:
|
|
579
579
|
if self.action == "bulk_destroy":
|
|
580
580
|
queryset = self.get_queryset()
|
|
581
|
+
bulk_delete_all = bool(self.request.POST.get("_all"))
|
|
582
|
+
if bulk_delete_all:
|
|
583
|
+
return ConfirmationForm
|
|
581
584
|
|
|
582
585
|
class BulkDestroyForm(ConfirmationForm):
|
|
583
586
|
pk = ModelMultipleChoiceField(queryset=queryset, widget=MultipleHiddenInput)
|
|
@@ -909,7 +912,48 @@ class ObjectEditViewMixin(NautobotViewSetMixin, mixins.CreateModelMixin, mixins.
|
|
|
909
912
|
return self.form_invalid(form)
|
|
910
913
|
|
|
911
914
|
|
|
912
|
-
class
|
|
915
|
+
class EditAndDeleteAllModelMixin:
|
|
916
|
+
"""
|
|
917
|
+
UI mixin to bulk destroy all and bulk edit all model instances.
|
|
918
|
+
"""
|
|
919
|
+
|
|
920
|
+
def _get_bulk_edit_delete_all_queryset(self, request):
|
|
921
|
+
"""
|
|
922
|
+
Retrieve the queryset of model instances to be bulk-deleted or bulk-deleted, filtered based on request parameters.
|
|
923
|
+
|
|
924
|
+
This method handles the retrieval of a queryset of model instances that match the specified
|
|
925
|
+
filter criteria in the request parameters, allowing a bulk delete operation to be performed
|
|
926
|
+
on all matching instances.
|
|
927
|
+
"""
|
|
928
|
+
model = self.queryset.model
|
|
929
|
+
|
|
930
|
+
# This Mixin is currently been used by both NautobotUIViewSet ObjectBulkDestroyViewMixin, ObjectBulkUpdateViewMixin
|
|
931
|
+
# BulkEditView, and BulkDeleteView which uses different keys for accessing filterset
|
|
932
|
+
filterset_class = getattr(self, "filterset", None)
|
|
933
|
+
if filterset_class is None:
|
|
934
|
+
filterset_class = getattr(self, "filterset_class", None)
|
|
935
|
+
|
|
936
|
+
if request.GET and filterset_class is not None:
|
|
937
|
+
queryset = filterset_class(request.GET, model.objects.all()).qs
|
|
938
|
+
# We take this approach because filterset.qs has already applied .distinct(),
|
|
939
|
+
# and performing a .delete directly on a queryset with .distinct applied is not allowed.
|
|
940
|
+
queryset = self.queryset.filter(pk__in=queryset)
|
|
941
|
+
else:
|
|
942
|
+
queryset = model.objects.all()
|
|
943
|
+
return queryset
|
|
944
|
+
|
|
945
|
+
def _bulk_delete_all_context(self, request, queryset):
|
|
946
|
+
model = queryset.model
|
|
947
|
+
return {
|
|
948
|
+
"obj_type_plural": model._meta.verbose_name_plural,
|
|
949
|
+
"return_url": self.get_return_url(request),
|
|
950
|
+
"total_objs_to_delete": queryset.count(),
|
|
951
|
+
"delete_all": True,
|
|
952
|
+
"table": None,
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
class ObjectBulkDestroyViewMixin(NautobotViewSetMixin, BulkDestroyModelMixin, EditAndDeleteAllModelMixin):
|
|
913
957
|
"""
|
|
914
958
|
UI mixin to bulk destroy model instances.
|
|
915
959
|
"""
|
|
@@ -923,7 +967,10 @@ class ObjectBulkDestroyViewMixin(NautobotViewSetMixin, BulkDestroyModelMixin):
|
|
|
923
967
|
queryset = self.get_queryset()
|
|
924
968
|
model = queryset.model
|
|
925
969
|
# Delete objects
|
|
926
|
-
|
|
970
|
+
if self.request.POST.get("_all"):
|
|
971
|
+
queryset = self._get_bulk_edit_delete_all_queryset(self.request)
|
|
972
|
+
else:
|
|
973
|
+
queryset = queryset.filter(pk__in=pk_list)
|
|
927
974
|
|
|
928
975
|
try:
|
|
929
976
|
with transaction.atomic():
|
|
@@ -951,35 +998,33 @@ class ObjectBulkDestroyViewMixin(NautobotViewSetMixin, BulkDestroyModelMixin):
|
|
|
951
998
|
request.POST "_confirm": Function to validate the table form/BulkDestroyConfirmationForm and to perform the action of bulk destroy. Render the form with errors if exceptions are raised.
|
|
952
999
|
"""
|
|
953
1000
|
queryset = self.get_queryset()
|
|
954
|
-
|
|
1001
|
+
delete_all = bool(request.POST.get("_all"))
|
|
1002
|
+
data = {}
|
|
955
1003
|
# Are we deleting *all* objects in the queryset or just a selected subset?
|
|
956
|
-
if
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
self.filterset_class(request.GET, model.objects.only("pk")).qs.values_list("pk", flat=True)
|
|
960
|
-
)
|
|
961
|
-
else:
|
|
962
|
-
self.pk_list = list(model.objects.all().values_list("pk", flat=True))
|
|
1004
|
+
if delete_all:
|
|
1005
|
+
queryset = self._get_bulk_edit_delete_all_queryset(self.request)
|
|
1006
|
+
data = self._bulk_delete_all_context(request, queryset)
|
|
963
1007
|
else:
|
|
964
1008
|
self.pk_list = list(request.POST.getlist("pk"))
|
|
1009
|
+
|
|
965
1010
|
form_class = self.get_form_class(**kwargs)
|
|
966
|
-
data = {}
|
|
967
1011
|
if "_confirm" in request.POST:
|
|
968
1012
|
form = form_class(request.POST, initial=normalize_querydict(request.GET, form_class=form_class))
|
|
969
1013
|
if form.is_valid():
|
|
970
1014
|
return self.form_valid(form)
|
|
971
1015
|
else:
|
|
972
1016
|
return self.form_invalid(form)
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1017
|
+
if not delete_all:
|
|
1018
|
+
table_class = self.get_table_class()
|
|
1019
|
+
table = table_class(queryset.filter(pk__in=self.pk_list), orderable=False)
|
|
1020
|
+
if not table.rows:
|
|
1021
|
+
messages.warning(
|
|
1022
|
+
request,
|
|
1023
|
+
f"No {queryset.model._meta.verbose_name_plural} were selected for deletion.",
|
|
1024
|
+
)
|
|
1025
|
+
return redirect(self.get_return_url(request))
|
|
981
1026
|
|
|
982
|
-
|
|
1027
|
+
data.update({"table": table})
|
|
983
1028
|
return Response(data)
|
|
984
1029
|
|
|
985
1030
|
|
|
@@ -1037,7 +1082,7 @@ class ObjectBulkCreateViewMixin(NautobotViewSetMixin): # 3.0 TODO: remove, unus
|
|
|
1037
1082
|
return self.form_invalid(form)
|
|
1038
1083
|
|
|
1039
1084
|
|
|
1040
|
-
class ObjectBulkUpdateViewMixin(NautobotViewSetMixin, BulkUpdateModelMixin):
|
|
1085
|
+
class ObjectBulkUpdateViewMixin(NautobotViewSetMixin, BulkUpdateModelMixin, EditAndDeleteAllModelMixin):
|
|
1041
1086
|
"""
|
|
1042
1087
|
UI mixin to bulk update model instances.
|
|
1043
1088
|
"""
|
|
@@ -1062,7 +1107,13 @@ class ObjectBulkUpdateViewMixin(NautobotViewSetMixin, BulkUpdateModelMixin):
|
|
|
1062
1107
|
nullified_fields = request.POST.getlist("_nullify")
|
|
1063
1108
|
with deferred_change_logging_for_bulk_operation():
|
|
1064
1109
|
updated_objects = []
|
|
1065
|
-
|
|
1110
|
+
edit_all = self.request.POST.get("_all")
|
|
1111
|
+
|
|
1112
|
+
if edit_all:
|
|
1113
|
+
queryset = self._get_bulk_edit_delete_all_queryset(self.request)
|
|
1114
|
+
else:
|
|
1115
|
+
queryset = queryset.filter(pk__in=form.cleaned_data["pk"])
|
|
1116
|
+
for obj in queryset:
|
|
1066
1117
|
self.obj = obj
|
|
1067
1118
|
# Update standard fields. If a field is listed in _nullify, delete its value.
|
|
1068
1119
|
for name in standard_fields:
|
|
@@ -1133,38 +1184,41 @@ class ObjectBulkUpdateViewMixin(NautobotViewSetMixin, BulkUpdateModelMixin):
|
|
|
1133
1184
|
request.POST "_edit": Function to render the user selection of objects in a table form/BulkUpdateForm via Response that is passed to NautobotHTMLRenderer.
|
|
1134
1185
|
request.POST "_apply": Function to validate the table form/BulkUpdateForm and to perform the action of bulk update. Render the form with errors if exceptions are raised.
|
|
1135
1186
|
"""
|
|
1136
|
-
|
|
1137
|
-
model = queryset.model
|
|
1187
|
+
edit_all = request.POST.get("_all")
|
|
1138
1188
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
self.pk_list = list(
|
|
1143
|
-
self.filterset_class(request.GET, model.objects.only("pk")).qs.values_list("pk", flat=True)
|
|
1144
|
-
)
|
|
1145
|
-
else:
|
|
1146
|
-
self.pk_list = list(model.objects.all().values_list("pk", flat=True))
|
|
1189
|
+
if edit_all:
|
|
1190
|
+
self.pk_list = None
|
|
1191
|
+
queryset = self._get_bulk_edit_delete_all_queryset(request)
|
|
1147
1192
|
else:
|
|
1148
1193
|
self.pk_list = list(request.POST.getlist("pk"))
|
|
1194
|
+
queryset = self.get_queryset().filter(pk__in=self.pk_list)
|
|
1195
|
+
|
|
1149
1196
|
data = {}
|
|
1150
1197
|
form_class = self.get_form_class()
|
|
1151
1198
|
if "_apply" in request.POST:
|
|
1152
1199
|
self.kwargs = kwargs
|
|
1153
|
-
form = form_class(queryset.model, request.POST)
|
|
1200
|
+
form = form_class(queryset.model, request.POST, edit_all=edit_all)
|
|
1154
1201
|
restrict_form_fields(form, request.user)
|
|
1155
1202
|
if form.is_valid():
|
|
1156
1203
|
return self.form_valid(form)
|
|
1157
1204
|
else:
|
|
1158
1205
|
return self.form_invalid(form)
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1206
|
+
table = None
|
|
1207
|
+
if not edit_all:
|
|
1208
|
+
table_class = self.get_table_class()
|
|
1209
|
+
table = table_class(queryset, orderable=False)
|
|
1210
|
+
if not table.rows:
|
|
1211
|
+
messages.warning(
|
|
1212
|
+
request,
|
|
1213
|
+
f"No {queryset.model._meta.verbose_name_plural} were selected to update.",
|
|
1214
|
+
)
|
|
1215
|
+
return redirect(self.get_return_url(request))
|
|
1216
|
+
data.update(
|
|
1217
|
+
{
|
|
1218
|
+
"table": table,
|
|
1219
|
+
"objs_count": queryset.count(),
|
|
1220
|
+
}
|
|
1221
|
+
)
|
|
1168
1222
|
return Response(data)
|
|
1169
1223
|
|
|
1170
1224
|
|
nautobot/core/views/renderers.py
CHANGED
|
@@ -249,19 +249,22 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
|
|
|
249
249
|
"return_url": return_url,
|
|
250
250
|
}
|
|
251
251
|
form = form_class(initial=initial)
|
|
252
|
-
|
|
252
|
+
delete_all = request.POST.get("_all")
|
|
253
|
+
if not delete_all:
|
|
254
|
+
table = self.construct_table(view, pk_list=pk_list)
|
|
253
255
|
elif view.action == "bulk_create": # 3.0 TODO: remove, replaced by ImportObjects system Job
|
|
254
256
|
form = view.get_form()
|
|
255
257
|
if request.data:
|
|
256
258
|
table = data.get("table")
|
|
257
259
|
elif view.action == "bulk_update":
|
|
260
|
+
edit_all = request.POST.get("_all")
|
|
258
261
|
pk_list = getattr(view, "pk_list", [])
|
|
259
|
-
if pk_list:
|
|
262
|
+
if pk_list or edit_all:
|
|
260
263
|
initial_data = {"pk": pk_list}
|
|
261
|
-
form = form_class(model, initial=initial_data)
|
|
262
|
-
|
|
264
|
+
form = form_class(model, initial=initial_data, edit_all=edit_all)
|
|
263
265
|
restrict_form_fields(form, request.user)
|
|
264
|
-
|
|
266
|
+
if not edit_all:
|
|
267
|
+
table = self.construct_table(view, pk_list=pk_list)
|
|
265
268
|
elif view.action == "notes":
|
|
266
269
|
initial_data = {
|
|
267
270
|
"assigned_object_type": content_type,
|
nautobot/dcim/choices.py
CHANGED
|
@@ -804,6 +804,9 @@ class InterfaceTypeChoices(ChoiceSet):
|
|
|
804
804
|
TYPE_400GE_CFP8 = "400gbase-x-cfp8"
|
|
805
805
|
TYPE_800GE_QSFP_DD = "800gbase-x-qsfpdd"
|
|
806
806
|
TYPE_800GE_OSFP = "800gbase-x-osfp"
|
|
807
|
+
TYPE_800GE_OSFP_XD = "800gbase-x-osfp-xd"
|
|
808
|
+
TYPE_1600GE_OSFP = "1600gbase-x-osfp"
|
|
809
|
+
TYPE_1600GE_OSFP_XD = "1600gbase-x-osfp-xd"
|
|
807
810
|
|
|
808
811
|
# Ethernet Backplane
|
|
809
812
|
TYPE_1GE_KX = "1000base-kx"
|
|
@@ -977,6 +980,9 @@ class InterfaceTypeChoices(ChoiceSet):
|
|
|
977
980
|
(TYPE_400GE_CFP8, "CPF8 (400GE)"),
|
|
978
981
|
(TYPE_800GE_QSFP_DD, "QSFP-DD (800GE)"),
|
|
979
982
|
(TYPE_800GE_OSFP, "OSFP (800GE)"),
|
|
983
|
+
(TYPE_800GE_OSFP_XD, "OSFP-XD (800GE)"),
|
|
984
|
+
(TYPE_1600GE_OSFP, "OSFP (1600GE)"),
|
|
985
|
+
(TYPE_1600GE_OSFP_XD, "OSFP-XD (1600GE)"),
|
|
980
986
|
),
|
|
981
987
|
),
|
|
982
988
|
(
|
nautobot/dcim/tables/devices.py
CHANGED
|
@@ -220,13 +220,11 @@ class DeviceTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
220
220
|
)
|
|
221
221
|
|
|
222
222
|
|
|
223
|
-
class DeviceImportTable(BaseTable):
|
|
223
|
+
class DeviceImportTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
224
224
|
name = tables.TemplateColumn(template_code=DEVICE_LINK)
|
|
225
|
-
status = ColoredLabelColumn()
|
|
226
225
|
tenant = TenantColumn()
|
|
227
226
|
location = tables.Column(linkify=True)
|
|
228
227
|
rack = tables.Column(linkify=True)
|
|
229
|
-
role = tables.Column(verbose_name="Role")
|
|
230
228
|
device_type = tables.Column(verbose_name="Type")
|
|
231
229
|
|
|
232
230
|
class Meta(BaseTable.Meta):
|
|
@@ -1277,6 +1275,9 @@ class SoftwareImageFileTable(StatusTableMixin, BaseTable):
|
|
|
1277
1275
|
class SoftwareVersionTable(StatusTableMixin, BaseTable):
|
|
1278
1276
|
pk = ToggleColumn()
|
|
1279
1277
|
version = tables.Column(linkify=True)
|
|
1278
|
+
platform = tables.Column(linkify=True)
|
|
1279
|
+
release_date = tables.DateColumn()
|
|
1280
|
+
end_of_support_date = tables.DateColumn()
|
|
1280
1281
|
software_image_file_count = LinkedCountColumn(
|
|
1281
1282
|
viewname="dcim:softwareimagefile_list",
|
|
1282
1283
|
url_params={"software_version": "pk"},
|
|
@@ -1330,15 +1331,13 @@ class SoftwareVersionTable(StatusTableMixin, BaseTable):
|
|
|
1330
1331
|
)
|
|
1331
1332
|
|
|
1332
1333
|
|
|
1333
|
-
class ControllerTable(BaseTable):
|
|
1334
|
+
class ControllerTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
1334
1335
|
"""Table for list view."""
|
|
1335
1336
|
|
|
1336
1337
|
pk = ToggleColumn()
|
|
1337
1338
|
name = tables.Column(linkify=True)
|
|
1338
|
-
status = ColoredLabelColumn()
|
|
1339
1339
|
location = tables.Column(linkify=True)
|
|
1340
1340
|
platform = tables.Column(linkify=True)
|
|
1341
|
-
role = tables.Column(linkify=True)
|
|
1342
1341
|
tenant = TenantColumn()
|
|
1343
1342
|
external_integration = tables.Column(linkify=True)
|
|
1344
1343
|
controller_device = tables.Column(linkify=True)
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
<span class="hover_copy">
|
|
59
59
|
<h1>
|
|
60
60
|
<span id="devicename">{% block title %}{{ object }}{% endblock title %}</span>
|
|
61
|
-
<button class="btn btn-xs btn-default hover_copy_button" data-clipboard-
|
|
61
|
+
<button class="btn btn-xs btn-default hover_copy_button" data-clipboard-text="{{ object }}">
|
|
62
62
|
<span class="mdi mdi-content-copy"></span>
|
|
63
63
|
</button>
|
|
64
64
|
</h1>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<form action="" method="post" class="form form-horizontal">
|
|
8
8
|
{% csrf_token %}
|
|
9
9
|
<div class="row">
|
|
10
|
-
<div class="col-md-
|
|
10
|
+
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
|
|
11
11
|
{% if form.non_field_errors %}
|
|
12
12
|
<div class="panel panel-danger">
|
|
13
13
|
<div class="panel-heading"><strong>Errors</strong></div>
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
27
27
|
{% include 'inc/extras_features_edit_form_fields.html' with form=model_form %}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
</
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="row">
|
|
31
|
+
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1 text-right">
|
|
32
|
+
<button type="submit" name="_create" class="btn btn-primary">Create</button>
|
|
33
|
+
<button type="submit" name="_addanother" class="btn btn-primary">Create and Add More</button>
|
|
34
|
+
<a href="{{ return_url }}" class="btn btn-default">Cancel</a>
|
|
35
35
|
</div>
|
|
36
36
|
</div>
|
|
37
37
|
</form>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<form action="" method="post" enctype="multipart/form-data" class="form form-horizontal">
|
|
6
6
|
{% csrf_token %}
|
|
7
7
|
<div class="row">
|
|
8
|
-
<div class="col-md-
|
|
8
|
+
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
|
|
9
9
|
<h3>{% block title %}Add New Member to Virtual Chassis {{ virtual_chassis }}{% endblock %}</h3>
|
|
10
10
|
{% if membership_form.non_field_errors %}
|
|
11
11
|
<div class="panel panel-danger">
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
27
27
|
<div class="row">
|
|
28
|
-
<div class="col-md-
|
|
28
|
+
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1 text-right">
|
|
29
29
|
<button type="submit" name="_save" class="btn btn-primary">Save</button>
|
|
30
30
|
<button type="submit" name="_addanother" class="btn btn-primary">Add Another</button>
|
|
31
31
|
<a href="{{ return_url }}" class="btn btn-default">Cancel</a>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
{{ pk_form.pk }}
|
|
9
9
|
{{ formset.management_form }}
|
|
10
10
|
<div class="row">
|
|
11
|
-
<div class="col-
|
|
11
|
+
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
|
|
12
12
|
<h3>{% block title %}{% if vc_form.instance %}Editing {{ vc_form.instance }}{% else %}New Virtual Chassis{% endif %}{% endblock %}</h3>
|
|
13
13
|
{% if vc_form.non_field_errors %}
|
|
14
14
|
<div class="panel panel-danger">
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
</div>
|
|
85
85
|
</div>
|
|
86
86
|
<div class="row">
|
|
87
|
-
<div class="col-
|
|
87
|
+
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1 text-right">
|
|
88
88
|
<button type="submit" name="_update" class="btn btn-primary">Update</button>
|
|
89
89
|
<a href="{{ return_url }}" class="btn btn-default">Cancel</a>
|
|
90
90
|
</div>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from django.urls import reverse
|
|
2
|
+
|
|
3
|
+
from nautobot.core.testing.integration import SeleniumTestCase
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CreateDeviceTestCase(SeleniumTestCase):
|
|
7
|
+
"""
|
|
8
|
+
Create a device and all pre-requisite objects through the UI.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def test_create_device(self):
|
|
12
|
+
"""
|
|
13
|
+
This test goes through the process of creating a device in the UI. All pre-requisite objects are created:
|
|
14
|
+
- Manufacturer
|
|
15
|
+
- Device Type
|
|
16
|
+
- LocationType
|
|
17
|
+
- Location
|
|
18
|
+
- Role
|
|
19
|
+
- Device
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
self.user.is_superuser = True
|
|
23
|
+
self.user.save()
|
|
24
|
+
self.login(self.user.username, self.password)
|
|
25
|
+
|
|
26
|
+
# Manufacturer
|
|
27
|
+
self.click_navbar_entry("Devices", "Manufacturers")
|
|
28
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:manufacturer_list"))
|
|
29
|
+
self.click_list_view_add_button()
|
|
30
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:manufacturer_add"))
|
|
31
|
+
self.browser.fill("name", "Test Manufacturer 1")
|
|
32
|
+
self.click_edit_form_create_button()
|
|
33
|
+
|
|
34
|
+
# Device Type
|
|
35
|
+
self.click_navbar_entry("Devices", "Device Types")
|
|
36
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:devicetype_list"))
|
|
37
|
+
self.click_list_view_add_button()
|
|
38
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:devicetype_add"))
|
|
39
|
+
self.fill_select2_field("manufacturer", "Test Manufacturer 1")
|
|
40
|
+
self.browser.fill("model", "Test Device Type 1")
|
|
41
|
+
self.click_edit_form_create_button()
|
|
42
|
+
|
|
43
|
+
# LocationType
|
|
44
|
+
self.click_navbar_entry("Organization", "Location Types")
|
|
45
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:locationtype_list"))
|
|
46
|
+
self.click_list_view_add_button()
|
|
47
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:locationtype_add"))
|
|
48
|
+
self.fill_select2_multiselect_field("content_types", "dcim | device")
|
|
49
|
+
self.browser.fill("name", "Test Location Type 1")
|
|
50
|
+
self.click_edit_form_create_button()
|
|
51
|
+
|
|
52
|
+
# Location
|
|
53
|
+
self.click_navbar_entry("Organization", "Locations")
|
|
54
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:location_list"))
|
|
55
|
+
self.click_list_view_add_button()
|
|
56
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:location_add"))
|
|
57
|
+
self.fill_select2_field("location_type", "Test Location Type 1")
|
|
58
|
+
self.fill_select2_field("status", "") # pick first status
|
|
59
|
+
self.browser.fill("name", "Test Location 1")
|
|
60
|
+
self.click_edit_form_create_button()
|
|
61
|
+
|
|
62
|
+
# Role
|
|
63
|
+
self.click_navbar_entry("Organization", "Roles")
|
|
64
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("extras:role_list"))
|
|
65
|
+
self.click_list_view_add_button()
|
|
66
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("extras:role_add"))
|
|
67
|
+
self.browser.fill("name", "Test Role 1")
|
|
68
|
+
self.fill_select2_multiselect_field("content_types", "dcim | device")
|
|
69
|
+
self.click_edit_form_create_button()
|
|
70
|
+
|
|
71
|
+
# Device
|
|
72
|
+
self.click_navbar_entry("Devices", "Devices")
|
|
73
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:device_list"))
|
|
74
|
+
self.click_list_view_add_button()
|
|
75
|
+
self.assertEqual(self.browser.url, self.live_server_url + reverse("dcim:device_add"))
|
|
76
|
+
self.browser.fill("name", "Test Device Integration Test 1")
|
|
77
|
+
self.fill_select2_field("role", "Test Role 1")
|
|
78
|
+
self.fill_select2_field("device_type", "Test Device Type 1")
|
|
79
|
+
self.fill_select2_field("location", "Test Location 1")
|
|
80
|
+
self.fill_select2_field("status", "") # pick first status
|
|
81
|
+
self.click_edit_form_create_button()
|
|
82
|
+
|
|
83
|
+
# Assert that the device was created
|
|
84
|
+
self.assertTrue(self.browser.is_text_present("Created device Test Device Integration Test 1", wait_time=5))
|
|
85
|
+
self.assertTrue(self.browser.is_text_present("Test Location 1", wait_time=5))
|
|
86
|
+
self.assertTrue(self.browser.is_text_present("Test Device Type 1", wait_time=5))
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Additional functions to process an OAuth2/OIDC user."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from django.conf import settings
|
|
6
|
+
from django.contrib.auth.models import Group
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
CLAIMS_GROUP_NAME = getattr(settings, "NAUTOBOT_SSO_CLAIMS_GROUP", "groups")
|
|
12
|
+
""" Which claim to look at in the OAuth2/OIDC response
|
|
13
|
+
|
|
14
|
+
For Okta you can look at `Okta -> Authorization Servers -> Claims`. And a reasonable
|
|
15
|
+
default is "groups". For Azure a reasonable default is "roles".
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
SUPERUSER_GROUPS = getattr(settings, "NAUTOBOT_SSO_SUPERUSER_GROUPS", [])
|
|
19
|
+
STAFF_GROUPS = getattr(settings, "NAUTOBOT_SSO_STAFF_GROUPS", [])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def group_sync(uid, user=None, response=None, *args, **kwargs):
|
|
23
|
+
"""Sync the users groups from OAuth2/OIDC auth and set staff/superuser as appropriate."""
|
|
24
|
+
if user and response and CLAIMS_GROUP_NAME and response.get(CLAIMS_GROUP_NAME, False):
|
|
25
|
+
group_memberships = response.get(CLAIMS_GROUP_NAME)
|
|
26
|
+
is_staff = False
|
|
27
|
+
is_superuser = False
|
|
28
|
+
logger.debug(f"User {uid} is a member of {', '.join(group_memberships)}")
|
|
29
|
+
# Make sure all groups exist in Nautobot
|
|
30
|
+
group_ids = []
|
|
31
|
+
for group in group_memberships:
|
|
32
|
+
if group in SUPERUSER_GROUPS:
|
|
33
|
+
is_superuser = True
|
|
34
|
+
if group in STAFF_GROUPS:
|
|
35
|
+
is_staff = True
|
|
36
|
+
group_ids.append(Group.objects.get_or_create(name=group)[0].id)
|
|
37
|
+
user.groups.set(group_ids)
|
|
38
|
+
user.is_superuser = is_superuser
|
|
39
|
+
user.is_staff = is_staff
|
|
40
|
+
user.save()
|
|
41
|
+
else:
|
|
42
|
+
logger.debug(f"Did not receive groups from OAuth2/OIDC, response: {response}")
|
|
@@ -201,6 +201,7 @@ class ObjectMetadata(ChangeLoggedModel, BaseModel):
|
|
|
201
201
|
objects = ObjectMetadataManager()
|
|
202
202
|
natural_key_field_names = ["pk"]
|
|
203
203
|
documentation_static_path = "docs/user-guide/platform-functionality/objectmetadata.html"
|
|
204
|
+
is_metadata_associable_model = False
|
|
204
205
|
|
|
205
206
|
class Meta:
|
|
206
207
|
ordering = ["metadata_type"]
|
nautobot/extras/models/models.py
CHANGED
|
@@ -831,7 +831,7 @@ class Note(ChangeLoggedModel, BaseModel):
|
|
|
831
831
|
unique_together = [["assigned_object_type", "assigned_object_id", "user_name", "created"]]
|
|
832
832
|
|
|
833
833
|
def __str__(self):
|
|
834
|
-
return f"{self.assigned_object} - {self.created.isoformat()}"
|
|
834
|
+
return f"{self.assigned_object} - {self.created.isoformat() if self.created else None}"
|
|
835
835
|
|
|
836
836
|
def save(self, *args, **kwargs):
|
|
837
837
|
# Record the user's name as static strings
|
|
@@ -207,8 +207,9 @@ class NautobotAppConfig(NautobotConfig):
|
|
|
207
207
|
override_views = import_object(f"{self.__module__}.{self.override_views}")
|
|
208
208
|
if override_views is not None:
|
|
209
209
|
for qualified_view_name, view in override_views.items():
|
|
210
|
+
view_class_name = view.view_class.__name__ if hasattr(view, "view_class") else view.cls.__name__
|
|
210
211
|
self.features.setdefault("overridden_views", []).append(
|
|
211
|
-
(qualified_view_name, f"{view.__module__}.{
|
|
212
|
+
(qualified_view_name, f"{view.__module__}.{view_class_name}")
|
|
212
213
|
)
|
|
213
214
|
register_override_views(override_views, self.name)
|
|
214
215
|
|
nautobot/extras/tables.py
CHANGED
|
@@ -978,6 +978,7 @@ class MetadataTypeTable(BaseTable):
|
|
|
978
978
|
|
|
979
979
|
class ObjectMetadataTable(BaseTable):
|
|
980
980
|
pk = ToggleColumn()
|
|
981
|
+
# NOTE: there is no identity column in this table; this is intentional as we have no detail view for ObjectMetadata
|
|
981
982
|
metadata_type = tables.Column(linkify=True)
|
|
982
983
|
assigned_object = tables.TemplateColumn(
|
|
983
984
|
template_code=ASSIGNED_OBJECT, verbose_name="Assigned object", orderable=False
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
</th>
|
|
29
29
|
</tr>
|
|
30
30
|
{% endifchanged %}
|
|
31
|
-
<tr class="collapseme-{{ row.record.grouping|slugify }}{% if not perms.extras.run_job or not row.record.runnable %} disabled{% endif %} collapse in" data-parent="#accordion" {{ row.attrs.as_html }}>
|
|
31
|
+
<tr class="{% cycle 'even' 'odd' %} collapseme-{{ row.record.grouping|slugify }}{% if not perms.extras.run_job or not row.record.runnable %} disabled{% endif %} collapse in" data-parent="#accordion" {{ row.attrs.as_html }}>
|
|
32
32
|
{% for column, cell in row.items %}
|
|
33
33
|
<td {{ column.attrs.td.as_html }}>{{ cell }}</td>
|
|
34
34
|
{% endfor %}
|
|
@@ -1395,6 +1395,7 @@ class RequiredRelationshipTestMixin:
|
|
|
1395
1395
|
# Protected FK to SoftwareVersion prevents deletion
|
|
1396
1396
|
Controller.objects.all().delete()
|
|
1397
1397
|
Device.objects.all().update(software_version=None)
|
|
1398
|
+
Device.objects.all().delete()
|
|
1398
1399
|
|
|
1399
1400
|
# Create required relationships:
|
|
1400
1401
|
device_ct = ContentType.objects.get_for_model(Device)
|
|
@@ -3033,8 +3033,6 @@ class ObjectChangeTestCase(TestCase):
|
|
|
3033
3033
|
|
|
3034
3034
|
|
|
3035
3035
|
class ObjectMetadataTestCase(
|
|
3036
|
-
ViewTestCases.GetObjectViewTestCase,
|
|
3037
|
-
ViewTestCases.GetObjectChangelogViewTestCase,
|
|
3038
3036
|
ViewTestCases.ListObjectsViewTestCase,
|
|
3039
3037
|
):
|
|
3040
3038
|
model = ObjectMetadata
|
nautobot/extras/views.py
CHANGED
|
@@ -2228,8 +2228,6 @@ class MetadataTypeUIViewSet(NautobotUIViewSet):
|
|
|
2228
2228
|
|
|
2229
2229
|
|
|
2230
2230
|
class ObjectMetadataUIViewSet(
|
|
2231
|
-
ObjectChangeLogViewMixin,
|
|
2232
|
-
ObjectDetailViewMixin,
|
|
2233
2231
|
ObjectListViewMixin,
|
|
2234
2232
|
):
|
|
2235
2233
|
filterset_class = filters.ObjectMetadataFilterSet
|
|
@@ -2846,6 +2844,7 @@ class StatusBulkDeleteView(generic.BulkDeleteView):
|
|
|
2846
2844
|
|
|
2847
2845
|
queryset = Status.objects.all()
|
|
2848
2846
|
table = tables.StatusTable
|
|
2847
|
+
filterset = filters.StatusFilterSet
|
|
2849
2848
|
|
|
2850
2849
|
|
|
2851
2850
|
class StatusDeleteView(generic.ObjectDeleteView):
|
nautobot/ipam/factory.py
CHANGED
|
@@ -238,6 +238,9 @@ class VLANFactory(PrimaryModelFactory):
|
|
|
238
238
|
lambda: Location.objects.filter(location_type__content_types__in=[vlan_ct]), minimum=0
|
|
239
239
|
)
|
|
240
240
|
)
|
|
241
|
+
if self.vlan_group and self.vlan_group.location:
|
|
242
|
+
# add the parent of the vlan group location to the vlan locations
|
|
243
|
+
self.locations.add(self.vlan_group.location.ancestors(include_self=True)[0])
|
|
241
244
|
|
|
242
245
|
|
|
243
246
|
class VLANGetOrCreateFactory(VLANFactory):
|
nautobot/ipam/filters.py
CHANGED
|
@@ -90,6 +90,11 @@ class VRFFilterSet(NautobotFilterSet, StatusModelFilterSetMixin, TenancyModelFil
|
|
|
90
90
|
to_field_name="name",
|
|
91
91
|
label="Device (ID or name)",
|
|
92
92
|
)
|
|
93
|
+
virtual_machines = NaturalKeyOrPKMultipleChoiceFilter(
|
|
94
|
+
queryset=VirtualMachine.objects.all(),
|
|
95
|
+
to_field_name="name",
|
|
96
|
+
label="Virtual Machine (ID or name)",
|
|
97
|
+
)
|
|
93
98
|
prefix = NaturalKeyOrPKMultipleChoiceFilter(
|
|
94
99
|
field_name="prefixes",
|
|
95
100
|
queryset=Prefix.objects.all(),
|