nautobot 2.0.0a2__py3-none-any.whl → 2.0.0b1__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.
- nautobot/__init__.py +1 -5
- nautobot/apps/api.py +6 -8
- nautobot/apps/forms.py +0 -2
- nautobot/apps/ui.py +0 -8
- nautobot/circuits/api/serializers.py +9 -119
- nautobot/circuits/api/urls.py +1 -1
- nautobot/circuits/api/views.py +0 -1
- nautobot/circuits/choices.py +0 -2
- nautobot/circuits/filters.py +7 -6
- nautobot/circuits/forms.py +3 -73
- nautobot/circuits/migrations/0001_initial_part_1.py +0 -1
- nautobot/circuits/migrations/0002_initial_part_2.py +0 -1
- nautobot/circuits/migrations/0003_auto_slug.py +0 -1
- nautobot/circuits/migrations/0004_increase_provider_account_length.py +0 -1
- nautobot/circuits/migrations/0005_providernetwork.py +0 -1
- nautobot/circuits/migrations/0006_cache_circuit_terminations.py +0 -1
- nautobot/circuits/migrations/0007_circuitterminations_primary_model.py +0 -1
- nautobot/circuits/migrations/0008_add_natural_indexing.py +0 -1
- nautobot/circuits/migrations/0009_circuittermination_location.py +0 -1
- nautobot/circuits/migrations/0010_rename_foreign_keys_and_related_names.py +0 -1
- nautobot/circuits/migrations/0011_remove_site_foreign_key_from_circuit_termination_class.py +0 -1
- nautobot/circuits/migrations/0012_created_datetime.py +0 -1
- nautobot/circuits/migrations/0013_alter_circuittermination__path.py +0 -1
- nautobot/circuits/migrations/0014_related_name_changes.py +1 -2
- nautobot/circuits/migrations/0015_remove_circuittype_provider_slug.py +20 -0
- nautobot/circuits/migrations/0016_tagsfield.py +34 -0
- nautobot/circuits/migrations/0017_fixup_null_statuses.py +22 -0
- nautobot/circuits/migrations/0018_status_nonnullable.py +22 -0
- nautobot/circuits/models.py +3 -93
- nautobot/circuits/navigation.py +14 -69
- nautobot/circuits/signals.py +0 -2
- nautobot/circuits/tables.py +42 -5
- nautobot/circuits/templates/circuits/circuit_retrieve.html +1 -1
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -1
- nautobot/circuits/templates/circuits/circuittype_retrieve.html +1 -1
- nautobot/circuits/templates/circuits/provider_create.html +0 -1
- nautobot/circuits/templates/circuits/provider_retrieve.html +1 -1
- nautobot/circuits/tests/integration/test_relationships.py +13 -16
- nautobot/circuits/tests/test_api.py +13 -43
- nautobot/circuits/tests/test_filters.py +20 -15
- nautobot/circuits/tests/test_models.py +7 -3
- nautobot/circuits/tests/test_views.py +57 -67
- nautobot/circuits/views.py +18 -9
- nautobot/core/api/__init__.py +8 -2
- nautobot/core/api/authentication.py +0 -3
- nautobot/core/api/fields.py +15 -6
- nautobot/core/api/filter_backends.py +3 -2
- nautobot/core/api/metadata.py +237 -30
- nautobot/core/api/mixins.py +94 -0
- nautobot/core/api/pagination.py +3 -3
- nautobot/core/api/parsers.py +154 -0
- nautobot/core/api/renderers.py +153 -2
- nautobot/core/api/schema.py +47 -3
- nautobot/core/api/serializers.py +377 -37
- nautobot/core/api/urls.py +11 -3
- nautobot/core/api/utils.py +174 -2
- nautobot/core/api/versioning.py +32 -10
- nautobot/core/api/views.py +266 -75
- nautobot/core/apps/__init__.py +138 -221
- nautobot/core/celery/__init__.py +112 -41
- nautobot/core/celery/backends.py +19 -13
- nautobot/core/celery/control.py +46 -0
- nautobot/core/celery/encoders.py +53 -0
- nautobot/core/celery/log.py +38 -0
- nautobot/core/celery/schedulers.py +23 -4
- nautobot/core/celery/task.py +1 -16
- nautobot/core/checks.py +0 -27
- nautobot/core/choices.py +21 -113
- nautobot/core/{cli.py → cli/__init__.py} +1 -2
- nautobot/core/cli/__main__.py +3 -0
- nautobot/core/constants.py +25 -43
- nautobot/core/context_processors.py +12 -0
- nautobot/core/filters.py +2 -2
- nautobot/core/forms/__init__.py +0 -4
- nautobot/core/forms/fields.py +39 -68
- nautobot/core/forms/forms.py +27 -27
- nautobot/core/forms/utils.py +7 -59
- nautobot/core/forms/widgets.py +0 -1
- nautobot/core/graphql/__init__.py +2 -2
- nautobot/core/graphql/schema.py +4 -27
- nautobot/core/jobs/__init__.py +75 -0
- nautobot/core/management/commands/build_ui.py +255 -0
- nautobot/core/management/commands/celery.py +0 -1
- nautobot/core/management/commands/generate_test_data.py +18 -13
- nautobot/core/management/commands/post_upgrade.py +24 -24
- nautobot/core/management/commands/validate_models.py +0 -1
- nautobot/core/middleware.py +0 -1
- nautobot/core/models/__init__.py +26 -1
- nautobot/core/models/fields.py +24 -5
- nautobot/core/models/generics.py +2 -46
- nautobot/core/models/managers.py +5 -0
- nautobot/core/models/name_color_content_types.py +1 -19
- nautobot/core/models/tree_queries.py +14 -4
- nautobot/core/models/utils.py +9 -10
- nautobot/core/models/validators.py +17 -8
- nautobot/core/releases.py +8 -10
- nautobot/core/settings.py +81 -53
- nautobot/core/tables.py +5 -5
- nautobot/core/tasks.py +4 -7
- nautobot/core/templates/base.html +1 -49
- nautobot/core/templates/base_django.html +49 -0
- nautobot/core/templates/base_react.html +55 -0
- nautobot/core/templates/buttons/export.html +6 -4
- nautobot/core/templates/generic/object_bulk_create.html +10 -21
- nautobot/core/templates/generic/object_list.html +4 -1
- nautobot/core/templates/generic/object_retrieve_plugin_full_width.html +3 -0
- nautobot/core/templates/inc/footer.html +1 -0
- nautobot/core/templates/inc/javascript.html +0 -14
- nautobot/core/templates/inc/nav_menu.html +28 -33
- nautobot/core/templates/inc/object_details_advanced_panel.html +13 -0
- nautobot/core/templates/inc/relationships_table_rows.html +2 -2
- nautobot/core/templates/nautobot_config.py.j2 +8 -25
- nautobot/core/templates/plugin_template/__init__.py-tpl +1 -2
- nautobot/core/templates/rest_framework/api.html +8 -0
- nautobot/core/templatetags/buttons.py +32 -29
- nautobot/core/templatetags/helpers.py +1 -1
- nautobot/core/testing/__init__.py +47 -44
- nautobot/core/testing/api.py +365 -47
- nautobot/core/testing/filters.py +12 -7
- nautobot/core/testing/integration.py +1 -1
- nautobot/core/testing/migrations.py +2 -0
- nautobot/core/testing/mixins.py +22 -12
- nautobot/core/testing/schema.py +2 -1
- nautobot/core/testing/views.py +28 -51
- nautobot/core/tests/integration/test_filters.py +17 -8
- nautobot/core/tests/integration/test_navbar.py +11 -34
- nautobot/core/tests/integration/test_plugin_navbar.py +9 -103
- nautobot/core/tests/nautobot_config.py +2 -3
- nautobot/core/tests/runner.py +0 -1
- nautobot/core/tests/test_api.py +290 -24
- nautobot/core/tests/test_authentication.py +57 -14
- nautobot/core/tests/test_checks.py +0 -7
- nautobot/core/tests/test_choices.py +0 -1
- nautobot/core/tests/test_filters.py +117 -110
- nautobot/core/tests/test_forms.py +47 -110
- nautobot/core/tests/test_graphql.py +158 -135
- nautobot/core/tests/test_logging.py +4 -1
- nautobot/core/tests/test_managers.py +3 -5
- nautobot/core/tests/test_models.py +2 -0
- nautobot/core/tests/test_ordering.py +0 -2
- nautobot/core/tests/test_paginator.py +3 -1
- nautobot/core/tests/test_releases.py +12 -12
- nautobot/core/tests/test_templatetags_helpers.py +7 -4
- nautobot/core/tests/test_utils.py +112 -78
- nautobot/core/tests/test_views.py +12 -17
- nautobot/core/tests/test_views_utils.py +6 -9
- nautobot/core/utils/data.py +17 -0
- nautobot/core/utils/deprecation.py +13 -20
- nautobot/core/utils/filtering.py +53 -9
- nautobot/core/utils/git.py +12 -4
- nautobot/core/utils/lookup.py +3 -1
- nautobot/core/utils/requests.py +23 -116
- nautobot/core/views/__init__.py +1 -2
- nautobot/core/views/generic.py +131 -119
- nautobot/core/views/mixins.py +53 -62
- nautobot/core/views/paginator.py +0 -1
- nautobot/core/views/renderers.py +14 -12
- nautobot/core/views/utils.py +87 -4
- nautobot/dcim/api/serializers.py +160 -672
- nautobot/dcim/api/urls.py +1 -1
- nautobot/dcim/api/views.py +7 -46
- nautobot/dcim/choices.py +2 -25
- nautobot/dcim/elevations.py +0 -1
- nautobot/dcim/factory.py +15 -4
- nautobot/dcim/filters/__init__.py +42 -13
- nautobot/dcim/form_mixins.py +1 -27
- nautobot/dcim/forms.py +58 -797
- nautobot/dcim/management/commands/trace_paths.py +0 -1
- nautobot/dcim/migrations/0001_initial_part_1.py +0 -1
- nautobot/dcim/migrations/0002_initial_part_2.py +0 -1
- nautobot/dcim/migrations/0003_initial_part_3.py +0 -1
- nautobot/dcim/migrations/0004_initial_part_4.py +0 -1
- nautobot/dcim/migrations/0005_device_local_context_schema.py +0 -1
- nautobot/dcim/migrations/0006_auto_slug.py +0 -1
- nautobot/dcim/migrations/0007_device_secrets_group.py +0 -1
- nautobot/dcim/migrations/0008_increase_all_serial_lengths.py +0 -1
- nautobot/dcim/migrations/0009_add_natural_indexing.py +0 -1
- nautobot/dcim/migrations/0010_interface_status.py +0 -1
- nautobot/dcim/migrations/0011_interface_status_data_migration.py +0 -1
- nautobot/dcim/migrations/0012_interface_parent_bridge.py +0 -1
- nautobot/dcim/migrations/0013_location_location_type.py +0 -1
- nautobot/dcim/migrations/0014_location_status_data_migration.py +0 -1
- nautobot/dcim/migrations/0015_device_components__changeloggedmodel.py +0 -1
- nautobot/dcim/migrations/0016_device_components__timestamp_data_migration.py +0 -1
- nautobot/dcim/migrations/0017_locationtype_nestable.py +0 -1
- nautobot/dcim/migrations/0018_device_redundancy_group.py +0 -1
- nautobot/dcim/migrations/0019_device_redundancy_group_data_migration.py +0 -1
- nautobot/dcim/migrations/0020_move_site_fields_to_location_model.py +0 -1
- nautobot/dcim/migrations/0021_mptt_to_tree_queries.py +0 -1
- nautobot/dcim/migrations/0022_interface_mac_address_data_migration.py +0 -1
- nautobot/dcim/migrations/0023_alter_interface_mac_address.py +0 -1
- nautobot/dcim/migrations/0024_alter_device_and_rack_role_add_new_role.py +2 -2
- nautobot/dcim/migrations/0025_device_and_rack_roles_data_migrations.py +19 -14
- nautobot/dcim/migrations/0026_rename_device_and_rack_role.py +0 -1
- nautobot/dcim/migrations/0027_remove_device_role_and_rack_role.py +1 -2
- nautobot/dcim/migrations/0028_rename_foreignkey_fields.py +1 -2
- nautobot/dcim/migrations/0029_add_tree_managers_and_foreign_keys_pre_data_migration.py +0 -1
- nautobot/dcim/migrations/0030_migrate_region_and_site_data_to_locations.py +2 -2
- nautobot/dcim/migrations/0031_rename_path_end_point_related_name.py +0 -1
- nautobot/dcim/migrations/0032_remove_site_foreign_key_from_dcim_models.py +0 -1
- nautobot/dcim/migrations/0033_created_datetime.py +0 -1
- nautobot/dcim/migrations/0034_fixup_fks_and_related_names.py +0 -1
- nautobot/dcim/migrations/0035_related_name_changes.py +1 -2
- nautobot/dcim/migrations/0036_remove_region_and_site.py +1 -2
- nautobot/dcim/migrations/0037_interface_ip_addresses_m2m.py +0 -1
- nautobot/dcim/migrations/0038_alter_location_managers.py +0 -1
- nautobot/dcim/migrations/0039_remove_slug.py +24 -0
- nautobot/dcim/migrations/0040_tagsfield.py +109 -0
- nautobot/dcim/migrations/0041_ipam__namespaces.py +25 -0
- nautobot/dcim/migrations/0042_fixup_null_statuses.py +51 -0
- nautobot/dcim/migrations/0043_status_nonnullable.py +72 -0
- nautobot/dcim/models/cables.py +4 -35
- nautobot/dcim/models/device_component_templates.py +7 -2
- nautobot/dcim/models/device_components.py +26 -203
- nautobot/dcim/models/devices.py +30 -152
- nautobot/dcim/models/locations.py +3 -64
- nautobot/dcim/models/power.py +3 -51
- nautobot/dcim/models/racks.py +7 -86
- nautobot/dcim/navigation.py +141 -467
- nautobot/dcim/signals.py +0 -2
- nautobot/dcim/tables/devices.py +8 -5
- nautobot/dcim/tables/devicetypes.py +1 -1
- nautobot/dcim/tables/locations.py +2 -2
- nautobot/dcim/tables/power.py +2 -2
- nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/device.html +15 -4
- nautobot/dcim/templates/dcim/device_edit.html +6 -0
- nautobot/dcim/templates/dcim/deviceredundancygroup_create.html +0 -1
- nautobot/dcim/templates/dcim/devicetype.html +2 -2
- nautobot/dcim/templates/dcim/interface.html +4 -0
- nautobot/dcim/templates/dcim/interface_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/location.html +16 -1
- nautobot/dcim/templates/dcim/locationtype.html +15 -0
- nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/rackgroup.html +0 -12
- nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
- nautobot/dcim/tests/test_api.py +202 -130
- nautobot/dcim/tests/test_cablepaths.py +47 -42
- nautobot/dcim/tests/test_filters.py +156 -134
- nautobot/dcim/tests/test_forms.py +12 -213
- nautobot/dcim/tests/test_graphql.py +8 -3
- nautobot/dcim/tests/test_migrations.py +6 -11
- nautobot/dcim/tests/test_models.py +208 -158
- nautobot/dcim/tests/test_natural_ordering.py +12 -14
- nautobot/dcim/tests/test_signals.py +7 -4
- nautobot/dcim/tests/test_views.py +270 -264
- nautobot/dcim/urls.py +21 -26
- nautobot/dcim/views.py +14 -156
- nautobot/docs/additional-features/caching.md +6 -87
- nautobot/docs/additional-features/job-scheduling-and-approvals.md +3 -0
- nautobot/docs/additional-features/jobs.md +179 -197
- nautobot/docs/administration/nautobot-server.md +9 -24
- nautobot/docs/administration/nautobot-shell.md +6 -6
- nautobot/docs/administration/replicating-nautobot.md +0 -10
- nautobot/docs/configuration/index.md +9 -9
- nautobot/docs/configuration/optional-settings.md +32 -61
- nautobot/docs/configuration/required-settings.md +11 -52
- nautobot/docs/development/application-registry.md +2 -13
- nautobot/docs/development/best-practices.md +2 -1
- nautobot/docs/development/docker-compose-advanced-use-cases.md +1 -1
- nautobot/docs/development/extending-models.md +15 -17
- nautobot/docs/development/generic-views.md +0 -2
- nautobot/docs/development/getting-started.md +56 -6
- nautobot/docs/development/navigation-menu.md +22 -93
- nautobot/docs/development/react-ui.md +105 -0
- nautobot/docs/development/release-checklist.md +3 -3
- nautobot/docs/development/role-internals.md +1 -3
- nautobot/docs/development/style-guide.md +6 -4
- nautobot/docs/development/templates.md +2 -1
- nautobot/docs/docker/index.md +16 -14
- nautobot/docs/index.md +7 -3
- nautobot/docs/installation/index.md +4 -1
- nautobot/docs/installation/migrating-from-netbox.md +12 -43
- nautobot/docs/installation/migrating-from-postgresql.md +1 -1
- nautobot/docs/installation/nautobot.md +1 -1
- nautobot/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
- nautobot/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
- nautobot/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
- nautobot/docs/installation/tables/v2-code-location-changes.yaml +241 -0
- nautobot/docs/installation/tables/v2-code-removals.yaml +67 -0
- nautobot/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
- nautobot/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
- nautobot/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
- nautobot/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
- nautobot/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
- nautobot/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
- nautobot/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
- nautobot/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
- nautobot/docs/installation/upgrading-from-nautobot-v1.md +190 -636
- nautobot/docs/installation/upgrading.md +5 -2
- nautobot/docs/models/dcim/device.md +3 -0
- nautobot/docs/models/dcim/deviceredundancygroup.md +3 -3
- nautobot/docs/models/extras/computedfield.md +4 -4
- nautobot/docs/models/extras/dynamicgroup.md +9 -9
- nautobot/docs/models/extras/gitrepository.md +3 -0
- nautobot/docs/models/extras/job.md +1 -0
- nautobot/docs/models/extras/jobbutton.md +18 -13
- nautobot/docs/models/extras/jobhook.md +7 -4
- nautobot/docs/models/extras/jobresult.md +6 -2
- nautobot/docs/models/extras/relationship.md +2 -2
- nautobot/docs/models/extras/status.md +6 -19
- nautobot/docs/models/ipam/ipaddress.md +3 -0
- nautobot/docs/models/ipam/vrf.md +0 -3
- nautobot/docs/models/virtualization/virtualmachine.md +3 -0
- nautobot/docs/plugins/development.md +92 -24
- nautobot/docs/release-notes/version-1.5.md +96 -0
- nautobot/docs/release-notes/version-2.0.md +216 -0
- nautobot/docs/requirements.txt +5 -4
- nautobot/docs/rest-api/overview.md +384 -215
- nautobot/docs/rest-api/ui-related-endpoints.md +9 -0
- nautobot/extras/admin.py +3 -5
- nautobot/extras/api/customfields.py +15 -39
- nautobot/extras/api/fields.py +0 -11
- nautobot/extras/api/mixins.py +45 -0
- nautobot/extras/api/relationships.py +63 -159
- nautobot/extras/api/serializers.py +165 -706
- nautobot/extras/api/urls.py +1 -1
- nautobot/extras/api/views.py +295 -282
- nautobot/extras/apps.py +4 -7
- nautobot/extras/choices.py +11 -22
- nautobot/extras/constants.py +9 -3
- nautobot/extras/datasources/__init__.py +2 -0
- nautobot/extras/datasources/git.py +135 -186
- nautobot/extras/datasources/registry.py +25 -35
- nautobot/extras/factory.py +1 -3
- nautobot/extras/filters/__init__.py +49 -47
- nautobot/extras/filters/mixins.py +10 -8
- nautobot/extras/forms/forms.py +72 -148
- nautobot/extras/forms/mixins.py +34 -57
- nautobot/extras/health_checks.py +0 -33
- nautobot/extras/jobs.py +387 -566
- nautobot/extras/management/__init__.py +55 -48
- nautobot/extras/management/commands/renaturalize.py +0 -1
- nautobot/extras/management/commands/runjob.py +24 -62
- nautobot/extras/management/commands/webhook_receiver.py +0 -1
- nautobot/extras/managers.py +30 -7
- nautobot/extras/migrations/0001_initial_part_1.py +0 -1
- nautobot/extras/migrations/0002_initial_part_2.py +0 -1
- nautobot/extras/migrations/0003_initial_part_3.py +0 -1
- nautobot/extras/migrations/0004_populate_default_status_records.py +0 -1
- nautobot/extras/migrations/0005_configcontext_device_types.py +0 -1
- nautobot/extras/migrations/0006_graphqlquery.py +0 -1
- nautobot/extras/migrations/0007_configcontextschema.py +0 -1
- nautobot/extras/migrations/0008_jobresult__custom_field_data.py +0 -1
- nautobot/extras/migrations/0009_computedfield.py +0 -1
- nautobot/extras/migrations/0010_change_cf_validation_max_min_field_to_bigint.py +0 -1
- nautobot/extras/migrations/0011_fileattachment_fileproxy.py +0 -1
- nautobot/extras/migrations/0012_healthchecktestmodel.py +0 -1
- nautobot/extras/migrations/0013_default_fallback_value_computedfield.py +0 -1
- nautobot/extras/migrations/0014_auto_slug.py +0 -1
- nautobot/extras/migrations/0015_scheduled_job.py +0 -1
- nautobot/extras/migrations/0016_secret.py +0 -1
- nautobot/extras/migrations/0017_joblogentry.py +0 -1
- nautobot/extras/migrations/0018_joblog_data_migration.py +0 -2
- nautobot/extras/migrations/0019_joblogentry__meta_options__related_name.py +0 -1
- nautobot/extras/migrations/0020_customfield_changelog.py +0 -1
- nautobot/extras/migrations/0021_customfield_changelog_data.py +0 -1
- nautobot/extras/migrations/0022_objectchange_object_datav2.py +0 -1
- nautobot/extras/migrations/0023_job_model.py +0 -1
- nautobot/extras/migrations/0024_job_data_migration.py +0 -1
- nautobot/extras/migrations/0025_add_advanced_ui_boolean_to_customfield_conputedfield_and_relationship.py +0 -1
- nautobot/extras/migrations/0026_job_add_gitrepository_fk.py +0 -1
- nautobot/extras/migrations/0027_job_gitrepository_data_migration.py +0 -1
- nautobot/extras/migrations/0028_job_reduce_source.py +0 -1
- nautobot/extras/migrations/0029_dynamicgroup.py +0 -1
- nautobot/extras/migrations/0030_webhook_alter_unique_together.py +0 -1
- nautobot/extras/migrations/0031_tag_content_types.py +0 -1
- nautobot/extras/migrations/0032_tag_content_types_data_migration.py +0 -1
- nautobot/extras/migrations/0033_add__optimized_indexing.py +0 -1
- nautobot/extras/migrations/0034_alter_fileattachment_mimetype.py +0 -1
- nautobot/extras/migrations/0035_scheduledjob_crontab.py +0 -1
- nautobot/extras/migrations/0036_job_add_has_sensitive_variables.py +0 -1
- nautobot/extras/migrations/0037_configcontextschema__remove_name_unique__create_constraint_unique_name_owner.py +0 -1
- nautobot/extras/migrations/0038_configcontext_locations.py +0 -1
- nautobot/extras/migrations/0039_objectchange__add_change_context.py +0 -1
- nautobot/extras/migrations/0040_dynamicgroup__dynamicgroupmembership.py +0 -1
- nautobot/extras/migrations/0041_jobresult_job_kwargs.py +0 -1
- nautobot/extras/migrations/0042_job__add_is_job_hook_receiver.py +0 -1
- nautobot/extras/migrations/0043_note.py +0 -1
- nautobot/extras/migrations/0044_add_job_hook.py +0 -1
- nautobot/extras/migrations/0045_add_custom_field_slug.py +0 -1
- nautobot/extras/migrations/0046_populate_custom_field_slug_label.py +0 -1
- nautobot/extras/migrations/0047_enforce_custom_field_slug.py +0 -1
- nautobot/extras/migrations/0048_alter_objectchange_change_context_detail.py +0 -1
- nautobot/extras/migrations/0049_alter_tag_slug.py +0 -1
- nautobot/extras/migrations/0050_customfield_grouping.py +0 -1
- nautobot/extras/migrations/0051_add_job_task_queues.py +0 -1
- nautobot/extras/migrations/0052_configcontext_device_redundancy_groups.py +0 -1
- nautobot/extras/migrations/0053_relationship_required_on.py +0 -1
- nautobot/extras/migrations/0054_scheduledjob_kwargs_request_user_change.py +0 -1
- nautobot/extras/migrations/0055_configcontext_dynamic_groups.py +0 -1
- nautobot/extras/migrations/0056_objectchange_add_reverse_time_idx.py +0 -1
- nautobot/extras/migrations/0057_jobbutton.py +0 -1
- nautobot/extras/migrations/0058_jobresult_add_time_status_idxs.py +38 -0
- nautobot/extras/migrations/{0058_joblogentry_scheduledjob_webhook_data_migration.py → 0059_joblogentry_scheduledjob_webhook_data_migration.py} +1 -2
- nautobot/extras/migrations/{0059_alter_joblogentry_scheduledjob_webhook_fields.py → 0060_alter_joblogentry_scheduledjob_webhook_fields.py} +1 -2
- nautobot/extras/migrations/{0060_role_and_alter_status.py → 0061_role_and_alter_status.py} +1 -8
- nautobot/extras/migrations/{0061_collect_roles_from_related_apps_roles.py → 0062_collect_roles_from_related_apps_roles.py} +33 -33
- nautobot/extras/migrations/{0062_alter_role_options.py → 0063_alter_role_options.py} +1 -2
- nautobot/extras/migrations/{0063_alter_configcontext_and_add_new_role.py → 0064_alter_configcontext_and_add_new_role.py} +1 -2
- nautobot/extras/migrations/0065_configcontext_data_migrations.py +44 -0
- nautobot/extras/migrations/{0065_rename_configcontext_role.py → 0066_rename_configcontext_role.py} +1 -2
- nautobot/extras/migrations/{0066_jobresult__add_celery_fields.py → 0067_jobresult__add_celery_fields.py} +36 -3
- nautobot/extras/migrations/{0067_created_datetime.py → 0068_created_datetime.py} +1 -2
- nautobot/extras/migrations/{0068_remove_site_and_region_attributes_from_config_context.py → 0069_remove_site_and_region_attributes_from_config_context.py} +1 -2
- nautobot/extras/migrations/{0069_replace_related_names.py → 0070_replace_related_names.py} +1 -1
- nautobot/extras/migrations/{0070_rename_model_fields.py → 0071_rename_model_fields.py} +1 -2
- nautobot/extras/migrations/0072_job__unique_name_data_migration.py +86 -0
- nautobot/extras/migrations/{0072_job__unique_name.py → 0073_job__unique_name.py} +13 -10
- nautobot/extras/migrations/{0073_remove_gitrepository_fields.py → 0074_remove_gitrepository_fields.py} +1 -2
- nautobot/extras/migrations/{0074_rename_slug_to_key_for_custom_field.py → 0075_rename_slug_to_key_for_custom_field.py} +1 -1
- nautobot/extras/migrations/{0075_migrate_custom_field_data.py → 0076_migrate_custom_field_data.py} +1 -1
- nautobot/extras/migrations/{0076_remove_name_field_and_make_label_field_non_nullable.py → 0077_remove_name_field_and_make_label_field_non_nullable.py} +1 -1
- nautobot/extras/migrations/0078_remove_slug.py +45 -0
- nautobot/extras/migrations/0079_tagsfield.py +28 -0
- nautobot/extras/migrations/0080_rename_relationship_slug_to_key.py +17 -0
- nautobot/extras/migrations/0081_rename_relationship_name_to_label.py +29 -0
- nautobot/extras/migrations/0082_ensure_relationship_keys_are_unique.py +43 -0
- nautobot/extras/migrations/0083_rename_computed_field_slug_to_key.py +21 -0
- nautobot/extras/migrations/0084_taggeditem_cleanup.py +43 -0
- nautobot/extras/migrations/0085_taggeditem_uniqueness.py +22 -0
- nautobot/extras/migrations/0086_job__celery_task_fields__dryrun_support.py +81 -0
- nautobot/extras/migrations/0087_job__commit_default_data_migration.py +26 -0
- nautobot/extras/migrations/0088_joblogentry__log_level_default.py +17 -0
- nautobot/extras/migrations/0089_joblogentry__log_level_data_migration.py +34 -0
- nautobot/extras/migrations/0090_scheduledjob__data_migration.py +57 -0
- nautobot/extras/models/__init__.py +2 -3
- nautobot/extras/models/change_logging.py +0 -36
- nautobot/extras/models/customfields.py +39 -33
- nautobot/extras/models/datasources.py +48 -50
- nautobot/extras/models/groups.py +5 -12
- nautobot/extras/models/jobs.py +190 -323
- nautobot/extras/models/mixins.py +0 -71
- nautobot/extras/models/models.py +1 -22
- nautobot/extras/models/relationships.py +20 -21
- nautobot/extras/models/roles.py +0 -23
- nautobot/extras/models/secrets.py +2 -31
- nautobot/extras/models/statuses.py +6 -5
- nautobot/extras/models/tags.py +2 -17
- nautobot/extras/navigation.py +89 -307
- nautobot/extras/plugins/__init__.py +3 -121
- nautobot/extras/plugins/utils.py +0 -3
- nautobot/extras/plugins/validators.py +5 -4
- nautobot/extras/plugins/views.py +16 -4
- nautobot/extras/querysets.py +1 -7
- nautobot/extras/registry.py +3 -0
- nautobot/extras/signals.py +26 -60
- nautobot/extras/tables.py +42 -49
- nautobot/extras/tasks.py +0 -12
- nautobot/extras/templates/extras/configcontext.html +1 -1
- nautobot/extras/templates/extras/configcontextschema.html +16 -1
- nautobot/extras/templates/extras/customfield.html +0 -13
- nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -1
- nautobot/extras/templates/extras/gitrepository.html +3 -3
- nautobot/extras/templates/extras/inc/jobresult.html +10 -0
- nautobot/extras/templates/extras/inc/panel_jobhistory.html +1 -1
- nautobot/extras/templates/extras/job.html +35 -25
- nautobot/extras/templates/extras/job_approval_request.html +15 -30
- nautobot/extras/templates/extras/job_detail.html +13 -31
- nautobot/extras/templates/extras/job_edit.html +14 -17
- nautobot/extras/templates/extras/jobresult.html +24 -6
- nautobot/extras/templates/extras/objectchange_list.html +1 -1
- nautobot/extras/templates/extras/scheduledjob.html +2 -2
- nautobot/extras/templates/extras/secret.html +28 -0
- nautobot/extras/templates/extras/secret_edit.html +0 -1
- nautobot/extras/templates/extras/secretsgroup_edit.html +0 -1
- nautobot/extras/templatetags/custom_links.py +0 -2
- nautobot/extras/templatetags/job_buttons.py +1 -0
- nautobot/extras/templatetags/plugins.py +0 -1
- nautobot/extras/{tests/example_jobs → test_jobs}/api_test_job.py +13 -6
- nautobot/extras/test_jobs/atomic_transaction.py +53 -0
- nautobot/extras/test_jobs/dry_run.py +29 -0
- nautobot/extras/{tests/example_jobs/test_duplicate_name.py → test_jobs/duplicate_name.py} +4 -0
- nautobot/extras/test_jobs/duplicate_name2.py +9 -0
- nautobot/extras/test_jobs/fail.py +23 -0
- nautobot/extras/{tests/example_jobs/test_field_default.py → test_jobs/field_default.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_field_order.py → test_jobs/field_order.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_file_upload_fail.py → test_jobs/file_upload_fail.py} +11 -6
- nautobot/extras/test_jobs/file_upload_pass.py +25 -0
- nautobot/extras/test_jobs/has_sensitive_variables.py +25 -0
- nautobot/extras/test_jobs/ipaddress_vars.py +66 -0
- nautobot/extras/test_jobs/job_button_receiver.py +28 -0
- nautobot/extras/test_jobs/job_hook_receiver.py +29 -0
- nautobot/extras/test_jobs/job_variables.py +88 -0
- nautobot/extras/test_jobs/location_with_custom_field.py +45 -0
- nautobot/extras/test_jobs/log_redaction.py +20 -0
- nautobot/extras/test_jobs/log_skip_db_logging.py +17 -0
- nautobot/extras/test_jobs/modify_db.py +25 -0
- nautobot/extras/{tests/example_jobs/test_no_field_order.py → test_jobs/no_field_order.py} +4 -0
- nautobot/extras/test_jobs/object_var_optional.py +21 -0
- nautobot/extras/test_jobs/object_var_required.py +21 -0
- nautobot/extras/test_jobs/object_vars.py +26 -0
- nautobot/extras/test_jobs/pass.py +25 -0
- nautobot/extras/test_jobs/profiling.py +32 -0
- nautobot/extras/test_jobs/read_only_job.py +15 -0
- nautobot/extras/{tests/example_jobs/test_required_args.py → test_jobs/required_args.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_soft_time_limit_greater_than_time_limit.py → test_jobs/soft_time_limit_greater_than_time_limit.py} +5 -1
- nautobot/extras/{tests/example_jobs/test_task_queues.py → test_jobs/task_queues.py} +5 -1
- nautobot/extras/tests/integration/__init__.py +3 -3
- nautobot/extras/tests/integration/test_computedfields.py +1 -1
- nautobot/extras/tests/integration/test_configcontextschema.py +7 -5
- nautobot/extras/tests/integration/test_customfields.py +4 -2
- nautobot/extras/tests/integration/test_dynamicgroups.py +2 -2
- nautobot/extras/tests/integration/test_jobs.py +25 -27
- nautobot/extras/tests/integration/test_notes.py +8 -4
- nautobot/extras/tests/integration/test_plugins.py +4 -4
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_api.py +371 -381
- nautobot/extras/tests/test_changelog.py +17 -16
- nautobot/extras/tests/test_context_managers.py +5 -6
- nautobot/extras/tests/test_customfields.py +112 -73
- nautobot/extras/tests/test_datasources.py +191 -117
- nautobot/extras/tests/test_dynamicgroups.py +45 -68
- nautobot/extras/tests/test_filters.py +170 -130
- nautobot/extras/tests/test_forms.py +107 -109
- nautobot/extras/tests/{test_scripts.py → test_job_variables.py} +43 -49
- nautobot/extras/tests/test_jobs.py +271 -273
- nautobot/extras/tests/test_management.py +3 -6
- nautobot/extras/tests/test_migrations.py +5 -3
- nautobot/extras/tests/test_models.py +121 -173
- nautobot/extras/tests/test_notes.py +0 -1
- nautobot/extras/tests/test_plugins.py +55 -89
- nautobot/extras/tests/test_relationships.py +174 -130
- nautobot/extras/tests/test_tags.py +6 -12
- nautobot/extras/tests/test_utils.py +31 -1
- nautobot/extras/tests/test_views.py +223 -184
- nautobot/extras/tests/test_webhooks.py +16 -15
- nautobot/extras/urls.py +69 -69
- nautobot/extras/utils.py +137 -163
- nautobot/extras/views.py +81 -153
- nautobot/ipam/api/fields.py +17 -0
- nautobot/ipam/api/serializers.py +77 -164
- nautobot/ipam/api/urls.py +4 -1
- nautobot/ipam/api/views.py +28 -19
- nautobot/ipam/apps.py +1 -0
- nautobot/ipam/choices.py +5 -12
- nautobot/ipam/constants.py +1 -0
- nautobot/ipam/factory.py +41 -30
- nautobot/ipam/filters.py +58 -25
- nautobot/ipam/forms.py +82 -211
- nautobot/ipam/graphql/types.py +0 -9
- nautobot/ipam/lookups.py +13 -8
- nautobot/ipam/management/commands/__init__.py +0 -0
- nautobot/ipam/management/commands/fix_prefix_broadcast.py +17 -0
- nautobot/ipam/migrations/0001_initial_part_1.py +0 -1
- nautobot/ipam/migrations/0002_initial_part_2.py +0 -1
- nautobot/ipam/migrations/0003_remove_max_length.py +0 -1
- nautobot/ipam/migrations/0004_fixup_p2p_broadcast.py +0 -1
- nautobot/ipam/migrations/0005_auto_slug.py +0 -1
- nautobot/ipam/migrations/0006_ipaddress_nat_outside_list.py +0 -1
- nautobot/ipam/migrations/0007_add_natural_indexing.py +0 -1
- nautobot/ipam/migrations/0008_prefix_vlan_vlangroup_location.py +0 -1
- nautobot/ipam/migrations/0009_alter_vlan_name.py +0 -1
- nautobot/ipam/migrations/0010_alter_ipam_role_add_new_role.py +1 -2
- nautobot/ipam/migrations/0011_migrate_ipam_role_data.py +32 -39
- nautobot/ipam/migrations/0012_rename_ipam_roles.py +0 -1
- nautobot/ipam/migrations/0013_delete_role.py +0 -1
- nautobot/ipam/migrations/0014_rename_foreign_keys_and_related_names.py +0 -1
- nautobot/ipam/migrations/0015_prefix_add_type.py +0 -1
- nautobot/ipam/migrations/0016_prefix_type_data_migration.py +0 -3
- nautobot/ipam/migrations/0017_prefix_remove_is_pool.py +0 -1
- nautobot/ipam/migrations/0018_remove_site_foreign_key_from_ipam_models.py +0 -1
- nautobot/ipam/migrations/0019_created_datetime.py +0 -1
- nautobot/ipam/migrations/0020_related_name_changes.py +1 -2
- nautobot/ipam/migrations/0021_prefix_add_rir_and_date_allocated.py +0 -1
- nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py +3 -5
- nautobot/ipam/migrations/0023_delete_aggregate.py +0 -1
- nautobot/ipam/migrations/0024_interface_to_ipaddress_m2m.py +0 -1
- nautobot/ipam/migrations/0025_interface_ipaddress_m2m_data_migration.py +0 -1
- nautobot/ipam/migrations/0026_ipaddress_remove_assigned_object.py +0 -1
- nautobot/ipam/migrations/0027_remove_rir_slug.py +16 -0
- nautobot/ipam/migrations/0028_tagsfield.py +44 -0
- nautobot/ipam/migrations/0029_ip_address_to_interface_uniqueness_constraints.py +18 -0
- nautobot/ipam/migrations/0030_ipam__namespaces.py +231 -0
- nautobot/ipam/migrations/0031_ipam__prefix__add_parent.py +58 -0
- nautobot/ipam/migrations/0032_ipam__namespaces_finish.py +63 -0
- nautobot/ipam/migrations/0033_fixup_null_statuses.py +26 -0
- nautobot/ipam/migrations/0034_status_nonnullable.py +36 -0
- nautobot/ipam/models.py +579 -368
- nautobot/ipam/navigation.py +36 -159
- nautobot/ipam/querysets.py +117 -90
- nautobot/ipam/signals.py +89 -0
- nautobot/ipam/tables.py +86 -28
- nautobot/ipam/templates/ipam/ipaddress.html +14 -30
- nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -0
- nautobot/ipam/templates/ipam/namespace_ipaddresses.html +11 -0
- nautobot/ipam/templates/ipam/namespace_prefixes.html +11 -0
- nautobot/ipam/templates/ipam/namespace_retrieve.html +42 -0
- nautobot/ipam/templates/ipam/namespace_vrfs.html +11 -0
- nautobot/ipam/templates/ipam/prefix.html +27 -33
- nautobot/ipam/templates/ipam/prefix_edit.html +7 -1
- nautobot/ipam/templates/ipam/vlangroup.html +0 -13
- nautobot/ipam/templates/ipam/vrf.html +6 -4
- nautobot/ipam/templates/ipam/vrf_edit.html +20 -2
- nautobot/ipam/tests/integration/test_prefixes.py +4 -27
- nautobot/ipam/tests/test_api.py +60 -61
- nautobot/ipam/tests/test_filters.py +187 -126
- nautobot/ipam/tests/test_forms.py +12 -6
- nautobot/ipam/tests/test_graphql.py +8 -6
- nautobot/ipam/tests/test_migrations.py +8 -13
- nautobot/ipam/tests/test_models.py +426 -274
- nautobot/ipam/tests/test_ordering.py +6 -3
- nautobot/ipam/tests/test_querysets.py +340 -96
- nautobot/ipam/tests/test_views.py +100 -55
- nautobot/ipam/urls.py +28 -5
- nautobot/ipam/{utils.py → utils/__init__.py} +2 -2
- nautobot/ipam/utils/migrations.py +713 -0
- nautobot/ipam/views.py +237 -122
- nautobot/project-static/docs/404.html +1399 -166
- nautobot/project-static/docs/additional-features/caching.html +1416 -320
- nautobot/project-static/docs/additional-features/change-logging.html +1389 -190
- nautobot/project-static/docs/additional-features/config-contexts.html +1389 -190
- nautobot/project-static/docs/additional-features/graphql.html +1389 -190
- nautobot/project-static/docs/additional-features/healthcheck.html +1389 -190
- nautobot/project-static/docs/additional-features/job-scheduling-and-approvals.html +1393 -190
- nautobot/project-static/docs/additional-features/jobs.html +1677 -460
- nautobot/project-static/docs/additional-features/napalm.html +1389 -190
- nautobot/project-static/docs/additional-features/prometheus-metrics.html +1389 -190
- nautobot/project-static/docs/additional-features/template-filters.html +1389 -190
- nautobot/project-static/docs/administration/celery-queues.html +1389 -190
- nautobot/project-static/docs/administration/nautobot-server.html +1553 -375
- nautobot/project-static/docs/administration/nautobot-shell.html +1395 -196
- nautobot/project-static/docs/administration/permissions.html +1389 -190
- nautobot/project-static/docs/administration/replicating-nautobot.html +1387 -207
- nautobot/project-static/docs/apps/index.html +1389 -190
- nautobot/project-static/docs/apps/nautobot-apps.html +1387 -175
- nautobot/project-static/docs/assets/javascripts/bundle.51198bba.min.js +29 -0
- nautobot/project-static/docs/assets/javascripts/bundle.51198bba.min.js.map +8 -0
- nautobot/project-static/docs/assets/javascripts/workers/{search.16e2a7d4.min.js → search.208ed371.min.js} +9 -15
- nautobot/project-static/docs/assets/javascripts/workers/{search.16e2a7d4.min.js.map → search.208ed371.min.js.map} +4 -4
- nautobot/project-static/docs/assets/stylesheets/main.ded33207.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.ded33207.min.css.map +1 -0
- nautobot/project-static/docs/assets/stylesheets/palette.a0c5b2b5.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/palette.a0c5b2b5.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +1775 -590
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +1389 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +3588 -1922
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +1461 -262
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +1401 -170
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +1396 -191
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +2095 -894
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2357 -1194
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2258 -940
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +1389 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1400 -201
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +11068 -7861
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2867 -2224
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +1389 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2641 -1573
- nautobot/project-static/docs/configuration/authentication/ldap.html +1389 -190
- nautobot/project-static/docs/configuration/authentication/remote.html +1389 -190
- nautobot/project-static/docs/configuration/authentication/sso.html +1389 -190
- nautobot/project-static/docs/configuration/index.html +1398 -199
- nautobot/project-static/docs/configuration/optional-settings.html +1418 -274
- nautobot/project-static/docs/configuration/required-settings.html +1419 -287
- nautobot/project-static/docs/core-functionality/circuits.html +1446 -247
- nautobot/project-static/docs/core-functionality/device-types.html +1448 -249
- nautobot/project-static/docs/core-functionality/devices.html +1452 -249
- nautobot/project-static/docs/core-functionality/ipam.html +1452 -253
- nautobot/project-static/docs/core-functionality/power.html +1448 -249
- nautobot/project-static/docs/core-functionality/secrets.html +1448 -249
- nautobot/project-static/docs/core-functionality/services.html +1448 -249
- nautobot/project-static/docs/core-functionality/sites-and-racks.html +1448 -249
- nautobot/project-static/docs/core-functionality/tenancy.html +1448 -249
- nautobot/project-static/docs/core-functionality/virtualization.html +1452 -249
- nautobot/project-static/docs/core-functionality/vlans.html +1448 -249
- nautobot/project-static/docs/development/application-registry.html +1393 -214
- nautobot/project-static/docs/development/best-practices.html +1392 -192
- nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1390 -191
- nautobot/project-static/docs/development/extending-models.html +1443 -257
- nautobot/project-static/docs/development/generic-views.html +1403 -174
- nautobot/project-static/docs/development/getting-started.html +1568 -262
- nautobot/project-static/docs/development/homepage.html +1389 -190
- nautobot/project-static/docs/development/index.html +1389 -190
- nautobot/project-static/docs/development/model-features.html +1389 -190
- nautobot/project-static/docs/development/natural-keys.html +1389 -190
- nautobot/project-static/docs/development/navigation-menu.html +1451 -330
- nautobot/project-static/docs/development/react-ui.html +4199 -0
- nautobot/project-static/docs/development/release-checklist.html +1392 -193
- nautobot/project-static/docs/development/role-internals.html +1402 -172
- nautobot/project-static/docs/development/style-guide.html +1399 -199
- nautobot/project-static/docs/development/templates.html +1391 -191
- nautobot/project-static/docs/development/testing.html +1389 -190
- nautobot/project-static/docs/development/user-preferences.html +1389 -190
- nautobot/project-static/docs/docker/index.html +1408 -206
- nautobot/project-static/docs/index.html +1397 -180
- nautobot/project-static/docs/installation/centos.html +1401 -170
- nautobot/project-static/docs/installation/external-authentication.html +1389 -190
- nautobot/project-static/docs/installation/http-server.html +1389 -190
- nautobot/project-static/docs/installation/index.html +1394 -191
- nautobot/project-static/docs/installation/migrating-from-netbox.html +1452 -305
- nautobot/project-static/docs/installation/migrating-from-postgresql.html +1390 -191
- nautobot/project-static/docs/installation/nautobot.html +1390 -191
- nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1389 -190
- nautobot/project-static/docs/installation/selinux-troubleshooting.html +1401 -170
- nautobot/project-static/docs/installation/services.html +1389 -190
- nautobot/project-static/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
- nautobot/project-static/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
- nautobot/project-static/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
- nautobot/project-static/docs/installation/tables/v2-code-location-changes.yaml +241 -0
- nautobot/project-static/docs/installation/tables/v2-code-removals.yaml +67 -0
- nautobot/project-static/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
- nautobot/project-static/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
- nautobot/project-static/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
- nautobot/project-static/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
- nautobot/project-static/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
- nautobot/project-static/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
- nautobot/project-static/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
- nautobot/project-static/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
- nautobot/project-static/docs/installation/ubuntu.html +1401 -170
- nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +4254 -1923
- nautobot/project-static/docs/installation/upgrading.html +1395 -192
- nautobot/project-static/docs/models/circuits/circuit.html +1427 -174
- nautobot/project-static/docs/models/circuits/circuittermination.html +1427 -174
- nautobot/project-static/docs/models/circuits/circuittype.html +1427 -174
- nautobot/project-static/docs/models/circuits/provider.html +1427 -174
- nautobot/project-static/docs/models/circuits/providernetwork.html +1427 -174
- nautobot/project-static/docs/models/dcim/cable.html +1458 -174
- nautobot/project-static/docs/models/dcim/consoleport.html +1427 -174
- nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/consoleserverport.html +1427 -174
- nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/device.html +1431 -174
- nautobot/project-static/docs/models/dcim/devicebay.html +1427 -174
- nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1522 -177
- nautobot/project-static/docs/models/dcim/devicetype.html +1427 -174
- nautobot/project-static/docs/models/dcim/frontport.html +1427 -174
- nautobot/project-static/docs/models/dcim/frontporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/interface.html +1427 -174
- nautobot/project-static/docs/models/dcim/interfacetemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/inventoryitem.html +1427 -174
- nautobot/project-static/docs/models/dcim/location.html +1427 -174
- nautobot/project-static/docs/models/dcim/locationtype.html +1427 -174
- nautobot/project-static/docs/models/dcim/manufacturer.html +1427 -174
- nautobot/project-static/docs/models/dcim/platform.html +1427 -174
- nautobot/project-static/docs/models/dcim/powerfeed.html +1425 -172
- nautobot/project-static/docs/models/dcim/poweroutlet.html +1427 -174
- nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/powerpanel.html +1425 -172
- nautobot/project-static/docs/models/dcim/powerport.html +1427 -174
- nautobot/project-static/docs/models/dcim/powerporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/rack.html +1427 -174
- nautobot/project-static/docs/models/dcim/rackgroup.html +1427 -174
- nautobot/project-static/docs/models/dcim/rackreservation.html +1427 -174
- nautobot/project-static/docs/models/dcim/rearport.html +1427 -174
- nautobot/project-static/docs/models/dcim/rearporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/region.html +1401 -170
- nautobot/project-static/docs/models/dcim/site.html +1401 -170
- nautobot/project-static/docs/models/dcim/virtualchassis.html +1425 -172
- nautobot/project-static/docs/models/extras/computedfield.html +1393 -194
- nautobot/project-static/docs/models/extras/configcontext.html +1465 -174
- nautobot/project-static/docs/models/extras/configcontextschema.html +1421 -168
- nautobot/project-static/docs/models/extras/customfield.html +1389 -190
- nautobot/project-static/docs/models/extras/customlink.html +1389 -190
- nautobot/project-static/docs/models/extras/dynamicgroup.html +1398 -199
- nautobot/project-static/docs/models/extras/exporttemplate.html +1389 -190
- nautobot/project-static/docs/models/extras/gitrepository.html +1393 -190
- nautobot/project-static/docs/models/extras/graphqlquery.html +1469 -171
- nautobot/project-static/docs/models/extras/imageattachment.html +1434 -181
- nautobot/project-static/docs/models/extras/job.html +1411 -157
- nautobot/project-static/docs/models/extras/jobbutton.html +1410 -207
- nautobot/project-static/docs/models/extras/jobhook.html +1397 -194
- nautobot/project-static/docs/models/extras/joblogentry.html +1408 -155
- nautobot/project-static/docs/models/extras/jobresult.html +1417 -159
- nautobot/project-static/docs/models/extras/note.html +1389 -190
- nautobot/project-static/docs/models/extras/relationship.html +1391 -192
- nautobot/project-static/docs/models/extras/role.html +1495 -198
- nautobot/project-static/docs/models/extras/secret.html +1492 -201
- nautobot/project-static/docs/models/extras/secretsgroup.html +1410 -157
- nautobot/project-static/docs/models/extras/status.html +1381 -221
- nautobot/project-static/docs/models/extras/tag.html +1389 -190
- nautobot/project-static/docs/models/extras/webhook.html +1389 -190
- nautobot/project-static/docs/models/ipam/ipaddress.html +1488 -200
- nautobot/project-static/docs/models/ipam/prefix.html +1410 -157
- nautobot/project-static/docs/models/ipam/rir.html +1410 -157
- nautobot/project-static/docs/models/ipam/routetarget.html +1410 -157
- nautobot/project-static/docs/models/ipam/service.html +1410 -157
- nautobot/project-static/docs/models/ipam/vlan.html +1410 -157
- nautobot/project-static/docs/models/ipam/vlangroup.html +1410 -157
- nautobot/project-static/docs/models/ipam/vrf.html +1410 -161
- nautobot/project-static/docs/models/tenancy/tenant.html +1412 -159
- nautobot/project-static/docs/models/tenancy/tenantgroup.html +1412 -159
- nautobot/project-static/docs/models/users/objectpermission.html +1462 -171
- nautobot/project-static/docs/models/users/token.html +1410 -157
- nautobot/project-static/docs/models/virtualization/cluster.html +1410 -157
- nautobot/project-static/docs/models/virtualization/clustergroup.html +1410 -157
- nautobot/project-static/docs/models/virtualization/clustertype.html +1410 -157
- nautobot/project-static/docs/models/virtualization/virtualmachine.html +1414 -157
- nautobot/project-static/docs/models/virtualization/vminterface.html +1410 -157
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/plugins/development.html +1916 -646
- nautobot/project-static/docs/plugins/index.html +1389 -190
- nautobot/project-static/docs/plugins/porting-from-netbox.html +1389 -190
- nautobot/project-static/docs/release-notes/index.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.0.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.1.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.2.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.3.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.4.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.5.html +2016 -397
- nautobot/project-static/docs/release-notes/version-2.0.html +1935 -287
- nautobot/project-static/docs/requirements.txt +5 -4
- nautobot/project-static/docs/rest-api/authentication.html +1389 -190
- nautobot/project-static/docs/rest-api/filtering.html +1389 -190
- nautobot/project-static/docs/rest-api/overview.html +2002 -576
- nautobot/project-static/docs/rest-api/ui-related-endpoints.html +4057 -0
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +197 -187
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guides/custom-fields.html +1390 -191
- nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1392 -193
- nautobot/project-static/docs/user-guides/getting-started/index.html +1388 -189
- nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1388 -189
- nautobot/project-static/docs/user-guides/getting-started/ipam.html +1386 -187
- nautobot/project-static/docs/user-guides/getting-started/platforms.html +1448 -249
- nautobot/project-static/docs/user-guides/getting-started/regions.html +1411 -212
- nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1395 -196
- nautobot/project-static/docs/user-guides/getting-started/tenants.html +1448 -249
- nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1448 -249
- nautobot/project-static/docs/user-guides/git-data-source.html +1405 -206
- nautobot/project-static/docs/user-guides/graphql.html +1402 -203
- nautobot/project-static/docs/user-guides/relationships.html +1448 -249
- nautobot/project-static/docs/user-guides/s3-django-storage.html +1448 -249
- nautobot/project-static/js/forms.js +16 -9
- nautobot/project-static/js/theme.js +5 -0
- nautobot/tenancy/api/serializers.py +4 -34
- nautobot/tenancy/api/urls.py +1 -1
- nautobot/tenancy/filters/__init__.py +9 -7
- nautobot/tenancy/filters/mixins.py +3 -2
- nautobot/tenancy/forms.py +3 -36
- nautobot/tenancy/migrations/0001_initial.py +0 -1
- nautobot/tenancy/migrations/0002_auto_slug.py +0 -1
- nautobot/tenancy/migrations/0003_mptt_to_tree_queries.py +0 -1
- nautobot/tenancy/migrations/0004_change_tree_manager_on_tree_models.py +0 -1
- nautobot/tenancy/migrations/0005_rename_foreign_keys_and_related_names.py +0 -1
- nautobot/tenancy/migrations/0006_created_datetime.py +0 -1
- nautobot/tenancy/migrations/0007_remove_tenant_tenantgroup_slug.py +20 -0
- nautobot/tenancy/migrations/0008_tagsfield.py +19 -0
- nautobot/tenancy/models.py +0 -30
- nautobot/tenancy/navigation.py +6 -39
- nautobot/tenancy/tables.py +4 -4
- nautobot/tenancy/templates/tenancy/tenant.html +12 -12
- nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -1
- nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
- nautobot/tenancy/tests/test_api.py +1 -12
- nautobot/tenancy/tests/test_filters.py +20 -12
- nautobot/tenancy/tests/test_views.py +11 -29
- nautobot/tenancy/urls.py +10 -10
- nautobot/tenancy/views.py +0 -3
- nautobot/ui/.eslintignore +6 -0
- nautobot/ui/.gitignore +10 -0
- nautobot/ui/.prettierignore +9 -0
- nautobot/ui/.prettierrc +4 -0
- nautobot/ui/README.md +33 -0
- nautobot/ui/app_imports.js.j2 +7 -0
- nautobot/ui/craco.config.js +46 -0
- nautobot/ui/jsconfig-base.json +11 -0
- nautobot/ui/jsconfig.json +5 -0
- nautobot/ui/lib/nautobot-craco-alias-plugin.js +40 -0
- nautobot/ui/package-lock.json +21451 -0
- nautobot/ui/package.json +70 -0
- nautobot/ui/public/index.html +47 -0
- nautobot/ui/public/logo192.png +0 -0
- nautobot/ui/public/logo512.png +0 -0
- nautobot/ui/public/manifest.json +25 -0
- nautobot/ui/public/nautobot_logo.svg +131 -0
- nautobot/ui/public/robots.txt +3 -0
- nautobot/ui/src/App.js +71 -0
- nautobot/ui/src/components/AppFullWidthComponents.js +8 -0
- nautobot/ui/src/components/AppTab.js +40 -0
- nautobot/ui/src/components/Apps.js +60 -0
- nautobot/ui/src/components/HomeChangelogPanel.js +98 -0
- nautobot/ui/src/components/HomePanel.js +58 -0
- nautobot/ui/src/components/JobHistoryTable.js +78 -0
- nautobot/ui/src/components/Layout.js +53 -0
- nautobot/ui/src/components/LoadingWidget.js +25 -0
- nautobot/ui/src/components/Navbar.js +116 -0
- nautobot/ui/src/components/NotificationPopover.js +27 -0
- nautobot/ui/src/components/ObjectListTable.js +209 -0
- nautobot/ui/src/components/ReferenceDataTag.js +35 -0
- nautobot/ui/src/components/RouterButton.js +10 -0
- nautobot/ui/src/components/RouterLink.js +10 -0
- nautobot/ui/src/components/SidebarNav.js +147 -0
- nautobot/ui/src/components/Table.js +48 -0
- nautobot/ui/src/components/TableItem.js +71 -0
- nautobot/ui/src/components/__tests__/AppFullWidthComponents.test.js +16 -0
- nautobot/ui/src/components/__tests__/AppTab.test.js +21 -0
- nautobot/ui/src/components/__tests__/Apps.test.js +14 -0
- nautobot/ui/src/components/__tests__/Layout.test.js +33 -0
- nautobot/ui/src/components/__tests__/Table.test.js +36 -0
- nautobot/ui/src/components/__tests__/TableItem.test.js +37 -0
- nautobot/ui/src/components/__tests__/paginator.test.js +43 -0
- nautobot/ui/src/components/__tests__/paginator_form.test.js +13 -0
- nautobot/ui/src/components/pagination.js +93 -0
- nautobot/ui/src/components/paginator.js +79 -0
- nautobot/ui/src/components/paginator_form.js +43 -0
- nautobot/ui/src/components/usePagination.js +57 -0
- nautobot/ui/src/constants/apiPath.js +10 -0
- nautobot/ui/src/constants/icons.js +15 -0
- nautobot/ui/src/constants/size.js +15 -0
- nautobot/ui/src/index.js +65 -0
- nautobot/ui/src/reportWebVitals.js +15 -0
- nautobot/ui/src/router.js +77 -0
- nautobot/ui/src/utils/api.js +131 -0
- nautobot/ui/src/utils/app-import.js +15 -0
- nautobot/ui/src/utils/color.js +15 -0
- nautobot/ui/src/utils/date.js +14 -0
- nautobot/ui/src/utils/index.js +15 -0
- nautobot/ui/src/utils/navigation.js +32 -0
- nautobot/ui/src/utils/session.js +64 -0
- nautobot/ui/src/utils/store.js +242 -0
- nautobot/ui/src/utils/string.js +6 -0
- nautobot/ui/src/utils/url.js +4 -0
- nautobot/ui/src/views/Home.js +138 -0
- nautobot/ui/src/views/InstalledApps.js +80 -0
- nautobot/ui/src/views/Login.js +48 -0
- nautobot/ui/src/views/Logout.js +20 -0
- nautobot/ui/src/views/__tests__/BSCreateViewTemplate.test.js +11 -0
- nautobot/ui/src/views/__tests__/BSListViewTemplate.test.js +107 -0
- nautobot/ui/src/views/__tests__/Login.test.js +15 -0
- nautobot/ui/src/views/generic/GenericView.js +142 -0
- nautobot/ui/src/views/generic/ObjectCreate.js +96 -0
- nautobot/ui/src/views/generic/ObjectList.js +127 -0
- nautobot/ui/src/views/generic/ObjectRetrieve.js +551 -0
- nautobot/users/admin.py +1 -1
- nautobot/users/api/serializers.py +51 -61
- nautobot/users/api/urls.py +1 -1
- nautobot/users/api/views.py +53 -2
- nautobot/users/migrations/0001_initial.py +0 -1
- nautobot/users/migrations/0002_token_ordering_by_created.py +0 -1
- nautobot/users/migrations/0003_alter_user_options.py +0 -1
- nautobot/users/migrations/0004_alter_user_managers.py +0 -1
- nautobot/users/tests/test_api.py +109 -28
- nautobot/users/tests/test_filters.py +0 -4
- nautobot/users/tests/test_models.py +0 -1
- nautobot/users/views.py +0 -7
- nautobot/virtualization/api/serializers.py +18 -132
- nautobot/virtualization/api/urls.py +1 -1
- nautobot/virtualization/api/views.py +1 -22
- nautobot/virtualization/choices.py +0 -2
- nautobot/virtualization/filters.py +12 -7
- nautobot/virtualization/forms.py +21 -117
- nautobot/virtualization/migrations/0001_initial.py +0 -1
- nautobot/virtualization/migrations/0002_virtualmachine_local_context_schema.py +0 -1
- nautobot/virtualization/migrations/0003_vminterface_verbose_name.py +0 -1
- nautobot/virtualization/migrations/0004_auto_slug.py +0 -1
- nautobot/virtualization/migrations/0005_add_natural_indexing.py +0 -1
- nautobot/virtualization/migrations/0006_vminterface_status.py +0 -1
- nautobot/virtualization/migrations/0007_vminterface_status_data_migration.py +0 -1
- nautobot/virtualization/migrations/0008_vminterface_parent.py +0 -1
- nautobot/virtualization/migrations/0009_cluster_location.py +0 -1
- nautobot/virtualization/migrations/0010_vminterface_mac_address_data_migration.py +0 -1
- nautobot/virtualization/migrations/0011_alter_vminterface_mac_address.py +0 -1
- nautobot/virtualization/migrations/0012_alter_virtualmachine_role_add_new_role.py +1 -2
- nautobot/virtualization/migrations/0013_migrate_virtualmachine_role_data.py +18 -12
- nautobot/virtualization/migrations/0014_rename_virtualmachine_roles.py +0 -1
- nautobot/virtualization/migrations/0015_rename_foreignkey_fields.py +1 -2
- nautobot/virtualization/migrations/0016_remove_site_foreign_key_from_cluster_class.py +0 -1
- nautobot/virtualization/migrations/0017_created_datetime.py +0 -1
- nautobot/virtualization/migrations/0018_related_name_changes.py +1 -2
- nautobot/virtualization/migrations/0019_vminterface_ip_addresses_m2m.py +0 -1
- nautobot/virtualization/migrations/0020_remove_clustergroup_clustertype_slug.py +20 -0
- nautobot/virtualization/migrations/0021_tagsfield_and_vminterface_to_primarymodel.py +39 -0
- nautobot/virtualization/migrations/0022_vminterface_timestamps_data_migration.py +17 -0
- nautobot/virtualization/migrations/0023_ipam__namespaces.py +25 -0
- nautobot/virtualization/migrations/0024_fixup_null_statuses.py +25 -0
- nautobot/virtualization/migrations/0025_status_nonnullable.py +29 -0
- nautobot/virtualization/models.py +39 -131
- nautobot/virtualization/navigation.py +18 -99
- nautobot/virtualization/tables.py +4 -4
- nautobot/virtualization/templates/virtualization/virtualmachine.html +13 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +6 -0
- nautobot/virtualization/tests/test_api.py +42 -52
- nautobot/virtualization/tests/test_filters.py +98 -75
- nautobot/virtualization/tests/test_models.py +36 -13
- nautobot/virtualization/tests/test_views.py +68 -73
- nautobot/virtualization/urls.py +10 -10
- nautobot/virtualization/views.py +8 -14
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/METADATA +15 -22
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/RECORD +987 -834
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/WHEEL +1 -1
- nautobot/circuits/api/nested_serializers.py +0 -69
- nautobot/core/templates/plugin_template/navigation.py-tpl +0 -22
- nautobot/dcim/api/nested_serializers.py +0 -356
- nautobot/dcim/templates/dcim/device_import.html +0 -5
- nautobot/dcim/templates/dcim/device_import_child.html +0 -5
- nautobot/dcim/templates/dcim/inc/device_import_header.html +0 -4
- nautobot/extras/api/nested_serializers.py +0 -353
- nautobot/extras/migrations/0064_configcontext_data_migrations.py +0 -42
- nautobot/extras/migrations/0071_job__unique_name_data_migration.py +0 -47
- nautobot/extras/reports.py +0 -60
- nautobot/extras/scripts.py +0 -72
- nautobot/extras/tests/example_jobs/script_variables.py +0 -67
- nautobot/extras/tests/example_jobs/test_duplicate_name2.py +0 -5
- nautobot/extras/tests/example_jobs/test_fail.py +0 -16
- nautobot/extras/tests/example_jobs/test_file_upload_pass.py +0 -20
- nautobot/extras/tests/example_jobs/test_ipaddress_vars.py +0 -52
- nautobot/extras/tests/example_jobs/test_job_button_receiver.py +0 -21
- nautobot/extras/tests/example_jobs/test_job_hook_receiver.py +0 -20
- nautobot/extras/tests/example_jobs/test_location_with_custom_field.py +0 -35
- nautobot/extras/tests/example_jobs/test_log_redaction.py +0 -14
- nautobot/extras/tests/example_jobs/test_modify_db.py +0 -19
- nautobot/extras/tests/example_jobs/test_object_var_optional.py +0 -14
- nautobot/extras/tests/example_jobs/test_object_var_required.py +0 -14
- nautobot/extras/tests/example_jobs/test_object_vars.py +0 -29
- nautobot/extras/tests/example_jobs/test_pass.py +0 -19
- nautobot/extras/tests/example_jobs/test_read_only_fail.py +0 -24
- nautobot/extras/tests/example_jobs/test_read_only_no_commit_field.py +0 -10
- nautobot/extras/tests/example_jobs/test_read_only_pass.py +0 -22
- nautobot/ipam/api/nested_serializers.py +0 -143
- nautobot/project-static/docs/assets/javascripts/bundle.5a2dcb6a.min.js +0 -29
- nautobot/project-static/docs/assets/javascripts/bundle.5a2dcb6a.min.js.map +0 -8
- nautobot/project-static/docs/assets/javascripts/extra/bundle.5f09fbc3.min.js +0 -18
- nautobot/project-static/docs/assets/javascripts/extra/bundle.5f09fbc3.min.js.map +0 -8
- nautobot/project-static/docs/assets/stylesheets/extra.0d2c79a8.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/extra.0d2c79a8.min.css.map +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.975780f9.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.975780f9.min.css.map +0 -1
- nautobot/project-static/docs/assets/stylesheets/palette.2505c338.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/palette.2505c338.min.css.map +0 -1
- nautobot/tenancy/api/nested_serializers.py +0 -31
- nautobot/users/api/nested_serializers.py +0 -67
- nautobot/virtualization/api/nested_serializers.py +0 -65
- /nautobot/extras/{tests/example_jobs → test_jobs}/__init__.py +0 -0
- /nautobot/{dcim/models/sites.py → ipam/management/__init__.py} +0 -0
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/entry_points.txt +0 -0
nautobot/extras/forms/forms.py
CHANGED
|
@@ -6,7 +6,6 @@ from django.core.exceptions import ValidationError
|
|
|
6
6
|
from django.db.models.fields import TextField
|
|
7
7
|
from django.forms import ModelMultipleChoiceField, inlineformset_factory
|
|
8
8
|
from django.urls.base import reverse
|
|
9
|
-
from django.utils.safestring import mark_safe
|
|
10
9
|
|
|
11
10
|
from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
|
|
12
11
|
from nautobot.core.forms import (
|
|
@@ -19,10 +18,7 @@ from nautobot.core.forms import (
|
|
|
19
18
|
ColorSelect,
|
|
20
19
|
CommentField,
|
|
21
20
|
CSVContentTypeField,
|
|
22
|
-
CSVModelChoiceField,
|
|
23
21
|
CSVModelForm,
|
|
24
|
-
CSVMultipleChoiceField,
|
|
25
|
-
CSVMultipleContentTypeField,
|
|
26
22
|
DateTimePicker,
|
|
27
23
|
DynamicModelChoiceField,
|
|
28
24
|
DynamicModelMultipleChoiceField,
|
|
@@ -113,7 +109,6 @@ __all__ = (
|
|
|
113
109
|
"ExportTemplateForm",
|
|
114
110
|
"ExportTemplateFilterForm",
|
|
115
111
|
"GitRepositoryForm",
|
|
116
|
-
"GitRepositoryCSVForm",
|
|
117
112
|
"GitRepositoryBulkEditForm",
|
|
118
113
|
"GitRepositoryFilterForm",
|
|
119
114
|
"GraphQLQueryForm",
|
|
@@ -139,21 +134,17 @@ __all__ = (
|
|
|
139
134
|
"RelationshipFilterForm",
|
|
140
135
|
"RelationshipAssociationFilterForm",
|
|
141
136
|
"RoleBulkEditForm",
|
|
142
|
-
"RoleCSVForm",
|
|
143
137
|
"RoleForm",
|
|
144
138
|
"ScheduledJobFilterForm",
|
|
145
139
|
"SecretForm",
|
|
146
|
-
"SecretCSVForm",
|
|
147
140
|
"SecretFilterForm",
|
|
148
141
|
"SecretsGroupForm",
|
|
149
142
|
"SecretsGroupFilterForm",
|
|
150
143
|
"SecretsGroupAssociationFormSet",
|
|
151
144
|
"StatusForm",
|
|
152
|
-
"StatusCSVForm",
|
|
153
145
|
"StatusFilterForm",
|
|
154
146
|
"StatusBulkEditForm",
|
|
155
147
|
"TagForm",
|
|
156
|
-
"TagCSVForm",
|
|
157
148
|
"TagFilterForm",
|
|
158
149
|
"TagBulkEditForm",
|
|
159
150
|
"WebhookForm",
|
|
@@ -172,7 +163,9 @@ class ComputedFieldForm(BootstrapMixin, forms.ModelForm):
|
|
|
172
163
|
required=True,
|
|
173
164
|
label="Content Type",
|
|
174
165
|
)
|
|
175
|
-
|
|
166
|
+
key = SlugField(
|
|
167
|
+
label="Key",
|
|
168
|
+
max_length=50,
|
|
176
169
|
slug_source="label",
|
|
177
170
|
help_text="Internal name of this field. Please use underscores rather than dashes.",
|
|
178
171
|
)
|
|
@@ -189,7 +182,7 @@ class ComputedFieldForm(BootstrapMixin, forms.ModelForm):
|
|
|
189
182
|
fields = (
|
|
190
183
|
"content_type",
|
|
191
184
|
"label",
|
|
192
|
-
"
|
|
185
|
+
"key",
|
|
193
186
|
"description",
|
|
194
187
|
"template",
|
|
195
188
|
"fallback_value",
|
|
@@ -197,6 +190,12 @@ class ComputedFieldForm(BootstrapMixin, forms.ModelForm):
|
|
|
197
190
|
"advanced_ui",
|
|
198
191
|
)
|
|
199
192
|
|
|
193
|
+
def __init__(self, *args, **kwargs):
|
|
194
|
+
super().__init__(*args, **kwargs)
|
|
195
|
+
|
|
196
|
+
if self.instance and self.instance.present_in_database:
|
|
197
|
+
self.fields["key"].widget.attrs["readonly"] = True
|
|
198
|
+
|
|
200
199
|
|
|
201
200
|
class ComputedFieldFilterForm(BootstrapMixin, forms.Form):
|
|
202
201
|
model = ComputedField
|
|
@@ -284,24 +283,24 @@ class ConfigContextFilterForm(BootstrapMixin, forms.Form):
|
|
|
284
283
|
schema = DynamicModelChoiceField(queryset=ConfigContextSchema.objects.all(), to_field_name="slug", required=False)
|
|
285
284
|
location = DynamicModelMultipleChoiceField(queryset=Location.objects.all(), to_field_name="slug", required=False)
|
|
286
285
|
role = DynamicModelMultipleChoiceField(
|
|
287
|
-
queryset=Role.objects.get_for_models([Device, VirtualMachine]), to_field_name="
|
|
286
|
+
queryset=Role.objects.get_for_models([Device, VirtualMachine]), to_field_name="name", required=False
|
|
288
287
|
)
|
|
289
288
|
type = DynamicModelMultipleChoiceField(queryset=DeviceType.objects.all(), to_field_name="slug", required=False)
|
|
290
|
-
platform = DynamicModelMultipleChoiceField(queryset=Platform.objects.all(), to_field_name="
|
|
289
|
+
platform = DynamicModelMultipleChoiceField(queryset=Platform.objects.all(), to_field_name="name", required=False)
|
|
291
290
|
cluster_group = DynamicModelMultipleChoiceField(
|
|
292
|
-
queryset=ClusterGroup.objects.all(), to_field_name="
|
|
291
|
+
queryset=ClusterGroup.objects.all(), to_field_name="name", required=False
|
|
293
292
|
)
|
|
294
293
|
cluster_id = DynamicModelMultipleChoiceField(queryset=Cluster.objects.all(), required=False, label="Cluster")
|
|
295
294
|
tenant_group = DynamicModelMultipleChoiceField(
|
|
296
|
-
queryset=TenantGroup.objects.all(), to_field_name="
|
|
295
|
+
queryset=TenantGroup.objects.all(), to_field_name="name", required=False
|
|
297
296
|
)
|
|
298
|
-
tenant = DynamicModelMultipleChoiceField(queryset=Tenant.objects.all(), to_field_name="
|
|
297
|
+
tenant = DynamicModelMultipleChoiceField(queryset=Tenant.objects.all(), to_field_name="name", required=False)
|
|
299
298
|
device_redundancy_group = DynamicModelMultipleChoiceField(
|
|
300
|
-
queryset=DeviceRedundancyGroup.objects.all(), to_field_name="
|
|
299
|
+
queryset=DeviceRedundancyGroup.objects.all(), to_field_name="name", required=False
|
|
301
300
|
)
|
|
302
301
|
tag = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), to_field_name="slug", required=False)
|
|
303
302
|
dynamic_groups = DynamicModelMultipleChoiceField(
|
|
304
|
-
queryset=DynamicGroup.objects.all(), to_field_name="
|
|
303
|
+
queryset=DynamicGroup.objects.all(), to_field_name="name", required=False
|
|
305
304
|
)
|
|
306
305
|
|
|
307
306
|
def __init__(self, *args, **kwargs):
|
|
@@ -401,9 +400,21 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm):
|
|
|
401
400
|
"validation_regex",
|
|
402
401
|
)
|
|
403
402
|
|
|
403
|
+
def __init__(self, *args, **kwargs):
|
|
404
|
+
super().__init__(*args, **kwargs)
|
|
405
|
+
|
|
406
|
+
if self.instance and self.instance.present_in_database:
|
|
407
|
+
self.fields["key"].widget.attrs["readonly"] = True
|
|
408
|
+
|
|
404
409
|
|
|
405
410
|
class CustomFieldModelCSVForm(CSVModelForm, CustomFieldModelFormMixin):
|
|
406
|
-
"""
|
|
411
|
+
"""
|
|
412
|
+
Base class for CSV/JSON/YAML import of models that support custom fields.
|
|
413
|
+
|
|
414
|
+
TODO: The class name is a misnomer; as of 2.0 this class is **not** used for any CSV imports,
|
|
415
|
+
as that's now handled by the REST API. However it is still used when importing component-templates as
|
|
416
|
+
part of a JSON/YAML DeviceType import.
|
|
417
|
+
"""
|
|
407
418
|
|
|
408
419
|
def _append_customfield_fields(self):
|
|
409
420
|
# Append form fields
|
|
@@ -464,7 +475,6 @@ class CustomLinkFilterForm(BootstrapMixin, forms.Form):
|
|
|
464
475
|
class DynamicGroupForm(NautobotModelForm):
|
|
465
476
|
"""DynamicGroup model form."""
|
|
466
477
|
|
|
467
|
-
slug = SlugField()
|
|
468
478
|
content_type = CSVContentTypeField(
|
|
469
479
|
queryset=ContentType.objects.filter(FeatureQuery("dynamic_groups").get_query()).order_by("app_label", "model"),
|
|
470
480
|
label="Content Type",
|
|
@@ -474,7 +484,6 @@ class DynamicGroupForm(NautobotModelForm):
|
|
|
474
484
|
model = DynamicGroup
|
|
475
485
|
fields = [
|
|
476
486
|
"name",
|
|
477
|
-
"slug",
|
|
478
487
|
"description",
|
|
479
488
|
"content_type",
|
|
480
489
|
]
|
|
@@ -613,36 +622,24 @@ class GitRepositoryForm(BootstrapMixin, RelationshipModelFormMixin):
|
|
|
613
622
|
"tags",
|
|
614
623
|
]
|
|
615
624
|
|
|
616
|
-
def
|
|
617
|
-
super().
|
|
618
|
-
|
|
619
|
-
# set dryrun after a successful clean
|
|
620
|
-
if "_dryrun_create" in self.data or "_dryrun_update" in self.data:
|
|
621
|
-
self.instance.set_dryrun()
|
|
625
|
+
def __init__(self, *args, **kwargs):
|
|
626
|
+
super().__init__(*args, **kwargs)
|
|
622
627
|
|
|
628
|
+
if self.instance and self.instance.present_in_database:
|
|
629
|
+
self.fields["slug"].widget.attrs["readonly"] = True
|
|
623
630
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
queryset=SecretsGroup.objects.all(),
|
|
627
|
-
to_field_name="name",
|
|
628
|
-
required=False,
|
|
629
|
-
help_text="Secrets group for repository access (if any)",
|
|
630
|
-
)
|
|
631
|
+
def save(self, commit=True):
|
|
632
|
+
instance = super().save(commit=commit)
|
|
631
633
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
634
|
+
# TODO(jathan): Move sync() call out of the form and into the view. However, in v2 UI this
|
|
635
|
+
# probably just goes away since UI views will be making API calls. For now, the user is
|
|
636
|
+
# magically stored on the instance by the view code.
|
|
637
|
+
if commit:
|
|
638
|
+
# Set dryrun if that button was clicked in the UI, otherwise perform a normal sync.
|
|
639
|
+
dry_run = "_dryrun_create" in self.data or "_dryrun_update" in self.data
|
|
640
|
+
instance.sync(user=instance.user, dry_run=dry_run)
|
|
635
641
|
|
|
636
|
-
|
|
637
|
-
super().__init__(*args, **kwargs)
|
|
638
|
-
self.fields["provided_contents"] = CSVMultipleChoiceField(
|
|
639
|
-
choices=get_git_datasource_content_choices(),
|
|
640
|
-
required=False,
|
|
641
|
-
help_text=mark_safe(
|
|
642
|
-
"The data types this repository provides. Multiple values must be comma-separated and wrapped in "
|
|
643
|
-
'double quotes (e.g. <code>"extras.job,extras.configcontext"</code>).'
|
|
644
|
-
),
|
|
645
|
-
)
|
|
642
|
+
return instance
|
|
646
643
|
|
|
647
644
|
|
|
648
645
|
class GitRepositoryBulkEditForm(NautobotBulkEditForm):
|
|
@@ -682,14 +679,12 @@ class GitRepositoryFilterForm(BootstrapMixin, forms.Form):
|
|
|
682
679
|
|
|
683
680
|
|
|
684
681
|
class GraphQLQueryForm(BootstrapMixin, forms.ModelForm):
|
|
685
|
-
slug = SlugField()
|
|
686
682
|
query = TextField()
|
|
687
683
|
|
|
688
684
|
class Meta:
|
|
689
685
|
model = GraphQLQuery
|
|
690
686
|
fields = (
|
|
691
687
|
"name",
|
|
692
|
-
"slug",
|
|
693
688
|
"query",
|
|
694
689
|
)
|
|
695
690
|
|
|
@@ -727,11 +722,11 @@ class JobForm(BootstrapMixin, forms.Form):
|
|
|
727
722
|
controlled by the job definition. See `nautobot.extras.jobs.BaseJob.as_form`
|
|
728
723
|
"""
|
|
729
724
|
|
|
730
|
-
|
|
725
|
+
_profile = forms.BooleanField(
|
|
731
726
|
required=False,
|
|
732
|
-
initial=
|
|
733
|
-
label="
|
|
734
|
-
help_text="
|
|
727
|
+
initial=False,
|
|
728
|
+
label="Profile job execution",
|
|
729
|
+
help_text="Profiles the job execution using cProfile and outputs a report to /tmp/",
|
|
735
730
|
)
|
|
736
731
|
_task_queue = forms.ChoiceField(
|
|
737
732
|
required=False,
|
|
@@ -742,27 +737,16 @@ class JobForm(BootstrapMixin, forms.Form):
|
|
|
742
737
|
def __init__(self, *args, **kwargs):
|
|
743
738
|
super().__init__(*args, **kwargs)
|
|
744
739
|
|
|
745
|
-
# Move
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
self.fields["_commit"] = commit
|
|
750
|
-
|
|
751
|
-
@property
|
|
752
|
-
def requires_input(self):
|
|
753
|
-
"""
|
|
754
|
-
A boolean indicating whether the form requires user input (ignore the _commit field).
|
|
755
|
-
"""
|
|
756
|
-
return bool(len(self.fields) > 1)
|
|
740
|
+
# Move special fields to the end of the form
|
|
741
|
+
for field in ["_task_queue", "_profile"]:
|
|
742
|
+
value = self.fields.pop(field)
|
|
743
|
+
self.fields[field] = value
|
|
757
744
|
|
|
758
745
|
|
|
759
746
|
class JobEditForm(NautobotModelForm):
|
|
760
|
-
slug = SlugField()
|
|
761
|
-
|
|
762
747
|
class Meta:
|
|
763
748
|
model = Job
|
|
764
749
|
fields = [
|
|
765
|
-
"slug",
|
|
766
750
|
"enabled",
|
|
767
751
|
"name_override",
|
|
768
752
|
"name",
|
|
@@ -770,12 +754,10 @@ class JobEditForm(NautobotModelForm):
|
|
|
770
754
|
"grouping",
|
|
771
755
|
"description_override",
|
|
772
756
|
"description",
|
|
773
|
-
"
|
|
774
|
-
"
|
|
757
|
+
"dryrun_default_override",
|
|
758
|
+
"dryrun_default",
|
|
775
759
|
"hidden_override",
|
|
776
760
|
"hidden",
|
|
777
|
-
"read_only_override",
|
|
778
|
-
"read_only",
|
|
779
761
|
"approval_required_override",
|
|
780
762
|
"approval_required",
|
|
781
763
|
"soft_time_limit_override",
|
|
@@ -814,7 +796,7 @@ class JobFilterForm(BootstrapMixin, forms.Form):
|
|
|
814
796
|
has_sensitive_variables = forms.NullBooleanField(
|
|
815
797
|
required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES)
|
|
816
798
|
)
|
|
817
|
-
|
|
799
|
+
dryrun_default = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES))
|
|
818
800
|
hidden = forms.NullBooleanField(
|
|
819
801
|
initial=False,
|
|
820
802
|
required=False,
|
|
@@ -1142,7 +1124,12 @@ class ObjectChangeFilterForm(BootstrapMixin, forms.Form):
|
|
|
1142
1124
|
|
|
1143
1125
|
|
|
1144
1126
|
class RelationshipForm(BootstrapMixin, forms.ModelForm):
|
|
1145
|
-
|
|
1127
|
+
key = SlugField(
|
|
1128
|
+
help_text="Internal name of this relationship. Please use underscores rather than dashes.",
|
|
1129
|
+
label="Key",
|
|
1130
|
+
max_length=50,
|
|
1131
|
+
slug_source="label",
|
|
1132
|
+
)
|
|
1146
1133
|
source_type = forms.ModelChoiceField(
|
|
1147
1134
|
queryset=ContentType.objects.filter(FeatureQuery("relationships").get_query()).order_by("app_label", "model"),
|
|
1148
1135
|
help_text="The source object type to which this relationship applies.",
|
|
@@ -1165,8 +1152,8 @@ class RelationshipForm(BootstrapMixin, forms.ModelForm):
|
|
|
1165
1152
|
class Meta:
|
|
1166
1153
|
model = Relationship
|
|
1167
1154
|
fields = [
|
|
1168
|
-
"
|
|
1169
|
-
"
|
|
1155
|
+
"label",
|
|
1156
|
+
"key",
|
|
1170
1157
|
"description",
|
|
1171
1158
|
"type",
|
|
1172
1159
|
"required_on",
|
|
@@ -1181,6 +1168,12 @@ class RelationshipForm(BootstrapMixin, forms.ModelForm):
|
|
|
1181
1168
|
"destination_filter",
|
|
1182
1169
|
]
|
|
1183
1170
|
|
|
1171
|
+
def __init__(self, *args, **kwargs):
|
|
1172
|
+
super().__init__(*args, **kwargs)
|
|
1173
|
+
|
|
1174
|
+
if self.instance and self.instance.present_in_database:
|
|
1175
|
+
self.fields["key"].widget.attrs["readonly"] = True
|
|
1176
|
+
|
|
1184
1177
|
def save(self, commit=True):
|
|
1185
1178
|
# TODO add support for owner when a CR is created in the UI
|
|
1186
1179
|
obj = super().save(commit)
|
|
@@ -1207,7 +1200,7 @@ class RelationshipAssociationFilterForm(BootstrapMixin, forms.Form):
|
|
|
1207
1200
|
|
|
1208
1201
|
relationship = DynamicModelMultipleChoiceField(
|
|
1209
1202
|
queryset=Relationship.objects.all(),
|
|
1210
|
-
to_field_name="
|
|
1203
|
+
to_field_name="key",
|
|
1211
1204
|
required=False,
|
|
1212
1205
|
)
|
|
1213
1206
|
|
|
@@ -1228,7 +1221,6 @@ class RelationshipAssociationFilterForm(BootstrapMixin, forms.Form):
|
|
|
1228
1221
|
class RoleForm(NautobotModelForm):
|
|
1229
1222
|
"""Generic create/update form for `Role` objects."""
|
|
1230
1223
|
|
|
1231
|
-
slug = SlugField()
|
|
1232
1224
|
content_types = MultipleContentTypeField(
|
|
1233
1225
|
required=False,
|
|
1234
1226
|
label="Content Type(s)",
|
|
@@ -1238,7 +1230,7 @@ class RoleForm(NautobotModelForm):
|
|
|
1238
1230
|
class Meta:
|
|
1239
1231
|
model = Role
|
|
1240
1232
|
widgets = {"color": ColorSelect()}
|
|
1241
|
-
fields = ["name", "
|
|
1233
|
+
fields = ["name", "weight", "description", "content_types", "color"]
|
|
1242
1234
|
|
|
1243
1235
|
|
|
1244
1236
|
class RoleBulkEditForm(NautobotBulkEditForm):
|
|
@@ -1254,28 +1246,6 @@ class RoleBulkEditForm(NautobotBulkEditForm):
|
|
|
1254
1246
|
nullable_fields = ["weight"]
|
|
1255
1247
|
|
|
1256
1248
|
|
|
1257
|
-
class RoleCSVForm(CustomFieldModelCSVForm):
|
|
1258
|
-
"""Generic CSV bulk import form for `Role` objects."""
|
|
1259
|
-
|
|
1260
|
-
content_types = CSVMultipleContentTypeField(
|
|
1261
|
-
queryset=RoleModelsQuery().as_queryset(),
|
|
1262
|
-
choices_as_strings=True,
|
|
1263
|
-
help_text=mark_safe(
|
|
1264
|
-
"The object types to which this role applies. Multiple values "
|
|
1265
|
-
"must be comma-separated and wrapped in double quotes. (e.g. "
|
|
1266
|
-
'<code>"dcim.device,dcim.rack"</code>)'
|
|
1267
|
-
),
|
|
1268
|
-
label="Content type(s)",
|
|
1269
|
-
)
|
|
1270
|
-
|
|
1271
|
-
class Meta:
|
|
1272
|
-
model = Role
|
|
1273
|
-
fields = ["name", "slug", "weight", "color", "content_types", "description"]
|
|
1274
|
-
help_texts = {
|
|
1275
|
-
"color": mark_safe("RGB color in hexadecimal (e.g. <code>00ff00</code>)"),
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
1249
|
#
|
|
1280
1250
|
# Secrets
|
|
1281
1251
|
#
|
|
@@ -1288,8 +1258,6 @@ def provider_choices():
|
|
|
1288
1258
|
class SecretForm(NautobotModelForm):
|
|
1289
1259
|
"""Create/update form for `Secret` objects."""
|
|
1290
1260
|
|
|
1291
|
-
slug = SlugField()
|
|
1292
|
-
|
|
1293
1261
|
provider = forms.ChoiceField(choices=provider_choices, widget=StaticSelect2())
|
|
1294
1262
|
|
|
1295
1263
|
parameters = JSONField(help_text='Enter parameters in <a href="https://json.org/">JSON</a> format.')
|
|
@@ -1298,7 +1266,6 @@ class SecretForm(NautobotModelForm):
|
|
|
1298
1266
|
model = Secret
|
|
1299
1267
|
fields = [
|
|
1300
1268
|
"name",
|
|
1301
|
-
"slug",
|
|
1302
1269
|
"description",
|
|
1303
1270
|
"provider",
|
|
1304
1271
|
"parameters",
|
|
@@ -1306,12 +1273,6 @@ class SecretForm(NautobotModelForm):
|
|
|
1306
1273
|
]
|
|
1307
1274
|
|
|
1308
1275
|
|
|
1309
|
-
class SecretCSVForm(CustomFieldModelCSVForm):
|
|
1310
|
-
class Meta:
|
|
1311
|
-
model = Secret
|
|
1312
|
-
fields = Secret.csv_headers
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
1276
|
def provider_choices_with_blank():
|
|
1316
1277
|
return add_blank_choice(sorted([(slug, provider.name) for slug, provider in registry["secrets_providers"].items()]))
|
|
1317
1278
|
|
|
@@ -1342,13 +1303,10 @@ SecretsGroupAssociationFormSet = inlineformset_factory(
|
|
|
1342
1303
|
class SecretsGroupForm(NautobotModelForm):
|
|
1343
1304
|
"""Create/update form for `SecretsGroup` objects."""
|
|
1344
1305
|
|
|
1345
|
-
slug = SlugField()
|
|
1346
|
-
|
|
1347
1306
|
class Meta:
|
|
1348
1307
|
model = SecretsGroup
|
|
1349
1308
|
fields = [
|
|
1350
1309
|
"name",
|
|
1351
|
-
"slug",
|
|
1352
1310
|
"description",
|
|
1353
1311
|
]
|
|
1354
1312
|
|
|
@@ -1366,35 +1324,12 @@ class SecretsGroupFilterForm(NautobotFilterForm):
|
|
|
1366
1324
|
class StatusForm(NautobotModelForm):
|
|
1367
1325
|
"""Generic create/update form for `Status` objects."""
|
|
1368
1326
|
|
|
1369
|
-
slug = SlugField()
|
|
1370
1327
|
content_types = MultipleContentTypeField(feature="statuses", label="Content Type(s)")
|
|
1371
1328
|
|
|
1372
1329
|
class Meta:
|
|
1373
1330
|
model = Status
|
|
1374
1331
|
widgets = {"color": ColorSelect()}
|
|
1375
|
-
fields = ["name", "
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
class StatusCSVForm(CustomFieldModelCSVForm):
|
|
1379
|
-
"""Generic CSV bulk import form for `Status` objects."""
|
|
1380
|
-
|
|
1381
|
-
content_types = CSVMultipleContentTypeField(
|
|
1382
|
-
feature="statuses",
|
|
1383
|
-
choices_as_strings=True,
|
|
1384
|
-
help_text=mark_safe(
|
|
1385
|
-
"The object types to which this status applies. Multiple values "
|
|
1386
|
-
"must be comma-separated and wrapped in double quotes. (e.g. "
|
|
1387
|
-
'<code>"dcim.device,dcim.rack"</code>)'
|
|
1388
|
-
),
|
|
1389
|
-
label="Content type(s)",
|
|
1390
|
-
)
|
|
1391
|
-
|
|
1392
|
-
class Meta:
|
|
1393
|
-
model = Status
|
|
1394
|
-
fields = Status.csv_headers
|
|
1395
|
-
help_texts = {
|
|
1396
|
-
"color": mark_safe("RGB color in hexadecimal (e.g. <code>00ff00</code>)"),
|
|
1397
|
-
}
|
|
1332
|
+
fields = ["name", "description", "content_types", "color"]
|
|
1398
1333
|
|
|
1399
1334
|
|
|
1400
1335
|
class StatusFilterForm(NautobotFilterForm):
|
|
@@ -1449,17 +1384,6 @@ class TagForm(NautobotModelForm):
|
|
|
1449
1384
|
return data
|
|
1450
1385
|
|
|
1451
1386
|
|
|
1452
|
-
class TagCSVForm(CustomFieldModelCSVForm):
|
|
1453
|
-
slug = SlugField()
|
|
1454
|
-
|
|
1455
|
-
class Meta:
|
|
1456
|
-
model = Tag
|
|
1457
|
-
fields = Tag.csv_headers
|
|
1458
|
-
help_texts = {
|
|
1459
|
-
"color": mark_safe("RGB color in hexadecimal (e.g. <code>00ff00</code>)"),
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
1387
|
class TagFilterForm(NautobotFilterForm):
|
|
1464
1388
|
model = Tag
|
|
1465
1389
|
q = forms.CharField(required=False, label="Search")
|
nautobot/extras/forms/mixins.py
CHANGED
|
@@ -8,8 +8,6 @@ from django.db.models import Q
|
|
|
8
8
|
from nautobot.core.forms import (
|
|
9
9
|
BulkEditForm,
|
|
10
10
|
CommentField,
|
|
11
|
-
CSVModelChoiceField,
|
|
12
|
-
CSVModelForm,
|
|
13
11
|
DynamicModelChoiceField,
|
|
14
12
|
DynamicModelMultipleChoiceField,
|
|
15
13
|
)
|
|
@@ -44,7 +42,6 @@ __all__ = (
|
|
|
44
42
|
"RelationshipModelFormMixin",
|
|
45
43
|
"StatusModelBulkEditFormMixin",
|
|
46
44
|
"StatusModelFilterFormMixin",
|
|
47
|
-
"StatusModelCSVFormMixin",
|
|
48
45
|
"TagsBulkEditFormMixin",
|
|
49
46
|
# 2.0 TODO: remove the below deprecated aliases
|
|
50
47
|
"AddRemoveTagsForm",
|
|
@@ -53,9 +50,7 @@ __all__ = (
|
|
|
53
50
|
"CustomFieldModelForm",
|
|
54
51
|
"RelationshipModelForm",
|
|
55
52
|
"RoleModelBulkEditFormMixin",
|
|
56
|
-
"RoleModelCSVFormMixin",
|
|
57
53
|
"RoleModelFilterFormMixin",
|
|
58
|
-
"RoleRequiredRoleModelCSVFormMixin",
|
|
59
54
|
"StatusBulkEditFormMixin",
|
|
60
55
|
"StatusFilterFormMixin",
|
|
61
56
|
)
|
|
@@ -214,10 +209,10 @@ class RelationshipModelBulkEditFormMixin(BulkEditForm):
|
|
|
214
209
|
peer_side = RelationshipSideChoices.OPPOSITE[side]
|
|
215
210
|
|
|
216
211
|
# If this model is on the "source" side of the relationship, then the field will be named
|
|
217
|
-
# "cr_<
|
|
218
|
-
# If we're on the "destination" side, the field will be "cr_<
|
|
219
|
-
# For a symmetric relationship, both sides are "peer", so the field will be "cr_<
|
|
220
|
-
field_name = f"cr_{relationship.
|
|
212
|
+
# "cr_<relationship_key>__destination" since it's used to pick the destination object(s).
|
|
213
|
+
# If we're on the "destination" side, the field will be "cr_<relationship_key>__source".
|
|
214
|
+
# For a symmetric relationship, both sides are "peer", so the field will be "cr_<relationship_key>__peer"
|
|
215
|
+
field_name = f"cr_{relationship.key}__{peer_side}"
|
|
221
216
|
|
|
222
217
|
if field_name in self.relationships:
|
|
223
218
|
# This is a symmetric relationship that we already processed from the opposing "initial_side".
|
|
@@ -257,7 +252,7 @@ class RelationshipModelBulkEditFormMixin(BulkEditForm):
|
|
|
257
252
|
for side, relationships_data in instance_relationships.items():
|
|
258
253
|
peer_side = RelationshipSideChoices.OPPOSITE[side]
|
|
259
254
|
for relationship, relationshipassociation_queryset in relationships_data.items():
|
|
260
|
-
field_name = f"cr_{relationship.
|
|
255
|
+
field_name = f"cr_{relationship.key}__{peer_side}"
|
|
261
256
|
logger.debug(
|
|
262
257
|
"Processing relationship %s %s (field %s) for instance %s",
|
|
263
258
|
relationship,
|
|
@@ -347,22 +342,25 @@ class RelationshipModelBulkEditFormMixin(BulkEditForm):
|
|
|
347
342
|
def clean(self):
|
|
348
343
|
# Get any initial required relationship objects errors (i.e. non-existent required objects)
|
|
349
344
|
required_objects_errors = self.model.required_related_objects_errors(output_for="ui")
|
|
350
|
-
|
|
345
|
+
already_invalidated_keys = []
|
|
351
346
|
for field, errors in required_objects_errors.items():
|
|
352
347
|
self.add_error(None, errors)
|
|
353
|
-
|
|
354
|
-
|
|
348
|
+
# rindex() find the last occurrence of "__" which is
|
|
349
|
+
# guaranteed to be cr_{key}__source, cr_{key}__destination, or cr_{key}__peer
|
|
350
|
+
# regardless of how {key} is formatted
|
|
351
|
+
relationship_key = field[: field.rindex("__")][3:]
|
|
352
|
+
already_invalidated_keys.append(relationship_key)
|
|
355
353
|
|
|
356
354
|
required_relationships = []
|
|
357
355
|
# The following query excludes already invalidated relationships (this happened above
|
|
358
356
|
# by checking for the existence of required objects
|
|
359
357
|
# with the call to self.Meta().model.required_related_objects_errors(output_for="ui"))
|
|
360
358
|
for relationship in Relationship.objects.get_required_for_model(self.model).exclude(
|
|
361
|
-
|
|
359
|
+
key__in=already_invalidated_keys
|
|
362
360
|
):
|
|
363
361
|
required_relationships.append(
|
|
364
362
|
{
|
|
365
|
-
"
|
|
363
|
+
"key": relationship.key,
|
|
366
364
|
"required_side": RelationshipSideChoices.OPPOSITE[relationship.required_on],
|
|
367
365
|
"relationship": relationship,
|
|
368
366
|
}
|
|
@@ -371,7 +369,7 @@ class RelationshipModelBulkEditFormMixin(BulkEditForm):
|
|
|
371
369
|
# Get difference of add/remove objects for each required relationship:
|
|
372
370
|
required_relationships_to_check = []
|
|
373
371
|
for required_relationship in required_relationships:
|
|
374
|
-
required_field = f"cr_{required_relationship['
|
|
372
|
+
required_field = f"cr_{required_relationship['key']}__{required_relationship['required_side']}"
|
|
375
373
|
|
|
376
374
|
add_list = []
|
|
377
375
|
if f"add_{required_field}" in self.cleaned_data:
|
|
@@ -456,10 +454,10 @@ class RelationshipModelFormMixin(forms.ModelForm):
|
|
|
456
454
|
for relationship, queryset in relationships.items():
|
|
457
455
|
peer_side = RelationshipSideChoices.OPPOSITE[side]
|
|
458
456
|
# If this model is on the "source" side of the relationship, then the field will be named
|
|
459
|
-
# cr_<
|
|
460
|
-
# If we're on the "destination" side, the field will be cr_<
|
|
461
|
-
# For a symmetric relationship, both sides are "peer", so the field will be cr_<
|
|
462
|
-
field_name = f"cr_{relationship.
|
|
457
|
+
# cr_<relationship_key>__destination since it's used to pick the destination object(s).
|
|
458
|
+
# If we're on the "destination" side, the field will be cr_<relationship_key>__source.
|
|
459
|
+
# For a symmetric relationship, both sides are "peer", so the field will be cr_<relationship_key>__peer
|
|
460
|
+
field_name = f"cr_{relationship.key}__{peer_side}"
|
|
463
461
|
self.fields[field_name] = relationship.to_form_field(side=side)
|
|
464
462
|
|
|
465
463
|
# HTML5 validation for required relationship field:
|
|
@@ -501,7 +499,7 @@ class RelationshipModelFormMixin(forms.ModelForm):
|
|
|
501
499
|
for relationship in relationships:
|
|
502
500
|
# The form field name reflects what it provides, i.e. the peer object(s) to link via this relationship.
|
|
503
501
|
peer_side = RelationshipSideChoices.OPPOSITE[side]
|
|
504
|
-
field_name = f"cr_{relationship.
|
|
502
|
+
field_name = f"cr_{relationship.key}__{peer_side}"
|
|
505
503
|
|
|
506
504
|
# Is the form trying to set this field (create/update a RelationshipAssociation(s))?
|
|
507
505
|
# If not (that is, clearing the field / deleting RelationshipAssociation(s)), we don't need to check.
|
|
@@ -649,11 +647,16 @@ class RelationshipModelFilterFormMixin(forms.Form):
|
|
|
649
647
|
"""
|
|
650
648
|
Append form fields for all Relationships assigned to this model.
|
|
651
649
|
"""
|
|
652
|
-
|
|
653
|
-
|
|
650
|
+
query = Q(source_type=self.obj_type, source_hidden=False) | Q(
|
|
651
|
+
destination_type=self.obj_type, destination_hidden=False
|
|
652
|
+
)
|
|
653
|
+
relationships = Relationship.objects.select_related("source_type", "destination_type").filter(query)
|
|
654
654
|
|
|
655
|
-
|
|
656
|
-
|
|
655
|
+
for rel in relationships.iterator():
|
|
656
|
+
if rel.source_type == self.obj_type and not rel.source_hidden:
|
|
657
|
+
self._append_relationships_side([rel], RelationshipSideChoices.SIDE_SOURCE)
|
|
658
|
+
if rel.destination_type == self.obj_type and not rel.destination_hidden:
|
|
659
|
+
self._append_relationships_side([rel], RelationshipSideChoices.SIDE_DESTINATION)
|
|
657
660
|
|
|
658
661
|
def _append_relationships_side(self, relationships, initial_side):
|
|
659
662
|
"""
|
|
@@ -667,10 +670,10 @@ class RelationshipModelFilterFormMixin(forms.Form):
|
|
|
667
670
|
peer_side = RelationshipSideChoices.OPPOSITE[side]
|
|
668
671
|
|
|
669
672
|
# If this model is on the "source" side of the relationship, then the field will be named
|
|
670
|
-
# "cr_<
|
|
671
|
-
# If we're on the "destination" side, the field will be "cr_<
|
|
672
|
-
# For a symmetric relationship, both sides are "peer", so the field will be "cr_<
|
|
673
|
-
field_name = f"cr_{relationship.
|
|
673
|
+
# "cr_<relationship_key>__destination" since it's used to pick the destination object(s).
|
|
674
|
+
# If we're on the "destination" side, the field will be "cr_<relationship_key>__source".
|
|
675
|
+
# For a symmetric relationship, both sides are "peer", so the field will be "cr_<relationship_key>__peer"
|
|
676
|
+
field_name = f"cr_{relationship.key}__{peer_side}"
|
|
674
677
|
|
|
675
678
|
if field_name in self.relationships:
|
|
676
679
|
# This is a symmetric relationship that we already processed from the opposing "initial_side".
|
|
@@ -710,27 +713,11 @@ class RoleModelFilterFormMixin(forms.Form):
|
|
|
710
713
|
required=False,
|
|
711
714
|
queryset=Role.objects.all(),
|
|
712
715
|
query_params={"content_types": self.model._meta.label_lower},
|
|
713
|
-
to_field_name="
|
|
716
|
+
to_field_name="name",
|
|
714
717
|
)
|
|
715
718
|
self.order_fields(self.field_order) # Reorder fields again
|
|
716
719
|
|
|
717
720
|
|
|
718
|
-
class RoleModelCSVFormMixin(CSVModelForm):
|
|
719
|
-
"""Mixin to add a non-required `role` choice field to CSV import forms."""
|
|
720
|
-
|
|
721
|
-
role = CSVModelChoiceField(
|
|
722
|
-
queryset=Role.objects.all(), to_field_name="name", required=False, help_text="Assigned role"
|
|
723
|
-
)
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
class RoleRequiredRoleModelCSVFormMixin(CSVModelForm):
|
|
727
|
-
"""Mixin to add a required `role` choice field to CSV import forms."""
|
|
728
|
-
|
|
729
|
-
role = CSVModelChoiceField(
|
|
730
|
-
queryset=Role.objects.all(), to_field_name="name", required=True, help_text="Assigned role"
|
|
731
|
-
)
|
|
732
|
-
|
|
733
|
-
|
|
734
721
|
class StatusModelBulkEditFormMixin(forms.Form):
|
|
735
722
|
"""Mixin to add non-required `status` choice field to forms."""
|
|
736
723
|
|
|
@@ -755,21 +742,11 @@ class StatusModelFilterFormMixin(forms.Form):
|
|
|
755
742
|
required=False,
|
|
756
743
|
queryset=Status.objects.all(),
|
|
757
744
|
query_params={"content_types": self.model._meta.label_lower},
|
|
758
|
-
to_field_name="
|
|
745
|
+
to_field_name="name",
|
|
759
746
|
)
|
|
760
747
|
self.order_fields(self.field_order) # Reorder fields again
|
|
761
748
|
|
|
762
749
|
|
|
763
|
-
class StatusModelCSVFormMixin(CSVModelForm):
|
|
764
|
-
"""Mixin to add a required `status` choice field to CSV import forms."""
|
|
765
|
-
|
|
766
|
-
status = CSVModelChoiceField(
|
|
767
|
-
queryset=Status.objects.all(),
|
|
768
|
-
to_field_name="slug",
|
|
769
|
-
help_text="Operational status",
|
|
770
|
-
)
|
|
771
|
-
|
|
772
|
-
|
|
773
750
|
class TagsBulkEditFormMixin(forms.Form):
|
|
774
751
|
def __init__(self, *args, **kwargs):
|
|
775
752
|
super().__init__(*args, **kwargs)
|