nautobot 2.4.18__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.

Files changed (583) hide show
  1. nautobot/apps/ui.py +6 -0
  2. nautobot/circuits/tables.py +1 -1
  3. nautobot/circuits/templates/circuits/circuit_create.html +7 -7
  4. nautobot/circuits/templates/circuits/circuit_retrieve.html +1 -5
  5. nautobot/circuits/templates/circuits/circuittermination_create.html +26 -26
  6. nautobot/circuits/templates/circuits/inc/circuit_termination.html +20 -20
  7. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +3 -3
  8. nautobot/circuits/templates/circuits/inc/circuit_termination_speed_fragment.html +7 -7
  9. nautobot/circuits/templates/circuits/providernetwork_retrieve.html +1 -3
  10. nautobot/circuits/views.py +26 -9
  11. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +1 -4
  12. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +1 -7
  13. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +1 -3
  14. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +1 -5
  15. nautobot/cloud/views.py +45 -0
  16. nautobot/core/graphql/generators.py +5 -2
  17. nautobot/core/jobs/bulk_actions.py +48 -85
  18. nautobot/core/models/querysets.py +2 -1
  19. nautobot/core/templates/40x.html +15 -15
  20. nautobot/core/templates/500.html +21 -21
  21. nautobot/core/templates/admin/app_index.html +8 -8
  22. nautobot/core/templates/admin/base.html +104 -104
  23. nautobot/core/templates/admin/change_form.html +65 -65
  24. nautobot/core/templates/admin/change_list.html +60 -60
  25. nautobot/core/templates/admin/change_list_results.html +39 -39
  26. nautobot/core/templates/admin/config/config.html +47 -47
  27. nautobot/core/templates/admin/delete_confirmation.html +47 -47
  28. nautobot/core/templates/admin/edit_inline/stacked.html +124 -124
  29. nautobot/core/templates/admin/edit_inline/tabular.html +60 -60
  30. nautobot/core/templates/admin/includes/fieldset.html +4 -4
  31. nautobot/core/templates/admin/index.html +60 -60
  32. nautobot/core/templates/admin/prepopulated_fields_js.html +18 -18
  33. nautobot/core/templates/admin/submit_line.html +4 -4
  34. nautobot/core/templates/base_django.html +46 -46
  35. nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +8 -8
  36. nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +8 -8
  37. nautobot/core/templates/buttons/export.html +3 -3
  38. nautobot/core/templates/components/breadcrumbs.html +5 -5
  39. nautobot/core/templates/components/button/default.html +3 -3
  40. nautobot/core/templates/components/button/dropdown.html +7 -7
  41. nautobot/core/templates/components/button/formbutton.html +4 -4
  42. nautobot/core/templates/components/panel/body_content_data_table.html +1 -1
  43. nautobot/core/templates/components/panel/body_wrapper_generic_table.html +3 -0
  44. nautobot/core/templates/components/panel/footer_content_table.html +3 -1
  45. nautobot/core/templates/components/panel/header_extra_content_table.html +10 -1
  46. nautobot/core/templates/components/tab/content_wrapper.html +1 -1
  47. nautobot/core/templates/components/tab/label_wrapper.html +1 -1
  48. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +10 -3
  49. nautobot/core/templates/generic/object_bulk_add_component.html +40 -40
  50. nautobot/core/templates/generic/object_bulk_create.html +3 -3
  51. nautobot/core/templates/generic/object_bulk_destroy.html +6 -6
  52. nautobot/core/templates/generic/object_bulk_update.html +52 -52
  53. nautobot/core/templates/generic/object_import.html +33 -33
  54. nautobot/core/templates/generic/object_list.html +267 -267
  55. nautobot/core/templates/generic/object_retrieve.html +261 -261
  56. nautobot/core/templates/graphene/graphiql.html +127 -127
  57. nautobot/core/templates/home.html +62 -62
  58. nautobot/core/templates/inc/computed_fields/panel_data.html +13 -13
  59. nautobot/core/templates/inc/created_updated.html +8 -8
  60. nautobot/core/templates/inc/custom_fields/panel_data.html +13 -13
  61. nautobot/core/templates/inc/dynamic_groups_panel.html +11 -11
  62. nautobot/core/templates/inc/footer.html +19 -19
  63. nautobot/core/templates/inc/javascript.html +1 -1
  64. nautobot/core/templates/inc/media.html +46 -46
  65. nautobot/core/templates/inc/nav_menu.html +1 -1
  66. nautobot/core/templates/inc/relationships_table_rows.html +22 -22
  67. nautobot/core/templates/inc/tenant_table_row.html +1 -1
  68. nautobot/core/templates/login.html +77 -77
  69. nautobot/core/templates/media_failure.html +38 -38
  70. nautobot/core/templates/panel_table.html +1 -1
  71. nautobot/core/templates/rest_framework/api.html +3 -3
  72. nautobot/core/templates/search.html +1 -1
  73. nautobot/core/templates/swagger_ui.html +9 -9
  74. nautobot/core/templates/utilities/confirmation_form.html +18 -18
  75. nautobot/core/templates/utilities/render_field.html +1 -1
  76. nautobot/core/templates/utilities/render_jinja2.html +43 -43
  77. nautobot/core/templates/utilities/templatetags/filter_form_modal.html +56 -56
  78. nautobot/core/templates/utilities/templatetags/utilization_graph.html +1 -1
  79. nautobot/core/templates/utilities/theme_preview.html +799 -799
  80. nautobot/core/templates/utilities/worker_status.html +122 -122
  81. nautobot/core/templates/widgets/clearable_file.html +3 -3
  82. nautobot/core/templates/widgets/sluginput.html +1 -1
  83. nautobot/core/templatetags/buttons.py +8 -2
  84. nautobot/core/templatetags/helpers.py +1 -1
  85. nautobot/core/testing/integration.py +7 -4
  86. nautobot/core/testing/views.py +24 -5
  87. nautobot/core/tests/test_breadcrumbs.py +78 -4
  88. nautobot/core/tests/test_commands.py +7 -4
  89. nautobot/core/tests/test_graphql.py +20 -5
  90. nautobot/core/tests/test_jobs.py +34 -21
  91. nautobot/core/tests/test_ui.py +175 -1
  92. nautobot/core/tests/test_utils.py +35 -0
  93. nautobot/core/tests/test_views_generic.py +43 -0
  94. nautobot/core/tests/test_views_utils.py +239 -5
  95. nautobot/core/ui/breadcrumbs.py +208 -21
  96. nautobot/core/ui/bulk_buttons.py +8 -0
  97. nautobot/core/ui/object_detail.py +138 -55
  98. nautobot/core/ui/titles.py +1 -0
  99. nautobot/core/utils/requests.py +27 -2
  100. nautobot/core/views/generic.py +41 -31
  101. nautobot/core/views/mixins.py +80 -110
  102. nautobot/core/views/utils.py +153 -1
  103. nautobot/dcim/api/serializers.py +8 -2
  104. nautobot/dcim/constants.py +1 -0
  105. nautobot/dcim/factory.py +4 -3
  106. nautobot/dcim/filters/mixins.py +1 -2
  107. nautobot/dcim/forms.py +5 -1
  108. nautobot/dcim/migrations/0074_alter_rack_u_height.py +21 -0
  109. nautobot/dcim/models/devices.py +26 -1
  110. nautobot/dcim/models/racks.py +2 -2
  111. nautobot/dcim/templates/dcim/cable.html +53 -53
  112. nautobot/dcim/templates/dcim/cable_connect.html +182 -182
  113. nautobot/dcim/templates/dcim/cable_trace.html +1 -1
  114. nautobot/dcim/templates/dcim/console_port_connection_list.html +5 -5
  115. nautobot/dcim/templates/dcim/consoleport.html +86 -86
  116. nautobot/dcim/templates/dcim/consoleserverport.html +86 -86
  117. nautobot/dcim/templates/dcim/controller_create.html +34 -34
  118. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +68 -68
  119. nautobot/dcim/templates/dcim/device/base.html +1 -104
  120. nautobot/dcim/templates/dcim/device/config.html +17 -17
  121. nautobot/dcim/templates/dcim/device/consoleports.html +1 -52
  122. nautobot/dcim/templates/dcim/device/consoleserverports.html +1 -52
  123. nautobot/dcim/templates/dcim/device/devicebays.html +1 -48
  124. nautobot/dcim/templates/dcim/device/frontports.html +1 -52
  125. nautobot/dcim/templates/dcim/device/interfaces.html +1 -56
  126. nautobot/dcim/templates/dcim/device/inventory.html +1 -48
  127. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +64 -64
  128. nautobot/dcim/templates/dcim/device/modulebays.html +1 -48
  129. nautobot/dcim/templates/dcim/device/poweroutlets.html +1 -52
  130. nautobot/dcim/templates/dcim/device/powerports.html +1 -52
  131. nautobot/dcim/templates/dcim/device/rearports.html +1 -52
  132. nautobot/dcim/templates/dcim/device/status.html +66 -66
  133. nautobot/dcim/templates/dcim/device/wireless.html +1 -72
  134. nautobot/dcim/templates/dcim/device.html +4 -422
  135. nautobot/dcim/templates/dcim/device_component_add.html +25 -25
  136. nautobot/dcim/templates/dcim/device_create.html +229 -0
  137. nautobot/dcim/templates/dcim/device_edit.html +2 -227
  138. nautobot/dcim/templates/dcim/devicebay.html +41 -41
  139. nautobot/dcim/templates/dcim/devicebay_populate.html +32 -32
  140. nautobot/dcim/templates/dcim/devicetype_component_add.html +28 -28
  141. nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -3
  142. nautobot/dcim/templates/dcim/frontport.html +84 -84
  143. nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
  144. nautobot/dcim/templates/dcim/inc/device_interface_filter.html +8 -0
  145. nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +1 -15
  146. nautobot/dcim/templates/dcim/inc/location_hierarchy.html +22 -22
  147. nautobot/dcim/templates/dcim/interface.html +206 -206
  148. nautobot/dcim/templates/dcim/interface_connection_list.html +5 -5
  149. nautobot/dcim/templates/dcim/interfaceredundancygroupassociation_create.html +6 -6
  150. nautobot/dcim/templates/dcim/inventoryitem.html +44 -44
  151. nautobot/dcim/templates/dcim/inventoryitem_add.html +32 -32
  152. nautobot/dcim/templates/dcim/inventoryitem_edit.html +22 -22
  153. nautobot/dcim/templates/dcim/location_migrate_data_to_contact.html +46 -46
  154. nautobot/dcim/templates/dcim/location_retrieve.html +1 -7
  155. nautobot/dcim/templates/dcim/locationtype.html +1 -6
  156. nautobot/dcim/templates/dcim/locationtype_retrieve.html +1 -7
  157. nautobot/dcim/templates/dcim/module/base.html +85 -85
  158. nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
  159. nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
  160. nautobot/dcim/templates/dcim/module_retrieve.html +52 -52
  161. nautobot/dcim/templates/dcim/module_update.html +61 -61
  162. nautobot/dcim/templates/dcim/modulebay_destroy.html +1 -1
  163. nautobot/dcim/templates/dcim/modulebay_retrieve.html +85 -85
  164. nautobot/dcim/templates/dcim/modulebay_update.html +33 -33
  165. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
  166. nautobot/dcim/templates/dcim/moduletype_retrieve.html +140 -144
  167. nautobot/dcim/templates/dcim/platform_create.html +38 -38
  168. nautobot/dcim/templates/dcim/power_port_connection_list.html +5 -5
  169. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -8
  170. nautobot/dcim/templates/dcim/poweroutlet.html +85 -85
  171. nautobot/dcim/templates/dcim/powerpanel_retrieve.html +1 -8
  172. nautobot/dcim/templates/dcim/powerport.html +91 -91
  173. nautobot/dcim/templates/dcim/rack_elevation_list.html +18 -18
  174. nautobot/dcim/templates/dcim/rack_retrieve.html +264 -274
  175. nautobot/dcim/templates/dcim/rackreservation_retrieve.html +0 -3
  176. nautobot/dcim/templates/dcim/rearport.html +78 -78
  177. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +1 -5
  178. nautobot/dcim/tests/integration/test_device_bulk_operations.py +3 -2
  179. nautobot/dcim/tests/integration/test_location_bulk_operations.py +6 -2
  180. nautobot/dcim/tests/test_api.py +33 -1
  181. nautobot/dcim/tests/test_views.py +148 -4
  182. nautobot/dcim/ui.py +29 -0
  183. nautobot/dcim/urls.py +1 -109
  184. nautobot/dcim/utils.py +30 -0
  185. nautobot/dcim/views.py +1009 -531
  186. nautobot/extras/tables.py +20 -0
  187. nautobot/extras/templates/extras/computedfield_edit.html +4 -4
  188. nautobot/extras/templates/extras/configcontext_update.html +1 -1
  189. nautobot/extras/templates/extras/configcontextschema_retrieve.html +32 -32
  190. nautobot/extras/templates/extras/customfield_update.html +23 -23
  191. nautobot/extras/templates/extras/dynamicgroup_retrieve.html +38 -38
  192. nautobot/extras/templates/extras/dynamicgroup_update.html +62 -62
  193. nautobot/extras/templates/extras/gitrepository_list.html +10 -10
  194. nautobot/extras/templates/extras/gitrepository_retrieve.html +68 -68
  195. nautobot/extras/templates/extras/graphqlquery_retrieve.html +73 -73
  196. nautobot/extras/templates/extras/inc/configcontext_format.html +2 -2
  197. nautobot/extras/templates/extras/inc/job_table.html +10 -10
  198. nautobot/extras/templates/extras/inc/jobresult.html +21 -21
  199. nautobot/extras/templates/extras/inc/jobresult_js.html +6 -6
  200. nautobot/extras/templates/extras/inc/tags_panel.html +10 -10
  201. nautobot/extras/templates/extras/job.html +64 -64
  202. nautobot/extras/templates/extras/job_approval_request.html +9 -9
  203. nautobot/extras/templates/extras/job_bulk_edit.html +13 -13
  204. nautobot/extras/templates/extras/job_edit.html +45 -45
  205. nautobot/extras/templates/extras/job_list.html +4 -4
  206. nautobot/extras/templates/extras/jobresult_retrieve.html +0 -25
  207. nautobot/extras/templates/extras/marketplace.html +101 -101
  208. nautobot/extras/templates/extras/metadatatype_create.html +20 -20
  209. nautobot/extras/templates/extras/object_assign_contact_or_team.html +18 -18
  210. nautobot/extras/templates/extras/object_configcontext.html +1 -3
  211. nautobot/extras/templates/extras/objectchange.html +2 -165
  212. nautobot/extras/templates/extras/objectchange_retrieve.html +165 -0
  213. nautobot/extras/templates/extras/plugin_detail.html +41 -41
  214. nautobot/extras/templates/extras/plugins_list.html +9 -9
  215. nautobot/extras/templates/extras/plugins_tiles.html +26 -26
  216. nautobot/extras/templates/extras/relationship_edit.html +4 -4
  217. nautobot/extras/templates/extras/role_retrieve.html +13 -13
  218. nautobot/extras/templates/extras/scheduled_jobs_approval_queue_list.html +21 -21
  219. nautobot/extras/templates/extras/scheduledjob.html +128 -128
  220. nautobot/extras/templates/extras/secret_create.html +53 -53
  221. nautobot/extras/templates/extras/secretsgroup_update.html +13 -13
  222. nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +3 -3
  223. nautobot/extras/templates/extras/webhook.html +79 -79
  224. nautobot/extras/tests/integration/test_relationships.py +6 -6
  225. nautobot/extras/tests/test_filters.py +1 -1
  226. nautobot/extras/tests/test_jobs.py +2 -0
  227. nautobot/extras/tests/test_views.py +3 -3
  228. nautobot/extras/urls.py +1 -3
  229. nautobot/extras/views.py +101 -27
  230. nautobot/ipam/filters.py +2 -2
  231. nautobot/ipam/migrations/0053_alter_vrfdeviceassignment_options_and_more.py +20 -0
  232. nautobot/ipam/models.py +34 -0
  233. nautobot/ipam/tables.py +3 -1
  234. nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +4 -0
  235. nautobot/ipam/templates/ipam/inc/toggle_available.html +8 -8
  236. nautobot/ipam/templates/ipam/inc/vlangroup_header.html +4 -4
  237. nautobot/ipam/templates/ipam/ipaddress.html +119 -123
  238. nautobot/ipam/templates/ipam/ipaddress_assign.html +10 -10
  239. nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -1
  240. nautobot/ipam/templates/ipam/ipaddress_merge.html +180 -180
  241. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +48 -48
  242. nautobot/ipam/templates/ipam/prefix.html +2 -107
  243. nautobot/ipam/templates/ipam/prefix_create.html +34 -0
  244. nautobot/ipam/templates/ipam/prefix_edit.html +1 -34
  245. nautobot/ipam/templates/ipam/prefix_retrieve.html +3 -0
  246. nautobot/ipam/templates/ipam/service_retrieve.html +1 -6
  247. nautobot/ipam/templates/ipam/vlan_retrieve.html +1 -7
  248. nautobot/ipam/templates/ipam/vrf_edit.html +1 -1
  249. nautobot/ipam/tests/test_views.py +34 -0
  250. nautobot/ipam/ui.py +145 -0
  251. nautobot/ipam/urls.py +1 -46
  252. nautobot/ipam/utils/__init__.py +26 -0
  253. nautobot/ipam/views.py +219 -106
  254. nautobot/project-static/docs/404.html +11 -11
  255. nautobot/project-static/docs/apps/index.html +11 -11
  256. nautobot/project-static/docs/apps/nautobot-apps.html +11 -11
  257. nautobot/project-static/docs/assets/javascripts/{bundle.92b07e13.min.js → bundle.f55a23d4.min.js} +2 -2
  258. nautobot/project-static/docs/assets/javascripts/{bundle.92b07e13.min.js.map → bundle.f55a23d4.min.js.map} +2 -2
  259. nautobot/project-static/docs/assets/stylesheets/{main.7e37652d.min.css → main.e53b48f4.min.css} +1 -1
  260. nautobot/project-static/docs/assets/stylesheets/{main.7e37652d.min.css.map → main.e53b48f4.min.css.map} +1 -1
  261. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +11 -11
  262. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +11 -11
  263. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +11 -11
  264. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +11 -11
  265. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +11 -11
  266. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +11 -11
  267. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +11 -11
  268. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +11 -11
  269. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +11 -11
  270. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +11 -11
  271. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +11 -11
  272. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +11 -11
  273. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +11 -11
  274. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +11 -11
  275. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +11 -11
  276. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +11 -11
  277. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +11 -11
  278. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +11 -11
  279. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +11 -11
  280. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +11 -11
  281. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2174 -1226
  282. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +11 -11
  283. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +12 -12
  284. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +72 -27
  285. nautobot/project-static/docs/development/apps/api/configuration-view.html +11 -11
  286. nautobot/project-static/docs/development/apps/api/database-backend-config.html +11 -11
  287. nautobot/project-static/docs/development/apps/api/models/django-admin.html +11 -11
  288. nautobot/project-static/docs/development/apps/api/models/global-search.html +11 -11
  289. nautobot/project-static/docs/development/apps/api/models/graphql.html +11 -11
  290. nautobot/project-static/docs/development/apps/api/models/index.html +11 -11
  291. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +11 -11
  292. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +11 -11
  293. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +11 -11
  294. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +11 -11
  295. nautobot/project-static/docs/development/apps/api/platform-features/index.html +11 -11
  296. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +11 -11
  297. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +11 -11
  298. nautobot/project-static/docs/development/apps/api/platform-features/prepopulating-data.html +11 -11
  299. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +11 -11
  300. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +11 -11
  301. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +11 -11
  302. nautobot/project-static/docs/development/apps/api/prometheus.html +11 -11
  303. nautobot/project-static/docs/development/apps/api/setup.html +11 -11
  304. nautobot/project-static/docs/development/apps/api/testing.html +11 -11
  305. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +11 -11
  306. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +11 -11
  307. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +11 -11
  308. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +11 -11
  309. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +11 -11
  310. nautobot/project-static/docs/development/apps/api/views/base-template.html +11 -11
  311. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +11 -11
  312. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +11 -11
  313. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +11 -11
  314. nautobot/project-static/docs/development/apps/api/views/index.html +11 -11
  315. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +11 -11
  316. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +11 -11
  317. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +11 -11
  318. nautobot/project-static/docs/development/apps/api/views/notes.html +11 -11
  319. nautobot/project-static/docs/development/apps/api/views/rest-api.html +11 -11
  320. nautobot/project-static/docs/development/apps/api/views/urls.html +11 -11
  321. nautobot/project-static/docs/development/apps/index.html +11 -11
  322. nautobot/project-static/docs/development/apps/migration/code-updates.html +11 -11
  323. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +11 -11
  324. nautobot/project-static/docs/development/apps/migration/from-v1.html +11 -11
  325. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +11 -11
  326. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +11 -11
  327. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +11 -11
  328. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +11 -11
  329. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +11 -11
  330. nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +11 -11
  331. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +11 -11
  332. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +11 -11
  333. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +11 -11
  334. nautobot/project-static/docs/development/apps/porting-from-netbox.html +11 -11
  335. nautobot/project-static/docs/development/core/application-registry.html +11 -11
  336. nautobot/project-static/docs/development/core/best-practices.html +11 -11
  337. nautobot/project-static/docs/development/core/bootstrap-ui.html +11 -11
  338. nautobot/project-static/docs/development/core/caching.html +11 -11
  339. nautobot/project-static/docs/development/core/controllers.html +11 -11
  340. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +11 -11
  341. nautobot/project-static/docs/development/core/generic-views.html +11 -11
  342. nautobot/project-static/docs/development/core/getting-started.html +50 -48
  343. nautobot/project-static/docs/development/core/homepage.html +11 -11
  344. nautobot/project-static/docs/development/core/index.html +11 -11
  345. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +11 -11
  346. nautobot/project-static/docs/development/core/model-checklist.html +11 -11
  347. nautobot/project-static/docs/development/core/model-features.html +11 -11
  348. nautobot/project-static/docs/development/core/natural-keys.html +11 -11
  349. nautobot/project-static/docs/development/core/navigation-menu.html +11 -11
  350. nautobot/project-static/docs/development/core/release-checklist.html +11 -11
  351. nautobot/project-static/docs/development/core/role-internals.html +11 -11
  352. nautobot/project-static/docs/development/core/settings.html +11 -11
  353. nautobot/project-static/docs/development/core/style-guide.html +15 -11
  354. nautobot/project-static/docs/development/core/templates.html +11 -11
  355. nautobot/project-static/docs/development/core/testing.html +11 -11
  356. nautobot/project-static/docs/development/core/ui-component-framework.html +11 -11
  357. nautobot/project-static/docs/development/core/user-preferences.html +11 -11
  358. nautobot/project-static/docs/development/index.html +11 -11
  359. nautobot/project-static/docs/development/jobs/getting-started.html +11 -11
  360. nautobot/project-static/docs/development/jobs/index.html +11 -11
  361. nautobot/project-static/docs/development/jobs/installation.html +11 -11
  362. nautobot/project-static/docs/development/jobs/job-extensions.html +11 -11
  363. nautobot/project-static/docs/development/jobs/job-logging.html +11 -11
  364. nautobot/project-static/docs/development/jobs/job-patterns.html +11 -11
  365. nautobot/project-static/docs/development/jobs/job-structure.html +11 -11
  366. nautobot/project-static/docs/development/jobs/migration/from-v1.html +11 -11
  367. nautobot/project-static/docs/development/jobs/testing.html +11 -11
  368. nautobot/project-static/docs/index.html +11 -11
  369. nautobot/project-static/docs/objects.inv +0 -0
  370. nautobot/project-static/docs/overview/application_stack.html +11 -11
  371. nautobot/project-static/docs/overview/design_philosophy.html +11 -11
  372. nautobot/project-static/docs/release-notes/index.html +11 -11
  373. nautobot/project-static/docs/release-notes/version-1.0.html +11 -11
  374. nautobot/project-static/docs/release-notes/version-1.1.html +11 -11
  375. nautobot/project-static/docs/release-notes/version-1.2.html +11 -11
  376. nautobot/project-static/docs/release-notes/version-1.3.html +11 -11
  377. nautobot/project-static/docs/release-notes/version-1.4.html +11 -11
  378. nautobot/project-static/docs/release-notes/version-1.5.html +11 -11
  379. nautobot/project-static/docs/release-notes/version-1.6.html +11 -11
  380. nautobot/project-static/docs/release-notes/version-2.0.html +11 -11
  381. nautobot/project-static/docs/release-notes/version-2.1.html +11 -11
  382. nautobot/project-static/docs/release-notes/version-2.2.html +11 -11
  383. nautobot/project-static/docs/release-notes/version-2.3.html +11 -11
  384. nautobot/project-static/docs/release-notes/version-2.4.html +196 -11
  385. nautobot/project-static/docs/search/search_index.json +1 -1
  386. nautobot/project-static/docs/sitemap.xml +300 -300
  387. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  388. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +11 -11
  389. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +11 -11
  390. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +11 -11
  391. nautobot/project-static/docs/user-guide/administration/configuration/index.html +11 -11
  392. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +11 -11
  393. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +11 -11
  394. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +11 -11
  395. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +89 -14
  396. nautobot/project-static/docs/user-guide/administration/guides/docker.html +11 -11
  397. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +11 -11
  398. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +11 -11
  399. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +11 -11
  400. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +11 -11
  401. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +11 -11
  402. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +11 -11
  403. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +11 -11
  404. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +11 -11
  405. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +11 -11
  406. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +11 -11
  407. nautobot/project-static/docs/user-guide/administration/installation/index.html +11 -11
  408. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +11 -11
  409. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +11 -11
  410. nautobot/project-static/docs/user-guide/administration/installation/services.html +11 -11
  411. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +11 -11
  412. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +11 -11
  413. nautobot/project-static/docs/user-guide/administration/security/index.html +11 -11
  414. nautobot/project-static/docs/user-guide/administration/security/notices.html +11 -11
  415. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +11 -11
  416. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +11 -11
  417. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +11 -11
  418. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +11 -11
  419. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +11 -11
  420. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +11 -11
  421. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +11 -11
  422. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +11 -11
  423. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +11 -11
  424. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +11 -11
  425. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +11 -11
  426. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +11 -11
  427. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +11 -11
  428. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +11 -11
  429. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +11 -11
  430. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +11 -11
  431. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +11 -11
  432. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +11 -11
  433. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +11 -11
  434. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +11 -11
  435. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +11 -11
  436. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +11 -11
  437. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +11 -11
  438. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +11 -11
  439. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +11 -11
  440. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +11 -11
  441. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +11 -11
  442. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +11 -11
  443. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +11 -11
  444. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +11 -11
  445. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +11 -11
  446. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +11 -11
  447. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +11 -11
  448. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +11 -11
  449. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +11 -11
  450. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +11 -11
  451. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +11 -11
  452. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +11 -11
  453. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +11 -11
  454. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +11 -11
  455. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +11 -11
  456. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +11 -11
  457. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +11 -11
  458. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +11 -11
  459. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +11 -11
  460. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +11 -11
  461. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +11 -11
  462. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +11 -11
  463. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +11 -11
  464. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +11 -11
  465. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +11 -11
  466. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +11 -11
  467. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +11 -11
  468. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +11 -11
  469. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +11 -11
  470. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +11 -11
  471. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +11 -11
  472. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +11 -11
  473. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +11 -11
  474. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +11 -11
  475. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +11 -11
  476. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +11 -11
  477. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +11 -11
  478. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +11 -11
  479. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +11 -11
  480. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +11 -11
  481. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +11 -11
  482. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +11 -11
  483. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +11 -11
  484. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +11 -11
  485. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +11 -11
  486. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +11 -11
  487. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +11 -11
  488. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +11 -11
  489. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +11 -11
  490. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +11 -11
  491. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +11 -11
  492. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +11 -11
  493. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +11 -11
  494. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +11 -11
  495. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +11 -11
  496. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +11 -11
  497. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +11 -11
  498. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +11 -11
  499. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +11 -11
  500. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +11 -11
  501. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +11 -11
  502. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +11 -11
  503. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +11 -11
  504. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +11 -11
  505. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +11 -11
  506. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +11 -11
  507. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +11 -11
  508. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +11 -11
  509. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +11 -11
  510. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +11 -11
  511. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +11 -11
  512. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +11 -11
  513. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +11 -11
  514. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +11 -11
  515. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +11 -11
  516. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +11 -11
  517. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +11 -11
  518. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +11 -11
  519. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +11 -11
  520. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +11 -11
  521. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +11 -11
  522. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +11 -11
  523. nautobot/project-static/docs/user-guide/index.html +11 -11
  524. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +11 -11
  525. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +11 -11
  526. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +11 -11
  527. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +11 -11
  528. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +11 -11
  529. nautobot/project-static/docs/user-guide/platform-functionality/events.html +11 -11
  530. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +11 -11
  531. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +11 -11
  532. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +11 -11
  533. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +11 -11
  534. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +11 -11
  535. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +11 -11
  536. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +11 -11
  537. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +11 -11
  538. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +11 -11
  539. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +11 -11
  540. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +11 -11
  541. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +11 -11
  542. nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +11 -11
  543. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +11 -11
  544. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +11 -11
  545. nautobot/project-static/docs/user-guide/platform-functionality/note.html +11 -11
  546. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +11 -11
  547. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +11 -11
  548. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +11 -11
  549. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +11 -11
  550. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +11 -11
  551. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +11 -11
  552. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +11 -11
  553. nautobot/project-static/docs/user-guide/platform-functionality/role.html +11 -11
  554. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +11 -11
  555. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +11 -11
  556. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +11 -11
  557. nautobot/project-static/docs/user-guide/platform-functionality/status.html +11 -11
  558. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +11 -11
  559. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +11 -11
  560. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +11 -11
  561. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +11 -11
  562. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +11 -11
  563. nautobot/tenancy/templates/tenancy/tenant.html +1 -7
  564. nautobot/tenancy/views.py +13 -0
  565. nautobot/users/templates/users/api_tokens.html +4 -4
  566. nautobot/users/templates/users/base.html +28 -28
  567. nautobot/virtualization/templates/virtualization/cluster.html +64 -64
  568. nautobot/virtualization/templates/virtualization/inc/virtualmachine_vminterface_filter.html +8 -0
  569. nautobot/virtualization/templates/virtualization/virtualmachine_component_add.html +25 -25
  570. nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +1 -251
  571. nautobot/virtualization/templates/virtualization/vminterface.html +70 -70
  572. nautobot/virtualization/urls.py +0 -12
  573. nautobot/virtualization/views.py +158 -54
  574. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +13 -13
  575. nautobot/wireless/tests/integration/test_radio_profile.py +1 -1
  576. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/METADATA +1 -1
  577. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/RECORD +581 -570
  578. nautobot/ipam/templates/ipam/prefix_ipaddresses.html +0 -11
  579. nautobot/ipam/templates/ipam/prefix_prefixes.html +0 -11
  580. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/LICENSE.txt +0 -0
  581. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/NOTICE +0 -0
  582. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/WHEEL +0 -0
  583. {nautobot-2.4.18.dist-info → nautobot-2.4.19.dist-info}/entry_points.txt +0 -0
@@ -2,151 +2,151 @@
2
2
  {% load helpers %}
3
3
 
4
4
  {% block extra_styles %}
5
- <style>
6
- .panel {
7
- overflow: hidden /* Fix for panel overflow issues */
8
- }
9
- </style>
5
+ <style>
6
+ .panel {
7
+ overflow: hidden /* Fix for panel overflow issues */
8
+ }
9
+ </style>
10
10
  {% endblock %}
11
11
 
12
12
  {% block header %}
13
- <h1>
14
- {% block title %}Nautobot Worker Status{% endblock %}
15
- </h1>
13
+ <h1>
14
+ {% block title %}Nautobot Worker Status{% endblock %}
15
+ </h1>
16
16
  {% endblock %}
17
17
 
18
18
  {% block content %}
19
- <div class="row">
20
- <div class="col-md-12">
21
- <div class="panel panel-default">
22
- <div class="panel-heading">
23
- <strong>Worker Queues</strong>
24
- </div>
25
- <table class="table table-hover panel-body attr-table">
26
- {% for queue_name, workers in worker_status.queue_worker_count.items %}
27
- <tr>
28
- <td><span class="label label-primary">{{ queue_name }}</span></td>
29
- <td>
30
- {% for worker in workers %}
31
- <span class="label label-default">{{ worker }}</span>
32
- {% empty %}
33
- No workers found.
34
- {% endfor %}
35
- </td>
36
- </tr>
37
- {% endfor %}
38
- </table>
39
- </div>
40
- </div>
41
- {% for worker in worker_status.workers %}
42
- <div class="col-md-6">
19
+ <div class="row">
20
+ <div class="col-md-12">
43
21
  <div class="panel panel-default">
44
22
  <div class="panel-heading">
45
- <strong>{{ worker.hostname }}</strong>
23
+ <strong>Worker Queues</strong>
46
24
  </div>
47
- <table id="accordion" class="table table-hover panel-body attr-table">
48
- <tbody>
49
- <tr>
50
- <td>Uptime</td>
51
- <td colspan="2">{{ worker.uptime|render_uptime }}</td>
52
- </tr>
25
+ <table class="table table-hover panel-body attr-table">
26
+ {% for queue_name, workers in worker_status.queue_worker_count.items %}
53
27
  <tr>
54
- <td>Queues</td>
55
- <td colspan="2">
56
- {% for queue in worker.queues %}
57
- <span class="label label-primary">{{ queue }}</span>
28
+ <td><span class="label label-primary">{{ queue_name }}</span></td>
29
+ <td>
30
+ {% for worker in workers %}
31
+ <span class="label label-default">{{ worker }}</span>
32
+ {% empty %}
33
+ No workers found.
58
34
  {% endfor %}
59
35
  </td>
60
36
  </tr>
61
- <tr>
62
- <th colspan="{{ worker.running_tasks_table.columns|length }}">
63
- <button type="button" class="btn-link accordion-toggle mdi mdi-chevron-right"
64
- name="running-tasks-{{ worker.hostname|slugify }}" data-toggle="collapse"
65
- data-target=".collapseme-running-tasks-{{ worker.hostname|slugify }}">
66
- Running Tasks {% badge worker.running_tasks_table.rows|length show_empty=True %}
67
- </button>
68
- </th>
69
- </tr>
70
- </tbody>
71
- <tbody class="collapseme-running-tasks-{{ worker.hostname|slugify }} collapse" data-parent="#accordion" aria-expanded="false">
72
- <tr>
73
- {% for column in worker.running_tasks_table.columns %}
74
- <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
75
- {% endfor %}
76
- </tr>
77
- {% for row in worker.running_tasks_table.page.object_list|default:worker.running_tasks_table.rows %}
78
- <tr {{ row.attrs.as_html }}>
79
- {% for column, cell in row.items %}
80
- <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
37
+ {% endfor %}
38
+ </table>
39
+ </div>
40
+ </div>
41
+ {% for worker in worker_status.workers %}
42
+ <div class="col-md-6">
43
+ <div class="panel panel-default">
44
+ <div class="panel-heading">
45
+ <strong>{{ worker.hostname }}</strong>
46
+ </div>
47
+ <table id="accordion" class="table table-hover panel-body attr-table">
48
+ <tbody>
49
+ <tr>
50
+ <td>Uptime</td>
51
+ <td colspan="2">{{ worker.uptime|render_uptime }}</td>
52
+ </tr>
53
+ <tr>
54
+ <td>Queues</td>
55
+ <td colspan="2">
56
+ {% for queue in worker.queues %}
57
+ <span class="label label-primary">{{ queue }}</span>
58
+ {% endfor %}
59
+ </td>
60
+ </tr>
61
+ <tr>
62
+ <th colspan="{{ worker.running_tasks_table.columns|length }}">
63
+ <button type="button" class="btn-link accordion-toggle mdi mdi-chevron-right"
64
+ name="running-tasks-{{ worker.hostname|slugify }}" data-toggle="collapse"
65
+ data-target=".collapseme-running-tasks-{{ worker.hostname|slugify }}">
66
+ Running Tasks {% badge worker.running_tasks_table.rows|length show_empty=True %}
67
+ </button>
68
+ </th>
69
+ </tr>
70
+ </tbody>
71
+ <tbody class="collapseme-running-tasks-{{ worker.hostname|slugify }} collapse" data-parent="#accordion" aria-expanded="false">
72
+ <tr>
73
+ {% for column in worker.running_tasks_table.columns %}
74
+ <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
81
75
  {% endfor %}
82
76
  </tr>
83
- {% empty %}
84
- {% if worker.running_tasks_table.empty_text %}
85
- <tr>
86
- <td colspan="{{ worker.running_tasks_table.columns|length }}" class="text-center text-muted">
87
- &mdash; {{ worker.running_tasks_table.empty_text }} &mdash;
88
- </td>
77
+ {% for row in worker.running_tasks_table.page.object_list|default:worker.running_tasks_table.rows %}
78
+ <tr {{ row.attrs.as_html }}>
79
+ {% for column, cell in row.items %}
80
+ <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
81
+ {% endfor %}
89
82
  </tr>
90
- {% endif %}
91
- {% endfor %}
92
- </tbody>
93
- <tbody>
94
- <tr>
95
- <th colspan="{{ worker.pending_tasks_table.columns|length }}">
96
- <button type="button" class="btn-link accordion-toggle mdi mdi-chevron-right"
97
- name="pending-tasks-{{ worker.hostname|slugify }}" data-toggle="collapse"
98
- data-target=".collapseme-pending-tasks-{{ worker.hostname|slugify }}">
99
- Pending Tasks {% badge worker.pending_tasks_table.rows|length show_empty=True %}
100
- </button>
101
- </th>
102
- </tr>
103
- </tbody>
104
- <tbody class="collapseme-pending-tasks-{{ worker.hostname|slugify }} collapse" data-parent="#accordion" aria-expanded="false">
105
- <tr>
106
- {% for column in worker.pending_tasks_table.columns %}
107
- <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
83
+ {% empty %}
84
+ {% if worker.running_tasks_table.empty_text %}
85
+ <tr>
86
+ <td colspan="{{ worker.running_tasks_table.columns|length }}" class="text-center text-muted">
87
+ &mdash; {{ worker.running_tasks_table.empty_text }} &mdash;
88
+ </td>
89
+ </tr>
90
+ {% endif %}
108
91
  {% endfor %}
109
- </tr>
110
- {% for row in worker.pending_tasks_table.page.object_list|default:worker.pending_tasks_table.rows %}
111
- <tr {{ row.attrs.as_html }}>
112
- {% for column, cell in row.items %}
113
- <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
92
+ </tbody>
93
+ <tbody>
94
+ <tr>
95
+ <th colspan="{{ worker.pending_tasks_table.columns|length }}">
96
+ <button type="button" class="btn-link accordion-toggle mdi mdi-chevron-right"
97
+ name="pending-tasks-{{ worker.hostname|slugify }}" data-toggle="collapse"
98
+ data-target=".collapseme-pending-tasks-{{ worker.hostname|slugify }}">
99
+ Pending Tasks {% badge worker.pending_tasks_table.rows|length show_empty=True %}
100
+ </button>
101
+ </th>
102
+ </tr>
103
+ </tbody>
104
+ <tbody class="collapseme-pending-tasks-{{ worker.hostname|slugify }} collapse" data-parent="#accordion" aria-expanded="false">
105
+ <tr>
106
+ {% for column in worker.pending_tasks_table.columns %}
107
+ <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
114
108
  {% endfor %}
115
109
  </tr>
116
- {% empty %}
117
- {% if worker.pending_tasks_table.empty_text %}
118
- <tr>
119
- <td colspan="{{ worker.pending_tasks_table.columns|length }}" class="text-center text-muted">
120
- &mdash; {{ worker.pending_tasks_table.empty_text }} &mdash;
121
- </td>
110
+ {% for row in worker.pending_tasks_table.page.object_list|default:worker.pending_tasks_table.rows %}
111
+ <tr {{ row.attrs.as_html }}>
112
+ {% for column, cell in row.items %}
113
+ <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
114
+ {% endfor %}
122
115
  </tr>
123
- {% endif %}
124
- {% endfor %}
125
- </tbody>
126
- </table>
116
+ {% empty %}
117
+ {% if worker.pending_tasks_table.empty_text %}
118
+ <tr>
119
+ <td colspan="{{ worker.pending_tasks_table.columns|length }}" class="text-center text-muted">
120
+ &mdash; {{ worker.pending_tasks_table.empty_text }} &mdash;
121
+ </td>
122
+ </tr>
123
+ {% endif %}
124
+ {% endfor %}
125
+ </tbody>
126
+ </table>
127
+ </div>
127
128
  </div>
128
- </div>
129
- {% empty %}
130
- </div>
131
- <div class="alert alert-warning">
132
- {% with increased_timeout=worker_status.timeout|add:5 %}
133
- <strong>Warning:</strong> No workers responded within the {{ worker_status.timeout }} second timeout.
134
- {% if increased_timeout <= worker_status.max_timeout %}
135
- <a href="{{ request.path }}?timeout={{ increased_timeout }}">Retry with a {{ increased_timeout }} second timeout</a>.
136
- {% else %}
137
- <a href="{{ request.get_full_path }}">Retry</a>.
138
- {% endif %}
139
- {% endwith %}
140
- {% endfor %}
141
- </div>
129
+ {% empty %}
130
+ </div>
131
+ <div class="alert alert-warning">
132
+ {% with increased_timeout=worker_status.timeout|add:5 %}
133
+ <strong>Warning:</strong> No workers responded within the {{ worker_status.timeout }} second timeout.
134
+ {% if increased_timeout <= worker_status.max_timeout %}
135
+ <a href="{{ request.path }}?timeout={{ increased_timeout }}">Retry with a {{ increased_timeout }} second timeout</a>.
136
+ {% else %}
137
+ <a href="{{ request.get_full_path }}">Retry</a>.
138
+ {% endif %}
139
+ {% endwith %}
140
+ {% endfor %}
141
+ </div>
142
142
  {% endblock %}
143
143
 
144
144
  {% block javascript %}
145
- {{ block.super }}
146
- <script>
145
+ {{ block.super }}
146
+ <script>
147
147
  // Toggle v -. >
148
- $("#accordion .accordion-toggle").click(function() {
149
- $(this).toggleClass("mdi-chevron-down mdi-chevron-right");
150
- });
151
- </script>
148
+ $("#accordion .accordion-toggle").click(function() {
149
+ $(this).toggleClass("mdi-chevron-down mdi-chevron-right");
150
+ });
151
+ </script>
152
152
  {% endblock %}
@@ -1,5 +1,5 @@
1
1
  {% if widget.is_initial %}{{ widget.initial_text }}: <a href="{{ widget.value.url }}">{{ widget.value }}</a>{% if not widget.required %}
2
- <input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}"{% if widget.attrs.disabled %} disabled{% endif %}{% if widget.attrs.checked %} checked{% endif %}>
3
- <label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}<br>
4
- {{ widget.input_text }}:{% endif %}
2
+ <input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}"{% if widget.attrs.disabled %} disabled{% endif %}{% if widget.attrs.checked %} checked{% endif %}>
3
+ <label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}<br>
4
+ {{ widget.input_text }}:{% endif %}
5
5
  <input type="{{ widget.type }}" name="{{ widget.name }}" class="filestyle" data-placeholder="No file selected" {% include "django/forms/widgets/attrs.html" %}>
@@ -3,7 +3,7 @@
3
3
  <span class="input-group-btn">
4
4
  <button class="btn btn-default reslugify"
5
5
  type="button"
6
- title="{% if widget.custom_title %}{{ widget.custom_title }}{% else %}Regenerate slug{% endif %}"
6
+ title="{% if widget.custom_title %}{{ widget.custom_title }}{% else %}Regenerate slug{% endif %}"
7
7
  data-regenerate="{{ widget.attrs.id }}"
8
8
  >
9
9
  <i class="mdi mdi-refresh"></i>
@@ -194,6 +194,9 @@ def consolidate_bulk_action_buttons(context):
194
194
  static_group_icon += " text-muted"
195
195
 
196
196
  if render_edit_button:
197
+ query_string = ""
198
+ if hasattr(context["request"], "GET") and context["request"].GET:
199
+ query_string = "?" + context["request"].GET.urlencode()
197
200
  bulk_action_buttons.append(
198
201
  format_html(
199
202
  primary_button_fragment,
@@ -201,7 +204,7 @@ def consolidate_bulk_action_buttons(context):
201
204
  attrs=render_tag_attrs(
202
205
  {
203
206
  "class": edit_button_classes,
204
- "formaction": reverse(context["bulk_edit_url"]),
207
+ "formaction": reverse(context["bulk_edit_url"]) + query_string,
205
208
  "type": "submit",
206
209
  }
207
210
  ),
@@ -231,6 +234,9 @@ def consolidate_bulk_action_buttons(context):
231
234
  )
232
235
 
233
236
  if render_delete_button:
237
+ query_string = ""
238
+ if hasattr(context["request"], "GET") and context["request"].GET:
239
+ query_string = "?" + context["request"].GET.urlencode()
234
240
  bulk_action_buttons.append(
235
241
  format_html(
236
242
  child_button_fragment,
@@ -240,7 +246,7 @@ def consolidate_bulk_action_buttons(context):
240
246
  "class": delete_button_classes,
241
247
  "type": "submit",
242
248
  "name": "_delete",
243
- "formaction": reverse(context["bulk_delete_url"]),
249
+ "formaction": reverse(context["bulk_delete_url"]) + query_string,
244
250
  }
245
251
  ),
246
252
  icon="mdi mdi-trash-can-outline",
@@ -1374,5 +1374,5 @@ class CaptureasNode(template.Node):
1374
1374
  def render(self, context):
1375
1375
  output = self.nodelist.render(context)
1376
1376
  output = output.strip()
1377
- context[self.varname] = output
1377
+ context[self.varname] = mark_safe(output) # noqa: S308 # we already rendered it, so it's 'safe' now?
1378
1378
  return ""
@@ -65,12 +65,12 @@ class ObjectsListMixin:
65
65
  Click bulk delete from dropdown menu on bottom of the items table list.
66
66
  """
67
67
  self.browser.execute_script(
68
- "document.querySelector('#object_list_form button[type=\"submit\"]').scrollIntoView()"
68
+ "document.querySelector('#bulk-action-buttons button[type=\"submit\"]').scrollIntoView()"
69
69
  )
70
70
  self.browser.find_by_xpath(
71
- '//*[@id="object_list_form"]//button[@type="submit"]/following-sibling::button[1]'
71
+ '//*[@id="bulk-action-buttons"]//button[@type="submit"]/following-sibling::button[1]'
72
72
  ).click()
73
- self.browser.find_by_css('#object_list_form button[name="_delete"]').click()
73
+ self.browser.find_by_css('#bulk-action-buttons button[name="_delete"]').click()
74
74
 
75
75
  def click_bulk_delete_all(self):
76
76
  """
@@ -82,7 +82,7 @@ class ObjectsListMixin:
82
82
  """
83
83
  Click bulk edit button on bottom of the items table list.
84
84
  """
85
- self.click_button('#object_list_form button[type="submit"]')
85
+ self.click_button('#bulk-action-buttons button[type="submit"]')
86
86
 
87
87
  def click_bulk_edit_all(self):
88
88
  """
@@ -312,6 +312,7 @@ class SeleniumTestCase(StaticLiveServerTestCase, testing.NautobotTestCaseMixin):
312
312
  search_box_class = "select2-search select2-search--dropdown"
313
313
 
314
314
  self.browser.find_by_xpath(f"//select[@id='id_{field_name}']//following-sibling::span").click()
315
+ self.browser.execute_script(f"""document.querySelector('#id_{field_name}').scrollIntoView()""")
315
316
  search_box = self.browser.find_by_xpath(f"//*[@class='{search_box_class}']//input", wait_time=5)
316
317
  for _ in search_box.first.type(value, slowly=True):
317
318
  pass
@@ -630,6 +631,8 @@ class BulkOperationsTestCases:
630
631
  self.assertJobStatusIsCompleted()
631
632
 
632
633
  self.go_to_model_list_page()
634
+ # We set page size to large number to avoid pagination issues
635
+ self.set_per_page(1000)
633
636
  rest_items_count = self.model_expected_counts["all"] - self.model_expected_counts["filtered"]
634
637
  self.assertEqual(self.objects_list_visible_items, rest_items_count)
635
638
 
@@ -10,8 +10,10 @@ from django.conf import settings
10
10
  from django.contrib.contenttypes.models import ContentType
11
11
  from django.core.exceptions import ObjectDoesNotExist, ValidationError
12
12
  from django.core.validators import URLValidator
13
+ from django.db import connection
13
14
  from django.db.models import ManyToManyField, Model, QuerySet
14
15
  from django.test import override_settings, tag, TestCase as _TestCase
16
+ from django.test.utils import CaptureQueriesContext
15
17
  from django.urls import NoReverseMatch, reverse
16
18
  from django.utils.html import escape
17
19
  from django.utils.http import urlencode
@@ -145,6 +147,10 @@ class ViewTestCases:
145
147
  """
146
148
 
147
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
+ }
148
154
 
149
155
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
150
156
  def test_get_object_anonymous(self):
@@ -181,7 +187,8 @@ class ViewTestCases:
181
187
  self.add_permissions(f"{self.model._meta.app_label}.view_{self.model._meta.model_name}")
182
188
 
183
189
  # Try GET with model-level permission
184
- response = self.client.get(instance.get_absolute_url())
190
+ with CaptureQueriesContext(connection) as capture_queries_context:
191
+ response = self.client.get(instance.get_absolute_url())
185
192
  # The object's display name or string representation should appear in the response body
186
193
  self.assertBodyContains(response, escape(getattr(instance, "display", str(instance))))
187
194
 
@@ -210,6 +217,22 @@ class ViewTestCases:
210
217
  else:
211
218
  self.assertBodyContains(response, escape(str(instance.cf.get(custom_field.key) or "")))
212
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
+
213
236
  return response # for consumption by child test cases if desired
214
237
 
215
238
  @override_settings(EXEMPT_VIEW_PERMISSIONS=[])
@@ -1404,10 +1427,6 @@ class ViewTestCases:
1404
1427
  # Expect a 200 status cause we are only rendering the bulk delete table after pressing Delete Selected button.
1405
1428
  self.assertHttpStatus(response, 200)
1406
1429
  response_body = utils.extract_page_body(response.content.decode(response.charset))
1407
- # Check if all pks is not part of the html.
1408
- self.assertNotIn(str(first_pk), response_body)
1409
- self.assertNotIn(str(second_pk), response_body)
1410
- self.assertNotIn(str(third_pk), response_body)
1411
1430
  self.assertIn("<strong>Warning:</strong> The following operation will delete 2 ", response_body)
1412
1431
  self.assertInHTML('<input type="hidden" name="_all" value="true" />', response_body)
1413
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
- response = self.client.get(endpoint, follow=True)
33
- self.assertHttpStatus(
34
- response, 200, f"{view_name}: {endpoint} returns status Code {response.status_code} instead of 200"
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()