nautobot 2.2.0__py3-none-any.whl → 2.2.0b1__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 (362) hide show
  1. nautobot/apps/api.py +2 -1
  2. nautobot/apps/utils.py +0 -4
  3. nautobot/apps/views.py +0 -2
  4. nautobot/circuits/api/urls.py +2 -1
  5. nautobot/circuits/api/views.py +12 -0
  6. nautobot/circuits/tests/test_filters.py +1 -1
  7. nautobot/core/api/routers.py +3 -25
  8. nautobot/core/api/utils.py +0 -4
  9. nautobot/core/api/views.py +15 -21
  10. nautobot/core/filters.py +1 -7
  11. nautobot/core/management/commands/generate_test_data.py +4 -4
  12. nautobot/core/settings.py +0 -1
  13. nautobot/core/tables.py +1 -2
  14. nautobot/core/templates/admin/base.html +94 -23
  15. nautobot/core/templates/graphene/graphiql.html +47 -18
  16. nautobot/core/templates/inc/footer.html +5 -5
  17. nautobot/core/templates/inc/nav_menu.html +7 -0
  18. nautobot/core/templates/rest_framework/api.html +5 -12
  19. nautobot/core/templatetags/helpers.py +2 -2
  20. nautobot/core/testing/views.py +0 -30
  21. nautobot/core/tests/test_api.py +6 -13
  22. nautobot/core/tests/test_csv.py +4 -5
  23. nautobot/core/tests/test_filters.py +1 -2
  24. nautobot/core/tests/test_graphql.py +14 -4
  25. nautobot/core/tests/test_navigations.py +0 -3
  26. nautobot/core/tests/test_views.py +16 -22
  27. nautobot/core/utils/lookup.py +0 -124
  28. nautobot/core/views/__init__.py +7 -3
  29. nautobot/core/views/generic.py +3 -19
  30. nautobot/core/views/mixins.py +0 -7
  31. nautobot/core/views/renderers.py +1 -4
  32. nautobot/dcim/api/serializers.py +4 -4
  33. nautobot/dcim/api/urls.py +3 -2
  34. nautobot/dcim/api/views.py +18 -7
  35. nautobot/dcim/factory.py +7 -7
  36. nautobot/dcim/filters/__init__.py +17 -16
  37. nautobot/dcim/forms.py +45 -61
  38. nautobot/dcim/homepage.py +3 -11
  39. nautobot/dcim/migrations/0057_controller_models.py +70 -11
  40. nautobot/dcim/models/__init__.py +2 -2
  41. nautobot/dcim/models/devices.py +16 -14
  42. nautobot/dcim/models/racks.py +3 -1
  43. nautobot/dcim/navigation.py +31 -23
  44. nautobot/dcim/signals.py +6 -6
  45. nautobot/dcim/tables/__init__.py +2 -2
  46. nautobot/dcim/tables/devices.py +15 -12
  47. nautobot/dcim/tables/template_code.py +1 -1
  48. nautobot/dcim/templates/dcim/controller_retrieve.html +18 -35
  49. nautobot/dcim/templates/dcim/controllerdevicegroup_create.html +43 -0
  50. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +43 -67
  51. nautobot/dcim/templates/dcim/device.html +2 -10
  52. nautobot/dcim/templates/dcim/device_edit.html +1 -1
  53. nautobot/dcim/tests/test_api.py +6 -11
  54. nautobot/dcim/tests/test_filters.py +81 -92
  55. nautobot/dcim/tests/test_graphql.py +1 -11
  56. nautobot/dcim/tests/test_models.py +15 -15
  57. nautobot/dcim/tests/test_signals.py +0 -2
  58. nautobot/dcim/tests/test_views.py +12 -24
  59. nautobot/dcim/urls.py +1 -1
  60. nautobot/dcim/views.py +15 -19
  61. nautobot/extras/api/urls.py +2 -1
  62. nautobot/extras/api/views.py +10 -0
  63. nautobot/extras/filters/__init__.py +2 -53
  64. nautobot/extras/forms/contacts.py +0 -7
  65. nautobot/extras/managers.py +0 -14
  66. nautobot/extras/navigation.py +65 -71
  67. nautobot/extras/plugins/views.py +11 -7
  68. nautobot/extras/tests/test_api.py +0 -2
  69. nautobot/extras/tests/test_dynamicgroups.py +0 -2
  70. nautobot/extras/tests/test_filters.py +4 -89
  71. nautobot/extras/tests/test_models.py +0 -9
  72. nautobot/extras/tests/test_relationships.py +1 -10
  73. nautobot/extras/tests/test_views.py +1 -112
  74. nautobot/extras/views.py +10 -10
  75. nautobot/ipam/api/urls.py +2 -1
  76. nautobot/ipam/api/views.py +11 -0
  77. nautobot/ipam/tables.py +22 -2
  78. nautobot/ipam/tests/test_graphql.py +3 -2
  79. nautobot/ipam/tests/test_views.py +0 -1
  80. nautobot/ipam/views.py +9 -9
  81. nautobot/project-static/css/base.css +0 -1
  82. nautobot/project-static/docs/404.html +3 -24
  83. nautobot/project-static/docs/apps/index.html +3 -24
  84. nautobot/project-static/docs/apps/nautobot-apps.html +3 -24
  85. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +3 -24
  86. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +3 -24
  87. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +5 -26
  88. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +3 -24
  89. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +3 -24
  90. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +3 -24
  91. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +3 -24
  92. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +3 -24
  93. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +3 -24
  94. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +3 -24
  95. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +3 -24
  96. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +3 -24
  97. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +3 -24
  98. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +3 -24
  99. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +3 -24
  100. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +3 -24
  101. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +3 -24
  102. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +3 -24
  103. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +3 -24
  104. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +3 -24
  105. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +3 -24
  106. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +3 -242
  107. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +5 -69
  108. nautobot/project-static/docs/development/apps/api/configuration-view.html +3 -24
  109. nautobot/project-static/docs/development/apps/api/database-backend-config.html +3 -24
  110. nautobot/project-static/docs/development/apps/api/models/django-admin.html +3 -24
  111. nautobot/project-static/docs/development/apps/api/models/global-search.html +3 -24
  112. nautobot/project-static/docs/development/apps/api/models/graphql.html +3 -24
  113. nautobot/project-static/docs/development/apps/api/models/index.html +3 -24
  114. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +3 -24
  115. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +3 -24
  116. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +3 -24
  117. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +3 -24
  118. nautobot/project-static/docs/development/apps/api/platform-features/index.html +3 -24
  119. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +3 -24
  120. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +3 -24
  121. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +3 -24
  122. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +3 -24
  123. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +3 -24
  124. nautobot/project-static/docs/development/apps/api/prometheus.html +3 -24
  125. nautobot/project-static/docs/development/apps/api/setup.html +3 -24
  126. nautobot/project-static/docs/development/apps/api/testing.html +3 -24
  127. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +3 -24
  128. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +3 -24
  129. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +3 -24
  130. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +3 -24
  131. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +3 -24
  132. nautobot/project-static/docs/development/apps/api/views/base-template.html +3 -24
  133. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +12 -38
  134. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +15 -41
  135. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +3 -24
  136. nautobot/project-static/docs/development/apps/api/views/index.html +3 -24
  137. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +3 -24
  138. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +3 -24
  139. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +3 -24
  140. nautobot/project-static/docs/development/apps/api/views/notes.html +3 -24
  141. nautobot/project-static/docs/development/apps/api/views/rest-api.html +3 -24
  142. nautobot/project-static/docs/development/apps/api/views/urls.html +3 -24
  143. nautobot/project-static/docs/development/apps/index.html +3 -24
  144. nautobot/project-static/docs/development/apps/migration/code-updates.html +3 -24
  145. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +3 -24
  146. nautobot/project-static/docs/development/apps/migration/from-v1.html +3 -24
  147. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +3 -24
  148. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +3 -24
  149. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +3 -24
  150. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +3 -24
  151. nautobot/project-static/docs/development/apps/porting-from-netbox.html +3 -24
  152. nautobot/project-static/docs/development/core/application-registry.html +3 -24
  153. nautobot/project-static/docs/development/core/best-practices.html +3 -24
  154. nautobot/project-static/docs/development/core/bootstrap-ui.html +3 -24
  155. nautobot/project-static/docs/development/core/caching.html +3 -24
  156. nautobot/project-static/docs/development/core/controllers.html +204 -35
  157. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +3 -24
  158. nautobot/project-static/docs/development/core/extending-models.html +3 -24
  159. nautobot/project-static/docs/development/core/generic-views.html +3 -24
  160. nautobot/project-static/docs/development/core/getting-started.html +13 -43
  161. nautobot/project-static/docs/development/core/homepage.html +3 -24
  162. nautobot/project-static/docs/development/core/index.html +3 -24
  163. nautobot/project-static/docs/development/core/model-features.html +3 -24
  164. nautobot/project-static/docs/development/core/natural-keys.html +3 -24
  165. nautobot/project-static/docs/development/core/navigation-menu.html +3 -24
  166. nautobot/project-static/docs/development/core/release-checklist.html +3 -24
  167. nautobot/project-static/docs/development/core/role-internals.html +3 -24
  168. nautobot/project-static/docs/development/core/settings.html +3 -24
  169. nautobot/project-static/docs/development/core/style-guide.html +3 -24
  170. nautobot/project-static/docs/development/core/templates.html +3 -24
  171. nautobot/project-static/docs/development/core/testing.html +3 -24
  172. nautobot/project-static/docs/development/core/user-preferences.html +3 -24
  173. nautobot/project-static/docs/development/index.html +3 -24
  174. nautobot/project-static/docs/development/jobs/index.html +3 -24
  175. nautobot/project-static/docs/development/jobs/migration/from-v1.html +3 -24
  176. nautobot/project-static/docs/index.html +3 -24
  177. nautobot/project-static/docs/models/dcim/{controllermanageddevicegroup.html → controllerdevicegroup.html} +3 -3
  178. nautobot/project-static/docs/objects.inv +0 -0
  179. nautobot/project-static/docs/release-notes/index.html +3 -24
  180. nautobot/project-static/docs/release-notes/version-1.0.html +3 -24
  181. nautobot/project-static/docs/release-notes/version-1.1.html +3 -24
  182. nautobot/project-static/docs/release-notes/version-1.2.html +3 -24
  183. nautobot/project-static/docs/release-notes/version-1.3.html +3 -24
  184. nautobot/project-static/docs/release-notes/version-1.4.html +3 -24
  185. nautobot/project-static/docs/release-notes/version-1.5.html +3 -24
  186. nautobot/project-static/docs/release-notes/version-1.6.html +3 -24
  187. nautobot/project-static/docs/release-notes/version-2.0.html +3 -24
  188. nautobot/project-static/docs/release-notes/version-2.1.html +162 -411
  189. nautobot/project-static/docs/release-notes/version-2.2.html +30 -212
  190. nautobot/project-static/docs/search/search_index.json +1 -1
  191. nautobot/project-static/docs/sitemap.xml +255 -260
  192. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  193. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +3 -24
  194. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +3 -24
  195. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +3 -24
  196. nautobot/project-static/docs/user-guide/administration/configuration/index.html +3 -24
  197. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +3 -24
  198. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +3 -24
  199. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +3 -24
  200. nautobot/project-static/docs/user-guide/administration/guides/caching.html +3 -24
  201. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +3 -24
  202. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +3 -24
  203. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +3 -24
  204. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +3 -24
  205. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +3 -24
  206. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +3 -24
  207. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +3 -24
  208. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +3 -24
  209. nautobot/project-static/docs/user-guide/administration/installation/docker.html +6 -31
  210. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +3 -24
  211. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +3 -24
  212. nautobot/project-static/docs/user-guide/administration/installation/index.html +3 -24
  213. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +3 -24
  214. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +3 -24
  215. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +6 -27
  216. nautobot/project-static/docs/user-guide/administration/installation/services.html +3 -24
  217. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +3 -24
  218. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +3 -24
  219. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +3 -24
  220. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +3 -24
  221. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +3 -24
  222. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +3 -24
  223. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +3 -24
  224. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +3 -24
  225. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +3 -24
  226. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +3 -24
  227. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +3 -24
  228. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +3 -24
  229. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +3 -24
  230. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +3 -24
  231. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +3 -24
  232. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +3 -24
  233. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +3 -24
  234. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +3 -24
  235. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +3 -24
  236. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +3 -24
  237. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +3 -24
  238. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +3 -24
  239. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +3 -24
  240. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +11 -259
  241. nautobot/project-static/docs/user-guide/core-data-model/dcim/{controllermanageddevicegroup.html → controllerdevicegroup.html} +17 -107
  242. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +3 -24
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +3 -24
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +3 -24
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +3 -24
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +3 -24
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +3 -24
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +3 -24
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +3 -24
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +3 -24
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +3 -24
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +3 -24
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +3 -24
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +3 -24
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +3 -24
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +3 -24
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +3 -24
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +3 -24
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +3 -24
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +3 -24
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +3 -24
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +3 -24
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +3 -24
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +3 -24
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +3 -24
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +3 -24
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +3 -24
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +3 -24
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +3 -24
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +3 -24
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +3 -24
  272. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +6 -27
  273. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +3 -24
  274. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +3 -24
  275. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +3 -24
  276. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +3 -24
  277. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +3 -24
  278. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +3 -24
  279. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +3 -24
  280. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +3 -24
  281. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +3 -24
  282. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +3 -24
  283. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +3 -24
  284. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +3 -24
  285. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +3 -24
  286. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +3 -24
  287. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +3 -24
  288. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +3 -24
  289. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +3 -24
  290. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +3 -24
  291. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +3 -24
  292. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +3 -24
  293. nautobot/project-static/docs/user-guide/feature-guides/{contacts-and-teams.html → contact-and-team.html} +4 -25
  294. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +5 -26
  295. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +3 -24
  296. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +3 -24
  297. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +3 -24
  298. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +3 -24
  299. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +3 -24
  300. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +3 -24
  301. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +5 -26
  302. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +3 -24
  303. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +3 -24
  304. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +3 -24
  305. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +3 -24
  306. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +3 -24
  307. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +3 -24
  308. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +3 -24
  309. nautobot/project-static/docs/user-guide/index.html +3 -24
  310. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +3 -24
  311. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +3 -24
  312. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +3 -24
  313. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +3 -24
  314. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +3 -24
  315. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +3 -24
  316. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +3 -24
  317. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +3 -24
  318. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +3 -24
  319. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +3 -24
  320. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +3 -24
  321. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +3 -24
  322. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +3 -24
  323. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +3 -24
  324. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +3 -24
  325. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +3 -24
  326. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +3 -24
  327. nautobot/project-static/docs/user-guide/platform-functionality/note.html +3 -24
  328. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +3 -24
  329. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +3 -24
  330. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +3 -24
  331. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +3 -24
  332. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +3 -24
  333. nautobot/project-static/docs/user-guide/platform-functionality/role.html +3 -24
  334. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +3 -24
  335. nautobot/project-static/docs/user-guide/platform-functionality/status.html +3 -24
  336. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +3 -24
  337. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +3 -24
  338. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +3 -24
  339. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +3 -24
  340. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +3 -24
  341. nautobot/tenancy/api/urls.py +2 -1
  342. nautobot/tenancy/api/views.py +12 -0
  343. nautobot/tenancy/tables.py +1 -1
  344. nautobot/tenancy/tests/test_views.py +0 -1
  345. nautobot/users/api/urls.py +2 -1
  346. nautobot/users/api/views.py +65 -2
  347. nautobot/users/views.py +8 -8
  348. nautobot/virtualization/api/urls.py +2 -1
  349. nautobot/virtualization/api/views.py +12 -0
  350. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/METADATA +3 -3
  351. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/RECORD +356 -361
  352. nautobot/core/tests/integration/test_view_authentication.py +0 -67
  353. nautobot/dcim/management/commands/migrate_location_contacts.py +0 -218
  354. nautobot/dcim/templates/dcim/controller_create.html +0 -70
  355. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +0 -88
  356. nautobot/ipam/tests/test_tables.py +0 -42
  357. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +0 -8581
  358. /nautobot/dcim/templates/dcim/{controllermanageddevicegroup_retrieve.html → controllerdevicegroup_retrieve.html} +0 -0
  359. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/LICENSE.txt +0 -0
  360. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/NOTICE +0 -0
  361. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/WHEEL +0 -0
  362. {nautobot-2.2.0.dist-info → nautobot-2.2.0b1.dist-info}/entry_points.txt +0 -0
@@ -3,7 +3,6 @@
3
3
  from django.test import TestCase
4
4
 
5
5
  from nautobot.dcim.models import (
6
- Controller,
7
6
  Device,
8
7
  DeviceRedundancyGroup,
9
8
  DeviceType,
@@ -104,7 +103,6 @@ class DeviceRedundancyGroupTest(TestCase):
104
103
  self.device.device_redundancy_group_priority = 1
105
104
  self.device.validated_save()
106
105
 
107
- Controller.objects.all().delete()
108
106
  deviceredundancygroup.delete()
109
107
 
110
108
  self.device.refresh_from_db()
@@ -40,8 +40,8 @@ from nautobot.dcim.choices import (
40
40
  )
41
41
  from nautobot.dcim.filters import (
42
42
  ConsoleConnectionFilterSet,
43
+ ControllerDeviceGroupFilterSet,
43
44
  ControllerFilterSet,
44
- ControllerManagedDeviceGroupFilterSet,
45
45
  InterfaceConnectionFilterSet,
46
46
  PowerConnectionFilterSet,
47
47
  SoftwareImageFileFilterSet,
@@ -55,7 +55,7 @@ from nautobot.dcim.models import (
55
55
  ConsoleServerPort,
56
56
  ConsoleServerPortTemplate,
57
57
  Controller,
58
- ControllerManagedDeviceGroup,
58
+ ControllerDeviceGroup,
59
59
  Device,
60
60
  DeviceBay,
61
61
  DeviceBayTemplate,
@@ -136,7 +136,6 @@ def create_test_device(name):
136
136
 
137
137
  class LocationTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
138
138
  model = LocationType
139
- sort_on_field = "nestable"
140
139
 
141
140
  @classmethod
142
141
  def setUpTestData(cls):
@@ -255,20 +254,15 @@ class LocationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
255
254
 
256
255
  class RackGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
257
256
  model = RackGroup
258
- sort_on_field = "name"
259
257
 
260
258
  @classmethod
261
259
  def setUpTestData(cls):
262
260
  location = Location.objects.filter(location_type=LocationType.objects.get(name="Campus")).first()
263
261
 
264
- rack_groups = (
265
- RackGroup.objects.create(name="Rack Group 1", location=location),
266
- RackGroup.objects.create(name="Rack Group 2", location=location),
267
- RackGroup.objects.create(name="Rack Group 3", location=location),
268
- RackGroup.objects.create(name="Rack Group 8", location=location),
269
- )
270
- RackGroup.objects.create(name="Rack Group Child 1", location=location, parent=rack_groups[0])
271
- RackGroup.objects.create(name="Rack Group Child 2", location=location, parent=rack_groups[0])
262
+ RackGroup.objects.create(name="Rack Group 1", location=location)
263
+ RackGroup.objects.create(name="Rack Group 2", location=location)
264
+ RackGroup.objects.create(name="Rack Group 3", location=location)
265
+ RackGroup.objects.create(name="Rack Group 8", location=location)
272
266
 
273
267
  cls.form_data = {
274
268
  "name": "Rack Group X",
@@ -573,7 +567,6 @@ class ManufacturerTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
573
567
  # FIXME(jathan): This has to be replaced with# `get_deletable_object` and
574
568
  # `get_deletable_object_pks` but this is a workaround just so all of these objects are
575
569
  # deletable for now.
576
- Controller.objects.filter(controller_device__isnull=False).delete()
577
570
  Device.objects.all().delete()
578
571
  DeviceType.objects.all().delete()
579
572
  Platform.objects.all().delete()
@@ -600,7 +593,6 @@ class DeviceTypeTestCase(
600
593
 
601
594
  @classmethod
602
595
  def setUpTestData(cls):
603
- Controller.objects.filter(controller_device__isnull=False).delete()
604
596
  Device.objects.all().delete()
605
597
  manufacturers = Manufacturer.objects.all()[:2]
606
598
 
@@ -1286,7 +1278,6 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1286
1278
 
1287
1279
  @classmethod
1288
1280
  def setUpTestData(cls):
1289
- Controller.objects.filter(controller_device__isnull=False).delete()
1290
1281
  Device.objects.all().delete()
1291
1282
  locations = Location.objects.filter(location_type=LocationType.objects.get(name="Campus"))[:2]
1292
1283
 
@@ -1454,7 +1445,7 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
1454
1445
  "face": DeviceFaceChoices.FACE_FRONT,
1455
1446
  "secrets_group": secrets_groups[1].pk,
1456
1447
  "software_version": software_versions[1].pk,
1457
- "controller_managed_device_group": ControllerManagedDeviceGroup.objects.first().pk,
1448
+ "controller_device_group": ControllerDeviceGroup.objects.first().pk,
1458
1449
  }
1459
1450
 
1460
1451
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
@@ -2236,9 +2227,6 @@ class InventoryItemTestCase(ViewTestCases.DeviceComponentViewTestCase):
2236
2227
  "software_version": software_versions[2].pk,
2237
2228
  }
2238
2229
 
2239
- def test_table_with_indentation_is_removed_on_filter_or_sort(self):
2240
- self.skipTest("InventoryItem table has no implementation of indentation.")
2241
-
2242
2230
 
2243
2231
  # TODO: Change base class to PrimaryObjectViewTestCase
2244
2232
  # Blocked by lack of common creation view for cables (termination A must be initialized)
@@ -3131,7 +3119,7 @@ class ControllerTestCase(ViewTestCases.PrimaryObjectViewTestCase):
3131
3119
  tenant = Tenant.objects.first()
3132
3120
 
3133
3121
  cls.form_data = {
3134
- "controller_device": device.pk,
3122
+ "deployed_controller_device": device.pk,
3135
3123
  "description": "Controller 1 description",
3136
3124
  "external_integration": external_integration.pk,
3137
3125
  "location": location.pk,
@@ -3152,16 +3140,16 @@ class ControllerTestCase(ViewTestCases.PrimaryObjectViewTestCase):
3152
3140
  }
3153
3141
 
3154
3142
 
3155
- class ControllerManagedDeviceGroupTestCase(ViewTestCases.PrimaryObjectViewTestCase):
3156
- model = ControllerManagedDeviceGroup
3157
- filterset = ControllerManagedDeviceGroupFilterSet
3143
+ class ControllerDeviceGroupTestCase(ViewTestCases.PrimaryObjectViewTestCase):
3144
+ model = ControllerDeviceGroup
3145
+ filterset = ControllerDeviceGroupFilterSet
3158
3146
 
3159
3147
  @classmethod
3160
3148
  def setUpTestData(cls):
3161
3149
  controllers = Controller.objects.all()
3162
3150
 
3163
3151
  cls.form_data = {
3164
- "name": "Managed Device Group 10",
3152
+ "name": "Controller Device Group 10",
3165
3153
  "controller": controllers[0].pk,
3166
3154
  "weight": 100,
3167
3155
  "devices": [item.pk for item in Device.objects.all()[:2]],
nautobot/dcim/urls.py CHANGED
@@ -40,7 +40,7 @@ router.register("interface-redundancy-groups-associations", views.InterfaceRedun
40
40
  router.register("software-image-files", views.SoftwareImageFileUIViewSet)
41
41
  router.register("software-versions", views.SoftwareVersionUIViewSet)
42
42
  router.register("controllers", views.ControllerUIViewSet)
43
- router.register("controller-managed-device-groups", views.ControllerManagedDeviceGroupUIViewSet)
43
+ router.register("controller-device-groups", views.ControllerDeviceGroupUIViewSet)
44
44
 
45
45
  urlpatterns = [
46
46
  # Location types
nautobot/dcim/views.py CHANGED
@@ -11,7 +11,7 @@ from django.forms import (
11
11
  ModelMultipleChoiceField,
12
12
  MultipleHiddenInput,
13
13
  )
14
- from django.shortcuts import get_object_or_404, HttpResponse, redirect, render
14
+ from django.shortcuts import get_object_or_404, redirect, render
15
15
  from django.utils.functional import cached_property
16
16
  from django.utils.html import format_html
17
17
  from django.views.generic import View
@@ -48,7 +48,7 @@ from .models import (
48
48
  ConsoleServerPort,
49
49
  ConsoleServerPortTemplate,
50
50
  Controller,
51
- ControllerManagedDeviceGroup,
51
+ ControllerDeviceGroup,
52
52
  Device,
53
53
  DeviceBay,
54
54
  DeviceBayTemplate,
@@ -1459,7 +1459,7 @@ class DeviceBulkEditView(generic.BulkEditView):
1459
1459
  "device_type__manufacturer",
1460
1460
  "secrets_group",
1461
1461
  "device_redundancy_group",
1462
- "controller_managed_device_group",
1462
+ "controller_device_group",
1463
1463
  )
1464
1464
  filterset = filters.DeviceFilterSet
1465
1465
  table = tables.DeviceTable
@@ -2359,7 +2359,7 @@ class CableCreateView(generic.ObjectEditView):
2359
2359
  "rear-port": forms.ConnectCableToRearPortForm,
2360
2360
  "power-feed": forms.ConnectCableToPowerFeedForm,
2361
2361
  "circuit-termination": forms.ConnectCableToCircuitTerminationForm,
2362
- }.get(kwargs.get("termination_b_type"), None)
2362
+ }[kwargs.get("termination_b_type")]
2363
2363
 
2364
2364
  return super().dispatch(request, *args, **kwargs)
2365
2365
 
@@ -2376,9 +2376,6 @@ class CableCreateView(generic.ObjectEditView):
2376
2376
  return obj
2377
2377
 
2378
2378
  def get(self, request, *args, **kwargs):
2379
- if self.model_form is None:
2380
- return HttpResponse(status_code=400)
2381
-
2382
2379
  obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs)
2383
2380
 
2384
2381
  # Parse initial data manually to avoid setting field values as lists
@@ -3024,13 +3021,12 @@ class ControllerUIViewSet(NautobotUIViewSet):
3024
3021
  queryset = Controller.objects.all()
3025
3022
  serializer_class = serializers.ControllerSerializer
3026
3023
  table_class = tables.ControllerTable
3027
- template_name = "dcim/controller_create.html"
3028
3024
 
3029
3025
  def get_extra_context(self, request, instance):
3030
3026
  context = super().get_extra_context(request, instance)
3031
3027
 
3032
3028
  if self.action == "retrieve" and instance:
3033
- devices = Device.objects.restrict(request.user).filter(controller_managed_device_group__controller=instance)
3029
+ devices = Device.objects.restrict(request.user).filter(controller_device_group__controller=instance)
3034
3030
  devices_table = tables.DeviceTable(devices)
3035
3031
 
3036
3032
  paginate = {
@@ -3044,19 +3040,19 @@ class ControllerUIViewSet(NautobotUIViewSet):
3044
3040
  return context
3045
3041
 
3046
3042
 
3047
- class ControllerManagedDeviceGroupUIViewSet(NautobotUIViewSet):
3048
- filterset_class = filters.ControllerManagedDeviceGroupFilterSet
3049
- filterset_form_class = forms.ControllerManagedDeviceGroupFilterForm
3050
- form_class = forms.ControllerManagedDeviceGroupForm
3051
- bulk_update_form_class = forms.ControllerManagedDeviceGroupBulkEditForm
3043
+ class ControllerDeviceGroupUIViewSet(NautobotUIViewSet):
3044
+ filterset_class = filters.ControllerDeviceGroupFilterSet
3045
+ filterset_form_class = forms.ControllerDeviceGroupFilterForm
3046
+ form_class = forms.ControllerDeviceGroupForm
3047
+ bulk_update_form_class = forms.ControllerDeviceGroupBulkEditForm
3052
3048
  queryset = (
3053
- ControllerManagedDeviceGroup.objects.all()
3049
+ ControllerDeviceGroup.objects.all()
3054
3050
  .prefetch_related("devices")
3055
- .annotate(device_count=count_related(Device, "controller_managed_device_group"))
3051
+ .annotate(device_count=count_related(Device, "controller_device_group"))
3056
3052
  )
3057
- serializer_class = serializers.ControllerManagedDeviceGroupSerializer
3058
- table_class = tables.ControllerManagedDeviceGroupTable
3059
- template_name = "dcim/controllermanageddevicegroup_create.html"
3053
+ serializer_class = serializers.ControllerDeviceGroupSerializer
3054
+ table_class = tables.ControllerDeviceGroupTable
3055
+ template_name = "dcim/controllerdevicegroup_create.html"
3060
3056
 
3061
3057
  def get_extra_context(self, request, instance):
3062
3058
  context = super().get_extra_context(request, instance)
@@ -2,7 +2,8 @@ from nautobot.core.api.routers import OrderedDefaultRouter
2
2
 
3
3
  from . import views
4
4
 
5
- router = OrderedDefaultRouter(view_name="Extras")
5
+ router = OrderedDefaultRouter()
6
+ router.APIRootView = views.ExtrasRootView
6
7
 
7
8
  # Computed Fields
8
9
  router.register("computed-fields", views.ComputedFieldViewSet)
@@ -16,6 +16,7 @@ from rest_framework.exceptions import MethodNotAllowed, PermissionDenied, Valida
16
16
  from rest_framework.parsers import JSONParser, MultiPartParser
17
17
  from rest_framework.permissions import IsAuthenticated
18
18
  from rest_framework.response import Response
19
+ from rest_framework.routers import APIRootView
19
20
 
20
21
  from nautobot.core.api.authentication import TokenPermissions
21
22
  from nautobot.core.api.utils import get_serializer_for_model
@@ -76,6 +77,15 @@ from nautobot.extras.utils import get_worker_count
76
77
  from . import serializers
77
78
 
78
79
 
80
+ class ExtrasRootView(APIRootView):
81
+ """
82
+ Extras API root view
83
+ """
84
+
85
+ def get_view_name(self):
86
+ return "Extras"
87
+
88
+
79
89
  class NotesViewSetMixin:
80
90
  def restrict_queryset(self, request, *args, **kwargs):
81
91
  """
@@ -1,11 +1,7 @@
1
- from difflib import get_close_matches
2
-
3
1
  from django.conf import settings
4
2
  from django.contrib.auth import get_user_model
5
3
  from django.contrib.contenttypes.models import ContentType
6
- from django.db.models import Q
7
4
  import django_filters
8
- from drf_spectacular.utils import extend_schema_field
9
5
 
10
6
  from nautobot.core.api.exceptions import SerializerNotFound
11
7
  from nautobot.core.api.utils import get_serializer_for_model
@@ -451,54 +447,7 @@ class NautobotFilterSet(
451
447
  #
452
448
 
453
449
 
454
- class ContactTeamFilterSet(NameSearchFilterSet, NautobotFilterSet):
455
- """Base filter set for Contacts and Teams."""
456
-
457
- similar_to_location_data = NaturalKeyOrPKMultipleChoiceFilter(
458
- queryset=Location.objects.all(),
459
- label="Similar to location contact data",
460
- method="_similar_to_location_data",
461
- )
462
-
463
- def generate_query__similar_to_location_data(self, queryset, locations):
464
- """Helper method used by _similar_to_location_data() method."""
465
- query_params = Q()
466
- for location in locations:
467
- contact_name = location.contact_name
468
- contact_phone = location.contact_phone
469
- contact_email = location.contact_email
470
- if contact_name:
471
- contact_names = list(queryset.order_by().values_list("name", flat=True).distinct())
472
- name_matches = get_close_matches(contact_name, contact_names, cutoff=0.8)
473
- if name_matches:
474
- query_params |= Q(name__in=name_matches)
475
- if contact_phone:
476
- contact_phones = list(queryset.order_by().values_list("phone", flat=True).distinct())
477
- phone_matches = get_close_matches(contact_phone, contact_phones, cutoff=0.8)
478
- if phone_matches:
479
- query_params |= Q(phone__in=phone_matches)
480
- if contact_email:
481
- contact_emails = list(queryset.order_by().values_list("email", flat=True).distinct())
482
- # fuzzy matching for emails doesn't make sense, use case insensitive match here
483
- email_matches = [e for e in contact_emails if e.casefold() == contact_email.casefold()]
484
- if email_matches:
485
- query_params |= Q(email__in=email_matches)
486
-
487
- return query_params
488
-
489
- @extend_schema_field({"type": "string"})
490
- def _similar_to_location_data(self, queryset, name, value):
491
- """FilterSet method for getting Contacts or Teams that are similar to the explicit contact fields of a location"""
492
- if value:
493
- params = self.generate_query__similar_to_location_data(queryset, value)
494
- if len(params) > 0:
495
- return queryset.filter(params)
496
- else:
497
- return queryset.none()
498
- return queryset
499
-
500
-
501
- class ContactFilterSet(ContactTeamFilterSet):
450
+ class ContactFilterSet(NameSearchFilterSet, NautobotFilterSet):
502
451
  class Meta:
503
452
  model = Contact
504
453
  fields = "__all__"
@@ -1160,7 +1109,7 @@ class TagFilterSet(NautobotFilterSet):
1160
1109
  #
1161
1110
 
1162
1111
 
1163
- class TeamFilterSet(ContactTeamFilterSet):
1112
+ class TeamFilterSet(NameSearchFilterSet, NautobotFilterSet):
1164
1113
  class Meta:
1165
1114
  model = Team
1166
1115
  fields = "__all__"
@@ -28,13 +28,6 @@ class ContactForm(NautobotModelForm):
28
28
  "tags",
29
29
  ]
30
30
 
31
- def __init__(self, instance=None, initial=None, **kwargs):
32
- if instance is not None:
33
- if initial is None:
34
- initial = {}
35
- initial.setdefault("teams", instance.teams.all())
36
- super().__init__(instance=instance, initial=initial, **kwargs)
37
-
38
31
  def save(self, *args, **kwargs):
39
32
  """
40
33
  Since `teams` field on Contact Model is the reverse side of an M2M,
@@ -8,20 +8,6 @@ from nautobot.core.models.querysets import RestrictedQuerySet
8
8
 
9
9
 
10
10
  class JobResultManager(BaseManager.from_queryset(RestrictedQuerySet), TaskResultManager):
11
- def get_task(self, task_id):
12
- """Get result for task by ``task_id``.
13
-
14
- This overloads `TaskResultManager.get_task` provided by `django-celery-results` to manage custom
15
- behaviors for integration with Nautobot.
16
- """
17
- try:
18
- return self.get(id=task_id)
19
- except self.model.DoesNotExist:
20
- if self._last_id == task_id:
21
- self.warn_if_repeatable_read()
22
- self._last_id = task_id
23
- return self.model(id=task_id)
24
-
25
11
  @transaction_retry(max_retries=2)
26
12
  def store_result(
27
13
  self,
@@ -13,51 +13,9 @@ menu_items = (
13
13
  name="Organization",
14
14
  weight=100,
15
15
  groups=(
16
- NavMenuGroup(
17
- name="Contacts",
18
- weight=400,
19
- items=(
20
- NavMenuItem(
21
- link="extras:contact_list",
22
- name="Contacts",
23
- weight=100,
24
- permissions=["extras.view_contact"],
25
- buttons=[NavMenuAddButton(link="extras:contact_add", permissions=["extras.add_contact"])],
26
- ),
27
- NavMenuItem(
28
- link="extras:team_list",
29
- name="Teams",
30
- weight=200,
31
- permissions=["extras.view_team"],
32
- buttons=[NavMenuAddButton(link="extras:team_add", permissions=["extras.add_team"])],
33
- ),
34
- ),
35
- ),
36
- NavMenuGroup(
37
- name="Groups",
38
- weight=500,
39
- items=(
40
- NavMenuItem(
41
- link="extras:dynamicgroup_list",
42
- name="Dynamic Groups",
43
- weight=100,
44
- permissions=[
45
- "extras.view_dynamicgroup",
46
- ],
47
- buttons=(
48
- NavMenuAddButton(
49
- link="extras:dynamicgroup_add",
50
- permissions=[
51
- "extras.add_dynamicgroup",
52
- ],
53
- ),
54
- ),
55
- ),
56
- ),
57
- ),
58
16
  NavMenuGroup(
59
17
  name="Metadata", # TODO: is there a better name for this grouping?
60
- weight=600,
18
+ weight=400,
61
19
  items=(
62
20
  NavMenuItem(
63
21
  link="extras:tag_list",
@@ -107,6 +65,42 @@ menu_items = (
107
65
  ),
108
66
  ),
109
67
  ),
68
+ NavMenuItem(
69
+ link="extras:contact_list",
70
+ name="Contacts",
71
+ weight=400,
72
+ permissions=["extras.view_contact"],
73
+ buttons=[NavMenuAddButton(link="extras:contact_add", permissions=["extras.add_contact"])],
74
+ ),
75
+ NavMenuItem(
76
+ link="extras:team_list",
77
+ name="Teams",
78
+ weight=500,
79
+ permissions=["extras.view_team"],
80
+ buttons=[NavMenuAddButton(link="extras:team_add", permissions=["extras.add_team"])],
81
+ ),
82
+ ),
83
+ ),
84
+ NavMenuGroup(
85
+ name="Dynamic Groups",
86
+ weight=500,
87
+ items=(
88
+ NavMenuItem(
89
+ link="extras:dynamicgroup_list",
90
+ name="Dynamic Groups",
91
+ weight=100,
92
+ permissions=[
93
+ "extras.view_dynamicgroup",
94
+ ],
95
+ buttons=(
96
+ NavMenuAddButton(
97
+ link="extras:dynamicgroup_add",
98
+ permissions=[
99
+ "extras.add_dynamicgroup",
100
+ ],
101
+ ),
102
+ ),
103
+ ),
110
104
  ),
111
105
  ),
112
106
  ),
@@ -282,6 +276,22 @@ menu_items = (
282
276
  ),
283
277
  ),
284
278
  ),
279
+ NavMenuItem(
280
+ link="extras:relationship_list",
281
+ name="Relationships",
282
+ weight=200,
283
+ permissions=[
284
+ "extras.view_relationship",
285
+ ],
286
+ buttons=(
287
+ NavMenuAddButton(
288
+ link="extras:relationship_add",
289
+ permissions=[
290
+ "extras.add_relationship",
291
+ ],
292
+ ),
293
+ ),
294
+ ),
285
295
  NavMenuItem(
286
296
  link="extras:note_list",
287
297
  name="Notes",
@@ -379,53 +389,37 @@ menu_items = (
379
389
  ),
380
390
  ),
381
391
  NavMenuGroup(
382
- name="Data Model",
392
+ name="Miscellaneous",
383
393
  weight=600,
384
394
  items=(
385
395
  NavMenuItem(
386
- link="extras:customfield_list",
387
- name="Custom Fields",
396
+ link="extras:computedfield_list",
397
+ name="Computed Fields",
388
398
  weight=100,
389
399
  permissions=[
390
- "extras.view_customfield",
400
+ "extras.view_computedfield",
391
401
  ],
392
402
  buttons=(
393
403
  NavMenuAddButton(
394
- link="extras:customfield_add",
404
+ link="extras:computedfield_add",
395
405
  permissions=[
396
- "extras.add_customfield",
406
+ "extras.add_computedfield",
397
407
  ],
398
408
  ),
399
409
  ),
400
410
  ),
401
411
  NavMenuItem(
402
- link="extras:relationship_list",
403
- name="Relationships",
412
+ link="extras:customfield_list",
413
+ name="Custom Fields",
404
414
  weight=200,
405
415
  permissions=[
406
- "extras.view_relationship",
407
- ],
408
- buttons=(
409
- NavMenuAddButton(
410
- link="extras:relationship_add",
411
- permissions=[
412
- "extras.add_relationship",
413
- ],
414
- ),
415
- ),
416
- ),
417
- NavMenuItem(
418
- link="extras:computedfield_list",
419
- name="Computed Fields",
420
- weight=300,
421
- permissions=[
422
- "extras.view_computedfield",
416
+ "extras.view_customfield",
423
417
  ],
424
418
  buttons=(
425
419
  NavMenuAddButton(
426
- link="extras:computedfield_add",
420
+ link="extras:customfield_add",
427
421
  permissions=[
428
- "extras.add_computedfield",
422
+ "extras.add_customfield",
429
423
  ],
430
424
  ),
431
425
  ),
@@ -433,7 +427,7 @@ menu_items = (
433
427
  NavMenuItem(
434
428
  link="extras:customlink_list",
435
429
  name="Custom Links",
436
- weight=400,
430
+ weight=300,
437
431
  permissions=[
438
432
  "extras.view_customlink",
439
433
  ],
@@ -2,9 +2,11 @@ from collections import OrderedDict
2
2
 
3
3
  from django.apps import apps
4
4
  from django.conf import settings
5
+ from django.contrib.auth.mixins import LoginRequiredMixin
5
6
  from django.http import Http404
6
7
  from django.shortcuts import render
7
8
  from django.urls.exceptions import NoReverseMatch
9
+ from django.views.generic import View
8
10
  from django_tables2 import RequestConfig
9
11
  from drf_spectacular.utils import extend_schema
10
12
  from rest_framework import permissions
@@ -12,14 +14,13 @@ from rest_framework.response import Response
12
14
  from rest_framework.reverse import reverse
13
15
  from rest_framework.views import APIView
14
16
 
15
- from nautobot.core.api.views import AuthenticatedAPIRootView, NautobotAPIVersionMixin
17
+ from nautobot.core.api.views import NautobotAPIVersionMixin
16
18
  from nautobot.core.forms import TableConfigForm
17
- from nautobot.core.views.generic import GenericView
18
19
  from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
19
20
  from nautobot.extras.plugins.tables import InstalledAppsTable
20
21
 
21
22
 
22
- class InstalledAppsView(GenericView):
23
+ class InstalledAppsView(LoginRequiredMixin, View):
23
24
  """
24
25
  View for listing all installed Apps.
25
26
  """
@@ -65,7 +66,7 @@ class InstalledAppsView(GenericView):
65
66
  )
66
67
 
67
68
 
68
- class InstalledAppDetailView(GenericView):
69
+ class InstalledAppDetailView(LoginRequiredMixin, View):
69
70
  """
70
71
  View for showing details of an installed App.
71
72
  """
@@ -92,6 +93,7 @@ class InstalledAppsAPIView(NautobotAPIVersionMixin, APIView):
92
93
  """
93
94
 
94
95
  permission_classes = [permissions.IsAdminUser]
96
+ _ignore_model_permissions = True
95
97
 
96
98
  def get_view_name(self):
97
99
  return "Installed Apps"
@@ -127,9 +129,11 @@ class InstalledAppsAPIView(NautobotAPIVersionMixin, APIView):
127
129
  return Response([self._get_app_data(apps.get_app_config(app)) for app in settings.PLUGINS])
128
130
 
129
131
 
130
- class AppsAPIRootView(AuthenticatedAPIRootView):
131
- name = "Apps"
132
- description = "API extension point for installed Nautobot Apps"
132
+ class AppsAPIRootView(NautobotAPIVersionMixin, APIView):
133
+ _ignore_model_permissions = True
134
+
135
+ def get_view_name(self):
136
+ return "Apps"
133
137
 
134
138
  @staticmethod
135
139
  def _get_app_entry(app_config, request, format_):
@@ -18,7 +18,6 @@ from nautobot.core.testing import APITestCase, APIViewTestCases
18
18
  from nautobot.core.testing.utils import disable_warnings
19
19
  from nautobot.core.utils.lookup import get_route_for_model
20
20
  from nautobot.dcim.models import (
21
- Controller,
22
21
  Device,
23
22
  DeviceType,
24
23
  Location,
@@ -2852,7 +2851,6 @@ class RelationshipTest(APIViewTestCases.APIViewTestCase, RequiredRelationshipTes
2852
2851
  vlan_groups = VLANGroup.objects.all()[:2]
2853
2852
 
2854
2853
  # Try deleting all devices and then creating 2 VLANs (fails):
2855
- Controller.objects.filter(controller_device__isnull=False).delete()
2856
2854
  Device.objects.all().delete()
2857
2855
  response = send_bulk_data(
2858
2856
  "post",
@@ -16,7 +16,6 @@ from nautobot.dcim.choices import PortTypeChoices
16
16
  from nautobot.dcim.filters import DeviceFilterSet
17
17
  from nautobot.dcim.forms import DeviceFilterForm, DeviceForm
18
18
  from nautobot.dcim.models import (
19
- Controller,
20
19
  Device,
21
20
  DeviceType,
22
21
  FrontPort,
@@ -49,7 +48,6 @@ from nautobot.tenancy.models import Tenant
49
48
  class DynamicGroupTestBase(TestCase):
50
49
  @classmethod
51
50
  def setUpTestData(cls):
52
- Controller.objects.filter(controller_device__isnull=False).delete()
53
51
  Device.objects.all().delete()
54
52
  cls.device_ct = ContentType.objects.get_for_model(Device)
55
53
  cls.dynamicgroup_ct = ContentType.objects.get_for_model(DynamicGroup)