nautobot 2.3.6__py3-none-any.whl → 2.3.8__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 (336) hide show
  1. nautobot/__init__.py +4 -2
  2. nautobot/circuits/tests/test_views.py +4 -5
  3. nautobot/core/api/views.py +15 -3
  4. nautobot/core/templates/inc/javascript.html +2 -0
  5. nautobot/core/templates/inc/nav_menu.html +0 -251
  6. nautobot/core/templates/inc/paginator.html +3 -0
  7. nautobot/core/templates/utilities/obj_table.html +1 -1
  8. nautobot/core/testing/mixins.py +59 -2
  9. nautobot/core/testing/views.py +45 -61
  10. nautobot/core/tests/runner.py +6 -3
  11. nautobot/core/tests/test_paginator.py +4 -3
  12. nautobot/core/tests/test_views.py +39 -56
  13. nautobot/core/views/__init__.py +27 -11
  14. nautobot/dcim/api/serializers.py +10 -5
  15. nautobot/dcim/forms.py +11 -7
  16. nautobot/dcim/models/device_components.py +7 -4
  17. nautobot/dcim/tests/test_api.py +28 -0
  18. nautobot/dcim/tests/test_forms.py +17 -1
  19. nautobot/dcim/tests/test_models.py +42 -4
  20. nautobot/dcim/tests/test_views.py +26 -67
  21. nautobot/dcim/utils.py +9 -6
  22. nautobot/extras/datasources/git.py +6 -1
  23. nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +3 -0
  24. nautobot/extras/migrations/0116_fix_dynamic_group_group_type_data_migration.py +16 -0
  25. nautobot/extras/plugins/views.py +18 -3
  26. nautobot/extras/tests/test_customfields.py +9 -16
  27. nautobot/extras/tests/test_dynamicgroups.py +116 -0
  28. nautobot/extras/tests/test_plugins.py +4 -6
  29. nautobot/extras/tests/test_utils.py +5 -0
  30. nautobot/extras/tests/test_views.py +61 -159
  31. nautobot/extras/utils.py +50 -11
  32. nautobot/ipam/filters.py +2 -2
  33. nautobot/ipam/models.py +29 -2
  34. nautobot/ipam/templates/ipam/ipaddress.html +2 -2
  35. nautobot/ipam/templates/ipam/ipaddress_interfaces.html +3 -0
  36. nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +3 -0
  37. nautobot/ipam/templates/ipam/prefix.html +3 -3
  38. nautobot/ipam/templates/ipam/routetarget.html +2 -2
  39. nautobot/ipam/templates/ipam/vlan.html +3 -0
  40. nautobot/ipam/templates/ipam/vrf.html +7 -4
  41. nautobot/ipam/tests/test_api.py +18 -12
  42. nautobot/ipam/tests/test_models.py +68 -12
  43. nautobot/ipam/tests/test_views.py +6 -15
  44. nautobot/ipam/views.py +43 -0
  45. nautobot/project-static/docs/404.html +3 -3
  46. nautobot/project-static/docs/apps/index.html +3 -3
  47. nautobot/project-static/docs/apps/nautobot-apps.html +3 -3
  48. nautobot/project-static/docs/assets/javascripts/bundle.525ec568.min.js +16 -0
  49. nautobot/project-static/docs/assets/javascripts/{bundle.56dfad97.min.js.map → bundle.525ec568.min.js.map} +4 -4
  50. nautobot/project-static/docs/assets/stylesheets/main.8c3ca2c6.min.css +1 -0
  51. nautobot/project-static/docs/assets/stylesheets/main.8c3ca2c6.min.css.map +1 -0
  52. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +3 -3
  53. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +3 -3
  54. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +3 -3
  55. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +3 -3
  56. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +3 -3
  57. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +3 -3
  58. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +3 -3
  59. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +3 -3
  60. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +3 -3
  61. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +3 -3
  62. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +3 -3
  63. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +3 -3
  64. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +3 -3
  65. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +3 -3
  66. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +3 -3
  67. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +3 -3
  68. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +3 -3
  69. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +3 -3
  70. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +124 -3
  71. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +3 -3
  72. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +3 -3
  73. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +3 -3
  74. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +3 -3
  75. nautobot/project-static/docs/development/apps/api/configuration-view.html +3 -3
  76. nautobot/project-static/docs/development/apps/api/database-backend-config.html +3 -3
  77. nautobot/project-static/docs/development/apps/api/models/django-admin.html +3 -3
  78. nautobot/project-static/docs/development/apps/api/models/global-search.html +3 -3
  79. nautobot/project-static/docs/development/apps/api/models/graphql.html +3 -3
  80. nautobot/project-static/docs/development/apps/api/models/index.html +3 -3
  81. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +3 -3
  82. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +3 -3
  83. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +3 -3
  84. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +3 -3
  85. nautobot/project-static/docs/development/apps/api/platform-features/index.html +3 -3
  86. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +3 -3
  87. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +3 -3
  88. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +3 -3
  89. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +3 -3
  90. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +3 -3
  91. nautobot/project-static/docs/development/apps/api/prometheus.html +3 -3
  92. nautobot/project-static/docs/development/apps/api/setup.html +3 -3
  93. nautobot/project-static/docs/development/apps/api/testing.html +3 -3
  94. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +3 -3
  95. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +3 -3
  96. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +3 -3
  97. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +3 -3
  98. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +3 -3
  99. nautobot/project-static/docs/development/apps/api/views/base-template.html +3 -3
  100. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +3 -3
  101. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +3 -3
  102. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +3 -3
  103. nautobot/project-static/docs/development/apps/api/views/index.html +3 -3
  104. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +3 -3
  105. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +3 -3
  106. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +3 -3
  107. nautobot/project-static/docs/development/apps/api/views/notes.html +3 -3
  108. nautobot/project-static/docs/development/apps/api/views/rest-api.html +3 -3
  109. nautobot/project-static/docs/development/apps/api/views/urls.html +3 -3
  110. nautobot/project-static/docs/development/apps/index.html +3 -3
  111. nautobot/project-static/docs/development/apps/migration/code-updates.html +3 -3
  112. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +3 -3
  113. nautobot/project-static/docs/development/apps/migration/from-v1.html +3 -3
  114. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +3 -3
  115. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +3 -3
  116. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +3 -3
  117. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +3 -3
  118. nautobot/project-static/docs/development/apps/porting-from-netbox.html +3 -3
  119. nautobot/project-static/docs/development/core/application-registry.html +3 -3
  120. nautobot/project-static/docs/development/core/best-practices.html +3 -3
  121. nautobot/project-static/docs/development/core/bootstrap-ui.html +3 -3
  122. nautobot/project-static/docs/development/core/caching.html +3 -3
  123. nautobot/project-static/docs/development/core/controllers.html +3 -3
  124. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +3 -3
  125. nautobot/project-static/docs/development/core/generic-views.html +3 -3
  126. nautobot/project-static/docs/development/core/getting-started.html +3 -3
  127. nautobot/project-static/docs/development/core/homepage.html +3 -3
  128. nautobot/project-static/docs/development/core/index.html +3 -3
  129. nautobot/project-static/docs/development/core/model-checklist.html +3 -3
  130. nautobot/project-static/docs/development/core/model-features.html +3 -3
  131. nautobot/project-static/docs/development/core/natural-keys.html +3 -3
  132. nautobot/project-static/docs/development/core/navigation-menu.html +3 -3
  133. nautobot/project-static/docs/development/core/release-checklist.html +3 -3
  134. nautobot/project-static/docs/development/core/role-internals.html +3 -3
  135. nautobot/project-static/docs/development/core/settings.html +3 -3
  136. nautobot/project-static/docs/development/core/style-guide.html +3 -3
  137. nautobot/project-static/docs/development/core/templates.html +3 -3
  138. nautobot/project-static/docs/development/core/testing.html +3 -3
  139. nautobot/project-static/docs/development/core/user-preferences.html +3 -3
  140. nautobot/project-static/docs/development/index.html +3 -3
  141. nautobot/project-static/docs/development/jobs/index.html +3 -3
  142. nautobot/project-static/docs/development/jobs/migration/from-v1.html +3 -3
  143. nautobot/project-static/docs/index.html +3 -3
  144. nautobot/project-static/docs/objects.inv +0 -0
  145. nautobot/project-static/docs/overview/application_stack.html +3 -3
  146. nautobot/project-static/docs/overview/design_philosophy.html +3 -3
  147. nautobot/project-static/docs/release-notes/index.html +3 -3
  148. nautobot/project-static/docs/release-notes/version-1.0.html +3 -3
  149. nautobot/project-static/docs/release-notes/version-1.1.html +3 -3
  150. nautobot/project-static/docs/release-notes/version-1.2.html +3 -3
  151. nautobot/project-static/docs/release-notes/version-1.3.html +3 -3
  152. nautobot/project-static/docs/release-notes/version-1.4.html +3 -3
  153. nautobot/project-static/docs/release-notes/version-1.5.html +3 -3
  154. nautobot/project-static/docs/release-notes/version-1.6.html +3 -3
  155. nautobot/project-static/docs/release-notes/version-2.0.html +3 -3
  156. nautobot/project-static/docs/release-notes/version-2.1.html +3 -3
  157. nautobot/project-static/docs/release-notes/version-2.2.html +3 -3
  158. nautobot/project-static/docs/release-notes/version-2.3.html +304 -96
  159. nautobot/project-static/docs/requirements.txt +1 -1
  160. nautobot/project-static/docs/search/search_index.json +1 -1
  161. nautobot/project-static/docs/sitemap.xml +269 -269
  162. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  163. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +3 -3
  164. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +3 -3
  165. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +3 -3
  166. nautobot/project-static/docs/user-guide/administration/configuration/index.html +3 -3
  167. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +3 -3
  168. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +3 -3
  169. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +3 -3
  170. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +3 -3
  171. nautobot/project-static/docs/user-guide/administration/guides/docker.html +3 -3
  172. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +3 -3
  173. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +3 -3
  174. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +3 -3
  175. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +3 -3
  176. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +3 -3
  177. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +3 -3
  178. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +3 -3
  179. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +3 -3
  180. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +3 -3
  181. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +3 -3
  182. nautobot/project-static/docs/user-guide/administration/installation/index.html +3 -3
  183. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +3 -3
  184. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +3 -3
  185. nautobot/project-static/docs/user-guide/administration/installation/services.html +3 -3
  186. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +3 -3
  187. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +3 -3
  188. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +3 -3
  189. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +3 -3
  190. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +3 -3
  191. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +3 -3
  192. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +3 -3
  193. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +3 -3
  194. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +3 -3
  195. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +3 -3
  196. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +3 -3
  197. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +3 -3
  198. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +3 -3
  199. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +3 -3
  200. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +3 -3
  201. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +3 -3
  202. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +3 -3
  203. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +3 -3
  204. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +3 -3
  205. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +3 -3
  206. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +3 -3
  207. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +3 -3
  208. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +3 -3
  209. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +3 -3
  210. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +3 -3
  211. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +3 -3
  212. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +3 -3
  213. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +3 -3
  214. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +3 -3
  215. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +3 -3
  216. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +3 -3
  217. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +3 -3
  218. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +3 -3
  219. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +3 -3
  220. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +3 -3
  221. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +3 -3
  222. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +3 -3
  223. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +3 -3
  224. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +3 -3
  225. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +3 -3
  226. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +3 -3
  227. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +3 -3
  228. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +3 -3
  229. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +3 -3
  230. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +3 -3
  231. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +3 -3
  232. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +3 -3
  233. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +3 -3
  234. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +3 -3
  235. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +3 -3
  236. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +3 -3
  237. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +3 -3
  238. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +3 -3
  239. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +3 -3
  240. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +3 -3
  241. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +3 -3
  242. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +3 -3
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +3 -3
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +3 -3
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +3 -3
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +3 -3
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +3 -3
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +3 -3
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +3 -3
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +3 -3
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +3 -3
  252. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +3 -3
  253. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +3 -3
  254. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +3 -3
  255. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +3 -3
  256. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +3 -3
  257. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +3 -3
  258. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +3 -3
  259. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +3 -3
  260. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +3 -3
  261. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +3 -3
  262. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +3 -3
  263. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +3 -3
  264. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +3 -3
  265. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +3 -3
  266. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +3 -3
  267. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +3 -3
  268. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +3 -3
  269. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +3 -3
  270. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +3 -3
  271. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +3 -3
  272. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +3 -3
  273. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +3 -3
  274. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +3 -3
  275. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +3 -3
  276. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +3 -3
  277. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +3 -3
  278. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +3 -3
  279. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +3 -3
  280. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +3 -3
  281. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +3 -3
  282. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +3 -3
  283. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +3 -3
  284. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +3 -3
  285. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +3 -3
  286. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +3 -3
  287. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +3 -3
  288. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +3 -3
  289. nautobot/project-static/docs/user-guide/index.html +3 -3
  290. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +3 -3
  291. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +3 -3
  292. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +3 -3
  293. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +3 -3
  294. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +3 -3
  295. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +3 -3
  296. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +3 -3
  297. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +3 -3
  298. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +3 -3
  299. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +3 -3
  300. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +3 -3
  301. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +3 -3
  302. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +3 -3
  303. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +3 -3
  304. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +3 -3
  305. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +3 -3
  306. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +3 -3
  307. nautobot/project-static/docs/user-guide/platform-functionality/note.html +3 -3
  308. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +3 -3
  309. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +3 -3
  310. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +3 -3
  311. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +3 -3
  312. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +3 -3
  313. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +3 -3
  314. nautobot/project-static/docs/user-guide/platform-functionality/role.html +3 -3
  315. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +3 -3
  316. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +3 -3
  317. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +3 -3
  318. nautobot/project-static/docs/user-guide/platform-functionality/status.html +3 -3
  319. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +3 -3
  320. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +3 -3
  321. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +3 -3
  322. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +3 -3
  323. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +3 -3
  324. nautobot/project-static/js/nav_menu.js +249 -0
  325. nautobot/tenancy/templates/tenancy/tenant.html +1 -1
  326. nautobot/users/tests/test_views.py +9 -11
  327. nautobot/virtualization/tests/test_views.py +3 -5
  328. {nautobot-2.3.6.dist-info → nautobot-2.3.8.dist-info}/METADATA +2 -1
  329. {nautobot-2.3.6.dist-info → nautobot-2.3.8.dist-info}/RECORD +333 -331
  330. {nautobot-2.3.6.dist-info → nautobot-2.3.8.dist-info}/WHEEL +1 -1
  331. nautobot/project-static/docs/assets/javascripts/bundle.56dfad97.min.js +0 -16
  332. nautobot/project-static/docs/assets/stylesheets/main.35f28582.min.css +0 -1
  333. nautobot/project-static/docs/assets/stylesheets/main.35f28582.min.css.map +0 -1
  334. {nautobot-2.3.6.dist-info → nautobot-2.3.8.dist-info}/LICENSE.txt +0 -0
  335. {nautobot-2.3.6.dist-info → nautobot-2.3.8.dist-info}/NOTICE +0 -0
  336. {nautobot-2.3.6.dist-info → nautobot-2.3.8.dist-info}/entry_points.txt +0 -0
@@ -21,6 +21,9 @@
21
21
  {% render_table vm_interface_table 'inc/table.html' %}
22
22
  </div>
23
23
  </form>
24
+ {% if vm_interface_table.paginator.num_pages > 1 %}
25
+ {% include "inc/paginator.html" with paginator=vm_interface_table.paginator page=vm_interface_table.page %}
26
+ {% endif %}
24
27
  {% table_config_form vm_interface_table %}
25
28
  {% endblock content %}
26
29
 
@@ -117,7 +117,7 @@
117
117
  {% endblock content_left_page %}
118
118
 
119
119
  {% block content_right_page %}
120
- {% include 'panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' panel_class='default' %}
121
- {% include "utilities/obj_table.html" with table=vrf_table table_template="panel_table.html" heading="Assigned VRFs" disable_pagination=False %}
122
- {% include "utilities/obj_table.html" with table=cloud_network_table table_template="panel_table.html" heading="Assigned Cloud Networks" disable_pagination=False %}
120
+ {% include "utilities/obj_table.html" with table=parent_prefix_table table_template="panel_table.html" heading="Parent Prefixes" %}
121
+ {% include "utilities/obj_table.html" with table=vrf_table table_template="panel_table.html" heading="Assigned VRFs" %}
122
+ {% include "utilities/obj_table.html" with table=cloud_network_table table_template="panel_table.html" heading="Assigned Cloud Networks" %}
123
123
  {% endblock content_right_page %}
@@ -24,6 +24,6 @@
24
24
  {% endblock content_left_page %}
25
25
 
26
26
  {% block content_right_page %}
27
- {% include 'panel_table.html' with table=importing_vrfs_table heading="Importing VRFs" %}
28
- {% include 'panel_table.html' with table=exporting_vrfs_table heading="Exporting VRFs" %}
27
+ {% include 'utilities/obj_table.html' with table=importing_vrfs_table table_template='panel_table.html' heading="Importing VRFs" %}
28
+ {% include 'utilities/obj_table.html' with table=exporting_vrfs_table table_template='panel_table.html' heading="Exporting VRFs" %}
29
29
  {% endblock content_right_page %}
@@ -86,4 +86,7 @@
86
86
  </div>
87
87
  {% endif %}
88
88
  </div>
89
+ {% if prefix_table.paginator.num_pages > 1 %}
90
+ {% include "inc/paginator.html" with paginator=prefix_table.paginator page=prefix_table.page %}
91
+ {% endif %}
89
92
  {% endblock content_full_width_page %}
@@ -38,8 +38,11 @@
38
38
  {% endblock content_left_page %}
39
39
 
40
40
  {% block content_right_page %}
41
- {% include 'panel_table.html' with table=import_targets_table heading="Import Route Targets" %}
42
- {% include 'panel_table.html' with table=export_targets_table heading="Export Route Targets" %}
43
- {% include 'panel_table.html' with table=prefix_table heading="Assigned Prefixes" %}
44
- {% include 'panel_table.html' with table=device_table heading="Assigned Devices" %}
41
+ {% include 'utilities/obj_table.html' with table=import_targets_table table_template='panel_table.html' heading="Import Route Targets" %}
42
+ {% include 'utilities/obj_table.html' with table=export_targets_table table_template='panel_table.html' heading="Export Route Targets" %}
45
43
  {% endblock content_right_page %}
44
+
45
+ {% block content_full_width_page %}
46
+ {% include 'utilities/obj_table.html' with table=prefix_table table_template='panel_table.html' heading="Assigned Prefixes" %}
47
+ {% include 'utilities/obj_table.html' with table=device_table table_template='panel_table.html' heading="Assigned Devices" %}
48
+ {% endblock content_full_width_page %}
@@ -200,14 +200,19 @@ class VRFDeviceAssignmentTest(APIViewTestCases.APIViewTestCase):
200
200
  }
201
201
  self.add_permissions("ipam.add_vrfdeviceassignment")
202
202
  response = self.client.post(self._get_list_url(), duplicate_device_create_data, format="json", **self.header)
203
- self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
204
- self.assertIn("The fields device, vrf must make a unique set.", str(response.content))
203
+ self.assertContains(
204
+ response, "The fields device, vrf must make a unique set.", status_code=status.HTTP_400_BAD_REQUEST
205
+ )
205
206
  response = self.client.post(self._get_list_url(), duplicate_vm_create_data, format="json", **self.header)
206
- self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
207
- self.assertIn("The fields virtual_machine, vrf must make a unique set.", str(response.content))
207
+ self.assertContains(
208
+ response, "The fields virtual_machine, vrf must make a unique set.", status_code=status.HTTP_400_BAD_REQUEST
209
+ )
208
210
  response = self.client.post(self._get_list_url(), invalid_create_data, format="json", **self.header)
209
- self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
210
- self.assertIn("A VRF cannot be associated with both a device and a virtual machine.", str(response.content))
211
+ self.assertContains(
212
+ response,
213
+ "A VRF cannot be associated with both a device and a virtual machine.",
214
+ status_code=status.HTTP_400_BAD_REQUEST,
215
+ )
211
216
 
212
217
 
213
218
  class VRFPrefixAssignmentTest(APIViewTestCases.APIViewTestCase):
@@ -266,14 +271,15 @@ class VRFPrefixAssignmentTest(APIViewTestCases.APIViewTestCase):
266
271
  }
267
272
  self.add_permissions("ipam.add_vrfprefixassignment")
268
273
  response = self.client.post(self._get_list_url(), duplicate_create_data, format="json", **self.header)
269
- self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
270
- self.assertIn("The fields vrf, prefix must make a unique set.", str(response.content))
274
+ self.assertContains(
275
+ response, "The fields vrf, prefix must make a unique set.", status_code=status.HTTP_400_BAD_REQUEST
276
+ )
271
277
  response = self.client.post(self._get_list_url(), wrong_namespace_create_data, format="json", **self.header)
272
- self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
273
- self.assertIn("Prefix must be in same namespace as VRF", str(response.content))
278
+ self.assertContains(
279
+ response, "Prefix must be in same namespace as VRF", status_code=status.HTTP_400_BAD_REQUEST
280
+ )
274
281
  response = self.client.post(self._get_list_url(), missing_field_create_data, format="json", **self.header)
275
- self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
276
- self.assertIn("This field may not be null.", str(response.content))
282
+ self.assertContains(response, "This field may not be null.", status_code=status.HTTP_400_BAD_REQUEST)
277
283
 
278
284
 
279
285
  class RouteTargetTest(APIViewTestCases.APIViewTestCase):
@@ -555,8 +555,9 @@ class TestPrefix(ModelTestCases.BaseModelTestCase):
555
555
  IPAddress.objects.create(address="10.0.2.1/24", status=self.status, namespace=self.namespace),
556
556
  IPAddress.objects.create(address="10.0.3.1/24", status=self.status, namespace=self.namespace),
557
557
  )
558
+ self.assertQuerysetEqualAndNotEmpty(parent_prefix.ip_addresses.all(), parent_prefix.get_child_ips())
559
+ self.assertQuerysetEqualAndNotEmpty(parent_prefix.ip_addresses.all(), parent_prefix.get_all_ips())
558
560
  child_ip_pks = {p.pk for p in parent_prefix.ip_addresses.all()}
559
-
560
561
  # Global container should return all children
561
562
  self.assertSetEqual(child_ip_pks, {ips[0].pk, ips[1].pk, ips[2].pk, ips[3].pk})
562
563
 
@@ -566,6 +567,8 @@ class TestPrefix(ModelTestCases.BaseModelTestCase):
566
567
  IPAddress.objects.create(address="20.0.4.0/31", status=self.status, namespace=self.namespace),
567
568
  IPAddress.objects.create(address="20.0.4.1/31", status=self.status, namespace=self.namespace),
568
569
  )
570
+ self.assertQuerysetEqualAndNotEmpty(parent_prefix_31.ip_addresses.all(), parent_prefix_31.get_child_ips())
571
+ self.assertQuerysetEqualAndNotEmpty(parent_prefix_31.ip_addresses.all(), parent_prefix_31.get_all_ips())
569
572
  child_ip_pks = {p.pk for p in parent_prefix_31.ip_addresses.all()}
570
573
  self.assertSetEqual(child_ip_pks, {ips_31[0].pk, ips_31[1].pk})
571
574
 
@@ -660,10 +663,22 @@ class TestPrefix(ModelTestCases.BaseModelTestCase):
660
663
  slash25 = Prefix.objects.create(prefix="10.0.0.128/25", status=self.status, namespace=self.namespace)
661
664
  self.assertEqual(prefix.get_utilization(), (192, 256))
662
665
 
663
- # Create 32 IPAddresses within the Prefix
666
+ # Create 32 IPAddresses within the /26 Prefix
664
667
  for i in range(1, 33):
665
668
  IPAddress.objects.create(address=f"10.0.0.{i}/32", status=self.status, namespace=self.namespace)
666
669
 
670
+ # Assert differing behavior of get_all_ips() versus get_child_ips() for the /24 and /26 prefixes
671
+ self.assertQuerysetEqual(prefix.get_child_ips(), IPAddress.objects.none())
672
+ self.assertQuerysetEqualAndNotEmpty(
673
+ prefix.get_all_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/24")
674
+ )
675
+ self.assertQuerysetEqualAndNotEmpty(
676
+ slash26.get_child_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/24")
677
+ )
678
+ self.assertQuerysetEqualAndNotEmpty(
679
+ slash26.get_all_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/24")
680
+ )
681
+
667
682
  # The parent prefix utilization does not change because the ip addresses are parented to the child /26 prefix.
668
683
  self.assertEqual(prefix.get_utilization(), (192, 256))
669
684
 
@@ -674,6 +689,17 @@ class TestPrefix(ModelTestCases.BaseModelTestCase):
674
689
  IPAddress.objects.create(address="10.0.0.0/32", status=self.status, namespace=self.namespace)
675
690
  IPAddress.objects.create(address="10.0.0.63/32", status=self.status, namespace=self.namespace)
676
691
 
692
+ self.assertQuerysetEqual(prefix.get_child_ips(), IPAddress.objects.none())
693
+ self.assertQuerysetEqualAndNotEmpty(
694
+ prefix.get_all_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/24")
695
+ )
696
+ self.assertQuerysetEqualAndNotEmpty(
697
+ slash26.get_child_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/24")
698
+ )
699
+ self.assertQuerysetEqualAndNotEmpty(
700
+ slash26.get_all_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/24")
701
+ )
702
+
677
703
  # The /26 denominator will change to 64
678
704
  self.assertEqual(slash26.get_utilization(), (34, 64))
679
705
 
@@ -688,30 +714,60 @@ class TestPrefix(ModelTestCases.BaseModelTestCase):
688
714
  pool.save()
689
715
  self.assertEqual(slash25.get_utilization(), (4, 126))
690
716
 
717
+ # Further distinguishing between get_child_ips() and get_all_ips():
718
+ IPAddress.objects.create(address="10.0.0.64/32", status=self.status, namespace=self.namespace)
719
+ self.assertQuerysetEqualAndNotEmpty(
720
+ prefix.get_child_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.64/26")
721
+ )
722
+ self.assertQuerysetEqualAndNotEmpty(
723
+ prefix.get_all_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/24")
724
+ )
725
+
726
+ slash27 = Prefix.objects.create(prefix="10.0.0.0/27", status=self.status, namespace=self.namespace)
727
+ self.assertEqual(slash27.get_utilization(), (32, 32))
728
+ self.assertQuerysetEqualAndNotEmpty(
729
+ prefix.get_child_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.64/26")
730
+ )
731
+ self.assertQuerysetEqualAndNotEmpty(
732
+ prefix.get_all_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/24")
733
+ )
734
+ self.assertQuerysetEqualAndNotEmpty(
735
+ slash26.get_child_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.32/27")
736
+ )
737
+ self.assertQuerysetEqualAndNotEmpty(
738
+ slash26.get_all_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/26")
739
+ )
740
+ self.assertQuerysetEqualAndNotEmpty(
741
+ slash27.get_child_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/27")
742
+ )
743
+ self.assertQuerysetEqualAndNotEmpty(
744
+ slash27.get_all_ips(), IPAddress.objects.filter(host__net_host_contained="10.0.0.0/27")
745
+ )
746
+
691
747
  # IPv4 Non-container Prefix /31, network and broadcast addresses count toward utilization
692
- prefix = Prefix.objects.create(prefix="10.0.1.0/31", status=self.status, namespace=self.namespace)
748
+ slash31 = Prefix.objects.create(prefix="10.0.1.0/31", status=self.status, namespace=self.namespace)
693
749
  IPAddress.objects.create(address="10.0.1.0/32", status=self.status, namespace=self.namespace)
694
750
  IPAddress.objects.create(address="10.0.1.1/32", status=self.status, namespace=self.namespace)
695
- self.assertEqual(prefix.get_utilization(), (2, 2))
751
+ self.assertEqual(slash31.get_utilization(), (2, 2))
696
752
 
697
753
  # IPv6 Non-container Prefix, first and last addresses count toward utilization
698
- prefix = Prefix.objects.create(prefix="aaab::/124", status=self.status, namespace=self.namespace)
754
+ slash124_1 = Prefix.objects.create(prefix="aaab::/124", status=self.status, namespace=self.namespace)
699
755
  IPAddress.objects.create(address="aaab::1/128", status=self.status, namespace=self.namespace)
700
756
  IPAddress.objects.create(address="aaab::2/128", status=self.status, namespace=self.namespace)
701
- self.assertEqual(prefix.get_utilization(), (2, 16))
757
+ self.assertEqual(slash124_1.get_utilization(), (2, 16))
702
758
 
703
- prefix = Prefix.objects.create(prefix="aaaa::/124", status=self.status, namespace=self.namespace)
759
+ slash124_2 = Prefix.objects.create(prefix="aaaa::/124", status=self.status, namespace=self.namespace)
704
760
  IPAddress.objects.create(address="aaaa::0/128", status=self.status, namespace=self.namespace)
705
761
  IPAddress.objects.create(address="aaaa::f/128", status=self.status, namespace=self.namespace)
706
- self.assertEqual(prefix.get_utilization(), (2, 16))
762
+ self.assertEqual(slash124_2.get_utilization(), (2, 16))
707
763
 
708
764
  # single address prefixes
709
- prefix = Prefix.objects.create(prefix="cccc::1/128", status=self.status, namespace=self.namespace)
765
+ slash128 = Prefix.objects.create(prefix="cccc::1/128", status=self.status, namespace=self.namespace)
710
766
  IPAddress.objects.create(address="cccc::1/128", status=self.status, namespace=self.namespace)
711
- self.assertEqual(prefix.get_utilization(), (1, 1))
712
- prefix = Prefix.objects.create(prefix="1.1.1.1/32", status=self.status, namespace=self.namespace)
767
+ self.assertEqual(slash128.get_utilization(), (1, 1))
768
+ slash32 = Prefix.objects.create(prefix="1.1.1.1/32", status=self.status, namespace=self.namespace)
713
769
  IPAddress.objects.create(address="1.1.1.1/32", status=self.status, namespace=self.namespace)
714
- self.assertEqual(prefix.get_utilization(), (1, 1))
770
+ self.assertEqual(slash32.get_utilization(), (1, 1))
715
771
 
716
772
  # Large Prefix
717
773
  large_prefix = Prefix.objects.create(
@@ -356,11 +356,10 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase, ViewTestCases.List
356
356
  url = reverse("ipam:prefix_ipaddresses", args=(instance.pk,))
357
357
  response = self.client.get(url)
358
358
  self.assertHttpStatus(response, 200)
359
- content = response.content.decode(response.charset)
359
+ content = extract_page_body(response.content.decode(response.charset))
360
360
  # This validates that both parent prefix and child prefix IPAddresses are present in parent prefix IPAddresses list
361
361
  self.assertIn("5.5.10.1/23", strip_tags(content))
362
362
  self.assertIn("5.5.10.4/23", strip_tags(content))
363
- print(response.content.decode(response.charset))
364
363
  ip_address_tab = (
365
364
  f'<li role="presentation" class="active"><a href="{url}">IP Addresses <span class="badge">2</span></a></li>'
366
365
  )
@@ -440,8 +439,7 @@ class IPAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
440
439
  "data": post_data(self.form_data),
441
440
  }
442
441
  response = self.client.post(**request)
443
- self.assertEqual(200, response.status_code)
444
- self.assertIn("Host address cannot be changed once created", str(response.content))
442
+ self.assertBodyContains(response, "Host address cannot be changed once created")
445
443
 
446
444
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
447
445
  def test_move_ip_addresses_between_namespaces(self):
@@ -461,8 +459,7 @@ class IPAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
461
459
  "data": post_data(form_data),
462
460
  }
463
461
  response = self.client.post(**request)
464
- self.assertEqual(200, response.status_code)
465
- self.assertIn("No suitable parent Prefix exists in this Namespace", str(response.content))
462
+ self.assertBodyContains(response, "No suitable parent Prefix exists in this Namespace")
466
463
  # Create an exact copy of the parent prefix but in a different namespace. See if the re-parenting is successful
467
464
  new_parent = Prefix.objects.create(
468
465
  prefix=instance.parent.prefix,
@@ -1151,9 +1148,7 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1151
1148
  "data": post_data(self.form_data),
1152
1149
  }
1153
1150
  response = self.client.post(**request)
1154
- self.assertHttpStatus(response, 200)
1155
- response_body = extract_page_body(response.content.decode(response.charset))
1156
- self.assertIn("Service with this Name and Device already exists.", response_body)
1151
+ self.assertBodyContains(response, "Service with this Name and Device already exists.")
1157
1152
 
1158
1153
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
1159
1154
  def test_service_cannot_be_assigned_to_both_device_and_vm(self):
@@ -1173,9 +1168,7 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1173
1168
  "data": post_data(self.form_data),
1174
1169
  }
1175
1170
  response = self.client.post(**request)
1176
- self.assertHttpStatus(response, 200)
1177
- response_body = extract_page_body(response.content.decode(response.charset))
1178
- self.assertIn("A service cannot be associated with both a device and a virtual machine.", response_body)
1171
+ self.assertBodyContains(response, "A service cannot be associated with both a device and a virtual machine.")
1179
1172
 
1180
1173
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
1181
1174
  def test_service_cannot_be_assigned_to_neither_device_nor_vm(self):
@@ -1195,6 +1188,4 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1195
1188
  "data": post_data(self.form_data),
1196
1189
  }
1197
1190
  response = self.client.post(**request)
1198
- self.assertHttpStatus(response, 200)
1199
- response_body = extract_page_body(response.content.decode(response.charset))
1200
- self.assertIn("A service must be associated with either a device or a virtual machine.", response_body)
1191
+ self.assertBodyContains(response, "A service must be associated with either a device or a virtual machine.")
nautobot/ipam/views.py CHANGED
@@ -270,6 +270,15 @@ class VRFView(generic.ObjectView):
270
270
  vrf_table.exclude = ("vrf",)
271
271
  # context["vrf_table"] = vrf_table
272
272
 
273
+ paginate = {
274
+ "paginator_class": EnhancedPaginator,
275
+ "per_page": get_paginate_count(request),
276
+ }
277
+ RequestConfig(request, paginate).configure(prefix_table)
278
+ RequestConfig(request, paginate).configure(vrf_table)
279
+ RequestConfig(request, paginate).configure(import_targets_table)
280
+ RequestConfig(request, paginate).configure(export_targets_table)
281
+
273
282
  context.update(
274
283
  {
275
284
  "device_table": vrf_table,
@@ -337,6 +346,13 @@ class RouteTargetView(generic.ObjectView):
337
346
  importing_vrfs_table = tables.VRFTable(instance.importing_vrfs.select_related("tenant"), orderable=False)
338
347
  exporting_vrfs_table = tables.VRFTable(instance.exporting_vrfs.select_related("tenant"), orderable=False)
339
348
 
349
+ paginate = {
350
+ "paginator_class": EnhancedPaginator,
351
+ "per_page": get_paginate_count(request),
352
+ }
353
+ RequestConfig(request, paginate).configure(importing_vrfs_table)
354
+ RequestConfig(request, paginate).configure(exporting_vrfs_table)
355
+
340
356
  return {
341
357
  "importing_vrfs_table": importing_vrfs_table,
342
358
  "exporting_vrfs_table": exporting_vrfs_table,
@@ -460,6 +476,14 @@ class PrefixView(generic.ObjectView):
460
476
  cloud_network_table = CloudNetworkTable(cloud_networks, orderable=False)
461
477
  cloud_network_table.exclude = ("actions", "assigned_prefix_count", "circuit_count", "cloud_service_count")
462
478
 
479
+ paginate = {
480
+ "paginator_class": EnhancedPaginator,
481
+ "per_page": get_paginate_count(request),
482
+ }
483
+ RequestConfig(request, paginate).configure(parent_prefix_table)
484
+ RequestConfig(request, paginate).configure(vrf_table)
485
+ RequestConfig(request, paginate).configure(cloud_network_table)
486
+
463
487
  return {
464
488
  "vrf_table": vrf_table,
465
489
  "parent_prefix_table": parent_prefix_table,
@@ -778,6 +802,7 @@ class IPAddressView(generic.ObjectView):
778
802
  "paginator_class": EnhancedPaginator,
779
803
  "per_page": get_paginate_count(request),
780
804
  }
805
+ RequestConfig(request, paginate).configure(parent_prefixes_table)
781
806
  RequestConfig(request, paginate).configure(related_ips_table)
782
807
 
783
808
  return {
@@ -1158,6 +1183,12 @@ class IPAddressInterfacesView(generic.ObjectView):
1158
1183
  if request.user.has_perm("dcim.change_interface") or request.user.has_perm("dcim.delete_interface"):
1159
1184
  interface_table.columns.show("pk")
1160
1185
 
1186
+ paginate = {
1187
+ "paginator_class": EnhancedPaginator,
1188
+ "per_page": get_paginate_count(request),
1189
+ }
1190
+ RequestConfig(request, paginate).configure(interface_table)
1191
+
1161
1192
  return {
1162
1193
  "interface_table": interface_table,
1163
1194
  "active_tab": "interfaces",
@@ -1178,6 +1209,12 @@ class IPAddressVMInterfacesView(generic.ObjectView):
1178
1209
  ):
1179
1210
  vm_interface_table.columns.show("pk")
1180
1211
 
1212
+ paginate = {
1213
+ "paginator_class": EnhancedPaginator,
1214
+ "per_page": get_paginate_count(request),
1215
+ }
1216
+ RequestConfig(request, paginate).configure(vm_interface_table)
1217
+
1181
1218
  return {
1182
1219
  "vm_interface_table": vm_interface_table,
1183
1220
  "active_tab": "vm_interfaces",
@@ -1316,6 +1353,12 @@ class VLANView(generic.ObjectView):
1316
1353
  prefix_table = tables.PrefixTable(list(prefixes), hide_hierarchy_ui=True)
1317
1354
  prefix_table.exclude = ("vlan",)
1318
1355
 
1356
+ paginate = {
1357
+ "paginator_class": EnhancedPaginator,
1358
+ "per_page": get_paginate_count(request),
1359
+ }
1360
+ RequestConfig(request, paginate).configure(prefix_table)
1361
+
1319
1362
  return {"prefix_table": prefix_table, **super().get_extra_context(request, instance)}
1320
1363
 
1321
1364
 
@@ -12,7 +12,7 @@
12
12
 
13
13
 
14
14
  <link rel="icon" href="/projects/core/en/stable/assets/favicon.ico">
15
- <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.35">
15
+ <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.39">
16
16
 
17
17
 
18
18
 
@@ -20,7 +20,7 @@
20
20
 
21
21
 
22
22
 
23
- <link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/main.35f28582.min.css">
23
+ <link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/main.8c3ca2c6.min.css">
24
24
 
25
25
 
26
26
  <link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/palette.06af60db.min.css">
@@ -8629,7 +8629,7 @@
8629
8629
  <script id="__config" type="application/json">{"base": "/projects/core/en/stable/", "features": ["content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "/projects/core/en/stable/assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
8630
8630
 
8631
8631
 
8632
- <script src="/projects/core/en/stable/assets/javascripts/bundle.56dfad97.min.js"></script>
8632
+ <script src="/projects/core/en/stable/assets/javascripts/bundle.525ec568.min.js"></script>
8633
8633
 
8634
8634
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
8635
8635
 
@@ -18,7 +18,7 @@
18
18
 
19
19
 
20
20
  <link rel="icon" href="../assets/favicon.ico">
21
- <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.35">
21
+ <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.39">
22
22
 
23
23
 
24
24
 
@@ -26,7 +26,7 @@
26
26
 
27
27
 
28
28
 
29
- <link rel="stylesheet" href="../assets/stylesheets/main.35f28582.min.css">
29
+ <link rel="stylesheet" href="../assets/stylesheets/main.8c3ca2c6.min.css">
30
30
 
31
31
 
32
32
  <link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
@@ -8796,7 +8796,7 @@
8796
8796
  <script id="__config" type="application/json">{"base": "..", "features": ["content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
8797
8797
 
8798
8798
 
8799
- <script src="../assets/javascripts/bundle.56dfad97.min.js"></script>
8799
+ <script src="../assets/javascripts/bundle.525ec568.min.js"></script>
8800
8800
 
8801
8801
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
8802
8802
 
@@ -16,7 +16,7 @@
16
16
 
17
17
 
18
18
  <link rel="icon" href="../assets/favicon.ico">
19
- <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.35">
19
+ <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.39">
20
20
 
21
21
 
22
22
 
@@ -24,7 +24,7 @@
24
24
 
25
25
 
26
26
 
27
- <link rel="stylesheet" href="../assets/stylesheets/main.35f28582.min.css">
27
+ <link rel="stylesheet" href="../assets/stylesheets/main.8c3ca2c6.min.css">
28
28
 
29
29
 
30
30
  <link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
@@ -8730,7 +8730,7 @@
8730
8730
  <script id="__config" type="application/json">{"base": "..", "features": ["content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
8731
8731
 
8732
8732
 
8733
- <script src="../assets/javascripts/bundle.56dfad97.min.js"></script>
8733
+ <script src="../assets/javascripts/bundle.525ec568.min.js"></script>
8734
8734
 
8735
8735
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
8736
8736