nautobot 2.4.15__py3-none-any.whl → 2.4.17__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 (374) hide show
  1. nautobot/apps/utils.py +2 -0
  2. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +3 -3
  3. nautobot/cloud/views.py +7 -0
  4. nautobot/core/apps/__init__.py +1 -0
  5. nautobot/core/celery/__init__.py +2 -1
  6. nautobot/core/templates/components/panel/panel.html +1 -1
  7. nautobot/core/templates/inc/paginator.html +3 -3
  8. nautobot/core/templates/inc/table.html +2 -2
  9. nautobot/core/templatetags/helpers.py +80 -6
  10. nautobot/core/testing/mixins.py +1 -1
  11. nautobot/core/testing/views.py +2 -4
  12. nautobot/core/ui/bulk_buttons.py +53 -53
  13. nautobot/core/ui/object_detail.py +9 -4
  14. nautobot/core/utils/data.py +13 -0
  15. nautobot/core/utils/deprecation.py +2 -0
  16. nautobot/dcim/migrations/0073_alter_powerport_power_factor_and_more.py +41 -0
  17. nautobot/dcim/models/device_component_templates.py +4 -2
  18. nautobot/dcim/models/device_components.py +3 -2
  19. nautobot/dcim/templates/dcim/rack_elevation_list.html +4 -4
  20. nautobot/dcim/views.py +9 -0
  21. nautobot/extras/models/customfields.py +45 -9
  22. nautobot/extras/tables.py +12 -0
  23. nautobot/extras/templates/extras/configcontext_retrieve.html +1 -1
  24. nautobot/extras/templates/extras/configcontext_update.html +49 -49
  25. nautobot/extras/templates/extras/configcontextschema_retrieve.html +47 -47
  26. nautobot/extras/templates/extras/configcontextschema_update.html +18 -18
  27. nautobot/extras/templates/extras/inc/job_table.html +1 -1
  28. nautobot/extras/templates/extras/inc/object_contact_header.html +2 -2
  29. nautobot/extras/templates/extras/marketplace.html +1 -1
  30. nautobot/extras/templates/extras/note_retrieve.html +53 -53
  31. nautobot/extras/templates/extras/secretsgroup_retrieve.html +2 -29
  32. nautobot/extras/templates/extras/tag_retrieve.html +1 -1
  33. nautobot/extras/templates/extras/tag_update.html +14 -14
  34. nautobot/extras/templates/extras/team_retrieve.html +1 -1
  35. nautobot/extras/tests/test_models.py +216 -0
  36. nautobot/extras/tests/test_plugins.py +12 -0
  37. nautobot/extras/tests/test_views.py +2 -2
  38. nautobot/extras/views.py +20 -4
  39. nautobot/ipam/apps.py +1 -0
  40. nautobot/ipam/jobs/__init__.py +10 -0
  41. nautobot/ipam/jobs/cleanup.py +296 -0
  42. nautobot/ipam/models.py +301 -178
  43. nautobot/ipam/templates/ipam/inc/ipadress_edit_header.html +3 -3
  44. nautobot/ipam/templates/ipam/inc/toggle_available.html +2 -2
  45. nautobot/ipam/templates/ipam/ipaddress_assign.html +1 -1
  46. nautobot/ipam/templates/ipam/prefix_list.html +1 -1
  47. nautobot/ipam/templates/ipam/vlan_retrieve.html +1 -77
  48. nautobot/ipam/tests/test_jobs.py +454 -0
  49. nautobot/ipam/tests/test_models.py +290 -122
  50. nautobot/ipam/tests/test_views.py +40 -164
  51. nautobot/ipam/urls.py +0 -11
  52. nautobot/ipam/utils/testing.py +9 -4
  53. nautobot/ipam/views.py +166 -235
  54. nautobot/project-static/docs/404.html +9 -6
  55. nautobot/project-static/docs/apps/index.html +9 -6
  56. nautobot/project-static/docs/apps/nautobot-apps.html +9 -6
  57. nautobot/project-static/docs/assets/javascripts/bundle.92b07e13.min.js +16 -0
  58. nautobot/project-static/docs/assets/javascripts/{bundle.50899def.min.js.map → bundle.92b07e13.min.js.map} +2 -2
  59. nautobot/project-static/docs/assets/javascripts/workers/{search.d50fe291.min.js → search.973d3a69.min.js} +4 -4
  60. nautobot/project-static/docs/assets/javascripts/workers/{search.d50fe291.min.js.map → search.973d3a69.min.js.map} +1 -1
  61. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +9 -6
  62. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +9 -6
  63. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +9 -6
  64. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +9 -6
  65. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +10 -7
  66. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +9 -6
  67. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +9 -6
  68. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +9 -6
  69. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9 -6
  70. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +9 -6
  71. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +9 -6
  72. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +9 -6
  73. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +9 -6
  74. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +9 -6
  75. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +9 -6
  76. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +11 -8
  77. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +9 -6
  78. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +9 -6
  79. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +11 -8
  80. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +9 -6
  81. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +28 -9
  82. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +9 -6
  83. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +69 -7
  84. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +9 -6
  85. nautobot/project-static/docs/development/apps/api/configuration-view.html +13 -10
  86. nautobot/project-static/docs/development/apps/api/database-backend-config.html +11 -8
  87. nautobot/project-static/docs/development/apps/api/models/django-admin.html +13 -10
  88. nautobot/project-static/docs/development/apps/api/models/global-search.html +10 -7
  89. nautobot/project-static/docs/development/apps/api/models/graphql.html +18 -15
  90. nautobot/project-static/docs/development/apps/api/models/index.html +14 -11
  91. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +11 -8
  92. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +15 -12
  93. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +9 -6
  94. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +15 -12
  95. nautobot/project-static/docs/development/apps/api/platform-features/index.html +9 -6
  96. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +11 -8
  97. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +16 -13
  98. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +12 -10305
  99. nautobot/project-static/docs/development/apps/api/platform-features/prepopulating-data.html +10722 -0
  100. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +15 -12
  101. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +14 -11
  102. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +9 -6
  103. nautobot/project-static/docs/development/apps/api/prometheus.html +15 -12
  104. nautobot/project-static/docs/development/apps/api/setup.html +9 -6
  105. nautobot/project-static/docs/development/apps/api/testing.html +9 -6
  106. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +12 -9
  107. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +9 -6
  108. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +9 -6
  109. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +9 -6
  110. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +20 -17
  111. nautobot/project-static/docs/development/apps/api/views/base-template.html +9 -6
  112. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +15 -12
  113. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +14 -11
  114. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +9 -6
  115. nautobot/project-static/docs/development/apps/api/views/index.html +9 -6
  116. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +10 -7
  117. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +24 -21
  118. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +12 -9
  119. nautobot/project-static/docs/development/apps/api/views/notes.html +10 -7
  120. nautobot/project-static/docs/development/apps/api/views/rest-api.html +19 -16
  121. nautobot/project-static/docs/development/apps/api/views/urls.html +11 -8
  122. nautobot/project-static/docs/development/apps/index.html +9 -6
  123. nautobot/project-static/docs/development/apps/migration/code-updates.html +19 -16
  124. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +9 -6
  125. nautobot/project-static/docs/development/apps/migration/from-v1.html +9 -6
  126. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +22 -19
  127. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +9 -6
  128. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +9 -6
  129. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +9 -6
  130. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9 -6
  131. nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +14 -11
  132. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +27 -24
  133. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +20 -17
  134. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +20 -17
  135. nautobot/project-static/docs/development/apps/porting-from-netbox.html +9 -6
  136. nautobot/project-static/docs/development/core/application-registry.html +23 -20
  137. nautobot/project-static/docs/development/core/best-practices.html +23 -20
  138. nautobot/project-static/docs/development/core/bootstrap-ui.html +9 -6
  139. nautobot/project-static/docs/development/core/caching.html +9 -6
  140. nautobot/project-static/docs/development/core/controllers.html +9 -6
  141. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +10 -7
  142. nautobot/project-static/docs/development/core/generic-views.html +9 -6
  143. nautobot/project-static/docs/development/core/getting-started.html +9 -6
  144. nautobot/project-static/docs/development/core/homepage.html +12 -9
  145. nautobot/project-static/docs/development/core/index.html +9 -6
  146. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +9 -6
  147. nautobot/project-static/docs/development/core/model-checklist.html +9 -6
  148. nautobot/project-static/docs/development/core/model-features.html +11 -8
  149. nautobot/project-static/docs/development/core/natural-keys.html +21 -18
  150. nautobot/project-static/docs/development/core/navigation-menu.html +10 -7
  151. nautobot/project-static/docs/development/core/release-checklist.html +9 -6
  152. nautobot/project-static/docs/development/core/role-internals.html +9 -6
  153. nautobot/project-static/docs/development/core/settings.html +9 -6
  154. nautobot/project-static/docs/development/core/style-guide.html +32 -29
  155. nautobot/project-static/docs/development/core/templates.html +9 -6
  156. nautobot/project-static/docs/development/core/testing.html +10 -7
  157. nautobot/project-static/docs/development/core/ui-component-framework.html +36 -33
  158. nautobot/project-static/docs/development/core/user-preferences.html +9 -6
  159. nautobot/project-static/docs/development/index.html +9 -6
  160. nautobot/project-static/docs/development/jobs/getting-started.html +13 -10
  161. nautobot/project-static/docs/development/jobs/index.html +9 -6
  162. nautobot/project-static/docs/development/jobs/installation.html +23 -20
  163. nautobot/project-static/docs/development/jobs/job-extensions.html +25 -22
  164. nautobot/project-static/docs/development/jobs/job-logging.html +12 -9
  165. nautobot/project-static/docs/development/jobs/job-patterns.html +45 -42
  166. nautobot/project-static/docs/development/jobs/job-structure.html +53 -50
  167. nautobot/project-static/docs/development/jobs/migration/from-v1.html +23 -20
  168. nautobot/project-static/docs/development/jobs/testing.html +14 -11
  169. nautobot/project-static/docs/index.html +9 -6
  170. nautobot/project-static/docs/objects.inv +0 -0
  171. nautobot/project-static/docs/overview/application_stack.html +9 -6
  172. nautobot/project-static/docs/overview/design_philosophy.html +9 -6
  173. nautobot/project-static/docs/release-notes/index.html +9 -6
  174. nautobot/project-static/docs/release-notes/version-1.0.html +9 -6
  175. nautobot/project-static/docs/release-notes/version-1.1.html +9 -6
  176. nautobot/project-static/docs/release-notes/version-1.2.html +10 -7
  177. nautobot/project-static/docs/release-notes/version-1.3.html +9 -6
  178. nautobot/project-static/docs/release-notes/version-1.4.html +9 -6
  179. nautobot/project-static/docs/release-notes/version-1.5.html +13 -10
  180. nautobot/project-static/docs/release-notes/version-1.6.html +9 -6
  181. nautobot/project-static/docs/release-notes/version-2.0.html +9 -6
  182. nautobot/project-static/docs/release-notes/version-2.1.html +9 -6
  183. nautobot/project-static/docs/release-notes/version-2.2.html +9 -6
  184. nautobot/project-static/docs/release-notes/version-2.3.html +9 -6
  185. nautobot/project-static/docs/release-notes/version-2.4.html +342 -6
  186. nautobot/project-static/docs/requirements.txt +2 -2
  187. nautobot/project-static/docs/search/search_index.json +1 -1
  188. nautobot/project-static/docs/sitemap.xml +301 -301
  189. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  190. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +15 -12
  191. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +9 -6
  192. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +16 -13
  193. nautobot/project-static/docs/user-guide/administration/configuration/index.html +9 -6
  194. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +9 -6
  195. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +11 -8
  196. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +9 -6
  197. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +9 -6
  198. nautobot/project-static/docs/user-guide/administration/guides/docker.html +9 -6
  199. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +9 -6
  200. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +9 -6
  201. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +9 -6
  202. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +9 -6
  203. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +9 -6
  204. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +16 -13
  205. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +9 -6
  206. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +9 -6
  207. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +9 -6
  208. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +9 -6
  209. nautobot/project-static/docs/user-guide/administration/installation/index.html +9 -6
  210. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +9 -6
  211. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +9 -6
  212. nautobot/project-static/docs/user-guide/administration/installation/services.html +12 -9
  213. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +13 -10
  214. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +10 -7
  215. nautobot/project-static/docs/user-guide/administration/security/index.html +9 -6
  216. nautobot/project-static/docs/user-guide/administration/security/notices.html +9 -6
  217. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +9 -6
  218. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +10 -7
  219. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +9 -6
  220. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +9 -6
  221. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +9 -6
  222. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +9 -6
  223. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +9 -6
  224. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +9 -6
  225. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +9 -6
  226. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +15 -12
  227. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +9 -6
  228. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +9 -6
  229. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +9 -6
  230. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +9 -6
  231. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +9 -6
  232. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +9 -6
  233. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +9 -6
  234. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +9 -6
  235. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +9 -6
  236. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +9 -6
  237. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +9 -6
  238. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +9 -6
  239. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +9 -6
  240. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +9 -6
  241. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +9 -6
  242. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +9 -6
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +9 -6
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +9 -6
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +9 -6
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +9 -6
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +9 -6
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +9 -6
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +9 -6
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +9 -6
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +13 -10
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +9 -6
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +9 -6
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +9 -6
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +9 -6
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +9 -6
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +9 -6
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +9 -6
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +9 -6
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +9 -6
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +9 -6
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +9 -6
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +9 -6
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +9 -6
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +9 -6
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +9 -6
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +9 -6
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +9 -6
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +9 -6
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +9 -6
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +9 -6
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +9 -6
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +9 -6
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +9 -6
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +9 -6
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +9 -6
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +9 -6
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +9 -6
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +9 -6
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +9 -6
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +9 -6
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9 -6
  283. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +9 -6
  284. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +9 -6
  285. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +11 -8
  286. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +11 -8
  287. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +41 -41
  288. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +9 -6
  289. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +197 -54
  290. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +9 -6
  291. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +9 -6
  292. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +9 -6
  293. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +9 -6
  294. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +9 -6
  295. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +9 -6
  296. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +9 -6
  297. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +9 -6
  298. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +9 -6
  299. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +9 -6
  300. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +9 -6
  301. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +9 -6
  302. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +9 -6
  303. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +9 -6
  304. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9 -6
  305. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9 -6
  306. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9 -6
  307. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9 -6
  308. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +9 -6
  309. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +9 -6
  310. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +9 -6
  311. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +9 -6
  312. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +9 -6
  313. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +9 -6
  314. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +9 -6
  315. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +9 -6
  316. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +9 -6
  317. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +9 -6
  318. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +9 -6
  319. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +9 -6
  320. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +13 -10
  321. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +9 -6
  322. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +9 -6
  323. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +9 -6
  324. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +9 -6
  325. nautobot/project-static/docs/user-guide/index.html +9 -6
  326. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +9 -6
  327. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +9 -6
  328. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +10 -7
  329. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +9 -6
  330. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +9 -6
  331. nautobot/project-static/docs/user-guide/platform-functionality/events.html +11 -8
  332. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +9 -6
  333. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +9 -6
  334. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +9 -6
  335. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +9 -6
  336. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +9 -6
  337. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +9 -6
  338. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +9 -6
  339. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +9 -6
  340. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +9 -6
  341. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +9 -6
  342. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9 -6
  343. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9 -6
  344. nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +9 -6
  345. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +9 -6
  346. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +9 -6
  347. nautobot/project-static/docs/user-guide/platform-functionality/note.html +9 -6
  348. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +12 -9
  349. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +9 -6
  350. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9 -6
  351. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +9 -6
  352. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +9 -6
  353. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +9 -6
  354. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +9 -6
  355. nautobot/project-static/docs/user-guide/platform-functionality/role.html +9 -6
  356. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9 -6
  357. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +11 -8
  358. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +9 -6
  359. nautobot/project-static/docs/user-guide/platform-functionality/status.html +9 -6
  360. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +9 -6
  361. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +9 -6
  362. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +9 -6
  363. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +9 -6
  364. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +9 -6
  365. nautobot/project-static/fonts/UFL.txt +96 -96
  366. nautobot/project-static/js/forms.js +35 -2
  367. nautobot/virtualization/filters.py +7 -0
  368. {nautobot-2.4.15.dist-info → nautobot-2.4.17.dist-info}/METADATA +6 -6
  369. {nautobot-2.4.15.dist-info → nautobot-2.4.17.dist-info}/RECORD +373 -368
  370. nautobot/project-static/docs/assets/javascripts/bundle.50899def.min.js +0 -16
  371. {nautobot-2.4.15.dist-info → nautobot-2.4.17.dist-info}/LICENSE.txt +0 -0
  372. {nautobot-2.4.15.dist-info → nautobot-2.4.17.dist-info}/NOTICE +0 -0
  373. {nautobot-2.4.15.dist-info → nautobot-2.4.17.dist-info}/WHEEL +0 -0
  374. {nautobot-2.4.15.dist-info → nautobot-2.4.17.dist-info}/entry_points.txt +0 -0
nautobot/apps/utils.py CHANGED
@@ -13,6 +13,7 @@ from nautobot.core.utils.data import (
13
13
  render_jinja2,
14
14
  shallow_compare_dict,
15
15
  to_meters,
16
+ validate_jinja2,
16
17
  )
17
18
  from nautobot.core.utils.deprecation import class_deprecated, class_deprecated_in_favor_of
18
19
  from nautobot.core.utils.filtering import (
@@ -139,5 +140,6 @@ __all__ = (
139
140
  "swap_status_initials",
140
141
  "task_queues_as_choices",
141
142
  "to_meters",
143
+ "validate_jinja2",
142
144
  "wrap_model_clean_methods",
143
145
  )
@@ -1,4 +1,4 @@
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>
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
4
  {% endblock extra_breadcrumbs %}
nautobot/cloud/views.py CHANGED
@@ -94,6 +94,7 @@ class CloudNetworkUIViewSet(NautobotUIViewSet):
94
94
  table_class=CloudNetworkTable,
95
95
  table_filter="parent",
96
96
  tab_id="children",
97
+ include_paginator=True,
97
98
  ),
98
99
  ),
99
100
  ),
@@ -111,6 +112,7 @@ class CloudNetworkUIViewSet(NautobotUIViewSet):
111
112
  table_filter="cloud_networks",
112
113
  exclude_columns=("location_count", "vlan"),
113
114
  tab_id="prefixes",
115
+ include_paginator=True,
114
116
  ),
115
117
  ),
116
118
  ),
@@ -129,6 +131,7 @@ class CloudNetworkUIViewSet(NautobotUIViewSet):
129
131
  related_field_name="cloud_network",
130
132
  exclude_columns=("circuit_termination_a", "circuit_termination_z"),
131
133
  tab_id="circuits",
134
+ include_paginator=True,
132
135
  ),
133
136
  ),
134
137
  ),
@@ -146,6 +149,7 @@ class CloudNetworkUIViewSet(NautobotUIViewSet):
146
149
  table_filter="cloud_networks",
147
150
  exclude_columns=("cloud_network_count"),
148
151
  tab_id="cloud_services",
152
+ include_paginator=True,
149
153
  ),
150
154
  ),
151
155
  ),
@@ -222,6 +226,7 @@ class CloudResourceTypeUIViewSet(NautobotUIViewSet):
222
226
  table_class=CloudNetworkTable,
223
227
  table_filter="cloud_resource_type",
224
228
  tab_id="networks",
229
+ include_paginator=True,
225
230
  ),
226
231
  ),
227
232
  ),
@@ -238,6 +243,7 @@ class CloudResourceTypeUIViewSet(NautobotUIViewSet):
238
243
  table_class=CloudServiceTable,
239
244
  table_filter="cloud_resource_type",
240
245
  tab_id="services",
246
+ include_paginator=True,
241
247
  ),
242
248
  ),
243
249
  ),
@@ -302,6 +308,7 @@ class CloudServiceUIViewSet(NautobotUIViewSet):
302
308
  table_filter="cloud_services",
303
309
  tab_id="cloud_networks",
304
310
  add_button_route=None,
311
+ include_paginator=True,
305
312
  ),
306
313
  ),
307
314
  ),
@@ -337,6 +337,7 @@ class CoreConfig(NautobotConfig):
337
337
  from graphene_django.converter import convert_django_field
338
338
 
339
339
  from nautobot.core.graphql import BigInteger
340
+ import nautobot.core.jobs # noqa: F401 # unused-import -- but this import registers the system jobs
340
341
 
341
342
  @convert_django_field.register(JSONField)
342
343
  def convert_json(field, registry=None): # pylint: disable=redefined-outer-name
@@ -54,7 +54,8 @@ def import_jobs(sender=None, **kwargs):
54
54
 
55
55
  Note that app-provided jobs are automatically imported at startup time via NautobotAppConfig.ready()
56
56
  """
57
- import nautobot.core.jobs # noqa: F401
57
+ import nautobot.core.jobs
58
+ import nautobot.ipam.jobs # noqa: F401
58
59
 
59
60
  _import_jobs_from_jobs_root()
60
61
  _import_dynamic_jobs_from_apps()
@@ -15,6 +15,6 @@
15
15
  {% endif %}
16
16
  </div>
17
17
 
18
- {% if body_content_table.paginator %}
18
+ {% if include_paginator and body_content_table.paginator%}
19
19
  {% include 'inc/paginator.html' with paginator=body_content_table.paginator page=body_content_table.page %}
20
20
  {% endif %}
@@ -5,17 +5,17 @@
5
5
  <nav>
6
6
  <ul class="pagination pull-right">
7
7
  {% if page.has_previous %}
8
- <li><a href="{% querystring request page=page.previous_page_number %}"><i class="mdi mdi-chevron-double-left"></i></a></li>
8
+ <li><a href="{% legacy_querystring request page=page.previous_page_number %}"><i class="mdi mdi-chevron-double-left"></i></a></li>
9
9
  {% endif %}
10
10
  {% for p in page.smart_pages %}
11
11
  {% if p %}
12
- <li{% if page.number == p %} class="active"{% endif %}><a href="{% querystring request page=p %}">{{ p }}</a></li>
12
+ <li{% if page.number == p %} class="active"{% endif %}><a href="{% legacy_querystring request page=p %}">{{ p }}</a></li>
13
13
  {% else %}
14
14
  <li class="disabled"><span>&hellip;</span></li>
15
15
  {% endif %}
16
16
  {% endfor %}
17
17
  {% if page.has_next %}
18
- <li><a href="{% querystring request page=page.next_page_number %}"><i class="mdi mdi-chevron-double-right"></i></a></li>
18
+ <li><a href="{% legacy_querystring request page=page.next_page_number %}"><i class="mdi mdi-chevron-double-right"></i></a></li>
19
19
  {% endif %}
20
20
  </ul>
21
21
  </nav>
@@ -1,6 +1,6 @@
1
- {% load django_tables2 %}
1
+ {% load querystring from django_tables2 %}
2
2
 
3
- <table{% if table.attrs %} {{ table.attrs.as_html }}{% endif %}>
3
+ <table {% if table.attrs %} {{ table.attrs.as_html }}{% endif %}>
4
4
  {% if table.show_header %}
5
5
  <thead>
6
6
  <tr>
@@ -1,3 +1,4 @@
1
+ from collections.abc import Iterable
1
2
  import datetime
2
3
  import json
3
4
  import logging
@@ -23,7 +24,7 @@ import yaml
23
24
  from nautobot.apps.config import get_app_settings_or_config
24
25
  from nautobot.core import forms
25
26
  from nautobot.core.constants import PAGINATE_COUNT_DEFAULT
26
- from nautobot.core.utils import color, config, data, logging as nautobot_logging, lookup
27
+ from nautobot.core.utils import color, config, data, deprecation, logging as nautobot_logging, lookup
27
28
  from nautobot.core.utils.requests import add_nautobot_version_query_param_to_url
28
29
 
29
30
  HTML_TRUE = mark_safe('<span class="text-success"><i class="mdi mdi-check-bold" title="Yes"></i></span>')
@@ -762,6 +763,23 @@ def render_address(address):
762
763
  return HTML_NONE
763
764
 
764
765
 
766
+ @register.filter()
767
+ def render_m2m(queryset, full_listing_link, verbose_name_plural, max_visible=5):
768
+ total_count = queryset.count()
769
+ display_count = min(total_count, max_visible)
770
+ if not display_count:
771
+ return HTML_NONE
772
+
773
+ items = [hyperlinked_object(record) for record in queryset[:display_count]]
774
+
775
+ remaining = total_count - display_count
776
+ if remaining > 0:
777
+ link = format_html('<a href="{}">... View {} more {}</a>', full_listing_link, remaining, verbose_name_plural)
778
+ items.append(link)
779
+
780
+ return format_html_join("", "<div>{}</div>", ((item,) for item in items)) if items else HTML_NONE
781
+
782
+
765
783
  @library.filter()
766
784
  @register.filter()
767
785
  def render_button_class(value):
@@ -823,11 +841,7 @@ def get_attr(obj, attr, default=None):
823
841
  return getattr(obj, attr, default)
824
842
 
825
843
 
826
- @register.simple_tag()
827
- def querystring(request, **kwargs):
828
- """
829
- Append or update the page number in a querystring.
830
- """
844
+ def _base_querystring(request, **kwargs):
831
845
  querydict = request.GET.copy()
832
846
  for k, v in kwargs.items():
833
847
  if v is not None:
@@ -841,6 +855,66 @@ def querystring(request, **kwargs):
841
855
  return ""
842
856
 
843
857
 
858
+ # TODO: Remove this tag in Nautobot 3.0.
859
+
860
+
861
+ @register.simple_tag()
862
+ @deprecation.method_deprecated(
863
+ "Leverage `legacy_querystring` instead of `querystring` if this templatetag is required. In Nautobot 3.0, "
864
+ "`querystring` will be removed in preparation for Django 5.2 in which there is a built-in querystring tag "
865
+ "that operates differently. You may find that `django_querystring` is more appropriate for your use case "
866
+ "and is a replica of Django 5.2's `querystring` templatetag."
867
+ )
868
+ def querystring(request, **kwargs):
869
+ return _base_querystring(request, **kwargs)
870
+
871
+
872
+ @register.simple_tag()
873
+ def legacy_querystring(request, **kwargs):
874
+ return _base_querystring(request, **kwargs)
875
+
876
+
877
+ # Note: This is vendored from Django 5.2
878
+ @register.simple_tag(name="django_querystring", takes_context=True)
879
+ def django_querystring(context, query_dict=None, **kwargs):
880
+ """
881
+ Add, remove, and change parameters of a ``QueryDict`` and return the result
882
+ as a query string. If the ``query_dict`` argument is not provided, default
883
+ to ``request.GET``.
884
+
885
+ For example::
886
+
887
+ {% django_querystring foo=3 %}
888
+
889
+ To remove a key::
890
+
891
+ {% django_querystring foo=None %}
892
+
893
+ To use with pagination::
894
+
895
+ {% django_querystring page=page_obj.next_page_number %}
896
+
897
+ A custom ``QueryDict`` can also be used::
898
+
899
+ {% django_querystring my_query_dict foo=3 %}
900
+ """
901
+ if query_dict is None:
902
+ query_dict = context.request.GET
903
+ params = query_dict.copy()
904
+ for key, value in kwargs.items():
905
+ if value is None:
906
+ if key in params:
907
+ del params[key]
908
+ elif isinstance(value, Iterable) and not isinstance(value, str):
909
+ params.setlist(key, value)
910
+ else:
911
+ params[key] = value
912
+ if not params and not query_dict:
913
+ return ""
914
+ query_string = params.urlencode()
915
+ return f"?{query_string}"
916
+
917
+
844
918
  @register.simple_tag()
845
919
  def table_config_button(table, table_name=None, extra_classes="", disabled=False):
846
920
  if table_name is None:
@@ -156,7 +156,7 @@ class NautobotTestCaseMixin:
156
156
  """
157
157
  for name in names:
158
158
  ct, action = permissions.resolve_permission_ct(name)
159
- obj_perm = users_models.ObjectPermission(name=name, actions=[action], **kwargs)
159
+ obj_perm, _ = users_models.ObjectPermission.objects.get_or_create(name=name, actions=[action], **kwargs)
160
160
  obj_perm.save()
161
161
  obj_perm.users.add(self.user)
162
162
  obj_perm.object_types.add(ct)
@@ -281,8 +281,7 @@ class ViewTestCases:
281
281
  if getattr(obj, "is_contact_associable_model", False):
282
282
  self.assertBodyContains(
283
283
  response,
284
- f'<a href="{obj.get_absolute_url()}#contacts" onclick="switch_tab(this.href)" aria-controls="contacts" role="tab" data-toggle="tab">Contacts</a>',
285
- html=True,
284
+ f'href="{obj.get_absolute_url()}#contacts" onclick="switch_tab(this.href)"',
286
285
  )
287
286
  else:
288
287
  self.assertNotContains(response, f"{obj.get_absolute_url()}#contacts")
@@ -304,8 +303,7 @@ class ViewTestCases:
304
303
  if getattr(obj, "is_contact_associable_model", False):
305
304
  self.assertBodyContains(
306
305
  response,
307
- f'<a href="{obj.get_absolute_url()}#contacts" onclick="switch_tab(this.href)" aria-controls="contacts" role="tab" data-toggle="tab">Contacts</a>',
308
- html=True,
306
+ f'href="{obj.get_absolute_url()}#contacts" onclick="switch_tab(this.href)"',
309
307
  )
310
308
  else:
311
309
  self.assertNotContains(response, f"{obj.get_absolute_url()}#contacts")
@@ -1,53 +1,53 @@
1
- from nautobot.core.choices import ButtonActionColorChoices
2
- from nautobot.core.ui import object_detail
3
-
4
-
5
- class BaseBulkButton(object_detail.FormButton):
6
- """Base class for bulk action buttons."""
7
-
8
- action = None
9
- color = None
10
- icon = None
11
- label = None
12
- weight = None
13
-
14
- def __init__(self, *, form_id: str, model, **kwargs):
15
- model_name = model.__name__.lower()
16
- app_label = model._meta.app_label
17
- link_name = f"{app_label}:{model_name}_bulk_{self.action}"
18
-
19
- super().__init__(
20
- link_name=link_name,
21
- link_includes_pk=False,
22
- label=self.label,
23
- color=self.color,
24
- icon=self.icon,
25
- size="xs",
26
- form_id=form_id,
27
- weight=self.weight,
28
- **kwargs,
29
- )
30
-
31
-
32
- class BulkRenameButton(BaseBulkButton):
33
- action = "rename"
34
- color = ButtonActionColorChoices.RENAME
35
- icon = "mdi-pencil"
36
- label = "Rename"
37
- weight = 200
38
-
39
-
40
- class BulkEditButton(BaseBulkButton):
41
- action = "edit"
42
- color = ButtonActionColorChoices.EDIT
43
- icon = "mdi-pencil"
44
- label = "Edit"
45
- weight = 300
46
-
47
-
48
- class BulkDeleteButton(BaseBulkButton):
49
- action = "delete"
50
- color = ButtonActionColorChoices.DELETE
51
- icon = "mdi-trash-can-outline"
52
- label = "Delete"
53
- weight = 400
1
+ from nautobot.core.choices import ButtonActionColorChoices
2
+ from nautobot.core.ui import object_detail
3
+
4
+
5
+ class BaseBulkButton(object_detail.FormButton):
6
+ """Base class for bulk action buttons."""
7
+
8
+ action = None
9
+ color = None
10
+ icon = None
11
+ label = None
12
+ weight = None
13
+
14
+ def __init__(self, *, form_id: str, model, **kwargs):
15
+ model_name = model.__name__.lower()
16
+ app_label = model._meta.app_label
17
+ link_name = f"{app_label}:{model_name}_bulk_{self.action}"
18
+
19
+ super().__init__(
20
+ link_name=link_name,
21
+ link_includes_pk=False,
22
+ label=self.label,
23
+ color=self.color,
24
+ icon=self.icon,
25
+ size="xs",
26
+ form_id=form_id,
27
+ weight=self.weight,
28
+ **kwargs,
29
+ )
30
+
31
+
32
+ class BulkRenameButton(BaseBulkButton):
33
+ action = "rename"
34
+ color = ButtonActionColorChoices.RENAME
35
+ icon = "mdi-pencil"
36
+ label = "Rename"
37
+ weight = 200
38
+
39
+
40
+ class BulkEditButton(BaseBulkButton):
41
+ action = "edit"
42
+ color = ButtonActionColorChoices.EDIT
43
+ icon = "mdi-pencil"
44
+ label = "Edit"
45
+ weight = 300
46
+
47
+
48
+ class BulkDeleteButton(BaseBulkButton):
49
+ action = "delete"
50
+ color = ButtonActionColorChoices.DELETE
51
+ icon = "mdi-trash-can-outline"
52
+ label = "Delete"
53
+ weight = 400
@@ -459,7 +459,7 @@ class DistinctViewTab(Tab):
459
459
  return format_html(
460
460
  "{} {}",
461
461
  self.label,
462
- render_to_string("utilities/templatetags/badge.html", badge(related_obj_count)),
462
+ render_to_string("utilities/templatetags/badge.html", badge(related_obj_count, True)),
463
463
  )
464
464
  except AttributeError:
465
465
  logger.warning(
@@ -704,6 +704,7 @@ class ObjectsTablePanel(Panel):
704
704
  footer_content_template_path="components/panel/footer_content_table.html",
705
705
  footer_buttons=None,
706
706
  form_id=None,
707
+ include_paginator=False,
707
708
  **kwargs,
708
709
  ):
709
710
  """Instantiate an ObjectsTable panel.
@@ -752,6 +753,7 @@ class ObjectsTablePanel(Panel):
752
753
  footer_buttons (list, optional): A list of Button or FormButton components to render in the panel footer.
753
754
  These buttons typically perform actions like bulk delete, edit, or custom form submission.
754
755
  form_id (str, optional): A unique ID for this table's form; used to set the `data-form-id` attribute on each `FormButton`.
756
+ include_paginator (bool, optional): If True, renders a paginator in the panel footer.
755
757
  """
756
758
  if context_table_key and any(
757
759
  [
@@ -796,6 +798,7 @@ class ObjectsTablePanel(Panel):
796
798
  self.tab_id = tab_id
797
799
  self.footer_buttons = footer_buttons
798
800
  self.form_id = form_id
801
+ self.include_paginator = include_paginator
799
802
 
800
803
  super().__init__(
801
804
  body_wrapper_template_path=body_wrapper_template_path,
@@ -953,6 +956,7 @@ class ObjectsTablePanel(Panel):
953
956
  "footer_buttons": self.footer_buttons,
954
957
  "form_id": self.form_id,
955
958
  "more_queryset_count": more_queryset_count,
959
+ "include_paginator": self.include_paginator,
956
960
  "show_table_config_button": self.show_table_config_button,
957
961
  }
958
962
 
@@ -1912,7 +1916,8 @@ class _ObjectDetailContactsTab(Tab):
1912
1916
  "{} {}",
1913
1917
  self.label,
1914
1918
  render_to_string(
1915
- "utilities/templatetags/badge.html", badge(get_obj_from_context(context).associated_contacts.count())
1919
+ "utilities/templatetags/badge.html",
1920
+ badge(get_obj_from_context(context).associated_contacts.count(), True),
1916
1921
  ),
1917
1922
  )
1918
1923
 
@@ -1956,7 +1961,7 @@ class _ObjectDetailGroupsTab(Tab):
1956
1961
  "{} {}",
1957
1962
  self.label,
1958
1963
  render_to_string(
1959
- "utilities/templatetags/badge.html", badge(get_obj_from_context(context).dynamic_groups.count())
1964
+ "utilities/templatetags/badge.html", badge(get_obj_from_context(context).dynamic_groups.count(), True)
1960
1965
  ),
1961
1966
  )
1962
1967
 
@@ -2003,6 +2008,6 @@ class _ObjectDetailMetadataTab(Tab):
2003
2008
  self.label,
2004
2009
  render_to_string(
2005
2010
  "utilities/templatetags/badge.html",
2006
- badge(get_obj_from_context(context).associated_object_metadata.count()),
2011
+ badge(get_obj_from_context(context).associated_object_metadata.count(), True),
2007
2012
  ),
2008
2013
  )
@@ -92,6 +92,19 @@ def merge_dicts_without_collision(d1, d2):
92
92
  return {**d1, **d2}
93
93
 
94
94
 
95
+ def validate_jinja2(template_code):
96
+ """
97
+ Parse a Jinja2 template to validate its syntax. Returns True if the template is valid.
98
+
99
+ Raises:
100
+ jinja2.TemplateSyntaxError: If the template is syntactically invalid.
101
+ """
102
+ rendering_engine = engines["jinja"]
103
+ rendering_engine.env.parse(template_code)
104
+
105
+ return True
106
+
107
+
95
108
  def render_jinja2(template_code, context):
96
109
  """
97
110
  Render a Jinja2 template with the provided context. Return the rendered content.
@@ -1,5 +1,6 @@
1
1
  """Utilities for handling deprecation of code and features."""
2
2
 
3
+ from functools import wraps
3
4
  import logging
4
5
  import traceback
5
6
  import warnings
@@ -51,6 +52,7 @@ def method_deprecated(message):
51
52
  """Decorator to mark a method as deprecated with a custom message about what to call instead."""
52
53
 
53
54
  def decorate(method):
55
+ @wraps(method)
54
56
  def decorated_method(*args, **kwargs):
55
57
  warnings.warn(
56
58
  f"Method `{method.__name__}` is deprecated, and will be removed in a future Nautobot release. "
@@ -0,0 +1,41 @@
1
+ # Generated by Django 4.2.23 on 2025-08-22 21:03
2
+
3
+ from decimal import Decimal
4
+
5
+ import django.core.validators
6
+ from django.db import migrations, models
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+ dependencies = [
11
+ ("dcim", "0072_alter_powerfeed_options_and_more"),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AlterField(
16
+ model_name="powerport",
17
+ name="power_factor",
18
+ field=models.DecimalField(
19
+ decimal_places=2,
20
+ default=Decimal("0.95"),
21
+ max_digits=4,
22
+ validators=[
23
+ django.core.validators.MinValueValidator(Decimal("0.01")),
24
+ django.core.validators.MaxValueValidator(Decimal("1.00")),
25
+ ],
26
+ ),
27
+ ),
28
+ migrations.AlterField(
29
+ model_name="powerporttemplate",
30
+ name="power_factor",
31
+ field=models.DecimalField(
32
+ decimal_places=2,
33
+ default=Decimal("0.95"),
34
+ max_digits=4,
35
+ validators=[
36
+ django.core.validators.MinValueValidator(Decimal("0.01")),
37
+ django.core.validators.MaxValueValidator(Decimal("1.00")),
38
+ ],
39
+ ),
40
+ ),
41
+ ]
@@ -1,3 +1,5 @@
1
+ from decimal import Decimal
2
+
1
3
  from django.contrib.contenttypes.models import ContentType
2
4
  from django.core.exceptions import ObjectDoesNotExist, ValidationError
3
5
  from django.core.validators import MaxValueValidator, MinValueValidator
@@ -252,8 +254,8 @@ class PowerPortTemplate(ModularComponentTemplateModel):
252
254
  power_factor = models.DecimalField(
253
255
  max_digits=4,
254
256
  decimal_places=2,
255
- default="0.95",
256
- validators=[MinValueValidator(0.01), MaxValueValidator(1.00)],
257
+ default=Decimal("0.95"),
258
+ validators=[MinValueValidator(Decimal("0.01")), MaxValueValidator(Decimal("1.00"))],
257
259
  help_text="Power factor (0.01-1.00) for converting between watts (W) and volt-amps (VA). Defaults to 0.95.",
258
260
  )
259
261
 
@@ -1,3 +1,4 @@
1
+ from decimal import Decimal
1
2
  import re
2
3
 
3
4
  from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
@@ -402,8 +403,8 @@ class PowerPort(ModularComponentModel, CableTermination, PathEndpoint):
402
403
  power_factor = models.DecimalField(
403
404
  max_digits=4,
404
405
  decimal_places=2,
405
- default="0.95",
406
- validators=[MinValueValidator(0.01), MaxValueValidator(1.00)],
406
+ default=Decimal("0.95"),
407
+ validators=[MinValueValidator(Decimal("0.01")), MaxValueValidator(Decimal("1.00"))],
407
408
  help_text="Power factor (0.01-1.00) for converting between watts (W) and volt-amps (VA). Defaults to 0.95.",
408
409
  )
409
410
 
@@ -10,12 +10,12 @@
10
10
  <span class="mdi mdi-checkbox-marked-circle-outline" aria-hidden="true"></span> Show Images
11
11
  </button>
12
12
  <div class="btn-group" role="group">
13
- <a href="{% url 'dcim:rack_elevation_list' %}{% querystring request face='front' %}" class="btn btn-default{% if rack_face == 'front' %} active{% endif %}">Front</a>
14
- <a href="{% url 'dcim:rack_elevation_list' %}{% querystring request face='rear' %}" class="btn btn-default{% if rack_face == 'rear' %} active{% endif %}">Rear</a>
13
+ <a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request face='front' %}" class="btn btn-default{% if rack_face == 'front' %} active{% endif %}">Front</a>
14
+ <a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request face='rear' %}" class="btn btn-default{% if rack_face == 'rear' %} active{% endif %}">Rear</a>
15
15
  </div>
16
16
  <div class="btn-group" role="group">
17
- <a href="{% url 'dcim:rack_elevation_list' %}{% querystring request reverse=None %}" class="btn btn-default{% if not reverse %} active{% endif %}">Normal</a>
18
- <a href="{% url 'dcim:rack_elevation_list' %}{% querystring request reverse='true' %}" class="btn btn-default{% if reverse %} active{% endif %}">Reversed</a>
17
+ <a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request reverse=None %}" class="btn btn-default{% if not reverse %} active{% endif %}">Normal</a>
18
+ <a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request reverse='true' %}" class="btn btn-default{% if reverse %} active{% endif %}">Reversed</a>
19
19
  </div>
20
20
  {% endblock %}
21
21
 
nautobot/dcim/views.py CHANGED
@@ -899,6 +899,7 @@ def make_bulk_tab(weight, tab_name, label, url_name, related_attr, table_class,
899
899
  enable_bulk_actions=True,
900
900
  form_id=form_id,
901
901
  footer_buttons=bulk_footer_buttons(form_id=form_id, model=model),
902
+ include_paginator=True,
902
903
  ),
903
904
  ),
904
905
  )
@@ -1965,6 +1966,7 @@ class DeviceView(generic.ObjectView):
1965
1966
  exclude_columns=["content_type"],
1966
1967
  add_button_route=None,
1967
1968
  related_field_name="member_id",
1969
+ include_paginator=True,
1968
1970
  ),
1969
1971
  ),
1970
1972
  )
@@ -4794,6 +4796,7 @@ class SoftwareImageFileUIViewSet(NautobotUIViewSet):
4794
4796
  table_filter="software_image_files",
4795
4797
  tab_id="device_types",
4796
4798
  add_button_route=None,
4799
+ include_paginator=True,
4797
4800
  ),
4798
4801
  ),
4799
4802
  ),
@@ -4812,6 +4815,7 @@ class SoftwareImageFileUIViewSet(NautobotUIViewSet):
4812
4815
  tab_id="devices",
4813
4816
  table_title="Devices overridden to use this file",
4814
4817
  add_button_route=None,
4818
+ include_paginator=True,
4815
4819
  ),
4816
4820
  ),
4817
4821
  ),
@@ -4830,6 +4834,7 @@ class SoftwareImageFileUIViewSet(NautobotUIViewSet):
4830
4834
  tab_id="inventory_items",
4831
4835
  table_title="Inventory items overridden to use this file",
4832
4836
  add_button_route=None,
4837
+ include_paginator=True,
4833
4838
  ),
4834
4839
  ),
4835
4840
  ),
@@ -4848,6 +4853,7 @@ class SoftwareImageFileUIViewSet(NautobotUIViewSet):
4848
4853
  tab_id="virtual_machines",
4849
4854
  table_title="Virtual machines overridden to use this file",
4850
4855
  add_button_route=None,
4856
+ include_paginator=True,
4851
4857
  ),
4852
4858
  ),
4853
4859
  ),
@@ -4993,6 +4999,7 @@ class ControllerUIViewSet(NautobotUIViewSet):
4993
4999
  add_button_route=None,
4994
5000
  select_related_fields=["wireless_network"],
4995
5001
  exclude_columns=["controller"],
5002
+ include_paginator=True,
4996
5003
  ),
4997
5004
  ),
4998
5005
  ),
@@ -5056,6 +5063,7 @@ class ControllerManagedDeviceGroupUIViewSet(NautobotUIViewSet):
5056
5063
  tab_id="wireless_networks",
5057
5064
  add_button_route=None,
5058
5065
  exclude_columns=["controller_managed_device_group", "controller"],
5066
+ include_paginator=True,
5059
5067
  ),
5060
5068
  ),
5061
5069
  ),
@@ -5074,6 +5082,7 @@ class ControllerManagedDeviceGroupUIViewSet(NautobotUIViewSet):
5074
5082
  table_filter="controller_managed_device_groups",
5075
5083
  tab_id="radio_profiles",
5076
5084
  add_button_route=None,
5085
+ include_paginator=True,
5077
5086
  ),
5078
5087
  ),
5079
5088
  ),