nautobot 2.4.14__py3-none-any.whl → 2.4.15__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/choices.py +8 -0
- nautobot/apps/ui.py +14 -0
- nautobot/core/api/views.py +2 -0
- nautobot/core/choices.py +4 -0
- nautobot/core/filters.py +21 -41
- nautobot/core/management/commands/check_job_approval_status.py +47 -0
- nautobot/core/management/commands/generate_test_data.py +1 -1
- nautobot/core/management/commands/migrate.py +1 -1
- nautobot/core/models/tree_queries.py +17 -0
- nautobot/core/settings.py +2 -2
- nautobot/core/tables.py +25 -2
- nautobot/core/templates/base_django.html +1 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
- nautobot/core/templates/generic/object_list.html +17 -20
- nautobot/core/templates/inc/breadcrumbs.html +14 -0
- nautobot/core/templatetags/buttons.py +2 -4
- nautobot/core/templatetags/helpers.py +29 -6
- nautobot/core/templatetags/ui_framework.py +21 -0
- nautobot/core/testing/filters.py +20 -3
- nautobot/core/testing/forms.py +1 -1
- nautobot/core/tests/integration/test_filters.py +2 -2
- nautobot/core/tests/test_breadcrumbs.py +366 -0
- nautobot/core/tests/test_commands.py +40 -0
- nautobot/core/tests/test_filters.py +51 -1
- nautobot/core/tests/test_forms.py +1 -1
- nautobot/core/tests/test_graphql.py +4 -4
- nautobot/core/tests/test_titles.py +183 -0
- nautobot/core/tests/test_tree_queries.py +30 -0
- nautobot/core/tests/test_views.py +2 -2
- nautobot/core/tests/test_views_utils.py +1 -1
- nautobot/core/ui/breadcrumbs.py +538 -0
- nautobot/core/ui/bulk_buttons.py +53 -0
- nautobot/core/ui/object_detail.py +31 -8
- nautobot/core/ui/titles.py +127 -0
- nautobot/core/ui/utils.py +25 -0
- nautobot/core/utils/migrations.py +1 -1
- nautobot/core/views/__init__.py +1 -1
- nautobot/core/views/mixins.py +26 -1
- nautobot/core/views/renderers.py +20 -2
- nautobot/core/views/utils.py +13 -12
- nautobot/dcim/api/serializers.py +9 -0
- nautobot/dcim/choices.py +53 -0
- nautobot/dcim/filters/__init__.py +15 -3
- nautobot/dcim/forms.py +120 -7
- nautobot/dcim/management/commands/trace_paths.py +1 -1
- nautobot/dcim/migrations/0072_alter_powerfeed_options_and_more.py +97 -0
- nautobot/dcim/models/device_component_templates.py +8 -0
- nautobot/dcim/models/device_components.py +31 -12
- nautobot/dcim/models/devices.py +1 -1
- nautobot/dcim/models/power.py +171 -10
- nautobot/dcim/models/racks.py +7 -4
- nautobot/dcim/tables/devices.py +2 -0
- nautobot/dcim/tables/devicetypes.py +1 -0
- nautobot/dcim/tables/power.py +30 -2
- nautobot/dcim/templates/dcim/device.html +2 -2
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -214
- nautobot/dcim/templates/dcim/location_retrieve.html +2 -2
- nautobot/dcim/templates/dcim/powerfeed_edit.html +8 -0
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -1
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +61 -0
- nautobot/dcim/tests/test_api.py +24 -4
- nautobot/dcim/tests/test_filters.py +91 -13
- nautobot/dcim/tests/test_models.py +262 -0
- nautobot/dcim/tests/test_views.py +20 -12
- nautobot/dcim/utils.py +9 -0
- nautobot/dcim/views.py +390 -77
- nautobot/extras/factory.py +19 -20
- nautobot/extras/filters/__init__.py +3 -2
- nautobot/extras/filters/mixins.py +15 -1
- nautobot/extras/forms/__init__.py +2 -1
- nautobot/extras/forms/forms.py +62 -0
- nautobot/extras/managers.py +4 -1
- nautobot/extras/migrations/0125_jobresult_date_started.py +18 -0
- nautobot/extras/models/customfields.py +1 -2
- nautobot/extras/models/datasources.py +1 -2
- nautobot/extras/models/jobs.py +7 -3
- nautobot/extras/plugins/views.py +24 -1
- nautobot/extras/secrets/__init__.py +1 -1
- nautobot/extras/tables.py +9 -0
- nautobot/extras/templates/extras/customfield.html +2 -129
- nautobot/extras/templates/extras/customfield_edit.html +2 -108
- nautobot/extras/templates/extras/customfield_retrieve.html +129 -0
- nautobot/extras/templates/extras/customfield_update.html +108 -0
- nautobot/extras/templates/extras/inc/jobresult.html +7 -3
- nautobot/extras/templates/extras/jobresult.html +2 -155
- nautobot/extras/templates/extras/jobresult_retrieve.html +155 -0
- nautobot/extras/templates/extras/marketplace.html +5 -6
- nautobot/extras/templates/extras/note.html +2 -53
- nautobot/extras/templates/extras/note_retrieve.html +53 -0
- nautobot/extras/templates/extras/plugins_list.html +5 -6
- nautobot/extras/templatetags/custom_links.py +2 -2
- nautobot/extras/templatetags/job_buttons.py +1 -1
- nautobot/extras/templatetags/plugins.py +1 -1
- nautobot/extras/tests/integration/test_computedfields.py +2 -2
- nautobot/extras/tests/integration/test_customfields.py +14 -11
- nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/integration/test_notes.py +1 -1
- nautobot/extras/tests/integration/test_plugins.py +6 -6
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_filters.py +9 -0
- nautobot/extras/tests/test_forms.py +2 -2
- nautobot/extras/tests/test_plugins.py +2 -3
- nautobot/extras/tests/test_relationships.py +7 -7
- nautobot/extras/tests/test_views.py +172 -1
- nautobot/extras/urls.py +3 -59
- nautobot/extras/utils.py +1 -1
- nautobot/extras/views.py +77 -178
- nautobot/ipam/tables.py +8 -15
- nautobot/ipam/tests/migration/test_migrations.py +8 -8
- nautobot/ipam/tests/test_api.py +2 -2
- nautobot/ipam/tests/test_models.py +1 -1
- nautobot/project-static/docs/404.html +23 -0
- nautobot/project-static/docs/apps/index.html +23 -0
- nautobot/project-static/docs/apps/nautobot-apps.html +23 -0
- nautobot/project-static/docs/assets/_mkdocstrings.css +44 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +28 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +25 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +128 -20
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +37 -4
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +39 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +25 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +24 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +32 -5
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +41 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +39 -7
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +43 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +74 -59
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +143 -28
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +43 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +135 -53
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +229 -36
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +27 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +30 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +162 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +258 -51
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5987 -2620
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +25 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +154 -55
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +150 -35
- nautobot/project-static/docs/development/apps/api/configuration-view.html +23 -0
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +23 -0
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +23 -0
- nautobot/project-static/docs/development/apps/api/models/global-search.html +23 -0
- nautobot/project-static/docs/development/apps/api/models/graphql.html +23 -0
- nautobot/project-static/docs/development/apps/api/models/index.html +23 -0
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +23 -0
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +23 -0
- nautobot/project-static/docs/development/apps/api/prometheus.html +23 -0
- nautobot/project-static/docs/development/apps/api/setup.html +23 -0
- nautobot/project-static/docs/development/apps/api/testing.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +23 -0
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/base-template.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/index.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +31 -2
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/notes.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +23 -0
- nautobot/project-static/docs/development/apps/api/views/urls.html +23 -0
- nautobot/project-static/docs/development/apps/index.html +23 -0
- nautobot/project-static/docs/development/apps/migration/code-updates.html +23 -0
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +23 -0
- nautobot/project-static/docs/development/apps/migration/from-v1.html +23 -0
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +23 -0
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +23 -0
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +23 -0
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +23 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +26 -3
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +10544 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +23 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +23 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +23 -0
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +26 -3
- nautobot/project-static/docs/development/core/application-registry.html +23 -0
- nautobot/project-static/docs/development/core/best-practices.html +23 -0
- nautobot/project-static/docs/development/core/bootstrap-ui.html +23 -0
- nautobot/project-static/docs/development/core/caching.html +23 -0
- nautobot/project-static/docs/development/core/controllers.html +23 -0
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +23 -0
- nautobot/project-static/docs/development/core/generic-views.html +23 -0
- nautobot/project-static/docs/development/core/getting-started.html +23 -0
- nautobot/project-static/docs/development/core/homepage.html +23 -0
- nautobot/project-static/docs/development/core/index.html +23 -0
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +23 -0
- nautobot/project-static/docs/development/core/model-checklist.html +23 -0
- nautobot/project-static/docs/development/core/model-features.html +23 -0
- nautobot/project-static/docs/development/core/natural-keys.html +23 -0
- nautobot/project-static/docs/development/core/navigation-menu.html +23 -0
- nautobot/project-static/docs/development/core/release-checklist.html +23 -0
- nautobot/project-static/docs/development/core/role-internals.html +23 -0
- nautobot/project-static/docs/development/core/settings.html +23 -0
- nautobot/project-static/docs/development/core/style-guide.html +23 -0
- nautobot/project-static/docs/development/core/templates.html +23 -0
- nautobot/project-static/docs/development/core/testing.html +23 -0
- nautobot/project-static/docs/development/core/ui-component-framework.html +713 -255
- nautobot/project-static/docs/development/core/user-preferences.html +23 -0
- nautobot/project-static/docs/development/index.html +23 -0
- nautobot/project-static/docs/development/jobs/getting-started.html +23 -0
- nautobot/project-static/docs/development/jobs/index.html +23 -0
- nautobot/project-static/docs/development/jobs/installation.html +23 -0
- nautobot/project-static/docs/development/jobs/job-extensions.html +23 -0
- nautobot/project-static/docs/development/jobs/job-logging.html +23 -0
- nautobot/project-static/docs/development/jobs/job-patterns.html +23 -0
- nautobot/project-static/docs/development/jobs/job-structure.html +23 -0
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +23 -0
- nautobot/project-static/docs/development/jobs/testing.html +23 -0
- nautobot/project-static/docs/index.html +23 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/breadcrumbs-titles-data-flow.png +0 -0
- nautobot/project-static/docs/media/power_distribution.png +0 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +23 -0
- nautobot/project-static/docs/overview/design_philosophy.html +23 -0
- nautobot/project-static/docs/release-notes/index.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.0.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.1.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.2.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.3.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.4.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.5.html +23 -0
- nautobot/project-static/docs/release-notes/version-1.6.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.0.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.1.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.2.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.3.html +23 -0
- nautobot/project-static/docs/release-notes/version-2.4.html +231 -0
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +303 -299
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +23 -0
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +23 -0
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/index.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +23 -0
- nautobot/project-static/docs/user-guide/administration/installation/services.html +23 -0
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +23 -0
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +23 -0
- nautobot/project-static/docs/user-guide/administration/security/index.html +23 -0
- nautobot/project-static/docs/user-guide/administration/security/notices.html +23 -0
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +284 -219
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +23 -0
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +305 -5
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +24 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +136 -3
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +41 -1
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +40 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +23 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +23 -0
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +23 -0
- nautobot/project-static/docs/user-guide/index.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +24 -1
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +23 -0
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +23 -0
- nautobot/users/tests/test_api.py +2 -2
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -252
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -75
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +252 -0
- nautobot/virtualization/templates/virtualization/virtualmachine_update.html +75 -0
- nautobot/virtualization/urls.py +3 -61
- nautobot/virtualization/views.py +48 -72
- {nautobot-2.4.14.dist-info → nautobot-2.4.15.dist-info}/METADATA +24 -24
- {nautobot-2.4.14.dist-info → nautobot-2.4.15.dist-info}/RECORD +433 -416
- {nautobot-2.4.14.dist-info → nautobot-2.4.15.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.14.dist-info → nautobot-2.4.15.dist-info}/NOTICE +0 -0
- {nautobot-2.4.14.dist-info → nautobot-2.4.15.dist-info}/WHEEL +0 -0
- {nautobot-2.4.14.dist-info → nautobot-2.4.15.dist-info}/entry_points.txt +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from django.contrib.contenttypes.models import ContentType
|
|
2
2
|
from django.db.models import Model, Q
|
|
3
|
+
from django.utils.encoding import force_str
|
|
4
|
+
from django.utils.text import capfirst
|
|
3
5
|
import django_filters
|
|
4
6
|
from django_filters.constants import EMPTY_VALUES
|
|
5
7
|
from django_filters.utils import verbose_lookup_expr
|
|
@@ -131,11 +133,21 @@ class CustomFieldModelFilterSetMixin(django_filters.FilterSet):
|
|
|
131
133
|
# Create new filters for each lookup expression in the map
|
|
132
134
|
for lookup_name, lookup_expr in lookup_map.items():
|
|
133
135
|
new_filter_name = f"{filter_name}__{lookup_name}"
|
|
136
|
+
|
|
137
|
+
# Based on logic in BaseFilterSet._generate_lookup_expression_filters
|
|
138
|
+
verbose_expression = (
|
|
139
|
+
["exclude", custom_field.label] if lookup_name.startswith("n") else [custom_field.label]
|
|
140
|
+
)
|
|
141
|
+
if isinstance(lookup_expr, str):
|
|
142
|
+
verbose_expression.append(verbose_lookup_expr(lookup_expr))
|
|
143
|
+
verbose_expression = [force_str(part) for part in verbose_expression if part]
|
|
144
|
+
label = capfirst(" ".join(verbose_expression))
|
|
145
|
+
|
|
134
146
|
new_filter = filter_type(
|
|
135
147
|
field_name=custom_field.key,
|
|
136
148
|
lookup_expr=lookup_expr,
|
|
137
149
|
custom_field=custom_field,
|
|
138
|
-
label=
|
|
150
|
+
label=label,
|
|
139
151
|
exclude=lookup_name.startswith("n"),
|
|
140
152
|
)
|
|
141
153
|
|
|
@@ -297,6 +309,7 @@ class RoleModelFilterSetMixin(django_filters.FilterSet):
|
|
|
297
309
|
field_name="role",
|
|
298
310
|
query_params={"content_types": [cls._meta.model._meta.label_lower]},
|
|
299
311
|
)
|
|
312
|
+
cls.declared_filters["role"] = filters["role"] # pylint: disable=no-member
|
|
300
313
|
|
|
301
314
|
return filters
|
|
302
315
|
|
|
@@ -326,5 +339,6 @@ class StatusModelFilterSetMixin(django_filters.FilterSet):
|
|
|
326
339
|
field_name="status",
|
|
327
340
|
query_params={"content_types": [cls._meta.model._meta.label_lower]},
|
|
328
341
|
)
|
|
342
|
+
cls.declared_filters["status"] = filters["status"] # pylint: disable=no-member
|
|
329
343
|
|
|
330
344
|
return filters
|
|
@@ -12,5 +12,6 @@ from .contacts import (
|
|
|
12
12
|
TeamFilterForm,
|
|
13
13
|
TeamForm,
|
|
14
14
|
)
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
from .mixins import * # noqa: F403 # undefined-local-with-import-star
|
|
17
|
+
from .forms import * # noqa: F403 # undefined-local-with-import-star
|
nautobot/extras/forms/forms.py
CHANGED
|
@@ -43,6 +43,7 @@ from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
|
|
|
43
43
|
from nautobot.dcim.models import Device, DeviceRedundancyGroup, DeviceType, Location, Platform
|
|
44
44
|
from nautobot.extras.choices import (
|
|
45
45
|
ButtonClassChoices,
|
|
46
|
+
CustomFieldFilterLogicChoices,
|
|
46
47
|
DynamicGroupTypeChoices,
|
|
47
48
|
JobExecutionType,
|
|
48
49
|
JobQueueTypeChoices,
|
|
@@ -134,6 +135,7 @@ __all__ = (
|
|
|
134
135
|
"ConfigContextSchemaForm",
|
|
135
136
|
"CustomFieldBulkCreateForm", # 2.0 TODO remove this deprecated class
|
|
136
137
|
"CustomFieldBulkDeleteForm",
|
|
138
|
+
"CustomFieldBulkEditForm",
|
|
137
139
|
"CustomFieldChoiceFormSet",
|
|
138
140
|
"CustomFieldFilterForm",
|
|
139
141
|
"CustomFieldForm",
|
|
@@ -465,6 +467,66 @@ class CustomFieldDescriptionField(CommentField):
|
|
|
465
467
|
return "Also used as the help text when editing models using this custom field.<br>" + super().default_helptext
|
|
466
468
|
|
|
467
469
|
|
|
470
|
+
class CustomFieldBulkEditForm(BootstrapMixin, NoteModelBulkEditFormMixin):
|
|
471
|
+
pk = forms.ModelMultipleChoiceField(queryset=CustomField.objects.all(), widget=forms.MultipleHiddenInput)
|
|
472
|
+
grouping = forms.CharField(
|
|
473
|
+
required=False,
|
|
474
|
+
max_length=CHARFIELD_MAX_LENGTH,
|
|
475
|
+
label="Grouping",
|
|
476
|
+
help_text="Human-readable grouping that this custom field belongs to.",
|
|
477
|
+
)
|
|
478
|
+
description = forms.CharField(
|
|
479
|
+
required=False,
|
|
480
|
+
max_length=CHARFIELD_MAX_LENGTH,
|
|
481
|
+
label="Description",
|
|
482
|
+
help_text="A helpful description for this field.",
|
|
483
|
+
)
|
|
484
|
+
required = forms.NullBooleanField(
|
|
485
|
+
required=False,
|
|
486
|
+
widget=BulkEditNullBooleanSelect,
|
|
487
|
+
label="Required",
|
|
488
|
+
help_text="If true, this field is required when creating new objects or editing an existing object.",
|
|
489
|
+
)
|
|
490
|
+
filter_logic = forms.ChoiceField(
|
|
491
|
+
required=False,
|
|
492
|
+
choices=add_blank_choice(CustomFieldFilterLogicChoices.CHOICES),
|
|
493
|
+
label="Filter logic",
|
|
494
|
+
help_text="Loose matches any instance of a given string; Exact matches the entire field.",
|
|
495
|
+
)
|
|
496
|
+
weight = forms.IntegerField(
|
|
497
|
+
required=False, label="Weight", help_text="Fields with higher weights appear lower in a form."
|
|
498
|
+
)
|
|
499
|
+
advanced_ui = forms.NullBooleanField(
|
|
500
|
+
required=False,
|
|
501
|
+
widget=BulkEditNullBooleanSelect,
|
|
502
|
+
label="Move to Advanced tab",
|
|
503
|
+
help_text="Hide this field from the object's primary information tab. It will appear in the 'Advanced' tab instead.",
|
|
504
|
+
)
|
|
505
|
+
add_content_types = MultipleContentTypeField(
|
|
506
|
+
limit_choices_to=FeatureQuery("custom_fields"), required=False, label="Add Content Types"
|
|
507
|
+
)
|
|
508
|
+
remove_content_types = MultipleContentTypeField(
|
|
509
|
+
limit_choices_to=FeatureQuery("custom_fields"), required=False, label="Remove Content Types"
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
class Meta:
|
|
513
|
+
model = CustomField
|
|
514
|
+
fields = (
|
|
515
|
+
"grouping",
|
|
516
|
+
"description",
|
|
517
|
+
"required",
|
|
518
|
+
"filter_logic",
|
|
519
|
+
"weight",
|
|
520
|
+
"advanced_ui",
|
|
521
|
+
"add_content_types",
|
|
522
|
+
"remove_content_types",
|
|
523
|
+
)
|
|
524
|
+
nullable_fields = [
|
|
525
|
+
"grouping",
|
|
526
|
+
"description",
|
|
527
|
+
]
|
|
528
|
+
|
|
529
|
+
|
|
468
530
|
class CustomFieldForm(BootstrapMixin, forms.ModelForm):
|
|
469
531
|
label = forms.CharField(
|
|
470
532
|
required=True, max_length=CHARFIELD_MAX_LENGTH, help_text="Name of the field as displayed to users."
|
nautobot/extras/managers.py
CHANGED
|
@@ -111,10 +111,13 @@ class JobResultManager(BaseManager.from_queryset(RestrictedQuerySet), TaskResult
|
|
|
111
111
|
except Job.DoesNotExist:
|
|
112
112
|
pass
|
|
113
113
|
|
|
114
|
+
if "date_started" in kwargs:
|
|
115
|
+
fields["date_started"] = kwargs["date_started"]
|
|
116
|
+
|
|
114
117
|
obj, created = self.using(using).get_or_create(id=task_id, defaults=fields)
|
|
115
118
|
|
|
116
119
|
if not created:
|
|
117
|
-
# Make sure `date_done` is allowed to stay null until the task
|
|
120
|
+
# Make sure `date_done` is allowed to stay null until the task reaches a ready state.
|
|
118
121
|
#
|
|
119
122
|
# Default behavior in `django-celery-results` has this field as a
|
|
120
123
|
# `DateField(auto_now=True)` which just automatically updates the `date_done` field on every
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 4.2.23 on 2025-08-11 16:18
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
("django_celery_results", "0012_taskresult_date_started"),
|
|
9
|
+
("extras", "0124_add_joblogentry_index"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name="jobresult",
|
|
15
|
+
name="date_started",
|
|
16
|
+
field=models.DateTimeField(blank=True, db_index=True, null=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -514,8 +514,7 @@ class CustomField(
|
|
|
514
514
|
blank=True,
|
|
515
515
|
null=True,
|
|
516
516
|
help_text=(
|
|
517
|
-
|
|
518
|
-
'"Foo").'
|
|
517
|
+
'Default value for the field (must be a JSON value). Encapsulate strings with double quotes (e.g. "Foo").'
|
|
519
518
|
),
|
|
520
519
|
)
|
|
521
520
|
weight = models.PositiveSmallIntegerField(
|
|
@@ -100,8 +100,7 @@ class GitRepository(PrimaryModel):
|
|
|
100
100
|
|
|
101
101
|
if self.present_in_database and self.slug != self.__initial_slug:
|
|
102
102
|
raise ValidationError(
|
|
103
|
-
f"Slug cannot be changed once set. Current slug is {self.__initial_slug}, "
|
|
104
|
-
f"requested slug is {self.slug}"
|
|
103
|
+
f"Slug cannot be changed once set. Current slug is {self.__initial_slug}, requested slug is {self.slug}"
|
|
105
104
|
)
|
|
106
105
|
|
|
107
106
|
if not self.present_in_database:
|
nautobot/extras/models/jobs.py
CHANGED
|
@@ -650,6 +650,7 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
650
650
|
help_text="Registered name of the Celery task for this job. Internal use only.",
|
|
651
651
|
)
|
|
652
652
|
date_created = models.DateTimeField(auto_now_add=True, db_index=True)
|
|
653
|
+
date_started = models.DateTimeField(null=True, blank=True, db_index=True)
|
|
653
654
|
date_done = models.DateTimeField(null=True, blank=True, db_index=True)
|
|
654
655
|
user = models.ForeignKey(
|
|
655
656
|
to=settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, related_name="+", blank=True, null=True
|
|
@@ -714,7 +715,7 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
714
715
|
natural_key_field_names = ["id"]
|
|
715
716
|
|
|
716
717
|
def __str__(self):
|
|
717
|
-
return f"{self.name}
|
|
718
|
+
return f"{self.name} created at {self.date_created} ({self.status})"
|
|
718
719
|
|
|
719
720
|
def as_dict(self):
|
|
720
721
|
"""This is required by the django-celery-results DB backend."""
|
|
@@ -736,7 +737,8 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
736
737
|
if not self.date_done:
|
|
737
738
|
return None
|
|
738
739
|
|
|
739
|
-
|
|
740
|
+
# Older records may not have a date_started value, so we use date_created as a fallback.
|
|
741
|
+
duration = self.date_done - (self.date_started or self.date_created)
|
|
740
742
|
minutes, seconds = divmod(duration.total_seconds(), 60)
|
|
741
743
|
|
|
742
744
|
return f"{int(minutes)} minutes, {seconds:.2f} seconds"
|
|
@@ -754,7 +756,8 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
754
756
|
# Only add metrics if we have a related job model. If we are moving to a terminal state we should always
|
|
755
757
|
# have a related job model, so this shouldn't be too tight of a restriction.
|
|
756
758
|
if self.job_model:
|
|
757
|
-
|
|
759
|
+
# Older records may not have a date_started value, so we use date_created as a fallback.
|
|
760
|
+
duration = self.date_done - (self.date_started or self.date_created)
|
|
758
761
|
JOB_RESULT_METRIC.labels(self.job_model.grouping, self.job_model.name, status).observe(
|
|
759
762
|
duration.total_seconds()
|
|
760
763
|
)
|
|
@@ -884,6 +887,7 @@ class JobResult(BaseModel, CustomFieldModel):
|
|
|
884
887
|
# synchronous tasks are run before the JobResult is saved, so any fields required by
|
|
885
888
|
# the job must be added before calling `apply()`
|
|
886
889
|
job_result.celery_kwargs = job_celery_kwargs
|
|
890
|
+
job_result.date_started = timezone.now()
|
|
887
891
|
job_result.save()
|
|
888
892
|
|
|
889
893
|
# setup synchronous task logging
|
nautobot/extras/plugins/views.py
CHANGED
|
@@ -16,6 +16,8 @@ import yaml
|
|
|
16
16
|
|
|
17
17
|
from nautobot.core.api.views import AuthenticatedAPIRootView, NautobotAPIVersionMixin
|
|
18
18
|
from nautobot.core.forms import TableConfigForm
|
|
19
|
+
from nautobot.core.ui.breadcrumbs import Breadcrumbs, ViewNameBreadcrumbItem
|
|
20
|
+
from nautobot.core.ui.titles import Titles
|
|
19
21
|
from nautobot.core.views.generic import GenericView
|
|
20
22
|
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
21
23
|
from nautobot.extras.plugins.tables import InstalledAppsTable
|
|
@@ -84,6 +86,10 @@ class InstalledAppsView(GenericView):
|
|
|
84
86
|
"""
|
|
85
87
|
|
|
86
88
|
table = InstalledAppsTable
|
|
89
|
+
breadcrumbs = Breadcrumbs(
|
|
90
|
+
items={"generic": [ViewNameBreadcrumbItem(view_name="apps:apps_list", label="Installed Apps")]}
|
|
91
|
+
)
|
|
92
|
+
view_titles = Titles(titles={"generic": "Installed Apps"})
|
|
87
93
|
|
|
88
94
|
def get(self, request):
|
|
89
95
|
marketplace_data = load_marketplace_data()
|
|
@@ -123,6 +129,9 @@ class InstalledAppsView(GenericView):
|
|
|
123
129
|
"filter_form": None,
|
|
124
130
|
"app_icons": app_icons,
|
|
125
131
|
"display": display,
|
|
132
|
+
"view_action": "generic",
|
|
133
|
+
"breadcrumbs": self.breadcrumbs,
|
|
134
|
+
"view_titles": self.view_titles,
|
|
126
135
|
},
|
|
127
136
|
)
|
|
128
137
|
|
|
@@ -228,6 +237,11 @@ class MarketplaceView(GenericView):
|
|
|
228
237
|
View for listing all available Apps.
|
|
229
238
|
"""
|
|
230
239
|
|
|
240
|
+
breadcrumbs = Breadcrumbs(
|
|
241
|
+
items={"generic": [ViewNameBreadcrumbItem(view_name="apps:apps_marketplace", label="Apps Marketplace")]}
|
|
242
|
+
)
|
|
243
|
+
view_titles = Titles(titles={"generic": "Apps Marketplace"})
|
|
244
|
+
|
|
231
245
|
def get(self, request):
|
|
232
246
|
marketplace_data = load_marketplace_data()
|
|
233
247
|
|
|
@@ -240,4 +254,13 @@ class MarketplaceView(GenericView):
|
|
|
240
254
|
marketplace_app["installed"] = True
|
|
241
255
|
break
|
|
242
256
|
|
|
243
|
-
return render(
|
|
257
|
+
return render(
|
|
258
|
+
request,
|
|
259
|
+
"extras/marketplace.html",
|
|
260
|
+
{
|
|
261
|
+
"apps": marketplace_data["apps"],
|
|
262
|
+
"view_action": "generic",
|
|
263
|
+
"breadcrumbs": self.breadcrumbs,
|
|
264
|
+
"view_titles": self.view_titles,
|
|
265
|
+
},
|
|
266
|
+
)
|
|
@@ -65,7 +65,7 @@ def register_secrets_provider(provider):
|
|
|
65
65
|
if provider.slug in registry["secrets_providers"]:
|
|
66
66
|
raise KeyError(
|
|
67
67
|
f'Cannot register {provider} as slug "{provider.slug}" is already registered '
|
|
68
|
-
f
|
|
68
|
+
f"by {registry['secrets_providers'][provider.slug]}"
|
|
69
69
|
)
|
|
70
70
|
registry["secrets_providers"][provider.slug] = provider
|
|
71
71
|
|
nautobot/extras/tables.py
CHANGED
|
@@ -890,6 +890,8 @@ class JobResultTable(BaseTable):
|
|
|
890
890
|
pk = ToggleColumn()
|
|
891
891
|
job_model = tables.Column(linkify=True)
|
|
892
892
|
date_created = tables.DateTimeColumn(linkify=True, format=settings.SHORT_DATETIME_FORMAT)
|
|
893
|
+
date_started = tables.DateTimeColumn(linkify=True, format=settings.SHORT_DATETIME_FORMAT)
|
|
894
|
+
date_done = tables.DateTimeColumn(linkify=True, format=settings.SHORT_DATETIME_FORMAT)
|
|
893
895
|
status = tables.TemplateColumn(
|
|
894
896
|
template_code="{% include 'extras/inc/job_label.html' with result=record %}",
|
|
895
897
|
)
|
|
@@ -961,6 +963,8 @@ class JobResultTable(BaseTable):
|
|
|
961
963
|
fields = (
|
|
962
964
|
"pk",
|
|
963
965
|
"date_created",
|
|
966
|
+
"date_started",
|
|
967
|
+
"date_done",
|
|
964
968
|
"name",
|
|
965
969
|
"job_model",
|
|
966
970
|
"scheduled_job",
|
|
@@ -1193,6 +1197,11 @@ class ObjectChangeTable(BaseTable):
|
|
|
1193
1197
|
"request_id",
|
|
1194
1198
|
)
|
|
1195
1199
|
|
|
1200
|
+
def __init__(self, *args, **kwargs):
|
|
1201
|
+
super().__init__(*args, **kwargs)
|
|
1202
|
+
# The `object_repr` column also uses the `changed_object` generic-foreign-key value
|
|
1203
|
+
self.add_conditional_prefetch("object_repr", "changed_object")
|
|
1204
|
+
|
|
1196
1205
|
|
|
1197
1206
|
#
|
|
1198
1207
|
# Relationship
|
|
@@ -1,129 +1,2 @@
|
|
|
1
|
-
{% extends '
|
|
2
|
-
{%
|
|
3
|
-
{% load helpers %}
|
|
4
|
-
|
|
5
|
-
{% block content_left_page %}
|
|
6
|
-
<div class="panel panel-default">
|
|
7
|
-
<div class="panel-heading">
|
|
8
|
-
<strong>Custom Field</strong>
|
|
9
|
-
</div>
|
|
10
|
-
<table class="table table-hover panel-body attr-table">
|
|
11
|
-
<tr>
|
|
12
|
-
<td>Label</td>
|
|
13
|
-
<td>{{ object.label }}</td>
|
|
14
|
-
</tr>
|
|
15
|
-
<tr>
|
|
16
|
-
<td>Key</td>
|
|
17
|
-
<td>{{ object.key }}</td>
|
|
18
|
-
</tr>
|
|
19
|
-
<tr>
|
|
20
|
-
<td>Type</td>
|
|
21
|
-
<td>{{ object.type | capfirst }}</td>
|
|
22
|
-
</tr>
|
|
23
|
-
<tr>
|
|
24
|
-
<td>Weight</td>
|
|
25
|
-
<td>{{ object.weight }}</td>
|
|
26
|
-
</tr>
|
|
27
|
-
<tr>
|
|
28
|
-
<td>Grouping</td>
|
|
29
|
-
<td>{{ object.grouping | placeholder }}</td>
|
|
30
|
-
</tr>
|
|
31
|
-
<tr>
|
|
32
|
-
<td>Description</td>
|
|
33
|
-
<td>{{ object.description | render_markdown | placeholder }}</td>
|
|
34
|
-
</tr>
|
|
35
|
-
<tr>
|
|
36
|
-
<td>Required</td>
|
|
37
|
-
<td>{{ object.required | render_boolean }}</td>
|
|
38
|
-
</tr>
|
|
39
|
-
<tr>
|
|
40
|
-
<td>Default</td>
|
|
41
|
-
<td>
|
|
42
|
-
{% if object.type == "markdown" %}
|
|
43
|
-
{{ object.default | render_markdown | placeholder }}
|
|
44
|
-
{% elif object.type == "json" and object.default is not None %}
|
|
45
|
-
<pre>{{ object.default | render_json }}</pre>
|
|
46
|
-
{% else %}
|
|
47
|
-
{{ object.default | placeholder }}
|
|
48
|
-
{% endif %}
|
|
49
|
-
</td>
|
|
50
|
-
</tr>
|
|
51
|
-
<tr>
|
|
52
|
-
<td>Filter Logic</td>
|
|
53
|
-
<td>{{ object.filter_logic | capfirst }}</td>
|
|
54
|
-
</tr>
|
|
55
|
-
<tr>
|
|
56
|
-
<td>Move to Advanced Tab</td>
|
|
57
|
-
<td>{{ object.advanced_ui | render_boolean }}</td>
|
|
58
|
-
</tr>
|
|
59
|
-
</table>
|
|
60
|
-
</div>
|
|
61
|
-
{% if object.custom_field_choices.exists %}
|
|
62
|
-
<div class="panel panel-default">
|
|
63
|
-
<div class="panel-heading">
|
|
64
|
-
<strong>Custom Field Choices</strong>
|
|
65
|
-
</div>
|
|
66
|
-
<table class="table table-hover panel-body attr-table">
|
|
67
|
-
<thead>
|
|
68
|
-
<tr>
|
|
69
|
-
<th>Value</th>
|
|
70
|
-
<th>Weight</th>
|
|
71
|
-
</tr>
|
|
72
|
-
</thead>
|
|
73
|
-
<tbody>
|
|
74
|
-
{% for choice in object.custom_field_choices.all %}
|
|
75
|
-
<tr>
|
|
76
|
-
<td>{{ choice.value }}</td>
|
|
77
|
-
<td>{{ choice.weight }}</td>
|
|
78
|
-
</tr>
|
|
79
|
-
{% endfor %}
|
|
80
|
-
</tbody>
|
|
81
|
-
</table>
|
|
82
|
-
</div>
|
|
83
|
-
{% endif %}
|
|
84
|
-
{% endblock content_left_page %}
|
|
85
|
-
|
|
86
|
-
{% block content_right_page %}
|
|
87
|
-
<div class="panel panel-default">
|
|
88
|
-
<div class="panel-heading">
|
|
89
|
-
<strong>Assignment</strong>
|
|
90
|
-
</div>
|
|
91
|
-
<table class="table table-hover panel-body attr-table">
|
|
92
|
-
<tr>
|
|
93
|
-
<td>Content Types</td>
|
|
94
|
-
<td>
|
|
95
|
-
<ul>
|
|
96
|
-
{% for ct in object.content_types.all %}
|
|
97
|
-
<li>{{ ct }}</li>
|
|
98
|
-
{% endfor %}
|
|
99
|
-
</ul>
|
|
100
|
-
</td>
|
|
101
|
-
</tr>
|
|
102
|
-
</table>
|
|
103
|
-
</div>
|
|
104
|
-
<div class="panel panel-default">
|
|
105
|
-
<div class="panel-heading">
|
|
106
|
-
<strong>Validation Rules</strong>
|
|
107
|
-
</div>
|
|
108
|
-
<table class="table table-hover panel-body attr-table">
|
|
109
|
-
<tr>
|
|
110
|
-
<td>Minimum Value/Length</td>
|
|
111
|
-
<td>{{ object.validation_minimum | placeholder }}</td>
|
|
112
|
-
</tr>
|
|
113
|
-
<tr>
|
|
114
|
-
<td>Maximum Value/Length</td>
|
|
115
|
-
<td>{{ object.validation_maximum | placeholder }}</td>
|
|
116
|
-
</tr>
|
|
117
|
-
<tr>
|
|
118
|
-
<td>Validation Regex</td>
|
|
119
|
-
<td>
|
|
120
|
-
{% if object.validation_regex %}
|
|
121
|
-
<code>{{ object.validation_regex | placeholder }}</code>
|
|
122
|
-
{% else %}
|
|
123
|
-
{{ object.validation_regex | placeholder }}
|
|
124
|
-
{% endif %}
|
|
125
|
-
</td>
|
|
126
|
-
</tr>
|
|
127
|
-
</table>
|
|
128
|
-
</div>
|
|
129
|
-
{% endblock content_right_page %}
|
|
1
|
+
{% extends 'extras/customfield_retrieve.html' %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -1,108 +1,2 @@
|
|
|
1
|
-
{% extends '
|
|
2
|
-
{%
|
|
3
|
-
{% load form_helpers %}
|
|
4
|
-
|
|
5
|
-
{% block form %}
|
|
6
|
-
<div class="panel panel-default">
|
|
7
|
-
<div class="panel-heading"><strong>Custom Field</strong></div>
|
|
8
|
-
<div class="panel-body">
|
|
9
|
-
{% render_field form.label %}
|
|
10
|
-
{% render_field form.grouping %}
|
|
11
|
-
{% render_field form.key %}
|
|
12
|
-
{% render_field form.type %}
|
|
13
|
-
{% render_field form.weight %}
|
|
14
|
-
{% render_field form.description %}
|
|
15
|
-
{% render_field form.required %}
|
|
16
|
-
{% render_field form.default %}
|
|
17
|
-
{% render_field form.filter_logic %}
|
|
18
|
-
{% render_field form.advanced_ui %}
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
<div class="panel panel-default">
|
|
22
|
-
<div class="panel-heading"><strong>Assignment</strong></div>
|
|
23
|
-
<div class="panel-body">
|
|
24
|
-
{% render_field form.content_types %}
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
<div class="panel panel-default">
|
|
28
|
-
<div class="panel-heading"><strong>Validation Rules</strong></div>
|
|
29
|
-
<div class="panel-body">
|
|
30
|
-
{% render_field form.validation_minimum %}
|
|
31
|
-
{% render_field form.validation_maximum %}
|
|
32
|
-
{% render_field form.validation_regex %}
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
<div class="panel panel-default">
|
|
36
|
-
<div class="panel-heading"><strong>Custom Field Choices</strong></div>
|
|
37
|
-
<div class="panel-body">
|
|
38
|
-
{% if choices.errors %}
|
|
39
|
-
<div class="text-danger">
|
|
40
|
-
Please correct the error(s) below:
|
|
41
|
-
|
|
42
|
-
{% for choice in choices.forms %}
|
|
43
|
-
{% if choice.errors %}
|
|
44
|
-
{% for error in choice.errors.values %}{{ error }}{% endfor %}
|
|
45
|
-
{% endif %}
|
|
46
|
-
{% endfor %}
|
|
47
|
-
</div>
|
|
48
|
-
{% endif %}
|
|
49
|
-
{{ choices.non_field_errors }}
|
|
50
|
-
<table class="table" id="custom-field-choices">
|
|
51
|
-
{{ choices.management_form }}
|
|
52
|
-
{% for choice in choices.forms %}
|
|
53
|
-
{% if forloop.first %}
|
|
54
|
-
<thead>
|
|
55
|
-
<tr>
|
|
56
|
-
{% for field in choice.visible_fields %}
|
|
57
|
-
<th>{{ field.label|capfirst }}</th>
|
|
58
|
-
{% endfor %}
|
|
59
|
-
</tr>
|
|
60
|
-
</thead>
|
|
61
|
-
{% endif %}
|
|
62
|
-
<tr class="formset_row-{{ choices.prefix }}">
|
|
63
|
-
{% for field in choice.visible_fields %}
|
|
64
|
-
<td>
|
|
65
|
-
{# Include the hidden fields in the form #}
|
|
66
|
-
{% if forloop.first %}
|
|
67
|
-
{% for hidden in choice.hidden_fields %}
|
|
68
|
-
{{ hidden }}
|
|
69
|
-
{% endfor %}
|
|
70
|
-
{% endif %}
|
|
71
|
-
{{ field }}
|
|
72
|
-
{% if field.errors %}
|
|
73
|
-
<ul>
|
|
74
|
-
{% for error in field.errors %}
|
|
75
|
-
{# Embed an HTML comment indicating the error for extraction by tests #}
|
|
76
|
-
<!-- FORM-ERROR {{ field.name }}: {{ error }} -->
|
|
77
|
-
<li class="text-danger">{{ error }}</li>
|
|
78
|
-
{% endfor %}
|
|
79
|
-
</ul>
|
|
80
|
-
{% endif %}
|
|
81
|
-
</td>
|
|
82
|
-
{% endfor %}
|
|
83
|
-
</tr>
|
|
84
|
-
{% endfor %}
|
|
85
|
-
</table>
|
|
86
|
-
</div>
|
|
87
|
-
</div>
|
|
88
|
-
{% include 'inc/extras_features_edit_form_fields.html' %}
|
|
89
|
-
|
|
90
|
-
{% endblock form %}
|
|
91
|
-
|
|
92
|
-
{% block javascript %}
|
|
93
|
-
{{ block.super }}
|
|
94
|
-
<script src="{% static 'jquery/jquery.formset.js' %}"></script>
|
|
95
|
-
<script type="text/javascript">
|
|
96
|
-
const slugify_prefer_underscores = true; // Custom fields work better in GraphQL (etc.) with underscore-based slugs
|
|
97
|
-
$('.formset_row-{{ choices.prefix }}').formset({
|
|
98
|
-
addText: '<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add another Custom Field Choice',
|
|
99
|
-
addCssClass: 'btn btn-primary add-row',
|
|
100
|
-
deleteText: '<span class="mdi mdi-trash-can-outline" aria-hidden="true"></span>',
|
|
101
|
-
deleteCssClass: 'btn btn-danger delete-row',
|
|
102
|
-
prefix: '{{ choices.prefix }}',
|
|
103
|
-
formCssClass: 'dynamic-formset-{{ choices.prefix }}',
|
|
104
|
-
keepFieldValues: 'input[type="number"]',
|
|
105
|
-
added: jsify_form
|
|
106
|
-
});
|
|
107
|
-
</script>
|
|
108
|
-
{% endblock javascript %}
|
|
1
|
+
{% extends 'extras/customfield_update.html' %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|