nautobot 2.2.9__py3-none-any.whl → 2.3.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.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/forms.py +4 -0
- nautobot/apps/models.py +10 -1
- nautobot/circuits/__init__.py +0 -1
- nautobot/circuits/apps.py +1 -0
- nautobot/circuits/factory.py +15 -3
- nautobot/circuits/filters.py +13 -0
- nautobot/circuits/forms.py +13 -0
- nautobot/circuits/migrations/0021_alter_circuit_status_alter_circuittermination__path.py +32 -0
- nautobot/circuits/migrations/0022_circuittermination_cloud_network.py +25 -0
- nautobot/circuits/models.py +16 -3
- nautobot/circuits/tables.py +16 -2
- nautobot/circuits/templates/circuits/circuittermination_create.html +10 -2
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +6 -0
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -1
- nautobot/circuits/tests/test_api.py +7 -5
- nautobot/circuits/tests/test_filters.py +12 -5
- nautobot/circuits/tests/test_models.py +33 -2
- nautobot/circuits/views.py +2 -3
- nautobot/cloud/__init__.py +0 -0
- nautobot/cloud/api/__init__.py +0 -0
- nautobot/cloud/api/serializers.py +54 -0
- nautobot/cloud/api/urls.py +16 -0
- nautobot/cloud/api/views.py +48 -0
- nautobot/cloud/apps.py +13 -0
- nautobot/cloud/factory.py +111 -0
- nautobot/cloud/filters.py +184 -0
- nautobot/cloud/forms.py +333 -0
- nautobot/cloud/homepage.py +43 -0
- nautobot/cloud/migrations/0001_initial.py +304 -0
- nautobot/cloud/migrations/__init__.py +0 -0
- nautobot/cloud/models.py +247 -0
- nautobot/cloud/navigation.py +85 -0
- nautobot/cloud/tables.py +173 -0
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +43 -0
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +128 -0
- nautobot/cloud/templates/cloud/cloudnetwork_update.html +33 -0
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +100 -0
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +65 -0
- nautobot/cloud/templates/cloud/cloudservice_update.html +25 -0
- nautobot/cloud/tests/__init__.py +0 -0
- nautobot/cloud/tests/test_api.py +248 -0
- nautobot/cloud/tests/test_filters.py +113 -0
- nautobot/cloud/tests/test_models.py +43 -0
- nautobot/cloud/tests/test_views.py +153 -0
- nautobot/cloud/urls.py +14 -0
- nautobot/cloud/views.py +181 -0
- nautobot/core/__init__.py +0 -3
- nautobot/core/api/metadata.py +1 -0
- nautobot/core/api/parsers.py +7 -1
- nautobot/core/api/urls.py +1 -0
- nautobot/core/api/utils.py +1 -0
- nautobot/core/api/views.py +4 -0
- nautobot/core/apps/__init__.py +6 -3
- nautobot/core/constants.py +8 -0
- nautobot/core/factory.py +32 -1
- nautobot/core/filters.py +96 -28
- nautobot/core/forms/fields.py +10 -4
- nautobot/core/forms/forms.py +1 -1
- nautobot/core/forms/widgets.py +18 -1
- nautobot/core/graphql/generators.py +2 -2
- nautobot/core/graphql/schema.py +34 -4
- nautobot/core/jobs/__init__.py +17 -6
- nautobot/core/jobs/cleanup.py +100 -0
- nautobot/core/jobs/groups.py +38 -0
- nautobot/core/management/commands/generate_test_data.py +116 -3
- nautobot/core/models/__init__.py +34 -9
- nautobot/core/models/generics.py +19 -3
- nautobot/core/models/name_color_content_types.py +7 -28
- nautobot/core/models/querysets.py +4 -3
- nautobot/core/models/tree_queries.py +1 -1
- nautobot/core/models/utils.py +21 -5
- nautobot/core/settings.py +4 -30
- nautobot/core/settings.yaml +34 -27
- nautobot/core/settings_funcs.py +103 -0
- nautobot/core/tables.py +127 -56
- nautobot/core/templates/admin/search_form.html +1 -1
- nautobot/core/templates/buttons/add.html +11 -3
- nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +13 -0
- nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +13 -0
- nautobot/core/templates/buttons/export.html +101 -53
- nautobot/core/templates/buttons/job_import.html +11 -3
- nautobot/core/templates/generic/object_bulk_destroy.html +3 -1
- nautobot/core/templates/generic/object_bulk_update.html +3 -1
- nautobot/core/templates/generic/object_changelog.html +0 -9
- nautobot/core/templates/generic/object_list.html +156 -17
- nautobot/core/templates/generic/object_retrieve.html +80 -16
- nautobot/core/templates/inc/extras_features_edit_form_fields.html +8 -0
- nautobot/core/templates/inc/javascript.html +2 -0
- nautobot/core/templates/inc/media.html +2 -2
- nautobot/core/templates/inc/nav_menu.html +1 -0
- nautobot/core/templates/inc/paginator.html +7 -7
- nautobot/core/templates/inc/search_panel.html +2 -2
- nautobot/core/templates/inc/table.html +2 -2
- nautobot/core/templates/nautobot_config.py.j2 +13 -23
- nautobot/core/templates/utilities/templatetags/dynamic_group_assignment_modal.html +37 -0
- nautobot/core/templates/utilities/templatetags/filter_form_modal.html +2 -2
- nautobot/core/templates/utilities/templatetags/saved_view_modal.html +38 -0
- nautobot/core/templates/utilities/theme_preview.html +25 -8
- nautobot/core/templates/utilities/worker_status.html +152 -0
- nautobot/core/templatetags/buttons.py +335 -38
- nautobot/core/templatetags/form_helpers.py +1 -1
- nautobot/core/templatetags/helpers.py +181 -11
- nautobot/core/testing/api.py +5 -4
- nautobot/core/testing/filters.py +51 -13
- nautobot/core/testing/mixins.py +46 -0
- nautobot/core/testing/models.py +22 -0
- nautobot/core/testing/schema.py +4 -8
- nautobot/core/testing/views.py +31 -14
- nautobot/core/tests/integration/test_general_functionality.py +1 -1
- nautobot/core/tests/integration/test_import_objects_ui.py +1 -0
- nautobot/core/tests/integration/test_swagger.py +1 -1
- nautobot/core/tests/nautobot_config.py +0 -1
- nautobot/core/tests/runner.py +2 -2
- nautobot/core/tests/test_api.py +1 -0
- nautobot/core/tests/test_authentication.py +7 -2
- nautobot/core/tests/test_filters.py +11 -9
- nautobot/core/tests/test_forms.py +9 -0
- nautobot/core/tests/test_graphql.py +27 -16
- nautobot/core/tests/test_jobs.py +123 -74
- nautobot/core/tests/test_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +12 -5
- nautobot/core/tests/test_utils.py +31 -20
- nautobot/core/tests/test_views.py +6 -6
- nautobot/core/urls.py +8 -3
- nautobot/core/utils/deprecation.py +29 -0
- nautobot/core/utils/filtering.py +12 -9
- nautobot/core/utils/lookup.py +37 -2
- nautobot/core/utils/requests.py +4 -1
- nautobot/core/views/__init__.py +137 -24
- nautobot/core/views/generic.py +118 -66
- nautobot/core/views/mixins.py +104 -35
- nautobot/core/views/paginator.py +9 -3
- nautobot/core/views/renderers.py +121 -56
- nautobot/core/views/utils.py +79 -1
- nautobot/dcim/__init__.py +0 -1
- nautobot/dcim/api/serializers.py +180 -44
- nautobot/dcim/api/urls.py +7 -3
- nautobot/dcim/api/views.py +53 -7
- nautobot/dcim/apps.py +3 -0
- nautobot/dcim/choices.py +25 -0
- nautobot/dcim/constants.py +7 -0
- nautobot/dcim/factory.py +249 -18
- nautobot/dcim/filters/__init__.py +369 -193
- nautobot/dcim/filters/mixins.py +274 -1
- nautobot/dcim/forms.py +817 -109
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/homepage.py +1 -1
- nautobot/dcim/migrations/0059_add_role_field_to_interface_models.py +27 -0
- nautobot/dcim/migrations/0060_alter_cable_status_alter_consoleport__path_and_more.py +303 -0
- nautobot/dcim/migrations/0061_module_models.py +861 -0
- nautobot/dcim/migrations/0062_module_data_migration.py +25 -0
- nautobot/dcim/models/__init__.py +8 -0
- nautobot/dcim/models/cables.py +15 -0
- nautobot/dcim/models/device_component_templates.py +207 -53
- nautobot/dcim/models/device_components.py +275 -106
- nautobot/dcim/models/devices.py +466 -13
- nautobot/dcim/navigation.py +47 -0
- nautobot/dcim/signals.py +3 -3
- nautobot/dcim/tables/__init__.py +35 -23
- nautobot/dcim/tables/devices.py +231 -59
- nautobot/dcim/tables/devicetypes.py +65 -9
- nautobot/dcim/tables/racks.py +5 -1
- nautobot/dcim/tables/template_code.py +46 -26
- nautobot/dcim/templates/dcim/cable_connect.html +76 -3
- nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/device/base.html +15 -7
- nautobot/dcim/templates/dcim/device/consoleports.html +2 -3
- nautobot/dcim/templates/dcim/device/consoleserverports.html +2 -3
- nautobot/dcim/templates/dcim/device/devicebays.html +6 -7
- nautobot/dcim/templates/dcim/device/frontports.html +2 -3
- nautobot/dcim/templates/dcim/device/interfaces.html +2 -3
- nautobot/dcim/templates/dcim/device/inventory.html +2 -3
- nautobot/dcim/templates/dcim/device/modulebays.html +49 -0
- nautobot/dcim/templates/dcim/device/poweroutlets.html +2 -3
- nautobot/dcim/templates/dcim/device/powerports.html +2 -3
- nautobot/dcim/templates/dcim/device/rearports.html +2 -3
- nautobot/dcim/templates/dcim/device.html +45 -1
- nautobot/dcim/templates/dcim/device_component.html +13 -5
- nautobot/dcim/templates/dcim/device_list.html +2 -1
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -6
- nautobot/dcim/templates/dcim/devicetype.html +99 -98
- nautobot/dcim/templates/dcim/devicetype_list.html +8 -16
- nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +39 -0
- nautobot/dcim/templates/dcim/interface.html +17 -2
- nautobot/dcim/templates/dcim/interface_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/manufacturer.html +24 -0
- nautobot/dcim/templates/dcim/module/base.html +97 -0
- nautobot/dcim/templates/dcim/module_bulk_destroy.html +5 -0
- nautobot/dcim/templates/dcim/module_consoleports.html +53 -0
- nautobot/dcim/templates/dcim/module_consoleserverports.html +53 -0
- nautobot/dcim/templates/dcim/module_destroy.html +5 -0
- nautobot/dcim/templates/dcim/module_frontports.html +53 -0
- nautobot/dcim/templates/dcim/module_interfaces.html +57 -0
- nautobot/dcim/templates/dcim/module_list.html +20 -0
- nautobot/dcim/templates/dcim/module_modulebays.html +49 -0
- nautobot/dcim/templates/dcim/module_poweroutlets.html +53 -0
- nautobot/dcim/templates/dcim/module_powerports.html +53 -0
- nautobot/dcim/templates/dcim/module_rearports.html +53 -0
- nautobot/dcim/templates/dcim/module_retrieve.html +63 -0
- nautobot/dcim/templates/dcim/module_update.html +71 -0
- nautobot/dcim/templates/dcim/modulebay_bulk_destroy.html +5 -0
- nautobot/dcim/templates/dcim/modulebay_destroy.html +8 -0
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +101 -0
- nautobot/dcim/templates/dcim/moduletype_list.html +11 -0
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +142 -0
- nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +65 -19
- nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
- nautobot/dcim/tests/test_api.py +691 -208
- nautobot/dcim/tests/test_filters.py +836 -217
- nautobot/dcim/tests/test_models.py +1072 -39
- nautobot/dcim/tests/test_views.py +1488 -358
- nautobot/dcim/urls.py +17 -2
- nautobot/dcim/utils.py +2 -3
- nautobot/dcim/views.py +1107 -120
- nautobot/extras/__init__.py +0 -1
- nautobot/extras/api/serializers.py +115 -3
- nautobot/extras/api/urls.py +12 -0
- nautobot/extras/api/views.py +125 -7
- nautobot/extras/apps.py +2 -2
- nautobot/extras/choices.py +43 -0
- nautobot/extras/context_managers.py +13 -8
- nautobot/extras/datasources/git.py +2 -0
- nautobot/extras/factory.py +422 -9
- nautobot/extras/filters/__init__.py +174 -3
- nautobot/extras/filters/mixins.py +46 -43
- nautobot/extras/forms/base.py +17 -4
- nautobot/extras/forms/forms.py +227 -8
- nautobot/extras/forms/mixins.py +93 -0
- nautobot/extras/graphql/types.py +23 -10
- nautobot/extras/homepage.py +16 -13
- nautobot/extras/jobs.py +2 -2
- nautobot/extras/management/__init__.py +1 -0
- nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +1 -16
- nautobot/extras/migrations/0021_customfield_changelog_data.py +1 -0
- nautobot/extras/migrations/0109_dynamicgroup_group_type_dynamicgroup_tags_and_more.py +108 -0
- nautobot/extras/migrations/0110_alter_configcontext_cluster_groups_and_more.py +111 -0
- nautobot/extras/migrations/0111_metadata.py +162 -0
- nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +28 -0
- nautobot/extras/migrations/0113_saved_views.py +77 -0
- nautobot/extras/models/__init__.py +15 -1
- nautobot/extras/models/change_logging.py +3 -3
- nautobot/extras/models/contacts.py +4 -0
- nautobot/extras/models/customfields.py +18 -3
- nautobot/extras/models/groups.py +389 -225
- nautobot/extras/models/jobs.py +4 -84
- nautobot/extras/models/metadata.py +441 -0
- nautobot/extras/models/mixins.py +72 -62
- nautobot/extras/models/models.py +116 -9
- nautobot/extras/models/relationships.py +9 -2
- nautobot/extras/models/tags.py +13 -2
- nautobot/extras/navigation.py +57 -0
- nautobot/extras/plugins/__init__.py +3 -1
- nautobot/extras/querysets.py +30 -66
- nautobot/extras/signals.py +96 -114
- nautobot/extras/tables.py +171 -47
- nautobot/extras/templates/extras/dynamicgroup.html +44 -15
- nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -0
- nautobot/extras/templates/extras/job.html +1 -1
- nautobot/extras/templates/extras/job_detail.html +0 -11
- nautobot/extras/templates/extras/jobresult.html +61 -74
- nautobot/extras/templates/extras/metadatatype_create.html +89 -0
- nautobot/extras/templates/extras/metadatatype_retrieve.html +67 -0
- nautobot/extras/templates/extras/object_dynamicgroups.html +7 -0
- nautobot/extras/templates/extras/objectchange_list.html +0 -12
- nautobot/extras/templates/extras/plugins_list.html +1 -3
- nautobot/extras/templates/extras/role_retrieve.html +48 -0
- nautobot/extras/templates/extras/staticgroupassociation_retrieve.html +20 -0
- nautobot/extras/tests/integration/test_customfields.py +1 -0
- nautobot/extras/tests/test_api.py +501 -22
- nautobot/extras/tests/test_changelog.py +20 -9
- nautobot/extras/tests/test_context_managers.py +22 -15
- nautobot/extras/tests/test_datasources.py +13 -1
- nautobot/extras/tests/test_dynamicgroups.py +201 -171
- nautobot/extras/tests/test_filters.py +211 -12
- nautobot/extras/tests/test_jobs.py +4 -4
- nautobot/extras/tests/test_models.py +499 -4
- nautobot/extras/tests/test_relationships.py +1 -0
- nautobot/extras/tests/test_views.py +565 -28
- nautobot/extras/tests/test_webhooks.py +1 -1
- nautobot/extras/urls.py +5 -0
- nautobot/extras/utils.py +56 -45
- nautobot/extras/views.py +585 -96
- nautobot/ipam/__init__.py +0 -1
- nautobot/ipam/apps.py +1 -0
- nautobot/ipam/factory.py +17 -19
- nautobot/ipam/filters.py +14 -1
- nautobot/ipam/forms.py +9 -5
- nautobot/ipam/graphql/types.py +2 -2
- nautobot/ipam/migrations/0047_alter_ipaddress_role_alter_ipaddress_status_and_more.py +59 -0
- nautobot/ipam/models.py +23 -9
- nautobot/ipam/querysets.py +1 -1
- nautobot/ipam/signals.py +4 -2
- nautobot/ipam/tables.py +1 -0
- nautobot/ipam/templates/ipam/ipaddress_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/prefix.html +1 -0
- nautobot/ipam/tests/test_api.py +37 -18
- nautobot/ipam/tests/test_filters.py +26 -2
- nautobot/ipam/tests/test_models.py +8 -3
- nautobot/ipam/tests/test_querysets.py +1 -1
- nautobot/ipam/tests/test_views.py +3 -2
- nautobot/ipam/urls.py +2 -2
- nautobot/ipam/views.py +25 -28
- nautobot/project-static/css/base.css +20 -1
- nautobot/project-static/css/dark.css +11 -0
- nautobot/project-static/docs/404.html +884 -80
- nautobot/project-static/docs/apps/index.html +884 -80
- nautobot/project-static/docs/apps/nautobot-apps.html +884 -80
- nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +911 -112
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +896 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1457 -790
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +927 -136
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +969 -180
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +893 -91
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +889 -85
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +983 -185
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +938 -143
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1064 -274
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1190 -346
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1663 -865
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1156 -373
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2200 -1502
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2229 -1421
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +904 -103
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +955 -155
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1002 -215
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1911 -1275
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1835 -1091
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +896 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2323 -1693
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1785 -1023
- nautobot/project-static/docs/development/apps/api/configuration-view.html +884 -80
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +884 -80
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +884 -80
- nautobot/project-static/docs/development/apps/api/models/global-search.html +884 -80
- nautobot/project-static/docs/development/apps/api/models/graphql.html +884 -80
- nautobot/project-static/docs/development/apps/api/models/index.html +922 -81
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +884 -80
- nautobot/project-static/docs/development/apps/api/prometheus.html +884 -80
- nautobot/project-static/docs/development/apps/api/setup.html +884 -80
- nautobot/project-static/docs/development/apps/api/testing.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/base-template.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/index.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/notes.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/urls.html +884 -80
- nautobot/project-static/docs/development/apps/index.html +884 -80
- nautobot/project-static/docs/development/apps/migration/code-updates.html +884 -80
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +884 -80
- nautobot/project-static/docs/development/apps/migration/from-v1.html +884 -80
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +884 -80
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +884 -80
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +884 -80
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +884 -80
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +884 -80
- nautobot/project-static/docs/development/core/application-registry.html +884 -80
- nautobot/project-static/docs/development/core/best-practices.html +885 -80
- nautobot/project-static/docs/development/core/bootstrap-ui.html +884 -80
- nautobot/project-static/docs/development/core/caching.html +884 -80
- nautobot/project-static/docs/development/core/controllers.html +884 -80
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +884 -80
- nautobot/project-static/docs/development/core/generic-views.html +884 -80
- nautobot/project-static/docs/development/core/getting-started.html +884 -80
- nautobot/project-static/docs/development/core/homepage.html +884 -80
- nautobot/project-static/docs/development/core/index.html +884 -91
- nautobot/project-static/docs/development/core/model-checklist.html +887 -81
- nautobot/project-static/docs/development/core/model-features.html +884 -80
- nautobot/project-static/docs/development/core/natural-keys.html +884 -80
- nautobot/project-static/docs/development/core/navigation-menu.html +884 -80
- nautobot/project-static/docs/development/core/release-checklist.html +887 -83
- nautobot/project-static/docs/development/core/role-internals.html +884 -80
- nautobot/project-static/docs/development/core/settings.html +884 -80
- nautobot/project-static/docs/development/core/style-guide.html +885 -81
- nautobot/project-static/docs/development/core/templates.html +896 -81
- nautobot/project-static/docs/development/core/testing.html +884 -80
- nautobot/project-static/docs/development/core/user-preferences.html +884 -80
- nautobot/project-static/docs/development/index.html +884 -80
- nautobot/project-static/docs/development/jobs/index.html +1247 -457
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +884 -80
- nautobot/project-static/docs/index.html +13 -8228
- nautobot/project-static/docs/media/models/cloud_aws_direct_connect_dark.png +0 -0
- nautobot/project-static/docs/media/models/cloud_aws_direct_connect_light.png +0 -0
- nautobot/project-static/docs/models/cloud/cloudaccount.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudnetwork.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudresourcetype.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudservice.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +15 -0
- nautobot/project-static/docs/models/dcim/module.html +15 -0
- nautobot/project-static/docs/models/dcim/modulebay.html +15 -0
- nautobot/project-static/docs/models/dcim/modulebaytemplate.html +15 -0
- nautobot/project-static/docs/models/dcim/moduletype.html +15 -0
- nautobot/project-static/docs/models/extras/metadatachoice.html +15 -0
- nautobot/project-static/docs/models/extras/metadatatype.html +15 -0
- nautobot/project-static/docs/models/extras/objectmetadata.html +15 -0
- nautobot/project-static/docs/models/extras/role.html +15 -0
- nautobot/project-static/docs/models/extras/savedview.html +15 -0
- nautobot/project-static/docs/models/extras/staticgroupassociation.html +15 -0
- nautobot/project-static/docs/models/extras/status.html +15 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +892 -81
- nautobot/project-static/docs/overview/design_philosophy.html +886 -82
- nautobot/project-static/docs/overview/index.html +9032 -13
- nautobot/project-static/docs/release-notes/index.html +887 -83
- nautobot/project-static/docs/release-notes/version-1.0.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.1.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.2.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.3.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.4.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.5.html +885 -81
- nautobot/project-static/docs/release-notes/version-1.6.html +885 -81
- nautobot/project-static/docs/release-notes/version-2.0.html +884 -80
- nautobot/project-static/docs/release-notes/version-2.1.html +884 -80
- nautobot/project-static/docs/release-notes/version-2.2.html +990 -323
- nautobot/project-static/docs/release-notes/version-2.3.html +9524 -0
- nautobot/project-static/docs/requirements.txt +4 -4
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +335 -260
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +983 -197
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +888 -84
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/index.html +888 -80
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/services.html +888 -80
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +900 -91
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +884 -80
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +884 -80
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +884 -80
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +915 -163
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +885 -81
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +888 -80
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +887 -83
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +8984 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +8829 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +8829 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +8833 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +915 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +915 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +910 -92
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +915 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +905 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +912 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +913 -109
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +910 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +906 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +918 -100
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +928 -110
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +920 -98
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +929 -111
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +920 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +910 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +913 -109
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +914 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +8846 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +8843 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +8823 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +932 -75
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +916 -98
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +935 -78
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +913 -95
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +921 -117
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +910 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +914 -96
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +916 -98
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +889 -81
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +889 -81
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +893 -88
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +889 -81
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/clear-view-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/cleared-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/config-table-columns-to-locations.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/configure-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/create-saved-view-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/current-saved-view-drop-down-menu.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/default-location-list-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/dropdown-button-after-new-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-application-to-locations.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/global-default-location-list-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/location-list-view-with-saved-views.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/navigation-menu.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-as-new-view-drop-down.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-view-modal.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-buttons.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view-unchecked.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-different-user.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-modal-unchecked.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/unsaved-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/updated-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +884 -80
- nautobot/project-static/docs/user-guide/index.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1250 -777
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +888 -80
- nautobot/project-static/docs/user-guide/platform-functionality/metadata.html +8948 -0
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +942 -113
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +884 -80
- nautobot/project-static/js/forms.js +71 -0
- nautobot/project-static/js/table_sorting_indicator.js +46 -0
- nautobot/project-static/js/tableconfig.js +6 -1
- nautobot/project-static/materialdesignicons-7.4.47/css/materialdesignicons.min.css +3 -0
- nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.eot +0 -0
- nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.ttf +0 -0
- nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff +0 -0
- nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff2 +0 -0
- nautobot/tenancy/__init__.py +0 -1
- nautobot/tenancy/apps.py +1 -0
- nautobot/tenancy/factory.py +3 -2
- nautobot/tenancy/filters/__init__.py +1 -0
- nautobot/tenancy/forms.py +1 -1
- nautobot/tenancy/templates/tenancy/tenant.html +22 -18
- nautobot/tenancy/views.py +11 -10
- nautobot/users/__init__.py +0 -1
- nautobot/users/api/serializers.py +1 -1
- nautobot/users/api/views.py +4 -2
- nautobot/users/apps.py +3 -2
- nautobot/users/factory.py +3 -3
- nautobot/users/migrations/0010_user_default_saved_views.py +20 -0
- nautobot/users/models.py +12 -0
- nautobot/users/tests/test_filters.py +6 -3
- nautobot/users/urls.py +8 -0
- nautobot/virtualization/__init__.py +0 -1
- nautobot/virtualization/apps.py +1 -0
- nautobot/virtualization/filters.py +6 -1
- nautobot/virtualization/forms.py +11 -3
- nautobot/virtualization/graphql/types.py +2 -2
- nautobot/virtualization/migrations/0029_add_role_field_to_interface_models.py +27 -0
- nautobot/virtualization/migrations/0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more.py +67 -0
- nautobot/virtualization/tables.py +15 -5
- nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
- nautobot/virtualization/templates/virtualization/vminterface.html +7 -1
- nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
- nautobot/virtualization/tests/test_api.py +9 -4
- nautobot/virtualization/tests/test_filters.py +22 -0
- nautobot/virtualization/tests/test_models.py +7 -3
- nautobot/virtualization/tests/test_views.py +19 -3
- nautobot/virtualization/urls.py +2 -2
- nautobot/virtualization/views.py +10 -32
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/METADATA +21 -19
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/RECORD +679 -559
- nautobot/project-static/materialdesignicons-6.5.95/.github/ISSUE_TEMPLATE.md +0 -3
- nautobot/project-static/materialdesignicons-6.5.95/README.md +0 -25
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css +0 -26654
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css.map +0 -16
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css +0 -3
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css.map +0 -16
- nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff +0 -0
- nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff2 +0 -0
- nautobot/project-static/materialdesignicons-6.5.95/package.json +0 -28
- nautobot/project-static/materialdesignicons-6.5.95/preview.html +0 -717
- nautobot/project-static/materialdesignicons-6.5.95/scss/_animated.scss +0 -27
- nautobot/project-static/materialdesignicons-6.5.95/scss/_core.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_extras.scss +0 -65
- nautobot/project-static/materialdesignicons-6.5.95/scss/_functions.scss +0 -20
- nautobot/project-static/materialdesignicons-6.5.95/scss/_icons.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_path.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_variables.scss +0 -6606
- nautobot/project-static/materialdesignicons-6.5.95/scss/materialdesignicons.scss +0 -8
- /nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/LICENSE +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/NOTICE +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/WHEEL +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/entry_points.txt +0 -0
nautobot/core/views/__init__.py
CHANGED
|
@@ -7,14 +7,15 @@ import time
|
|
|
7
7
|
from db_file_storage.views import get_file
|
|
8
8
|
from django.apps import apps
|
|
9
9
|
from django.conf import settings
|
|
10
|
+
from django.contrib import messages
|
|
10
11
|
from django.contrib.auth.decorators import permission_required
|
|
11
|
-
from django.contrib.auth.mixins import AccessMixin, LoginRequiredMixin
|
|
12
|
+
from django.contrib.auth.mixins import AccessMixin, LoginRequiredMixin, UserPassesTestMixin
|
|
12
13
|
from django.contrib.contenttypes.models import ContentType
|
|
13
14
|
from django.http import HttpResponseForbidden, HttpResponseServerError, JsonResponse
|
|
14
15
|
from django.shortcuts import get_object_or_404, render
|
|
15
16
|
from django.template import loader, RequestContext, Template
|
|
16
17
|
from django.template.exceptions import TemplateDoesNotExist
|
|
17
|
-
from django.urls import resolve, reverse
|
|
18
|
+
from django.urls import NoReverseMatch, resolve, reverse
|
|
18
19
|
from django.utils.encoding import smart_str
|
|
19
20
|
from django.views.csrf import csrf_failure as _csrf_failure
|
|
20
21
|
from django.views.decorators.csrf import requires_csrf_token
|
|
@@ -37,6 +38,7 @@ from rest_framework.response import Response
|
|
|
37
38
|
from rest_framework.versioning import AcceptHeaderVersioning
|
|
38
39
|
from rest_framework.views import APIView
|
|
39
40
|
|
|
41
|
+
from nautobot.core.celery import app
|
|
40
42
|
from nautobot.core.constants import SEARCH_MAX_RESULTS
|
|
41
43
|
from nautobot.core.forms import SearchForm
|
|
42
44
|
from nautobot.core.releases import get_latest_release
|
|
@@ -125,6 +127,112 @@ class HomeView(AccessMixin, TemplateView):
|
|
|
125
127
|
return self.render_to_response(context)
|
|
126
128
|
|
|
127
129
|
|
|
130
|
+
class WorkerStatusView(UserPassesTestMixin, TemplateView):
|
|
131
|
+
template_name = "utilities/worker_status.html"
|
|
132
|
+
|
|
133
|
+
def test_func(self):
|
|
134
|
+
return self.request.user.is_staff
|
|
135
|
+
|
|
136
|
+
def get(self, request, *args, **kwargs):
|
|
137
|
+
from nautobot.extras.models import JobResult
|
|
138
|
+
from nautobot.extras.tables import JobResultTable
|
|
139
|
+
|
|
140
|
+
# Sort queues but move the default queue to the front so that it appears first
|
|
141
|
+
def sort_queues(queue):
|
|
142
|
+
return (queue != settings.CELERY_TASK_DEFAULT_QUEUE, queue) # False sorts before true in Python sorted
|
|
143
|
+
|
|
144
|
+
# Sort workers on hostname first, then worker name -- celery worker names are in the form name@hostname (celery@worker.example.com)
|
|
145
|
+
def sort_workers(worker):
|
|
146
|
+
return list(reversed(worker.split("@")))
|
|
147
|
+
|
|
148
|
+
# Use a long timeout to retrieve the initial list of workers
|
|
149
|
+
max_timeout = 60
|
|
150
|
+
timeout = request.GET.get("timeout", "5")
|
|
151
|
+
if not timeout.isdigit():
|
|
152
|
+
timeout = 5
|
|
153
|
+
elif int(timeout) > max_timeout:
|
|
154
|
+
timeout = max_timeout
|
|
155
|
+
else:
|
|
156
|
+
timeout = int(timeout)
|
|
157
|
+
celery_inspect = app.control.inspect(timeout=timeout)
|
|
158
|
+
|
|
159
|
+
# stats() returns a dict of {worker_name: stats_dict}
|
|
160
|
+
worker_stats = celery_inspect.stats()
|
|
161
|
+
|
|
162
|
+
if worker_stats:
|
|
163
|
+
# Set explicit list of workers to speed up subsequent queries
|
|
164
|
+
celery_inspect = app.control.inspect(list(worker_stats.keys()), timeout=5.0)
|
|
165
|
+
|
|
166
|
+
# active() returns a dict of {worker_name: [task_dict, task_dict, ...]}
|
|
167
|
+
active_tasks = celery_inspect.active() or {}
|
|
168
|
+
|
|
169
|
+
# reserved() returns a dict of {worker_name: [task_dict, task_dict, ...]}
|
|
170
|
+
reserved_tasks = celery_inspect.reserved() or {}
|
|
171
|
+
|
|
172
|
+
# active_queues() returns a dict of {worker_name: [queue_dict, queue_dict, ...]}
|
|
173
|
+
active_queues = celery_inspect.active_queues() or {}
|
|
174
|
+
else:
|
|
175
|
+
# No workers were found, default to empty dicts for all commands
|
|
176
|
+
worker_stats = active_tasks = reserved_tasks = active_queues = {}
|
|
177
|
+
|
|
178
|
+
workers = []
|
|
179
|
+
for worker_name in sorted(worker_stats, key=sort_workers):
|
|
180
|
+
worker_details = worker_stats[worker_name]
|
|
181
|
+
active_task_job_results = JobResult.objects.filter(
|
|
182
|
+
id__in=[task["id"] for task in active_tasks.get(worker_name, [])]
|
|
183
|
+
).only("name", "date_created")
|
|
184
|
+
reserved_task_job_results = JobResult.objects.filter(
|
|
185
|
+
id__in=[task["id"] for task in reserved_tasks.get(worker_name, [])]
|
|
186
|
+
).only("name", "date_created")
|
|
187
|
+
running_tasks_table = JobResultTable(
|
|
188
|
+
active_task_job_results, exclude=["actions", "job_model", "summary", "user", "status"]
|
|
189
|
+
)
|
|
190
|
+
pending_tasks_table = JobResultTable(
|
|
191
|
+
reserved_task_job_results, exclude=["actions", "job_model", "summary", "user", "status"]
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
# Sort the worker's queue list
|
|
195
|
+
queues = sorted([queue["name"] for queue in active_queues.get(worker_name, [])], key=sort_queues)
|
|
196
|
+
|
|
197
|
+
workers.append(
|
|
198
|
+
{
|
|
199
|
+
"hostname": worker_name,
|
|
200
|
+
"running_tasks_table": running_tasks_table,
|
|
201
|
+
"pending_tasks_table": pending_tasks_table,
|
|
202
|
+
"queues": queues,
|
|
203
|
+
"uptime": worker_details["uptime"],
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Count the number of workers per queue
|
|
208
|
+
queue_worker_count = {
|
|
209
|
+
settings.CELERY_TASK_DEFAULT_QUEUE: set(),
|
|
210
|
+
}
|
|
211
|
+
for worker_name, task_queue_list in active_queues.items():
|
|
212
|
+
distinct_queues = {q["name"] for q in task_queue_list}
|
|
213
|
+
for queue in distinct_queues:
|
|
214
|
+
queue_worker_count.setdefault(queue, set())
|
|
215
|
+
queue_worker_count[queue].add(worker_name)
|
|
216
|
+
|
|
217
|
+
# Sort the queue_worker_count dictionary by queue name, then by worker hostname/name
|
|
218
|
+
# Then make the default queue the first entry
|
|
219
|
+
queue_worker_count = {
|
|
220
|
+
queue_name: sorted(queue_worker_count[queue_name], key=sort_workers)
|
|
221
|
+
for queue_name in sorted(queue_worker_count, key=sort_queues)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
context = {
|
|
225
|
+
"worker_status": {
|
|
226
|
+
"max_timeout": max_timeout,
|
|
227
|
+
"queue_worker_count": queue_worker_count,
|
|
228
|
+
"timeout": timeout,
|
|
229
|
+
"workers": workers,
|
|
230
|
+
},
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return self.render_to_response(context)
|
|
234
|
+
|
|
235
|
+
|
|
128
236
|
class ThemePreviewView(LoginRequiredMixin, TemplateView):
|
|
129
237
|
template_name = "utilities/theme_preview.html"
|
|
130
238
|
|
|
@@ -132,6 +240,8 @@ class ThemePreviewView(LoginRequiredMixin, TemplateView):
|
|
|
132
240
|
return {
|
|
133
241
|
"content_type": ContentType.objects.get_for_model(Status),
|
|
134
242
|
"object": Status.objects.first(),
|
|
243
|
+
"verbose_name": Status.objects.all().model._meta.verbose_name,
|
|
244
|
+
"verbose_name_plural": Status.objects.all().model._meta.verbose_name_plural,
|
|
135
245
|
}
|
|
136
246
|
|
|
137
247
|
|
|
@@ -177,28 +287,31 @@ class SearchView(AccessMixin, View):
|
|
|
177
287
|
# corresponding to that URL, and finally the queryset, filterset, and table classes needed
|
|
178
288
|
# to find and display the model search results.
|
|
179
289
|
url = get_route_for_model(f"{label}.{modelname}", "list")
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
290
|
+
try:
|
|
291
|
+
view_func = resolve(reverse(url)).func
|
|
292
|
+
# For UIViewSet, view_func.cls gets what we need; for an ObjectListView, view_func.view_class is it.
|
|
293
|
+
view_or_viewset = getattr(view_func, "cls", getattr(view_func, "view_class", None))
|
|
294
|
+
queryset = view_or_viewset.queryset.restrict(request.user, "view")
|
|
295
|
+
# For a UIViewSet, .filterset_class, for an ObjectListView, .filterset.
|
|
296
|
+
filterset = getattr(view_or_viewset, "filterset_class", getattr(view_or_viewset, "filterset", None))
|
|
297
|
+
# For a UIViewSet, .table_class, for an ObjectListView, .table.
|
|
298
|
+
table = getattr(view_or_viewset, "table_class", getattr(view_or_viewset, "table", None))
|
|
299
|
+
|
|
300
|
+
# Construct the results table for this object type
|
|
301
|
+
filtered_queryset = filterset({"q": form.cleaned_data["q"]}, queryset=queryset).qs
|
|
302
|
+
table = table(filtered_queryset, orderable=False)
|
|
303
|
+
table.paginate(per_page=SEARCH_MAX_RESULTS)
|
|
304
|
+
|
|
305
|
+
if table.page:
|
|
306
|
+
results.append(
|
|
307
|
+
{
|
|
308
|
+
"name": queryset.model._meta.verbose_name_plural,
|
|
309
|
+
"table": table,
|
|
310
|
+
"url": f"{reverse(url)}?q={form.cleaned_data.get('q')}",
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
except NoReverseMatch:
|
|
314
|
+
messages.error(request, f'Missing URL "{url}" - unable to show search results for {modelname}.')
|
|
202
315
|
|
|
203
316
|
return render(
|
|
204
317
|
request,
|
nautobot/core/views/generic.py
CHANGED
|
@@ -5,6 +5,7 @@ import re
|
|
|
5
5
|
from django.conf import settings
|
|
6
6
|
from django.contrib import messages
|
|
7
7
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
8
|
+
from django.contrib.auth.models import AnonymousUser
|
|
8
9
|
from django.contrib.contenttypes.models import ContentType
|
|
9
10
|
from django.core.exceptions import (
|
|
10
11
|
FieldDoesNotExist,
|
|
@@ -12,10 +13,11 @@ from django.core.exceptions import (
|
|
|
12
13
|
ValidationError,
|
|
13
14
|
)
|
|
14
15
|
from django.db import IntegrityError, transaction
|
|
15
|
-
from django.db.models import ManyToManyField, ProtectedError
|
|
16
|
+
from django.db.models import ManyToManyField, ProtectedError, Q
|
|
16
17
|
from django.forms import Form, ModelMultipleChoiceField, MultipleHiddenInput
|
|
17
|
-
from django.http import HttpResponse
|
|
18
|
+
from django.http import HttpResponse
|
|
18
19
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
20
|
+
from django.urls import reverse
|
|
19
21
|
from django.utils.encoding import iri_to_uri
|
|
20
22
|
from django.utils.html import format_html
|
|
21
23
|
from django.utils.http import url_has_allowed_host_and_scheme
|
|
@@ -38,7 +40,6 @@ from nautobot.core.forms import (
|
|
|
38
40
|
from nautobot.core.forms.forms import DynamicFilterFormSet
|
|
39
41
|
from nautobot.core.templatetags.helpers import bettertitle, validated_viewname
|
|
40
42
|
from nautobot.core.utils.config import get_settings_or_config
|
|
41
|
-
from nautobot.core.utils.lookup import get_created_and_last_updated_usernames_for_model
|
|
42
43
|
from nautobot.core.utils.permissions import get_permission_for_model
|
|
43
44
|
from nautobot.core.utils.requests import (
|
|
44
45
|
convert_querydict_to_factory_formset_acceptable_querydict,
|
|
@@ -49,14 +50,15 @@ from nautobot.core.views.mixins import GetReturnURLMixin, ObjectPermissionRequir
|
|
|
49
50
|
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
50
51
|
from nautobot.core.views.utils import (
|
|
51
52
|
check_filter_for_display,
|
|
53
|
+
common_detail_view_context,
|
|
52
54
|
get_csv_form_fields_from_serializer_class,
|
|
53
55
|
handle_protectederror,
|
|
54
56
|
import_csv_helper,
|
|
55
57
|
prepare_cloned_fields,
|
|
58
|
+
view_changes_not_saved,
|
|
56
59
|
)
|
|
57
60
|
from nautobot.extras.context_managers import deferred_change_logging_for_bulk_operation
|
|
58
|
-
from nautobot.extras.models import
|
|
59
|
-
from nautobot.extras.tables import AssociatedContactsTable
|
|
61
|
+
from nautobot.extras.models import ExportTemplate, SavedView, UserSavedViewAssociation
|
|
60
62
|
from nautobot.extras.utils import bulk_delete_with_bulk_change_logging, remove_prefix_from_cf_key
|
|
61
63
|
|
|
62
64
|
|
|
@@ -111,53 +113,17 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
|
|
|
111
113
|
Generic GET handler for accessing an object.
|
|
112
114
|
"""
|
|
113
115
|
instance = get_object_or_404(self.queryset, **kwargs)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
temp_fake_context = {
|
|
125
|
-
"object": instance,
|
|
126
|
-
"request": request,
|
|
127
|
-
"settings": {},
|
|
128
|
-
"csrf_token": "",
|
|
129
|
-
"perms": {},
|
|
130
|
-
}
|
|
116
|
+
content_type = ContentType.objects.get_for_model(self.queryset.model)
|
|
117
|
+
context = {
|
|
118
|
+
"object": instance,
|
|
119
|
+
"content_type": content_type,
|
|
120
|
+
"verbose_name": self.queryset.model._meta.verbose_name,
|
|
121
|
+
"verbose_name_plural": self.queryset.model._meta.verbose_name_plural,
|
|
122
|
+
**common_detail_view_context(request, instance),
|
|
123
|
+
**self.get_extra_context(request, instance),
|
|
124
|
+
}
|
|
131
125
|
|
|
132
|
-
|
|
133
|
-
resp = {"tabs": plugin_tabs}
|
|
134
|
-
return JsonResponse(resp)
|
|
135
|
-
else:
|
|
136
|
-
content_type = ContentType.objects.get_for_model(self.queryset.model)
|
|
137
|
-
context = {
|
|
138
|
-
"object": instance,
|
|
139
|
-
"content_type": content_type,
|
|
140
|
-
"verbose_name": self.queryset.model._meta.verbose_name,
|
|
141
|
-
"verbose_name_plural": self.queryset.model._meta.verbose_name_plural,
|
|
142
|
-
"created_by": created_by,
|
|
143
|
-
"last_updated_by": last_updated_by,
|
|
144
|
-
**self.get_extra_context(request, instance),
|
|
145
|
-
}
|
|
146
|
-
if instance.is_contact_associable_model:
|
|
147
|
-
paginate = {"paginator_class": EnhancedPaginator, "per_page": get_paginate_count(request)}
|
|
148
|
-
associations = (
|
|
149
|
-
ContactAssociation.objects.filter(
|
|
150
|
-
associated_object_id=instance.id,
|
|
151
|
-
associated_object_type=content_type,
|
|
152
|
-
)
|
|
153
|
-
.restrict(request.user, "view")
|
|
154
|
-
.order_by("role__name")
|
|
155
|
-
)
|
|
156
|
-
associations_table = AssociatedContactsTable(associations, orderable=False)
|
|
157
|
-
RequestConfig(request, paginate).configure(associations_table)
|
|
158
|
-
associations_table.columns.show("pk")
|
|
159
|
-
context["associated_contacts_table"] = associations_table
|
|
160
|
-
return render(request, self.get_template_name(), context)
|
|
126
|
+
return render(request, self.get_template_name(), context)
|
|
161
127
|
|
|
162
128
|
|
|
163
129
|
class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
@@ -184,12 +150,19 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
184
150
|
"page", # used by django-tables2.RequestConfig
|
|
185
151
|
"per_page", # used by get_paginate_count
|
|
186
152
|
"sort", # table sorting
|
|
153
|
+
"saved_view", # saved_view indicator pk or composite keys
|
|
154
|
+
"table_changes_pending", # indicator for if there is any table changes not applied to the saved view
|
|
155
|
+
"all_filters_removed", # indicator for if all filters have been removed from the saved view
|
|
156
|
+
"clear_view", # indicator for if the clear view button is clicked or not
|
|
187
157
|
)
|
|
188
158
|
|
|
189
159
|
def get_filter_params(self, request):
|
|
190
160
|
"""Helper function - take request.GET and discard any parameters that are not used for queryset filtering."""
|
|
191
|
-
|
|
192
|
-
|
|
161
|
+
params = request.GET.copy()
|
|
162
|
+
filter_params = get_filterable_params_from_filter_params(params, self.non_filter_params, self.filterset())
|
|
163
|
+
if params.get("saved_view") and not filter_params and not params.get("all_filters_removed"):
|
|
164
|
+
return SavedView.objects.get(pk=params.get("saved_view")).config.get("filter_params", {})
|
|
165
|
+
return filter_params
|
|
193
166
|
|
|
194
167
|
def get_required_permission(self):
|
|
195
168
|
return get_permission_for_model(self.queryset.model, "view")
|
|
@@ -225,10 +198,41 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
225
198
|
model = self.queryset.model
|
|
226
199
|
content_type = ContentType.objects.get_for_model(model)
|
|
227
200
|
|
|
201
|
+
filter_params = request.GET
|
|
202
|
+
user = request.user
|
|
228
203
|
display_filter_params = []
|
|
229
204
|
dynamic_filter_form = None
|
|
230
205
|
filter_form = None
|
|
231
206
|
hide_hierarchy_ui = False
|
|
207
|
+
clear_view = request.GET.get("clear_view", False)
|
|
208
|
+
|
|
209
|
+
# If the user clicks on the clear view button, we do not check for global or user defaults
|
|
210
|
+
if not clear_view and not request.GET.get("saved_view"):
|
|
211
|
+
# Check if there is a default for this view for this specific user
|
|
212
|
+
app_label, model_name = model._meta.label.split(".")
|
|
213
|
+
view_name = f"{app_label}:{model_name.lower()}_list"
|
|
214
|
+
|
|
215
|
+
if not isinstance(user, AnonymousUser):
|
|
216
|
+
try:
|
|
217
|
+
user_default_saved_view_pk = UserSavedViewAssociation.objects.get(
|
|
218
|
+
user=user, view_name=view_name
|
|
219
|
+
).saved_view.pk
|
|
220
|
+
# Saved view should either belong to the user or be public
|
|
221
|
+
SavedView.objects.get(
|
|
222
|
+
Q(pk=user_default_saved_view_pk),
|
|
223
|
+
Q(owner=user) | Q(is_shared=True),
|
|
224
|
+
)
|
|
225
|
+
sv_url = reverse("extras:savedview", kwargs={"pk": user_default_saved_view_pk})
|
|
226
|
+
return redirect(sv_url)
|
|
227
|
+
except ObjectDoesNotExist:
|
|
228
|
+
pass
|
|
229
|
+
|
|
230
|
+
# Check if there is a global default for this view
|
|
231
|
+
try:
|
|
232
|
+
global_saved_view = SavedView.objects.get(view=view_name, is_global_default=True)
|
|
233
|
+
return redirect(reverse("extras:savedview", kwargs={"pk": global_saved_view.pk}))
|
|
234
|
+
except ObjectDoesNotExist:
|
|
235
|
+
pass
|
|
232
236
|
|
|
233
237
|
if self.filterset:
|
|
234
238
|
filter_params = self.get_filter_params(request)
|
|
@@ -254,7 +258,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
254
258
|
|
|
255
259
|
if request.GET:
|
|
256
260
|
factory_formset_params = convert_querydict_to_factory_formset_acceptable_querydict(
|
|
257
|
-
|
|
261
|
+
filter_params, filterset
|
|
258
262
|
)
|
|
259
263
|
dynamic_filter_form = DynamicFilterFormSet(filterset=filterset, data=factory_formset_params)
|
|
260
264
|
else:
|
|
@@ -296,18 +300,50 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
296
300
|
|
|
297
301
|
table = None
|
|
298
302
|
table_config_form = None
|
|
303
|
+
current_saved_view = None
|
|
304
|
+
current_saved_view_pk = self.request.GET.get("saved_view", None)
|
|
305
|
+
list_url = validated_viewname(model, "list")
|
|
306
|
+
# We are not using .restrict(request.user, "view") here
|
|
307
|
+
# User should be able to see any saved view that he has the list view access to.
|
|
308
|
+
if user.has_perms(["extras.view_savedview"]):
|
|
309
|
+
saved_views = SavedView.objects.filter(view=list_url).order_by("name").only("pk", "name")
|
|
310
|
+
else:
|
|
311
|
+
shared_saved_views = (
|
|
312
|
+
SavedView.objects.filter(view=list_url, is_shared=True).order_by("name").only("pk", "name")
|
|
313
|
+
)
|
|
314
|
+
user_owned_saved_views = (
|
|
315
|
+
SavedView.objects.filter(view=list_url, owner=user).order_by("name").only("pk", "name")
|
|
316
|
+
)
|
|
317
|
+
saved_views = shared_saved_views | user_owned_saved_views
|
|
299
318
|
if self.table:
|
|
300
319
|
# Construct the objects table
|
|
301
|
-
if
|
|
320
|
+
if current_saved_view_pk:
|
|
321
|
+
try:
|
|
322
|
+
# We are not using .restrict(request.user, "view") here
|
|
323
|
+
# User should be able to see any saved view that he has the list view access to.
|
|
324
|
+
current_saved_view = SavedView.objects.get(view=list_url, pk=current_saved_view_pk)
|
|
325
|
+
except ObjectDoesNotExist:
|
|
326
|
+
messages.error(request, f"Saved view {current_saved_view_pk} not found")
|
|
327
|
+
if self.request.GET.getlist("sort") or (
|
|
328
|
+
current_saved_view is not None and current_saved_view.config.get("sort_order")
|
|
329
|
+
):
|
|
302
330
|
hide_hierarchy_ui = True # hide tree hierarchy if custom sort is used
|
|
303
|
-
|
|
331
|
+
table_changes_pending = self.request.GET.get("table_changes_pending", False)
|
|
332
|
+
|
|
333
|
+
table = self.table(
|
|
334
|
+
self.queryset,
|
|
335
|
+
table_changes_pending=table_changes_pending,
|
|
336
|
+
saved_view=current_saved_view,
|
|
337
|
+
user=request.user,
|
|
338
|
+
hide_hierarchy_ui=hide_hierarchy_ui,
|
|
339
|
+
)
|
|
304
340
|
if "pk" in table.base_columns and (permissions["change"] or permissions["delete"]):
|
|
305
341
|
table.columns.show("pk")
|
|
306
342
|
|
|
307
343
|
# Apply the request context
|
|
308
344
|
paginate = {
|
|
309
345
|
"paginator_class": EnhancedPaginator,
|
|
310
|
-
"per_page": get_paginate_count(request),
|
|
346
|
+
"per_page": get_paginate_count(request, current_saved_view),
|
|
311
347
|
}
|
|
312
348
|
RequestConfig(request, paginate).configure(table)
|
|
313
349
|
table_config_form = TableConfigForm(table=table)
|
|
@@ -320,10 +356,13 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
320
356
|
|
|
321
357
|
# For the search form field, use a custom placeholder.
|
|
322
358
|
q_placeholder = "Search " + bettertitle(model._meta.verbose_name_plural)
|
|
323
|
-
search_form = SearchForm(data=
|
|
359
|
+
search_form = SearchForm(data=filter_params, q_placeholder=q_placeholder)
|
|
324
360
|
|
|
325
361
|
valid_actions = self.validate_action_buttons(request)
|
|
326
362
|
|
|
363
|
+
# Query SavedViews for dropdown button
|
|
364
|
+
new_changes_not_applied = view_changes_not_saved(request, self, current_saved_view)
|
|
365
|
+
|
|
327
366
|
context = {
|
|
328
367
|
"content_type": content_type,
|
|
329
368
|
"table": table,
|
|
@@ -334,8 +373,12 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
334
373
|
"filter_form": filter_form,
|
|
335
374
|
"dynamic_filter_form": dynamic_filter_form,
|
|
336
375
|
"search_form": search_form,
|
|
337
|
-
"list_url":
|
|
376
|
+
"list_url": list_url,
|
|
338
377
|
"title": bettertitle(model._meta.verbose_name_plural),
|
|
378
|
+
"new_changes_not_applied": new_changes_not_applied,
|
|
379
|
+
"current_saved_view": current_saved_view,
|
|
380
|
+
"saved_views": saved_views,
|
|
381
|
+
"model": model,
|
|
339
382
|
}
|
|
340
383
|
|
|
341
384
|
# `extra_context()` would require `request` access, however `request` parameter cannot simply be
|
|
@@ -439,7 +482,12 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
439
482
|
def post(self, request, *args, **kwargs):
|
|
440
483
|
logger = logging.getLogger(__name__ + ".ObjectEditView")
|
|
441
484
|
obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs)
|
|
442
|
-
form = self.model_form(
|
|
485
|
+
form = self.model_form(
|
|
486
|
+
data=request.POST,
|
|
487
|
+
files=request.FILES,
|
|
488
|
+
initial=normalize_querydict(request.GET, form_class=self.model_form),
|
|
489
|
+
instance=obj,
|
|
490
|
+
)
|
|
443
491
|
restrict_form_fields(form, request.user)
|
|
444
492
|
|
|
445
493
|
if form.is_valid():
|
|
@@ -752,7 +800,9 @@ class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
752
800
|
|
|
753
801
|
related_obj_pks = []
|
|
754
802
|
for i, rel_obj_data in enumerate(data.get(field_name, [])):
|
|
755
|
-
|
|
803
|
+
# add parent object key to related object data
|
|
804
|
+
rel_obj_data[obj._meta.verbose_name.replace(" ", "_")] = str(obj.pk)
|
|
805
|
+
f = related_object_form(rel_obj_data)
|
|
756
806
|
|
|
757
807
|
for subfield_name, field in f.fields.items():
|
|
758
808
|
if subfield_name not in rel_obj_data and hasattr(field, "initial"):
|
|
@@ -1210,7 +1260,7 @@ class BulkDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
1210
1260
|
Delete objects in bulk.
|
|
1211
1261
|
|
|
1212
1262
|
queryset: Custom queryset to use when retrieving objects (e.g. to select related objects)
|
|
1213
|
-
|
|
1263
|
+
filterset: FilterSet to apply when deleting by QuerySet
|
|
1214
1264
|
table: The table used to display devices being deleted
|
|
1215
1265
|
form: The form class used to delete objects in bulk
|
|
1216
1266
|
template_name: The name of the template
|
|
@@ -1336,7 +1386,7 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|
|
1336
1386
|
return get_permission_for_model(self.queryset.model, "add")
|
|
1337
1387
|
|
|
1338
1388
|
def get(self, request):
|
|
1339
|
-
form = self.form(initial=request.GET)
|
|
1389
|
+
form = self.form(initial=normalize_querydict(request.GET, form_class=self.form))
|
|
1340
1390
|
model_form = self.model_form(request.GET)
|
|
1341
1391
|
|
|
1342
1392
|
return render(
|
|
@@ -1352,8 +1402,8 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|
|
1352
1402
|
|
|
1353
1403
|
def post(self, request):
|
|
1354
1404
|
logger = logging.getLogger(__name__ + ".ComponentCreateView")
|
|
1355
|
-
form = self.form(request.POST, initial=request.GET)
|
|
1356
|
-
model_form = self.model_form(request.POST)
|
|
1405
|
+
form = self.form(request.POST, initial=normalize_querydict(request.GET, form_class=self.form))
|
|
1406
|
+
model_form = self.model_form(request.POST, initial=normalize_querydict(request.GET, form_class=self.model_form))
|
|
1357
1407
|
|
|
1358
1408
|
if form.is_valid():
|
|
1359
1409
|
new_components = []
|
|
@@ -1368,7 +1418,9 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|
|
1368
1418
|
data["label"] = label
|
|
1369
1419
|
if hasattr(form, "get_iterative_data"):
|
|
1370
1420
|
data.update(form.get_iterative_data(i))
|
|
1371
|
-
component_form = self.model_form(
|
|
1421
|
+
component_form = self.model_form(
|
|
1422
|
+
data, initial=normalize_querydict(request.GET, form_class=self.model_form)
|
|
1423
|
+
)
|
|
1372
1424
|
|
|
1373
1425
|
if component_form.is_valid():
|
|
1374
1426
|
new_components.append(component_form)
|