nautobot 2.4.17__py3-none-any.whl → 2.4.19__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/ui.py +6 -0
- nautobot/apps/views.py +2 -0
- nautobot/circuits/tables.py +1 -1
- nautobot/circuits/templates/circuits/circuit_create.html +7 -7
- nautobot/circuits/templates/circuits/circuit_retrieve.html +1 -5
- nautobot/circuits/templates/circuits/circuittermination_create.html +26 -26
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -8
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +20 -20
- nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +3 -3
- nautobot/circuits/templates/circuits/inc/circuit_termination_speed_fragment.html +9 -0
- nautobot/circuits/templates/circuits/providernetwork_retrieve.html +1 -3
- nautobot/circuits/tests/integration/test_circuit.py +2 -2
- nautobot/circuits/views.py +49 -15
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +1 -4
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +1 -7
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +1 -3
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +1 -5
- nautobot/cloud/views.py +45 -0
- nautobot/core/filters.py +2 -2
- nautobot/core/graphql/generators.py +5 -2
- nautobot/core/jobs/bulk_actions.py +48 -85
- nautobot/core/models/querysets.py +2 -1
- nautobot/core/settings.py +1 -0
- nautobot/core/settings.yaml +9 -0
- nautobot/core/tables.py +21 -23
- nautobot/core/templates/40x.html +15 -15
- nautobot/core/templates/500.html +21 -21
- nautobot/core/templates/admin/app_index.html +8 -8
- nautobot/core/templates/admin/base.html +104 -104
- nautobot/core/templates/admin/change_form.html +65 -65
- nautobot/core/templates/admin/change_list.html +60 -60
- nautobot/core/templates/admin/change_list_results.html +39 -39
- nautobot/core/templates/admin/config/config.html +47 -47
- nautobot/core/templates/admin/delete_confirmation.html +47 -47
- nautobot/core/templates/admin/edit_inline/stacked.html +124 -124
- nautobot/core/templates/admin/edit_inline/tabular.html +60 -60
- nautobot/core/templates/admin/includes/fieldset.html +4 -4
- nautobot/core/templates/admin/index.html +60 -60
- nautobot/core/templates/admin/prepopulated_fields_js.html +18 -18
- nautobot/core/templates/admin/submit_line.html +4 -4
- nautobot/core/templates/base_django.html +46 -46
- nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +8 -8
- nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +8 -8
- nautobot/core/templates/buttons/export.html +3 -3
- nautobot/core/templates/components/breadcrumbs.html +19 -0
- nautobot/core/templates/components/button/default.html +3 -3
- nautobot/core/templates/components/button/dropdown.html +7 -7
- nautobot/core/templates/components/button/formbutton.html +4 -4
- nautobot/core/templates/components/panel/body_content_data_table.html +1 -1
- nautobot/core/templates/components/panel/body_wrapper_generic_table.html +3 -0
- nautobot/core/templates/components/panel/footer_content_table.html +3 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +10 -1
- nautobot/core/templates/components/tab/content_wrapper.html +1 -1
- nautobot/core/templates/components/tab/label_wrapper.html +1 -1
- nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +10 -3
- nautobot/core/templates/generic/object_bulk_add_component.html +40 -40
- nautobot/core/templates/generic/object_bulk_create.html +3 -3
- nautobot/core/templates/generic/object_bulk_destroy.html +6 -6
- nautobot/core/templates/generic/object_bulk_update.html +52 -52
- nautobot/core/templates/generic/object_changelog.html +0 -2
- nautobot/core/templates/generic/object_import.html +33 -33
- nautobot/core/templates/generic/object_list.html +271 -268
- nautobot/core/templates/generic/object_notes.html +0 -2
- nautobot/core/templates/generic/object_retrieve.html +264 -257
- nautobot/core/templates/graphene/graphiql.html +127 -127
- nautobot/core/templates/home.html +62 -62
- nautobot/core/templates/inc/computed_fields/panel_data.html +13 -13
- nautobot/core/templates/inc/created_updated.html +8 -8
- nautobot/core/templates/inc/custom_fields/panel_data.html +13 -13
- nautobot/core/templates/inc/dynamic_groups_panel.html +11 -11
- nautobot/core/templates/inc/footer.html +19 -19
- nautobot/core/templates/inc/javascript.html +1 -1
- nautobot/core/templates/inc/media.html +46 -46
- nautobot/core/templates/inc/nav_menu.html +1 -1
- nautobot/core/templates/inc/relationships_table_rows.html +22 -22
- nautobot/core/templates/inc/tenant_table_row.html +1 -1
- nautobot/core/templates/login.html +77 -77
- nautobot/core/templates/media_failure.html +38 -38
- nautobot/core/templates/panel_table.html +1 -1
- nautobot/core/templates/rest_framework/api.html +3 -3
- nautobot/core/templates/search.html +1 -1
- nautobot/core/templates/swagger_ui.html +9 -9
- nautobot/core/templates/utilities/confirmation_form.html +18 -18
- nautobot/core/templates/utilities/render_field.html +1 -1
- nautobot/core/templates/utilities/render_jinja2.html +43 -43
- nautobot/core/templates/utilities/templatetags/filter_form_modal.html +56 -56
- nautobot/core/templates/utilities/templatetags/utilization_graph.html +1 -1
- nautobot/core/templates/utilities/theme_preview.html +799 -799
- nautobot/core/templates/utilities/worker_status.html +122 -122
- nautobot/core/templates/widgets/clearable_file.html +3 -3
- nautobot/core/templates/widgets/sluginput.html +1 -1
- nautobot/core/templatetags/buttons.py +8 -2
- nautobot/core/templatetags/helpers.py +24 -0
- nautobot/core/templatetags/ui_framework.py +40 -5
- nautobot/core/testing/filters.py +37 -21
- nautobot/core/testing/integration.py +7 -4
- nautobot/core/testing/views.py +49 -5
- nautobot/core/tests/test_breadcrumbs.py +78 -4
- nautobot/core/tests/test_commands.py +7 -4
- nautobot/core/tests/test_graphql.py +20 -5
- nautobot/core/tests/test_jobs.py +34 -21
- nautobot/core/tests/test_tables.py +43 -6
- nautobot/core/tests/test_templatetags_ui_framework.py +146 -0
- nautobot/core/tests/test_titles.py +2 -2
- nautobot/core/tests/test_ui.py +188 -1
- nautobot/core/tests/test_utils.py +35 -0
- nautobot/core/tests/test_views.py +45 -0
- nautobot/core/tests/test_views_generic.py +43 -0
- nautobot/core/tests/test_views_utils.py +239 -5
- nautobot/core/ui/breadcrumbs.py +220 -28
- nautobot/core/ui/bulk_buttons.py +8 -0
- nautobot/core/ui/object_detail.py +181 -60
- nautobot/core/ui/titles.py +10 -5
- nautobot/core/utils/requests.py +27 -2
- nautobot/core/views/__init__.py +24 -3
- nautobot/core/views/generic.py +70 -35
- nautobot/core/views/mixins.py +226 -122
- nautobot/core/views/utils.py +270 -1
- nautobot/dcim/api/serializers.py +8 -2
- nautobot/dcim/constants.py +1 -0
- nautobot/dcim/factory.py +4 -3
- nautobot/dcim/filters/mixins.py +1 -2
- nautobot/dcim/forms.py +5 -1
- nautobot/dcim/migrations/0074_alter_rack_u_height.py +21 -0
- nautobot/dcim/models/devices.py +30 -1
- nautobot/dcim/models/racks.py +2 -2
- nautobot/dcim/tables/__init__.py +2 -0
- nautobot/dcim/tables/devices.py +24 -0
- nautobot/dcim/tables/power.py +2 -2
- nautobot/dcim/templates/dcim/cable.html +53 -53
- nautobot/dcim/templates/dcim/cable_connect.html +182 -182
- nautobot/dcim/templates/dcim/cable_trace.html +1 -1
- nautobot/dcim/templates/dcim/console_port_connection_list.html +5 -5
- nautobot/dcim/templates/dcim/consoleport.html +86 -86
- nautobot/dcim/templates/dcim/consoleserverport.html +86 -86
- nautobot/dcim/templates/dcim/controller_create.html +34 -34
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +68 -68
- nautobot/dcim/templates/dcim/device/base.html +1 -114
- nautobot/dcim/templates/dcim/device/config.html +17 -17
- nautobot/dcim/templates/dcim/device/consoleports.html +1 -52
- nautobot/dcim/templates/dcim/device/consoleserverports.html +1 -52
- nautobot/dcim/templates/dcim/device/devicebays.html +1 -48
- nautobot/dcim/templates/dcim/device/frontports.html +1 -52
- nautobot/dcim/templates/dcim/device/interfaces.html +1 -56
- nautobot/dcim/templates/dcim/device/inventory.html +1 -48
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +64 -64
- nautobot/dcim/templates/dcim/device/modulebays.html +1 -48
- nautobot/dcim/templates/dcim/device/poweroutlets.html +1 -52
- nautobot/dcim/templates/dcim/device/powerports.html +1 -52
- nautobot/dcim/templates/dcim/device/rearports.html +1 -52
- nautobot/dcim/templates/dcim/device/status.html +66 -66
- nautobot/dcim/templates/dcim/device/wireless.html +1 -72
- nautobot/dcim/templates/dcim/device.html +4 -422
- nautobot/dcim/templates/dcim/device_component.html +0 -19
- nautobot/dcim/templates/dcim/device_component_add.html +25 -25
- nautobot/dcim/templates/dcim/device_create.html +229 -0
- nautobot/dcim/templates/dcim/device_edit.html +2 -227
- nautobot/dcim/templates/dcim/devicebay.html +41 -41
- nautobot/dcim/templates/dcim/devicebay_populate.html +32 -32
- nautobot/dcim/templates/dcim/devicetype_component_add.html +28 -28
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -3
- nautobot/dcim/templates/dcim/frontport.html +84 -84
- nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
- nautobot/dcim/templates/dcim/inc/device_interface_filter.html +8 -0
- nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +1 -15
- nautobot/dcim/templates/dcim/inc/location_hierarchy.html +22 -22
- nautobot/dcim/templates/dcim/interface.html +206 -206
- nautobot/dcim/templates/dcim/interface_connection_list.html +5 -5
- nautobot/dcim/templates/dcim/interfaceredundancygroupassociation_create.html +6 -6
- nautobot/dcim/templates/dcim/inventoryitem.html +44 -44
- nautobot/dcim/templates/dcim/inventoryitem_add.html +32 -32
- nautobot/dcim/templates/dcim/inventoryitem_edit.html +22 -22
- nautobot/dcim/templates/dcim/location_migrate_data_to_contact.html +46 -46
- nautobot/dcim/templates/dcim/location_retrieve.html +1 -7
- nautobot/dcim/templates/dcim/locationtype.html +1 -6
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +1 -7
- nautobot/dcim/templates/dcim/module/base.html +85 -85
- nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
- nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
- nautobot/dcim/templates/dcim/module_retrieve.html +52 -52
- nautobot/dcim/templates/dcim/module_update.html +61 -61
- nautobot/dcim/templates/dcim/modulebay_destroy.html +1 -1
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +83 -99
- nautobot/dcim/templates/dcim/modulebay_update.html +33 -33
- nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +140 -144
- nautobot/dcim/templates/dcim/platform_create.html +38 -38
- nautobot/dcim/templates/dcim/power_port_connection_list.html +5 -5
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -8
- nautobot/dcim/templates/dcim/poweroutlet.html +85 -85
- nautobot/dcim/templates/dcim/powerpanel_retrieve.html +1 -8
- nautobot/dcim/templates/dcim/powerport.html +91 -91
- nautobot/dcim/templates/dcim/rack_elevation_list.html +18 -18
- nautobot/dcim/templates/dcim/rack_retrieve.html +264 -274
- nautobot/dcim/templates/dcim/rackreservation_retrieve.html +0 -3
- nautobot/dcim/templates/dcim/rearport.html +78 -78
- nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +1 -50
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +1 -5
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +3 -2
- nautobot/dcim/tests/integration/test_location_bulk_operations.py +6 -2
- nautobot/dcim/tests/test_api.py +33 -1
- nautobot/dcim/tests/test_views.py +189 -4
- nautobot/dcim/ui.py +29 -0
- nautobot/dcim/urls.py +1 -109
- nautobot/dcim/utils.py +30 -0
- nautobot/dcim/views.py +1149 -550
- nautobot/extras/filters/mixins.py +1 -1
- nautobot/extras/forms/forms.py +15 -0
- nautobot/extras/models/groups.py +10 -1
- nautobot/extras/models/jobs.py +2 -2
- nautobot/extras/plugins/views.py +18 -5
- nautobot/extras/tables.py +24 -2
- nautobot/extras/templates/extras/computedfield_edit.html +4 -4
- nautobot/extras/templates/extras/configcontext_update.html +1 -1
- nautobot/extras/templates/extras/configcontextschema_retrieve.html +32 -32
- nautobot/extras/templates/extras/customfield_retrieve.html +1 -128
- nautobot/extras/templates/extras/customfield_update.html +23 -23
- nautobot/extras/templates/extras/dynamicgroup.html +2 -99
- nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -199
- nautobot/extras/templates/extras/dynamicgroup_retrieve.html +99 -0
- nautobot/extras/templates/extras/dynamicgroup_update.html +199 -0
- nautobot/extras/templates/extras/gitrepository.html +2 -82
- nautobot/extras/templates/extras/gitrepository_list.html +10 -10
- nautobot/extras/templates/extras/gitrepository_object_edit.html +2 -13
- nautobot/extras/templates/extras/gitrepository_retrieve.html +82 -0
- nautobot/extras/templates/extras/gitrepository_update.html +13 -0
- nautobot/extras/templates/extras/graphqlquery_retrieve.html +73 -73
- nautobot/extras/templates/extras/inc/configcontext_format.html +2 -2
- nautobot/extras/templates/extras/inc/job_table.html +10 -10
- nautobot/extras/templates/extras/inc/jobresult.html +21 -21
- nautobot/extras/templates/extras/inc/jobresult_js.html +6 -6
- nautobot/extras/templates/extras/inc/tags_panel.html +10 -10
- nautobot/extras/templates/extras/job.html +64 -64
- nautobot/extras/templates/extras/job_approval_request.html +9 -9
- nautobot/extras/templates/extras/job_bulk_edit.html +13 -13
- nautobot/extras/templates/extras/job_edit.html +45 -45
- nautobot/extras/templates/extras/job_list.html +4 -4
- nautobot/extras/templates/extras/jobresult_retrieve.html +0 -25
- nautobot/extras/templates/extras/marketplace.html +101 -101
- nautobot/extras/templates/extras/metadatatype_create.html +20 -20
- nautobot/extras/templates/extras/note_retrieve.html +0 -52
- nautobot/extras/templates/extras/object_assign_contact_or_team.html +18 -18
- nautobot/extras/templates/extras/object_configcontext.html +1 -3
- nautobot/extras/templates/extras/objectchange.html +2 -165
- nautobot/extras/templates/extras/objectchange_retrieve.html +165 -0
- nautobot/extras/templates/extras/plugin_detail.html +44 -48
- nautobot/extras/templates/extras/plugins_list.html +9 -11
- nautobot/extras/templates/extras/plugins_tiles.html +26 -26
- nautobot/extras/templates/extras/relationship_edit.html +4 -4
- nautobot/extras/templates/extras/role_retrieve.html +13 -13
- nautobot/extras/templates/extras/scheduled_jobs_approval_queue_list.html +21 -21
- nautobot/extras/templates/extras/scheduledjob.html +128 -128
- nautobot/extras/templates/extras/secret_create.html +53 -53
- nautobot/extras/templates/extras/secretsgroup_update.html +13 -13
- nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +3 -3
- nautobot/extras/templates/extras/webhook.html +79 -79
- nautobot/extras/tests/integration/test_relationships.py +6 -6
- nautobot/extras/tests/test_dynamicgroups.py +73 -18
- nautobot/extras/tests/test_filters.py +1 -1
- nautobot/extras/tests/test_jobs.py +2 -0
- nautobot/extras/tests/test_views.py +8 -3
- nautobot/extras/urls.py +3 -97
- nautobot/extras/views.py +524 -456
- nautobot/ipam/filters.py +2 -2
- nautobot/ipam/migrations/0053_alter_vrfdeviceassignment_options_and_more.py +20 -0
- nautobot/ipam/models.py +34 -0
- nautobot/ipam/querysets.py +3 -3
- nautobot/ipam/signals.py +6 -1
- nautobot/ipam/tables.py +3 -1
- nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +4 -0
- nautobot/ipam/templates/ipam/inc/toggle_available.html +8 -8
- nautobot/ipam/templates/ipam/inc/vlangroup_header.html +4 -4
- nautobot/ipam/templates/ipam/ipaddress.html +119 -123
- nautobot/ipam/templates/ipam/ipaddress_assign.html +10 -10
- nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -1
- nautobot/ipam/templates/ipam/ipaddress_merge.html +180 -180
- nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +48 -48
- nautobot/ipam/templates/ipam/prefix.html +2 -115
- nautobot/ipam/templates/ipam/prefix_create.html +34 -0
- nautobot/ipam/templates/ipam/prefix_edit.html +1 -34
- nautobot/ipam/templates/ipam/prefix_retrieve.html +3 -0
- nautobot/ipam/templates/ipam/service_retrieve.html +1 -6
- nautobot/ipam/templates/ipam/vlan_retrieve.html +1 -7
- nautobot/ipam/templates/ipam/vrf_edit.html +1 -1
- nautobot/ipam/tests/test_api.py +5 -0
- nautobot/ipam/tests/test_models.py +387 -0
- nautobot/ipam/tests/test_querysets.py +46 -0
- nautobot/ipam/tests/test_views.py +34 -0
- nautobot/ipam/ui.py +145 -0
- nautobot/ipam/urls.py +1 -46
- nautobot/ipam/utils/__init__.py +26 -0
- nautobot/ipam/utils/migrations.py +1 -1
- nautobot/ipam/views.py +234 -112
- nautobot/project-static/docs/404.html +11 -11
- nautobot/project-static/docs/apps/index.html +11 -11
- nautobot/project-static/docs/apps/nautobot-apps.html +11 -11
- nautobot/project-static/docs/assets/javascripts/{bundle.92b07e13.min.js → bundle.f55a23d4.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.92b07e13.min.js.map → bundle.f55a23d4.min.js.map} +2 -2
- nautobot/project-static/docs/assets/stylesheets/{main.7e37652d.min.css → main.e53b48f4.min.css} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.7e37652d.min.css.map → main.e53b48f4.min.css.map} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +83 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1265 -281
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +12 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +452 -29
- nautobot/project-static/docs/development/apps/api/configuration-view.html +11 -11
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +11 -11
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +11 -11
- nautobot/project-static/docs/development/apps/api/models/global-search.html +11 -11
- nautobot/project-static/docs/development/apps/api/models/graphql.html +11 -11
- nautobot/project-static/docs/development/apps/api/models/index.html +11 -11
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +12 -12
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/prepopulating-data.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +11 -11
- nautobot/project-static/docs/development/apps/api/prometheus.html +11 -11
- nautobot/project-static/docs/development/apps/api/setup.html +11 -11
- nautobot/project-static/docs/development/apps/api/testing.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/base-template.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/index.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/notes.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/urls.html +11 -11
- nautobot/project-static/docs/development/apps/index.html +11 -11
- nautobot/project-static/docs/development/apps/migration/code-updates.html +11 -11
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +11 -11
- nautobot/project-static/docs/development/apps/migration/from-v1.html +11 -11
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +11 -11
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +11 -11
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +11 -11
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +11 -11
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +11 -11
- nautobot/project-static/docs/development/core/application-registry.html +11 -11
- nautobot/project-static/docs/development/core/best-practices.html +11 -11
- nautobot/project-static/docs/development/core/bootstrap-ui.html +11 -11
- nautobot/project-static/docs/development/core/caching.html +11 -11
- nautobot/project-static/docs/development/core/controllers.html +11 -11
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +11 -11
- nautobot/project-static/docs/development/core/generic-views.html +11 -11
- nautobot/project-static/docs/development/core/getting-started.html +50 -63
- nautobot/project-static/docs/development/core/homepage.html +11 -11
- nautobot/project-static/docs/development/core/index.html +11 -11
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +11 -11
- nautobot/project-static/docs/development/core/model-checklist.html +11 -11
- nautobot/project-static/docs/development/core/model-features.html +11 -11
- nautobot/project-static/docs/development/core/natural-keys.html +11 -11
- nautobot/project-static/docs/development/core/navigation-menu.html +11 -11
- nautobot/project-static/docs/development/core/release-checklist.html +11 -11
- nautobot/project-static/docs/development/core/role-internals.html +11 -11
- nautobot/project-static/docs/development/core/settings.html +11 -11
- nautobot/project-static/docs/development/core/style-guide.html +15 -11
- nautobot/project-static/docs/development/core/templates.html +11 -11
- nautobot/project-static/docs/development/core/testing.html +11 -11
- nautobot/project-static/docs/development/core/ui-component-framework.html +17 -22
- nautobot/project-static/docs/development/core/user-preferences.html +11 -11
- nautobot/project-static/docs/development/index.html +11 -11
- nautobot/project-static/docs/development/jobs/getting-started.html +11 -11
- nautobot/project-static/docs/development/jobs/index.html +11 -11
- nautobot/project-static/docs/development/jobs/installation.html +11 -11
- nautobot/project-static/docs/development/jobs/job-extensions.html +11 -11
- nautobot/project-static/docs/development/jobs/job-logging.html +11 -11
- nautobot/project-static/docs/development/jobs/job-patterns.html +11 -11
- nautobot/project-static/docs/development/jobs/job-structure.html +11 -11
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +11 -11
- nautobot/project-static/docs/development/jobs/testing.html +11 -11
- nautobot/project-static/docs/index.html +11 -11
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +11 -11
- nautobot/project-static/docs/overview/design_philosophy.html +11 -11
- nautobot/project-static/docs/release-notes/index.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.0.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.1.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.2.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.3.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.4.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.5.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.6.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.0.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.1.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.2.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.3.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.4.html +418 -11
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +300 -300
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +38 -11
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +89 -14
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/index.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/services.html +11 -11
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +11 -11
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +11 -11
- nautobot/project-static/docs/user-guide/administration/security/index.html +11 -11
- nautobot/project-static/docs/user-guide/administration/security/notices.html +11 -11
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +11 -11
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +11 -11
- nautobot/project-static/docs/user-guide/index.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +11 -11
- nautobot/project-static/img/nautobot_icon.svg +32 -34
- nautobot/project-static/js/table_sorting_indicator.js +0 -2
- nautobot/tenancy/templates/tenancy/tenant.html +1 -7
- nautobot/tenancy/views.py +13 -0
- nautobot/users/templates/users/api_tokens.html +4 -4
- nautobot/users/templates/users/base.html +28 -28
- nautobot/virtualization/templates/virtualization/cluster.html +64 -64
- nautobot/virtualization/templates/virtualization/inc/virtualmachine_vminterface_filter.html +8 -0
- nautobot/virtualization/templates/virtualization/virtualmachine_component_add.html +25 -25
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +1 -251
- nautobot/virtualization/templates/virtualization/vminterface.html +70 -70
- nautobot/virtualization/urls.py +0 -12
- nautobot/virtualization/views.py +158 -54
- nautobot/wireless/templates/wireless/wirelessnetwork_create.html +13 -13
- nautobot/wireless/tests/integration/test_radio_profile.py +1 -1
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/METADATA +4 -4
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/RECORD +623 -607
- nautobot/core/templates/inc/breadcrumbs.html +0 -14
- nautobot/ipam/templates/ipam/prefix_ipaddresses.html +0 -11
- nautobot/ipam/templates/ipam/prefix_prefixes.html +0 -11
- nautobot/project-static/docs/requirements.txt +0 -14
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/NOTICE +0 -0
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/WHEEL +0 -0
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/entry_points.txt +0 -0
nautobot/core/testing/views.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import contextlib
|
|
2
|
+
import inspect
|
|
2
3
|
import re
|
|
3
4
|
from typing import Optional, Sequence
|
|
4
5
|
from unittest import mock, skipIf
|
|
@@ -9,8 +10,10 @@ from django.conf import settings
|
|
|
9
10
|
from django.contrib.contenttypes.models import ContentType
|
|
10
11
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
11
12
|
from django.core.validators import URLValidator
|
|
13
|
+
from django.db import connection
|
|
12
14
|
from django.db.models import ManyToManyField, Model, QuerySet
|
|
13
15
|
from django.test import override_settings, tag, TestCase as _TestCase
|
|
16
|
+
from django.test.utils import CaptureQueriesContext
|
|
14
17
|
from django.urls import NoReverseMatch, reverse
|
|
15
18
|
from django.utils.html import escape
|
|
16
19
|
from django.utils.http import urlencode
|
|
@@ -144,6 +147,10 @@ class ViewTestCases:
|
|
|
144
147
|
"""
|
|
145
148
|
|
|
146
149
|
custom_action_required_permissions = {}
|
|
150
|
+
# TODO: Expand to other relevant view types, e.g. 'list'.
|
|
151
|
+
allowed_number_of_tree_queries_per_view_type = {
|
|
152
|
+
"retrieve": 0,
|
|
153
|
+
}
|
|
147
154
|
|
|
148
155
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
149
156
|
def test_get_object_anonymous(self):
|
|
@@ -180,7 +187,8 @@ class ViewTestCases:
|
|
|
180
187
|
self.add_permissions(f"{self.model._meta.app_label}.view_{self.model._meta.model_name}")
|
|
181
188
|
|
|
182
189
|
# Try GET with model-level permission
|
|
183
|
-
|
|
190
|
+
with CaptureQueriesContext(connection) as capture_queries_context:
|
|
191
|
+
response = self.client.get(instance.get_absolute_url())
|
|
184
192
|
# The object's display name or string representation should appear in the response body
|
|
185
193
|
self.assertBodyContains(response, escape(getattr(instance, "display", str(instance))))
|
|
186
194
|
|
|
@@ -209,6 +217,22 @@ class ViewTestCases:
|
|
|
209
217
|
else:
|
|
210
218
|
self.assertBodyContains(response, escape(str(instance.cf.get(custom_field.key) or "")))
|
|
211
219
|
|
|
220
|
+
# Check that no more than the appropriate number of tree CTE queries have been run.
|
|
221
|
+
captured_tree_cte_queries = [
|
|
222
|
+
query["sql"] for query in capture_queries_context.captured_queries if "WITH RECURSIVE" in query["sql"]
|
|
223
|
+
]
|
|
224
|
+
_query_separator = "\n" + ("-" * 10) + "\n" + "NEXT QUERY" + "\n" + ("-" * 10)
|
|
225
|
+
self.assertEqual(
|
|
226
|
+
len(captured_tree_cte_queries),
|
|
227
|
+
self.allowed_number_of_tree_queries_per_view_type["retrieve"],
|
|
228
|
+
f"This view was expected to execute {self.allowed_number_of_tree_queries_per_view_type['retrieve']}"
|
|
229
|
+
f" recursive database queries but {len(captured_tree_cte_queries)} were executed."
|
|
230
|
+
f" If this is expected, please update the {self.__class__.__name__}.allowed_number_of_tree_queries_per_view_type['retrieve']"
|
|
231
|
+
" property. Care should be taken to only increase these numbers where necessary - recursive queries can become really"
|
|
232
|
+
" slow with bigger datasets."
|
|
233
|
+
f" The following queries were used:\n{_query_separator.join(captured_tree_cte_queries)}",
|
|
234
|
+
)
|
|
235
|
+
|
|
212
236
|
return response # for consumption by child test cases if desired
|
|
213
237
|
|
|
214
238
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=[])
|
|
@@ -776,6 +800,30 @@ class ViewTestCases:
|
|
|
776
800
|
response_body = response.content.decode(response.charset)
|
|
777
801
|
self.assertNotIn('<i class="mdi mdi-circle-small"></i>', response_body)
|
|
778
802
|
|
|
803
|
+
def test_model_properties_as_table_columns_are_not_orderable(self):
|
|
804
|
+
"""
|
|
805
|
+
Check for table columns that are property-based and not orderable.
|
|
806
|
+
"""
|
|
807
|
+
table_class = getattr(self.get_list_view(), "table_class", None)
|
|
808
|
+
if not table_class:
|
|
809
|
+
return
|
|
810
|
+
|
|
811
|
+
queryset = self._get_queryset()
|
|
812
|
+
table = table_class(queryset)
|
|
813
|
+
model_cls = table._meta.model
|
|
814
|
+
|
|
815
|
+
property_fields = {name for name, _ in inspect.getmembers(model_cls, lambda o: isinstance(o, property))}
|
|
816
|
+
|
|
817
|
+
for name, column in table.base_columns.items():
|
|
818
|
+
if hasattr(column, "order_by") and column.order_by:
|
|
819
|
+
continue
|
|
820
|
+
if name in property_fields and name != "pk":
|
|
821
|
+
with self.subTest(column_name=name):
|
|
822
|
+
self.assertFalse(
|
|
823
|
+
column.orderable,
|
|
824
|
+
f"On Table `{table_class.__name__}` the property-based column `{name}` should be orderable=False or use a custom order_by",
|
|
825
|
+
)
|
|
826
|
+
|
|
779
827
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
780
828
|
def test_list_objects_anonymous(self):
|
|
781
829
|
# Make the request as an unauthenticated user
|
|
@@ -1379,10 +1427,6 @@ class ViewTestCases:
|
|
|
1379
1427
|
# Expect a 200 status cause we are only rendering the bulk delete table after pressing Delete Selected button.
|
|
1380
1428
|
self.assertHttpStatus(response, 200)
|
|
1381
1429
|
response_body = utils.extract_page_body(response.content.decode(response.charset))
|
|
1382
|
-
# Check if all pks is not part of the html.
|
|
1383
|
-
self.assertNotIn(str(first_pk), response_body)
|
|
1384
|
-
self.assertNotIn(str(second_pk), response_body)
|
|
1385
|
-
self.assertNotIn(str(third_pk), response_body)
|
|
1386
1430
|
self.assertIn("<strong>Warning:</strong> The following operation will delete 2 ", response_body)
|
|
1387
1431
|
self.assertInHTML('<input type="hidden" name="_all" value="true" />', response_body)
|
|
1388
1432
|
|
|
@@ -12,11 +12,14 @@ from nautobot.core.testing import TestCase
|
|
|
12
12
|
from nautobot.core.ui.breadcrumbs import (
|
|
13
13
|
BaseBreadcrumbItem,
|
|
14
14
|
Breadcrumbs,
|
|
15
|
+
context_object_attr,
|
|
15
16
|
InstanceBreadcrumbItem,
|
|
17
|
+
InstanceParentBreadcrumbItem,
|
|
16
18
|
ModelBreadcrumbItem,
|
|
17
19
|
ViewNameBreadcrumbItem,
|
|
18
20
|
)
|
|
19
|
-
from nautobot.dcim.models import Device, LocationType
|
|
21
|
+
from nautobot.dcim.models import Device, Location, LocationType
|
|
22
|
+
from nautobot.extras.models import Status
|
|
20
23
|
|
|
21
24
|
|
|
22
25
|
class BreadcrumbItemsTestCase(TestCase):
|
|
@@ -150,6 +153,13 @@ class BreadcrumbItemsTestCase(TestCase):
|
|
|
150
153
|
self.assertEqual(url, test_case["expected_url"])
|
|
151
154
|
self.assertEqual(label, test_case["expected_label"])
|
|
152
155
|
|
|
156
|
+
def test_model_item_not_format_custom_label(self):
|
|
157
|
+
item = ModelBreadcrumbItem(model_key="object", label="custom LaBeL")
|
|
158
|
+
context = Context({"object": self.location_type})
|
|
159
|
+
|
|
160
|
+
_, label = item.as_pair(context)
|
|
161
|
+
self.assertEqual(label, "custom LaBeL")
|
|
162
|
+
|
|
153
163
|
def test_model_item_from_context(self):
|
|
154
164
|
"""Test breadcrumb item with model from context."""
|
|
155
165
|
item = ModelBreadcrumbItem(model_key="object")
|
|
@@ -209,6 +219,69 @@ class BreadcrumbItemsTestCase(TestCase):
|
|
|
209
219
|
self.assertEqual(url, "")
|
|
210
220
|
self.assertEqual(label, "")
|
|
211
221
|
|
|
222
|
+
def test_instance_item_not_add_title_casing(self):
|
|
223
|
+
context = Context({"object": LocationType.objects.create(name="custom name")})
|
|
224
|
+
item = InstanceBreadcrumbItem()
|
|
225
|
+
|
|
226
|
+
_, label = item.as_pair(context)
|
|
227
|
+
self.assertEqual(label, "custom name")
|
|
228
|
+
|
|
229
|
+
def test_instance_item_is_working_with_directly_passed_instance(self):
|
|
230
|
+
context = Context({})
|
|
231
|
+
instance = LocationType.objects.create(name="cUsToM CoUnTrY")
|
|
232
|
+
item = InstanceBreadcrumbItem(instance=instance)
|
|
233
|
+
|
|
234
|
+
url, label = item.as_pair(context)
|
|
235
|
+
self.assertEqual(url, f"/dcim/location-types/{instance.pk}/")
|
|
236
|
+
self.assertEqual(label, "cUsToM CoUnTrY")
|
|
237
|
+
|
|
238
|
+
def test_context_object_attr_works_with_various_breadcrumb_items(self):
|
|
239
|
+
parent_location_type = LocationType.objects.create(name="Country", nestable=True)
|
|
240
|
+
location_type = LocationType.objects.create(name="State", parent=parent_location_type)
|
|
241
|
+
status = Status.objects.get_for_model(Location).first()
|
|
242
|
+
location = Location.objects.create(name="Pomorskie", location_type=location_type, status=status)
|
|
243
|
+
|
|
244
|
+
context = Context({"object": location, "status": status})
|
|
245
|
+
|
|
246
|
+
item = InstanceBreadcrumbItem(instance=context_object_attr("location_type"))
|
|
247
|
+
url, label = item.as_pair(context)
|
|
248
|
+
self.assertEqual(url, f"/dcim/location-types/{location_type.pk}/")
|
|
249
|
+
self.assertEqual(label, "Country → State")
|
|
250
|
+
|
|
251
|
+
item = BaseBreadcrumbItem(label=context_object_attr("name", context_key="status"))
|
|
252
|
+
url, label = item.as_pair(context)
|
|
253
|
+
self.assertEqual(url, "")
|
|
254
|
+
self.assertEqual(label, status.name)
|
|
255
|
+
|
|
256
|
+
item = InstanceBreadcrumbItem(instance=context_object_attr("location_type.parent"))
|
|
257
|
+
url, label = item.as_pair(context)
|
|
258
|
+
self.assertEqual(url, f"/dcim/location-types/{parent_location_type.pk}/")
|
|
259
|
+
self.assertEqual(label, "Country")
|
|
260
|
+
|
|
261
|
+
def test_instance_parent_not_add_title_casing(self):
|
|
262
|
+
parent_location_type = LocationType.objects.create(name="cUsToM CoUnTrY", nestable=True)
|
|
263
|
+
context = Context({"object": LocationType.objects.create(name="custom name", parent=parent_location_type)})
|
|
264
|
+
item = InstanceParentBreadcrumbItem()
|
|
265
|
+
|
|
266
|
+
_, label = item.as_pair(context)
|
|
267
|
+
self.assertEqual(label, "cUsToM CoUnTrY")
|
|
268
|
+
|
|
269
|
+
def test_instance_parent_is_create_proper_url(self):
|
|
270
|
+
parent_location_type = LocationType.objects.create(name="Country", nestable=True)
|
|
271
|
+
location_type = LocationType.objects.create(name="State", parent=parent_location_type)
|
|
272
|
+
|
|
273
|
+
context = Context({"object": location_type})
|
|
274
|
+
|
|
275
|
+
item = InstanceParentBreadcrumbItem()
|
|
276
|
+
url, label = item.as_pair(context)
|
|
277
|
+
self.assertEqual(url, f"/dcim/location-types/?parent={parent_location_type.pk}")
|
|
278
|
+
self.assertEqual(label, "Country")
|
|
279
|
+
|
|
280
|
+
item = InstanceParentBreadcrumbItem(parent_query_param="location", parent_lookup_key="name")
|
|
281
|
+
url, label = item.as_pair(context)
|
|
282
|
+
self.assertEqual(url, "/dcim/location-types/?location=Country")
|
|
283
|
+
self.assertEqual(label, "Country")
|
|
284
|
+
|
|
212
285
|
|
|
213
286
|
class BreadcrumbsTestCase(TestCase):
|
|
214
287
|
"""Test cases for Breadcrumbs class."""
|
|
@@ -260,19 +333,20 @@ class BreadcrumbsTestCase(TestCase):
|
|
|
260
333
|
"list": [ViewNameBreadcrumbItem(view_name="", label="List Item")],
|
|
261
334
|
"detail": [ViewNameBreadcrumbItem(view_name="", label="Detail Item")],
|
|
262
335
|
}
|
|
336
|
+
context = Context({})
|
|
263
337
|
|
|
264
338
|
# Test specific action found
|
|
265
|
-
result = Breadcrumbs.get_items_for_action(test_items, "list", False)
|
|
339
|
+
result = Breadcrumbs().get_items_for_action(test_items, "list", False, context)
|
|
266
340
|
self.assertEqual(len(result), 1)
|
|
267
341
|
self.assertEqual(result[0].label, "List Item")
|
|
268
342
|
|
|
269
343
|
# Test fallback to detail when action not found and detail=True
|
|
270
|
-
result = Breadcrumbs.get_items_for_action(test_items, "nonexistent", True)
|
|
344
|
+
result = Breadcrumbs().get_items_for_action(test_items, "nonexistent", True, context)
|
|
271
345
|
self.assertEqual(len(result), 1)
|
|
272
346
|
self.assertEqual(result[0].label, "Detail Item")
|
|
273
347
|
|
|
274
348
|
# Test no fallback when detail=False
|
|
275
|
-
result = Breadcrumbs.get_items_for_action(test_items, "nonexistent", False)
|
|
349
|
+
result = Breadcrumbs().get_items_for_action(test_items, "nonexistent", False, context)
|
|
276
350
|
self.assertEqual(len(result), 0)
|
|
277
351
|
self.assertEqual(result, [])
|
|
278
352
|
|
|
@@ -29,10 +29,13 @@ class ManagementCommandTestCase(TestCase):
|
|
|
29
29
|
# status_code_to_endpoints = collections.defaultdict(list)
|
|
30
30
|
for view_name, value in endpoints_dict.items():
|
|
31
31
|
for endpoint in value:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
with self.subTest(endpoint=endpoint):
|
|
33
|
+
response = self.client.get(endpoint, follow=True)
|
|
34
|
+
self.assertHttpStatus(
|
|
35
|
+
response,
|
|
36
|
+
200,
|
|
37
|
+
f"{view_name}: {endpoint} returns status Code {response.status_code} instead of 200",
|
|
38
|
+
)
|
|
36
39
|
|
|
37
40
|
def test_check_job_approval_status_no_jobs(self):
|
|
38
41
|
out = StringIO()
|
|
@@ -11,7 +11,7 @@ from django.contrib.auth.models import Group
|
|
|
11
11
|
from django.contrib.contenttypes.models import ContentType
|
|
12
12
|
from django.core.cache import cache
|
|
13
13
|
from django.db.models import Count, Q
|
|
14
|
-
from django.test import override_settings
|
|
14
|
+
from django.test import override_settings
|
|
15
15
|
from django.test.client import RequestFactory
|
|
16
16
|
from django.urls import reverse
|
|
17
17
|
import graphene.types
|
|
@@ -38,7 +38,7 @@ from nautobot.core.graphql.schema import (
|
|
|
38
38
|
)
|
|
39
39
|
from nautobot.core.graphql.types import DateType, OptimizedNautobotObjectType
|
|
40
40
|
from nautobot.core.graphql.utils import str_to_var_name
|
|
41
|
-
from nautobot.core.testing import create_test_user, NautobotTestClient
|
|
41
|
+
from nautobot.core.testing import create_test_user, NautobotTestClient, TestCase
|
|
42
42
|
from nautobot.dcim.choices import ConsolePortTypeChoices, InterfaceModeChoices, InterfaceTypeChoices, PortTypeChoices
|
|
43
43
|
from nautobot.dcim.filters import DeviceFilterSet, LocationFilterSet
|
|
44
44
|
from nautobot.dcim.graphql.types import DeviceType as DeviceTypeGraphQL
|
|
@@ -1453,9 +1453,7 @@ query {
|
|
|
1453
1453
|
# Assert GraphQL returned properties match those expected
|
|
1454
1454
|
self.assertEqual(console_server_port_entry["connected_console_port"], connected_console_port)
|
|
1455
1455
|
|
|
1456
|
-
@skip(
|
|
1457
|
-
"Works in isolation, fails as part of the overall test suite due to issue #446, also something is broken with content types"
|
|
1458
|
-
)
|
|
1456
|
+
@skip("Works in isolation, fails as part of the overall test suite due to issue #446")
|
|
1459
1457
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
1460
1458
|
def test_query_relationship_associations(self):
|
|
1461
1459
|
"""Test queries involving relationship associations."""
|
|
@@ -2442,6 +2440,23 @@ query {
|
|
|
2442
2440
|
expected_interfaces_first = {"ip_addresses": [{"primary_ip4_for": [{"id": str(self.device1.id)}]}]}
|
|
2443
2441
|
self.assertEqual(result.data["device"]["interfaces"][0], expected_interfaces_first)
|
|
2444
2442
|
|
|
2443
|
+
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
2444
|
+
def test_query_optimizer_reverse_lookup(self):
|
|
2445
|
+
"""
|
|
2446
|
+
Test query optimization in the case of a query mixing reverse and forward nested lookups.
|
|
2447
|
+
|
|
2448
|
+
See https://github.com/nautobot/nautobot/issues/7651.
|
|
2449
|
+
"""
|
|
2450
|
+
query = """query { tenant_groups { name tenants { name } } }"""
|
|
2451
|
+
# Prewarm caches of Relationships and such to reduce variation in the number of queries below
|
|
2452
|
+
result = self.execute_query(query)
|
|
2453
|
+
self.assertNotIn("error", str(result))
|
|
2454
|
+
# Run it again and assert that the optimized query is run.
|
|
2455
|
+
# Before the fix for #7651 this would result in N+1 queries where N is the number of tenant-groups!
|
|
2456
|
+
with self.assertNumQueries(2):
|
|
2457
|
+
result = self.execute_query(query)
|
|
2458
|
+
self.assertNotIn("error", str(result))
|
|
2459
|
+
|
|
2445
2460
|
|
|
2446
2461
|
class GraphQLTypeTestCase(UnitTestTestCase):
|
|
2447
2462
|
def test_date_type(self):
|
nautobot/core/tests/test_jobs.py
CHANGED
|
@@ -798,7 +798,8 @@ class BulkEditTestCase(TransactionTestCase):
|
|
|
798
798
|
"BulkEditObjects",
|
|
799
799
|
content_type=self.role_ct.id,
|
|
800
800
|
edit_all=False,
|
|
801
|
-
filter_query_params={"per_page": 2},
|
|
801
|
+
filter_query_params={"per_page": [2]},
|
|
802
|
+
pk_list=pk_list,
|
|
802
803
|
form_data={"pk": pk_list, "color": "aa1409"},
|
|
803
804
|
username=self.user.username,
|
|
804
805
|
)
|
|
@@ -818,7 +819,8 @@ class BulkEditTestCase(TransactionTestCase):
|
|
|
818
819
|
"BulkEditObjects",
|
|
819
820
|
content_type=self.role_ct.id,
|
|
820
821
|
edit_all=False,
|
|
821
|
-
|
|
822
|
+
pk_list=pk_list,
|
|
823
|
+
filter_query_params={"sort": ["name"]},
|
|
822
824
|
form_data={"pk": pk_list, "color": "aa1409"},
|
|
823
825
|
username=self.user.username,
|
|
824
826
|
)
|
|
@@ -872,6 +874,7 @@ class BulkEditTestCase(TransactionTestCase):
|
|
|
872
874
|
content_type=self.namespace_ct.id,
|
|
873
875
|
edit_all=False,
|
|
874
876
|
filter_query_params={},
|
|
877
|
+
pk_list=pk_list,
|
|
875
878
|
form_data={
|
|
876
879
|
"pk": pk_list,
|
|
877
880
|
"description": "Example description for bulk edit",
|
|
@@ -969,15 +972,16 @@ class BulkEditTestCase(TransactionTestCase):
|
|
|
969
972
|
"nautobot.core.jobs.bulk_actions",
|
|
970
973
|
"BulkEditObjects",
|
|
971
974
|
content_type=self.status_ct.id,
|
|
972
|
-
edit_all=
|
|
973
|
-
filter_query_params={"name__isw": "A", "sort": "name"},
|
|
975
|
+
edit_all=True,
|
|
976
|
+
filter_query_params={"name__isw": ["A"], "sort": ["name"]},
|
|
977
|
+
pk_list=[str(statuses[0].pk)],
|
|
974
978
|
form_data={
|
|
975
979
|
"pk": [str(statuses[0].pk)],
|
|
976
980
|
"color": "aa1409",
|
|
977
981
|
},
|
|
978
982
|
username=self.user.username,
|
|
979
983
|
)
|
|
980
|
-
self._common_no_error_test_assertion(Status, job_result,
|
|
984
|
+
self._common_no_error_test_assertion(Status, job_result, len(statuses), name__istartswith="A", color="aa1409")
|
|
981
985
|
self.assertNotEqual(status_to_ignore.color, "aa1409")
|
|
982
986
|
|
|
983
987
|
def test_bulk_edit_objects_passing_in_both_pk_list_and_edit_all(self):
|
|
@@ -994,7 +998,7 @@ class BulkEditTestCase(TransactionTestCase):
|
|
|
994
998
|
"BulkEditObjects",
|
|
995
999
|
content_type=self.status_ct.id,
|
|
996
1000
|
edit_all=True,
|
|
997
|
-
filter_query_params={"name__isw": "A"},
|
|
1001
|
+
filter_query_params={"name__isw": ["A"]},
|
|
998
1002
|
# pk ignored if edit_all is True
|
|
999
1003
|
form_data={
|
|
1000
1004
|
"pk": [str(statuses[0].pk)],
|
|
@@ -1110,9 +1114,12 @@ class BulkDeleteTestCase(TransactionTestCase):
|
|
|
1110
1114
|
job_result = create_job_result_and_run_job(
|
|
1111
1115
|
"nautobot.core.jobs.bulk_actions",
|
|
1112
1116
|
"BulkDeleteObjects",
|
|
1117
|
+
username=self.user.username,
|
|
1113
1118
|
content_type=self.status_ct.id,
|
|
1119
|
+
delete_all=False,
|
|
1120
|
+
filter_query_params={},
|
|
1114
1121
|
pk_list=statuses_to_delete,
|
|
1115
|
-
|
|
1122
|
+
saved_view_id=None,
|
|
1116
1123
|
)
|
|
1117
1124
|
self.assertJobResultStatus(job_result, JobResultStatusChoices.STATUS_FAILURE)
|
|
1118
1125
|
job_log = JobLogEntry.objects.get(job_result=job_result, log_level=LogLevelChoices.LOG_ERROR)
|
|
@@ -1129,19 +1136,19 @@ class BulkDeleteTestCase(TransactionTestCase):
|
|
|
1129
1136
|
obj_perm.save()
|
|
1130
1137
|
obj_perm.users.add(self.user)
|
|
1131
1138
|
obj_perm.object_types.add(ContentType.objects.get_for_model(Status))
|
|
1132
|
-
|
|
1133
1139
|
job_result = create_job_result_and_run_job(
|
|
1134
1140
|
"nautobot.core.jobs.bulk_actions",
|
|
1135
1141
|
"BulkDeleteObjects",
|
|
1142
|
+
username=self.user.username,
|
|
1136
1143
|
content_type=self.status_ct.id,
|
|
1144
|
+
delete_all=False,
|
|
1145
|
+
filter_query_params={},
|
|
1137
1146
|
pk_list=statuses_to_delete,
|
|
1138
|
-
|
|
1147
|
+
saved_view_id=None,
|
|
1139
1148
|
)
|
|
1140
1149
|
self.assertJobResultStatus(job_result, JobResultStatusChoices.STATUS_FAILURE)
|
|
1141
1150
|
error_log = JobLogEntry.objects.get(job_result=job_result, log_level=LogLevelChoices.LOG_ERROR)
|
|
1142
|
-
self.
|
|
1143
|
-
error_log.message, "You do not have permissions to delete some of the objects provided in `pk_list`."
|
|
1144
|
-
)
|
|
1151
|
+
self.assertIn("Cannot delete some instances of model", error_log.message)
|
|
1145
1152
|
self.assertEqual(Status.objects.filter(pk__in=statuses_to_delete).count(), len(statuses_to_delete))
|
|
1146
1153
|
|
|
1147
1154
|
def test_bulk_delete_objects_select_all(self):
|
|
@@ -1155,11 +1162,12 @@ class BulkDeleteTestCase(TransactionTestCase):
|
|
|
1155
1162
|
job_result = create_job_result_and_run_job(
|
|
1156
1163
|
"nautobot.core.jobs.bulk_actions",
|
|
1157
1164
|
"BulkDeleteObjects",
|
|
1165
|
+
username=self.user.username,
|
|
1158
1166
|
content_type=ContentType.objects.get_for_model(Circuit).id,
|
|
1159
1167
|
delete_all=True,
|
|
1160
|
-
filter_query_params={"per_page": 10},
|
|
1168
|
+
filter_query_params={"per_page": [10]},
|
|
1161
1169
|
pk_list=[],
|
|
1162
|
-
|
|
1170
|
+
saved_view_id=None,
|
|
1163
1171
|
)
|
|
1164
1172
|
self._common_no_error_test_assertion(Circuit, job_result)
|
|
1165
1173
|
|
|
@@ -1174,11 +1182,12 @@ class BulkDeleteTestCase(TransactionTestCase):
|
|
|
1174
1182
|
job_result = create_job_result_and_run_job(
|
|
1175
1183
|
"nautobot.core.jobs.bulk_actions",
|
|
1176
1184
|
"BulkDeleteObjects",
|
|
1185
|
+
username=self.user.username,
|
|
1177
1186
|
content_type=self.role_ct.id,
|
|
1178
1187
|
delete_all=False,
|
|
1179
1188
|
filter_query_params={},
|
|
1180
1189
|
pk_list=roles_pks,
|
|
1181
|
-
|
|
1190
|
+
saved_view_id=None,
|
|
1182
1191
|
)
|
|
1183
1192
|
self._common_no_error_test_assertion(Role, job_result, pk__in=roles_pks)
|
|
1184
1193
|
self.assertTrue(Role.objects.filter(name=roles_to_ignore.name).exists())
|
|
@@ -1192,10 +1201,12 @@ class BulkDeleteTestCase(TransactionTestCase):
|
|
|
1192
1201
|
job_result = create_job_result_and_run_job(
|
|
1193
1202
|
"nautobot.core.jobs.bulk_actions",
|
|
1194
1203
|
"BulkDeleteObjects",
|
|
1204
|
+
username=self.user.username,
|
|
1195
1205
|
content_type=self.status_ct.id,
|
|
1196
1206
|
delete_all=True,
|
|
1197
|
-
filter_query_params={"name__isw": "Example Status", "sort": "name"},
|
|
1198
|
-
|
|
1207
|
+
filter_query_params={"name__isw": ["Example Status"], "sort": ["name"]},
|
|
1208
|
+
pk_list=[],
|
|
1209
|
+
saved_view_id=None,
|
|
1199
1210
|
)
|
|
1200
1211
|
self._common_no_error_test_assertion(Status, job_result, name__istartswith="Example Status")
|
|
1201
1212
|
self.assertTrue(Status.objects.filter(name=status_to_ignore.name).exists())
|
|
@@ -1211,11 +1222,12 @@ class BulkDeleteTestCase(TransactionTestCase):
|
|
|
1211
1222
|
job_result = create_job_result_and_run_job(
|
|
1212
1223
|
"nautobot.core.jobs.bulk_actions",
|
|
1213
1224
|
"BulkDeleteObjects",
|
|
1225
|
+
username=self.user.username,
|
|
1214
1226
|
content_type=self.role_ct.id,
|
|
1215
1227
|
delete_all=False,
|
|
1216
|
-
filter_query_params={"name__isw": "Example Status"},
|
|
1228
|
+
filter_query_params={"name__isw": ["Example Status"]},
|
|
1217
1229
|
pk_list=roles_pks,
|
|
1218
|
-
|
|
1230
|
+
saved_view_id=None,
|
|
1219
1231
|
)
|
|
1220
1232
|
self._common_no_error_test_assertion(Role, job_result, pk__in=roles_pks)
|
|
1221
1233
|
self.assertTrue(Role.objects.filter(name=roles_to_ignore.name).exists())
|
|
@@ -1228,10 +1240,11 @@ class BulkDeleteTestCase(TransactionTestCase):
|
|
|
1228
1240
|
job_result = create_job_result_and_run_job(
|
|
1229
1241
|
"nautobot.core.jobs.bulk_actions",
|
|
1230
1242
|
"BulkDeleteObjects",
|
|
1243
|
+
username=self.user.username,
|
|
1231
1244
|
content_type=self.status_ct.pk,
|
|
1232
1245
|
delete_all=True,
|
|
1233
|
-
filter_query_params={"name__isw": "Example Status"
|
|
1246
|
+
filter_query_params={"name__isw": ["Example Status"]},
|
|
1234
1247
|
pk_list=[str(Status.objects.first().pk)],
|
|
1235
|
-
|
|
1248
|
+
saved_view_id=None,
|
|
1236
1249
|
)
|
|
1237
1250
|
self._common_no_error_test_assertion(Role, job_result, name__istartswith="Example Status")
|
|
@@ -18,8 +18,18 @@ class TableTestCase(TestCase):
|
|
|
18
18
|
def _validate_sorted_tree_queryset_same_with_table_queryset(self, queryset, table_class, field_name):
|
|
19
19
|
with self.subTest(f"Assert sorting {table_class.__name__} on '{field_name}'"):
|
|
20
20
|
table = table_class(queryset.with_tree_fields(), order_by=field_name)
|
|
21
|
-
table_queryset_data = table.data.data.values_list(
|
|
22
|
-
sorted_queryset =
|
|
21
|
+
table_queryset_data = table.data.data.values_list(field_name, flat=True)
|
|
22
|
+
sorted_queryset = (
|
|
23
|
+
queryset.with_tree_fields().extra(order_by=[field_name]).values_list(field_name, flat=True)
|
|
24
|
+
)
|
|
25
|
+
self.assertEqual(list(table_queryset_data), list(sorted_queryset))
|
|
26
|
+
|
|
27
|
+
with self.subTest(f"Assert sorting {table_class.__name__} on '-{field_name}'"):
|
|
28
|
+
table = table_class(queryset.with_tree_fields(), order_by=f"-{field_name}")
|
|
29
|
+
table_queryset_data = table.data.data.values_list(field_name, flat=True)
|
|
30
|
+
sorted_queryset = (
|
|
31
|
+
queryset.with_tree_fields().extra(order_by=[f"-{field_name}"]).values_list(field_name, flat=True)
|
|
32
|
+
)
|
|
23
33
|
self.assertEqual(list(table_queryset_data), list(sorted_queryset))
|
|
24
34
|
|
|
25
35
|
def test_tree_model_table_orderable(self):
|
|
@@ -61,14 +71,41 @@ class TableTestCase(TestCase):
|
|
|
61
71
|
table_avail_fields = set(model_field_names) & set(table_class.Meta.fields)
|
|
62
72
|
for table_field_name in table_avail_fields:
|
|
63
73
|
self._validate_sorted_tree_queryset_same_with_table_queryset(queryset, table_class, table_field_name)
|
|
64
|
-
self._validate_sorted_tree_queryset_same_with_table_queryset(
|
|
65
|
-
queryset, table_class, f"-{table_field_name}"
|
|
66
|
-
)
|
|
67
74
|
|
|
68
75
|
# Test for `rack_count`
|
|
69
76
|
queryset = RackGroupTable.Meta.model.objects.annotate(rack_count=count_related(Rack, "rack_group")).all()
|
|
70
77
|
self._validate_sorted_tree_queryset_same_with_table_queryset(queryset, RackGroupTable, "rack_count")
|
|
71
|
-
|
|
78
|
+
|
|
79
|
+
# https://github.com/nautobot/nautobot/issues/7330 - sorting by custom field
|
|
80
|
+
l1 = Location.objects.first()
|
|
81
|
+
l1._custom_field_data["example_app_auto_custom_field"] = "alpha"
|
|
82
|
+
l1.validated_save()
|
|
83
|
+
l2 = Location.objects.last()
|
|
84
|
+
l2._custom_field_data["example_app_auto_custom_field"] = "omega"
|
|
85
|
+
l2.validated_save()
|
|
86
|
+
table = LocationTable(
|
|
87
|
+
Location.objects.exclude(_custom_field_data__example_app_auto_custom_field="Default value")
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
table.order_by = ["cf_example_app_auto_custom_field"]
|
|
91
|
+
table_queryset_data = table.data.data.values_list("pk", flat=True)
|
|
92
|
+
sorted_queryset = (
|
|
93
|
+
Location.objects.with_tree_fields()
|
|
94
|
+
.exclude(_custom_field_data__example_app_auto_custom_field="Default value")
|
|
95
|
+
.extra(order_by=["_custom_field_data__example_app_auto_custom_field"])
|
|
96
|
+
.values_list("pk", flat=True)
|
|
97
|
+
)
|
|
98
|
+
self.assertEqual(list(table_queryset_data), list(sorted_queryset))
|
|
99
|
+
|
|
100
|
+
table.order_by = ["-cf_example_app_auto_custom_field"]
|
|
101
|
+
table_queryset_data = table.data.data.values_list("pk", flat=True)
|
|
102
|
+
sorted_queryset = (
|
|
103
|
+
Location.objects.with_tree_fields()
|
|
104
|
+
.exclude(_custom_field_data__example_app_auto_custom_field="Default value")
|
|
105
|
+
.extra(order_by=["-_custom_field_data__example_app_auto_custom_field"])
|
|
106
|
+
.values_list("pk", flat=True)
|
|
107
|
+
)
|
|
108
|
+
self.assertEqual(list(table_queryset_data), list(sorted_queryset))
|
|
72
109
|
|
|
73
110
|
def test_base_table_apis(self):
|
|
74
111
|
"""
|