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
nautobot/apps/ui.py CHANGED
@@ -3,9 +3,12 @@
3
3
  from nautobot.core.choices import ButtonColorChoices
4
4
  from nautobot.core.ui.base import PermissionsMixin
5
5
  from nautobot.core.ui.breadcrumbs import (
6
+ AncestorsBreadcrumbs,
6
7
  BaseBreadcrumbItem,
7
8
  Breadcrumbs,
9
+ context_object_attr,
8
10
  InstanceBreadcrumbItem,
11
+ InstanceParentBreadcrumbItem,
9
12
  ModelBreadcrumbItem,
10
13
  ViewNameBreadcrumbItem,
11
14
  )
@@ -49,6 +52,7 @@ from nautobot.extras.choices import BannerClassChoices
49
52
  from nautobot.extras.plugins import Banner, TemplateExtension
50
53
 
51
54
  __all__ = (
55
+ "AncestorsBreadcrumbs",
52
56
  "Banner",
53
57
  "BannerClassChoices",
54
58
  "BaseBreadcrumbItem",
@@ -66,6 +70,7 @@ __all__ = (
66
70
  "HomePageItem",
67
71
  "HomePagePanel",
68
72
  "InstanceBreadcrumbItem",
73
+ "InstanceParentBreadcrumbItem",
69
74
  "KeyValueTablePanel",
70
75
  "LayoutChoices",
71
76
  "ModelBreadcrumbItem",
@@ -89,5 +94,6 @@ __all__ = (
89
94
  "TextPanel",
90
95
  "Titles",
91
96
  "ViewNameBreadcrumbItem",
97
+ "context_object_attr",
92
98
  "render_component_template",
93
99
  )
@@ -18,7 +18,7 @@ CIRCUIT_TERMINATION_PARENT = """
18
18
  {% if value.provider_network %}
19
19
  {{ value.provider_network|hyperlinked_object }}
20
20
  {% elif value.location %}
21
- {{ value.location|hyperlinked_object }}
21
+ {{ value.location|hyperlinked_object:"name" }}
22
22
  {% elif value.cloud_network %}
23
23
  {{ value.cloud_network|hyperlinked_object }}
24
24
  {% else %}
@@ -34,11 +34,11 @@
34
34
  {% endblock %}
35
35
 
36
36
  {% block javascript %}
37
- {{ block.super }}
38
- <script type="text/javascript">
39
- $("a.set_speed").click(function(e) {
40
- e.preventDefault();
41
- $("#id_" + $(this).attr("target")).val($(this).attr("data"));
42
- });
43
- </script>
37
+ {{ block.super }}
38
+ <script type="text/javascript">
39
+ $("a.set_speed").click(function(e) {
40
+ e.preventDefault();
41
+ $("#id_" + $(this).attr("target")).val($(this).attr("data"));
42
+ });
43
+ </script>
44
44
  {% endblock %}
@@ -1,6 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% load helpers %}
3
-
4
- {% block extra_breadcrumbs %}
5
- <li><a href="{% url 'circuits:circuit_list' %}?provider={{ object.provider.pk }}">{{ object.provider }}</a></li>
6
- {% endblock extra_breadcrumbs %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -25,28 +25,28 @@
25
25
  <p class="form-control-static">{{ form.term_side.value }}</p>
26
26
  </div>
27
27
  </div>
28
- {% with location_tab_active=form.initial.location %}
28
+ {% with location_tab_active=form.initial.location %}
29
29
  {% with providernetwork_tab_active=form.initial.provider_network %}
30
- {% with cloudnetwork_tab_active=form.initial.cloud_network %}
31
- <ul class="nav nav-tabs" role="tablist">
32
- <li role="presentation"{% if location_tab_active or not providernetwork_tab_active and not cloudnetwork_tab_active %} class="active"{% endif %}><a href="#location" role="tab" data-toggle="tab">Location</a></li>
33
- <li role="presentation"{% if providernetwork_tab_active %} class="active"{% endif %}><a href="#providernetwork" role="tab" data-toggle="tab">Provider Network</a></li>
34
- <li role="presentation"{% if cloudnetwork_tab_active %} class="active"{% endif %}><a href="#cloudnetwork" role="tab" data-toggle="tab">Cloud Network</a></li>
35
- </ul>
36
- <div class="tab-content">
37
- <div class="tab-pane{% if location_tab_active or not providernetwork_tab_active and not cloudnetwork_tab_active %} active{% endif %}" id="location">
38
- {% render_field form.location %}
30
+ {% with cloudnetwork_tab_active=form.initial.cloud_network %}
31
+ <ul class="nav nav-tabs" role="tablist">
32
+ <li role="presentation"{% if location_tab_active or not providernetwork_tab_active and not cloudnetwork_tab_active %} class="active"{% endif %}><a href="#location" role="tab" data-toggle="tab">Location</a></li>
33
+ <li role="presentation"{% if providernetwork_tab_active %} class="active"{% endif %}><a href="#providernetwork" role="tab" data-toggle="tab">Provider Network</a></li>
34
+ <li role="presentation"{% if cloudnetwork_tab_active %} class="active"{% endif %}><a href="#cloudnetwork" role="tab" data-toggle="tab">Cloud Network</a></li>
35
+ </ul>
36
+ <div class="tab-content">
37
+ <div class="tab-pane{% if location_tab_active or not providernetwork_tab_active and not cloudnetwork_tab_active %} active{% endif %}" id="location">
38
+ {% render_field form.location %}
39
+ </div>
40
+ <div class="tab-pane{% if providernetwork_tab_active %} active{% endif %}" id="providernetwork">
41
+ {% render_field form.provider_network %}
42
+ </div>
43
+ <div class="tab-pane{% if cloudnetwork_tab_active %} active{% endif %}" id="cloudnetwork">
44
+ {% render_field form.cloud_network %}
45
+ </div>
39
46
  </div>
40
- <div class="tab-pane{% if providernetwork_tab_active %} active{% endif %}" id="providernetwork">
41
- {% render_field form.provider_network %}
42
- </div>
43
- <div class="tab-pane{% if cloudnetwork_tab_active %} active{% endif %}" id="cloudnetwork">
44
- {% render_field form.cloud_network %}
45
- </div>
46
- </div>
47
- {% endwith %}
48
- {% endwith %}
47
+ {% endwith %}
49
48
  {% endwith %}
49
+ {% endwith %}
50
50
  </div>
51
51
  </div>
52
52
  <div class="panel panel-default">
@@ -81,11 +81,11 @@
81
81
  {% endblock %}
82
82
 
83
83
  {% block javascript %}
84
- {{ block.super }}
85
- <script type="text/javascript">
86
- $("a.set_speed").click(function(e) {
87
- e.preventDefault();
88
- $("#id_" + $(this).attr("target")).val($(this).attr("data"));
89
- });
90
- </script>
84
+ {{ block.super }}
85
+ <script type="text/javascript">
86
+ $("a.set_speed").click(function(e) {
87
+ e.preventDefault();
88
+ $("#id_" + $(this).attr("target")).val($(this).attr("data"));
89
+ });
90
+ </script>
91
91
  {% endblock %}
@@ -12,28 +12,28 @@ In a future release, we should delete this file.
12
12
  {% if termination %}
13
13
  <table class="table table-hover panel-body attr-table">
14
14
  {% if termination.location %}
15
- <tr>
16
- <td>Location</td>
17
- <td>
18
- {% include 'dcim/inc/location_hierarchy.html' with location=termination.location %}
19
- </td>
20
- </tr>
21
- <tr>
22
- <td>Cable</td>
23
- <td>
24
- {% include 'circuits/inc/circuit_termination_cable_fragment.html' %}
25
- </td>
26
- </tr>
15
+ <tr>
16
+ <td>Location</td>
17
+ <td>
18
+ {% include 'dcim/inc/location_hierarchy.html' with location=termination.location %}
19
+ </td>
20
+ </tr>
21
+ <tr>
22
+ <td>Cable</td>
23
+ <td>
24
+ {% include 'circuits/inc/circuit_termination_cable_fragment.html' %}
25
+ </td>
26
+ </tr>
27
27
  {% elif termination.provider_network %}
28
- <tr>
29
- <td>Provider Network</td>
30
- <td>{{ termination.provider_network|hyperlinked_object }}</td>
31
- </tr>
28
+ <tr>
29
+ <td>Provider Network</td>
30
+ <td>{{ termination.provider_network|hyperlinked_object }}</td>
31
+ </tr>
32
32
  {% else %}
33
- <tr>
34
- <td>Cloud Network</td>
35
- <td>{{ termination.cloud_network|hyperlinked_object }}</td>
36
- </tr>
33
+ <tr>
34
+ <td>Cloud Network</td>
35
+ <td>{{ termination.cloud_network|hyperlinked_object }}</td>
36
+ </tr>
37
37
  {% endif %}
38
38
  <tr>
39
39
  <td>Speed</td>
@@ -19,8 +19,8 @@
19
19
  </a>
20
20
  {% endif %}
21
21
  {% if termination %}
22
- <a href="{% url 'circuits:circuittermination' pk=termination.pk %}" class="btn btn-xs btn-default">
23
- <span class="mdi mdi-information-outline" aria-hidden="true"></span> Detail
24
- </a>
22
+ <a href="{% url 'circuits:circuittermination' pk=termination.pk %}" class="btn btn-xs btn-default">
23
+ <span class="mdi mdi-information-outline" aria-hidden="true"></span> Detail
24
+ </a>
25
25
  {% endif %}
26
26
  </div>
@@ -1,9 +1,9 @@
1
1
  {% spaceless %}
2
- {% load helpers %}
3
- {% if termination.port_speed and termination.upstream_speed %}
4
- <i class="mdi mdi-arrow-down-bold" title="Downstream"></i>{{ termination.port_speed|humanize_speed }}&nbsp;
5
- <i class="mdi mdi-arrow-up-bold" title="Upstream"></i>{{ termination.upstream_speed|humanize_speed }}
6
- {% else %}
7
- {{ termination.port_speed|humanize_speed|placeholder }}
8
- {% endif %}
2
+ {% load helpers %}
3
+ {% if termination.port_speed and termination.upstream_speed %}
4
+ <i class="mdi mdi-arrow-down-bold" title="Downstream"></i>{{ termination.port_speed|humanize_speed }}&nbsp;
5
+ <i class="mdi mdi-arrow-up-bold" title="Upstream"></i>{{ termination.upstream_speed|humanize_speed }}
6
+ {% else %}
7
+ {{ termination.port_speed|humanize_speed|placeholder }}
8
+ {% endif %}
9
9
  {% endspaceless %}
@@ -1,4 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% block extra_breadcrumbs %}
3
- <li><a href="{% url 'circuits:providernetwork_list' %}?provider={{ object.provider_id }}">{{ object.provider }}</a></li>
4
- {% endblock extra_breadcrumbs %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -5,7 +5,13 @@ from django.utils.html import format_html, format_html_join
5
5
 
6
6
  from nautobot.core.forms import ConfirmationForm
7
7
  from nautobot.core.templatetags import helpers
8
- from nautobot.core.ui.breadcrumbs import Breadcrumbs, InstanceBreadcrumbItem, ModelBreadcrumbItem
8
+ from nautobot.core.ui.breadcrumbs import (
9
+ Breadcrumbs,
10
+ context_object_attr,
11
+ InstanceBreadcrumbItem,
12
+ InstanceParentBreadcrumbItem,
13
+ ModelBreadcrumbItem,
14
+ )
9
15
  from nautobot.core.ui.choices import SectionChoices
10
16
  from nautobot.core.ui.object_detail import (
11
17
  ObjectDetailContent,
@@ -101,17 +107,12 @@ class CircuitTerminationUIViewSet(NautobotUIViewSet):
101
107
  queryset = CircuitTermination.objects.all()
102
108
  serializer_class = serializers.CircuitTerminationSerializer
103
109
  table_class = tables.CircuitTerminationTable
104
-
105
110
  breadcrumbs = Breadcrumbs(
106
111
  items={
107
112
  "detail": [
108
- ModelBreadcrumbItem(model=Circuit),
109
- ModelBreadcrumbItem(
110
- model=Circuit,
111
- label=lambda c: c["object"].circuit.provider,
112
- reverse_query_params=lambda c: {"provider": c["object"].circuit.provider.pk},
113
- ),
114
- InstanceBreadcrumbItem(instance=lambda c: c["object"].circuit),
113
+ ModelBreadcrumbItem(),
114
+ InstanceParentBreadcrumbItem(instance=context_object_attr("circuit"), parent_key="provider"),
115
+ InstanceBreadcrumbItem(instance=context_object_attr("circuit")),
115
116
  ]
116
117
  }
117
118
  )
@@ -191,6 +192,14 @@ class CircuitUIViewSet(NautobotUIViewSet):
191
192
  queryset = Circuit.objects.all()
192
193
  serializer_class = serializers.CircuitSerializer
193
194
  table_class = tables.CircuitTable
195
+ breadcrumbs = Breadcrumbs(
196
+ items={
197
+ "detail": [
198
+ ModelBreadcrumbItem(),
199
+ InstanceParentBreadcrumbItem(parent_key="provider"),
200
+ ]
201
+ }
202
+ )
194
203
 
195
204
  class CircuitTerminationPanel(ObjectFieldsPanel):
196
205
  def __init__(self, **kwargs):
@@ -364,6 +373,14 @@ class ProviderNetworkUIViewSet(NautobotUIViewSet):
364
373
  queryset = ProviderNetwork.objects.all()
365
374
  serializer_class = serializers.ProviderNetworkSerializer
366
375
  table_class = tables.ProviderNetworkTable
376
+ breadcrumbs = Breadcrumbs(
377
+ items={
378
+ "detail": [
379
+ ModelBreadcrumbItem(),
380
+ InstanceParentBreadcrumbItem(parent_key="provider"),
381
+ ]
382
+ }
383
+ )
367
384
 
368
385
  object_detail_content = ObjectDetailContent(
369
386
  panels=(
@@ -1,5 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% block extra_breadcrumbs %}
3
- <li><a href="{% url 'cloud:cloudaccount_list' %}?provider={{ object.provider.pk }}">{{ object.provider }}</a></li>
4
- {% endblock extra_breadcrumbs %}
5
- {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,8 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% load helpers %}
3
-
4
- {% block extra_breadcrumbs %}
5
- {% if object.parent %}
6
- <li>{{ object.parent|hyperlinked_object:"name" }}</li>
7
- {% endif %}
8
- {% endblock extra_breadcrumbs %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,4 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% block extra_breadcrumbs %}
3
- <li><a href="{% url 'cloud:cloudresourcetype_list' %}?provider={{ object.provider.pk }}">{{ object.provider }}</a></li>
4
- {% endblock extra_breadcrumbs %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,6 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% load helpers %}
3
-
4
- {% block extra_breadcrumbs %}
5
- <li><a href="{% url 'cloud:cloudresourcetype' pk=object.cloud_resource_type.pk %}">{{ object.cloud_resource_type }}</a></li>
6
- {% endblock extra_breadcrumbs %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
nautobot/cloud/views.py CHANGED
@@ -31,6 +31,13 @@ from nautobot.cloud.forms import (
31
31
  from nautobot.cloud.models import CloudAccount, CloudNetwork, CloudResourceType, CloudService
32
32
  from nautobot.cloud.tables import CloudAccountTable, CloudNetworkTable, CloudResourceTypeTable, CloudServiceTable
33
33
  from nautobot.core.ui import object_detail
34
+ from nautobot.core.ui.breadcrumbs import (
35
+ Breadcrumbs,
36
+ context_object_attr,
37
+ InstanceBreadcrumbItem,
38
+ InstanceParentBreadcrumbItem,
39
+ ModelBreadcrumbItem,
40
+ )
34
41
  from nautobot.core.ui.choices import SectionChoices
35
42
  from nautobot.core.views.viewsets import NautobotUIViewSet
36
43
  from nautobot.ipam.tables import PrefixTable
@@ -44,6 +51,16 @@ class CloudAccountUIViewSet(NautobotUIViewSet):
44
51
  serializer_class = CloudAccountSerializer
45
52
  table_class = CloudAccountTable
46
53
  form_class = CloudAccountForm
54
+ breadcrumbs = Breadcrumbs(
55
+ items={
56
+ "detail": [
57
+ ModelBreadcrumbItem(),
58
+ InstanceParentBreadcrumbItem(
59
+ parent_key="provider",
60
+ ),
61
+ ]
62
+ }
63
+ )
47
64
 
48
65
  object_detail_content = object_detail.ObjectDetailContent(
49
66
  panels=(
@@ -64,6 +81,17 @@ class CloudNetworkUIViewSet(NautobotUIViewSet):
64
81
  table_class = CloudNetworkTable
65
82
  form_class = CloudNetworkForm
66
83
  bulk_update_form_class = CloudNetworkBulkEditForm
84
+ breadcrumbs = Breadcrumbs(
85
+ items={
86
+ "detail": [
87
+ ModelBreadcrumbItem(model_key="object"),
88
+ InstanceBreadcrumbItem(
89
+ instance=context_object_attr("parent"), should_render=context_object_attr("parent")
90
+ ),
91
+ ]
92
+ }
93
+ )
94
+
67
95
  object_detail_content = object_detail.ObjectDetailContent(
68
96
  panels=(
69
97
  object_detail.ObjectFieldsPanel(
@@ -197,6 +225,15 @@ class CloudResourceTypeUIViewSet(NautobotUIViewSet):
197
225
  table_class = CloudResourceTypeTable
198
226
  form_class = CloudResourceTypeForm
199
227
  bulk_update_form_class = CloudResourceTypeBulkEditForm
228
+ breadcrumbs = Breadcrumbs(
229
+ items={
230
+ "detail": [
231
+ ModelBreadcrumbItem(),
232
+ InstanceParentBreadcrumbItem(parent_key="provider"),
233
+ ]
234
+ }
235
+ )
236
+
200
237
  object_detail_content = object_detail.ObjectDetailContent(
201
238
  panels=(
202
239
  object_detail.ObjectFieldsPanel(
@@ -277,6 +314,14 @@ class CloudServiceUIViewSet(NautobotUIViewSet):
277
314
  table_class = CloudServiceTable
278
315
  form_class = CloudServiceForm
279
316
  bulk_update_form_class = CloudServiceBulkEditForm
317
+ breadcrumbs = Breadcrumbs(
318
+ items={
319
+ "detail": [
320
+ ModelBreadcrumbItem(),
321
+ InstanceBreadcrumbItem(instance=context_object_attr("cloud_resource_type")),
322
+ ]
323
+ }
324
+ )
280
325
 
281
326
  object_detail_content = object_detail.ObjectDetailContent(
282
327
  panels=(
@@ -67,15 +67,18 @@ def generate_filter_resolver(schema_type, resolver_name, field_name):
67
67
  """
68
68
  filterset_class = schema_type._meta.filterset_class
69
69
 
70
+ @gql_optimizer.resolver_hints(model_field=field_name)
70
71
  def resolve_filter(self, info, **kwargs):
72
+ field = getattr(self, field_name)
73
+
71
74
  if not filterset_class or not kwargs:
72
- return getattr(self, field_name).all()
75
+ return field.all()
73
76
 
74
77
  # Inverse of substitution logic from get_filtering_args_from_filterset() - transform "_type" back to "type"
75
78
  if "_type" in kwargs:
76
79
  kwargs["type"] = kwargs.pop("_type")
77
80
 
78
- resolved_obj = filterset_class(kwargs, getattr(self, field_name).all())
81
+ resolved_obj = filterset_class(kwargs, field.all())
79
82
 
80
83
  # Check result filter for errors.
81
84
  if not resolved_obj.errors:
@@ -7,10 +7,9 @@ from django.core.exceptions import (
7
7
  )
8
8
  from django.db.models import ManyToManyField, ProtectedError
9
9
 
10
- from nautobot.core import exceptions
11
10
  from nautobot.core.forms.utils import restrict_form_fields
12
- from nautobot.core.utils.filtering import get_filterset_field
13
- from nautobot.core.utils.lookup import get_filterset_for_model, get_form_for_model
11
+ from nautobot.core.utils.lookup import get_form_for_model
12
+ from nautobot.core.views.utils import get_bulk_queryset_from_view
14
13
  from nautobot.extras.context_managers import deferred_change_logging_for_bulk_operation
15
14
  from nautobot.extras.jobs import (
16
15
  BooleanVar,
@@ -19,6 +18,7 @@ from nautobot.extras.jobs import (
19
18
  ObjectVar,
20
19
  RunJobTaskFailed,
21
20
  )
21
+ from nautobot.extras.models import SavedView
22
22
  from nautobot.extras.utils import bulk_delete_with_bulk_change_logging, remove_prefix_from_cf_key
23
23
 
24
24
  name = "System Jobs"
@@ -32,8 +32,10 @@ class BulkEditObjects(Job):
32
32
  description="Type of objects to update",
33
33
  )
34
34
  form_data = JSONVar(description="BulkEditForm data")
35
+ pk_list = JSONVar(description="List of objects pks to edit", required=False)
35
36
  edit_all = BooleanVar(description="Bulk Edit all object / all filtered objects", required=False)
36
37
  filter_query_params = JSONVar(label="Filter Query Params", required=False)
38
+ saved_view = ObjectVar(model=SavedView, required=False)
37
39
 
38
40
  class Meta:
39
41
  name = "Bulk Edit Objects"
@@ -41,42 +43,14 @@ class BulkEditObjects(Job):
41
43
  has_sensitive_variables = False
42
44
  soft_time_limit = 1800
43
45
  time_limit = 2000
46
+ hidden = True
47
+
48
+ def _update_objects(self, model, form, filter_query_params, pk_list, edit_all, nullified_fields, saved_view_id):
49
+ base_queryset = model.objects.restrict(self.user, "change")
50
+ queryset = get_bulk_queryset_from_view(user=self.user, action="change", log=self.logger, **self.key_params)
44
51
 
45
- def _update_objects(self, model, form, filter_query_params, edit_all, nullified_fields):
46
52
  with deferred_change_logging_for_bulk_operation():
47
- base_queryset = model.objects.restrict(self.user, "change")
48
53
  updated_objects_pk = []
49
- filterset_cls = get_filterset_for_model(model)
50
-
51
- if filter_query_params:
52
- if not filterset_cls:
53
- self.logger.error(f"Filterset not found for {model._meta.verbose_name}")
54
- raise RunJobTaskFailed(
55
- f"Filter query provided but {model._meta.verbose_name} does not have a filterset."
56
- )
57
-
58
- # Discarding non-filter query params
59
- new_filter_query_params = {}
60
-
61
- for key, value in filter_query_params.items():
62
- try:
63
- get_filterset_field(filterset_cls(), key)
64
- new_filter_query_params[key] = value
65
- except exceptions.FilterSetFieldNotFound:
66
- self.logger.debug(
67
- f"Query parameter `{key}` not found in filterset for `{filterset_cls}`, discarding it"
68
- )
69
-
70
- filter_query_params = new_filter_query_params
71
-
72
- if edit_all:
73
- if filter_query_params:
74
- queryset = filterset_cls(filter_query_params).qs.restrict(self.user, "change")
75
- else:
76
- queryset = model.objects.restrict(self.user, "change")
77
- else:
78
- queryset = model.objects.restrict(self.user, "change").filter(pk__in=form.cleaned_data["pk"])
79
-
80
54
  form_custom_fields = getattr(form, "custom_fields", [])
81
55
  form_relationships = getattr(form, "relationships", [])
82
56
  standard_fields = [
@@ -130,14 +104,18 @@ class BulkEditObjects(Job):
130
104
  if hasattr(form, "save_note") and callable(form.save_note):
131
105
  form.save_note(instance=obj, user=self.user)
132
106
  total_updated_objs = len(updated_objects_pk)
133
- # Enforce object-level permissions
107
+ # Enforce object-level permissions. This works because we used .restrict() above and if the user
108
+ # doesn't have permission to change one of the objects after the change, it won't be in base_queryset
109
+ # filtered to the pks of the objects we just changed.
134
110
  if base_queryset.filter(pk__in=updated_objects_pk).count() != total_updated_objs:
135
111
  raise ObjectDoesNotExist
136
112
  return total_updated_objs
137
113
 
138
- def _process_valid_form(self, model, form, filter_query_params, edit_all, nullified_fields):
114
+ def _process_valid_form(self, model, form, filter_query_params, pk_list, edit_all, nullified_fields, saved_view_id):
139
115
  try:
140
- total_updated_objs = self._update_objects(model, form, filter_query_params, edit_all, nullified_fields)
116
+ total_updated_objs = self._update_objects(
117
+ model, form, filter_query_params, pk_list, edit_all, nullified_fields, saved_view_id
118
+ )
141
119
  msg = f"Updated {total_updated_objs} {model._meta.verbose_name_plural}"
142
120
  self.logger.info(msg)
143
121
  return msg
@@ -149,12 +127,24 @@ class BulkEditObjects(Job):
149
127
  raise RunJobTaskFailed("Bulk Edit not fully successful, see logs")
150
128
 
151
129
  def run( # pylint: disable=arguments-differ
152
- self, *, content_type, form_data, edit_all=False, filter_query_params=None
130
+ self, *, content_type, form_data, pk_list=None, edit_all=False, filter_query_params=None, saved_view=None
153
131
  ):
132
+ saved_view_id = saved_view.pk if saved_view is not None else None
133
+ if not filter_query_params:
134
+ filter_query_params = {}
135
+
154
136
  if not self.user.has_perm(f"{content_type.app_label}.change_{content_type.model}"):
155
137
  self.logger.error('User "%s" does not have permission to update %s objects', self.user, content_type.model)
156
138
  raise PermissionDenied("User does not have change permissions on the requested content-type")
157
139
 
140
+ self.key_params = {
141
+ "content_type": content_type,
142
+ "edit_all": edit_all,
143
+ "filter_query_params": filter_query_params,
144
+ "pk_list": pk_list,
145
+ "saved_view_id": saved_view_id,
146
+ }
147
+
158
148
  model = content_type.model_class()
159
149
  if model is None:
160
150
  self.logger.error(
@@ -178,7 +168,9 @@ class BulkEditObjects(Job):
178
168
  if form.is_valid():
179
169
  self.logger.debug("Form validation was successful")
180
170
  nullified_fields = form_data.get("_nullify")
181
- return self._process_valid_form(model, form, filter_query_params, edit_all, nullified_fields)
171
+ return self._process_valid_form(
172
+ model, form, filter_query_params, pk_list, edit_all, nullified_fields, saved_view_id
173
+ )
182
174
  else:
183
175
  self.logger.error(f"Form validation unsuccessful: {form.errors.as_json()}")
184
176
 
@@ -197,6 +189,7 @@ class BulkDeleteObjects(Job):
197
189
  pk_list = JSONVar(description="List of objects pks to delete", required=False)
198
190
  delete_all = BooleanVar(description="Delete all (filtered) objects instead of a list of PKs", required=False)
199
191
  filter_query_params = JSONVar(label="Filter Query Params", required=False)
192
+ saved_view = ObjectVar(model=SavedView, required=False)
200
193
 
201
194
  class Meta:
202
195
  name = "Bulk Delete Objects"
@@ -204,14 +197,26 @@ class BulkDeleteObjects(Job):
204
197
  has_sensitive_variables = False
205
198
  soft_time_limit = 1800
206
199
  time_limit = 2000
200
+ hidden = True
207
201
 
208
202
  def run( # pylint: disable=arguments-differ
209
- self, *, content_type, pk_list=None, delete_all=False, filter_query_params=None
203
+ self, *, content_type, pk_list=None, delete_all=False, filter_query_params=None, saved_view=None
210
204
  ):
205
+ saved_view_id = saved_view.pk if saved_view is not None else None
206
+ if not filter_query_params:
207
+ filter_query_params = {}
211
208
  if not self.user.has_perm(f"{content_type.app_label}.delete_{content_type.model}"):
212
209
  self.logger.error('User "%s" does not have permission to delete %s objects', self.user, content_type.model)
213
210
  raise PermissionDenied("User does not have delete permissions on the requested content-type")
214
211
 
212
+ key_params = {
213
+ "content_type": content_type,
214
+ "delete_all": delete_all,
215
+ "filter_query_params": filter_query_params,
216
+ "pk_list": pk_list,
217
+ "saved_view_id": saved_view_id,
218
+ }
219
+
215
220
  model = content_type.model_class()
216
221
  if model is None:
217
222
  self.logger.error(
@@ -221,49 +226,7 @@ class BulkDeleteObjects(Job):
221
226
  )
222
227
  raise RunJobTaskFailed("Model not found")
223
228
 
224
- filterset_cls = get_filterset_for_model(model)
225
-
226
- if filter_query_params:
227
- if not filterset_cls:
228
- self.logger.error(f"Filterset not found for {model._meta.verbose_name}")
229
- raise RunJobTaskFailed(
230
- f"Filter query provided but {model._meta.verbose_name} does not have a filterset."
231
- )
232
-
233
- # Discarding non-filter query params
234
- new_filter_query_params = {}
235
-
236
- for key, value in filter_query_params.items():
237
- try:
238
- get_filterset_field(filterset_cls(), key)
239
- new_filter_query_params[key] = value
240
- except exceptions.FilterSetFieldNotFound:
241
- self.logger.debug(f"Query parameter `{key}` not found in `{filterset_cls}`, discarding it")
242
-
243
- filter_query_params = new_filter_query_params
244
-
245
- if delete_all:
246
- # Case for selecting all objects (or all filtered objects) to delete
247
- if filter_query_params:
248
- # If there is filter query params, we need to apply it to the queryset
249
- queryset = filterset_cls(filter_query_params).qs.restrict(self.user, "delete")
250
- # We take this approach because filterset.qs has already applied .distinct(),
251
- # and performing a .delete directly on a queryset with .distinct applied is not allowed.
252
- queryset = model.objects.filter(pk__in=queryset)
253
- else:
254
- # If there is not, we can just restrict the queryset to the user's permissions
255
- queryset = model.objects.restrict(self.user, "delete")
256
- elif pk_list:
257
- # Case for selecting specific objects to delete, delete_all overrides this option
258
- queryset = model.objects.restrict(self.user, "delete").filter(pk__in=pk_list)
259
- if queryset.count() < len(pk_list):
260
- # We do not check ObjectPermission error for `delete_all` case because user is trying to
261
- # delete all objs they have permission to which would not raise any issue.
262
- self.logger.error("You do not have permissions to delete some of the objects provided in `pk_list`.")
263
- raise RunJobTaskFailed("Caught ObjectPermission error while attempting to delete objects")
264
- elif not pk_list and not delete_all:
265
- self.logger.error("You must select at least one object instance to delete.")
266
- raise RunJobTaskFailed("Either `pk_list` or `delete_all` is required.")
229
+ queryset = get_bulk_queryset_from_view(user=self.user, action="delete", log=self.logger, **key_params)
267
230
 
268
231
  verbose_name_plural = model._meta.verbose_name_plural
269
232