nautobot 2.2.3__py3-none-any.whl → 2.2.5__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 (327) hide show
  1. nautobot/circuits/forms.py +15 -0
  2. nautobot/circuits/navigation.py +9 -1
  3. nautobot/circuits/views.py +2 -0
  4. nautobot/core/filters.py +11 -0
  5. nautobot/core/settings.py +6 -4
  6. nautobot/core/settings.yaml +54 -19
  7. nautobot/core/templates/admin/base.html +2 -2
  8. nautobot/core/templates/base_django.html +2 -2
  9. nautobot/core/templates/buttons/export.html +47 -47
  10. nautobot/core/templates/inc/javascript.html +3 -0
  11. nautobot/core/templates/inc/media.html +3 -0
  12. nautobot/core/templates/login.html +2 -2
  13. nautobot/core/templates/nautobot_config.py.j2 +2 -0
  14. nautobot/core/testing/filters.py +24 -1
  15. nautobot/core/testing/views.py +13 -1
  16. nautobot/core/tests/test_jobs.py +79 -2
  17. nautobot/core/tests/test_views.py +33 -0
  18. nautobot/core/views/mixins.py +4 -0
  19. nautobot/core/views/utils.py +18 -1
  20. nautobot/dcim/filters/__init__.py +1 -1
  21. nautobot/dcim/forms.py +23 -4
  22. nautobot/dcim/tables/devicetypes.py +15 -4
  23. nautobot/dcim/tests/test_views.py +323 -55
  24. nautobot/dcim/views.py +26 -20
  25. nautobot/extras/api/serializers.py +17 -6
  26. nautobot/extras/api/views.py +2 -2
  27. nautobot/extras/context_managers.py +3 -0
  28. nautobot/extras/filters/__init__.py +15 -1
  29. nautobot/extras/forms/forms.py +33 -0
  30. nautobot/extras/forms/mixins.py +0 -6
  31. nautobot/extras/signals.py +6 -1
  32. nautobot/extras/tests/test_api.py +24 -2
  33. nautobot/extras/tests/test_context_managers.py +51 -1
  34. nautobot/extras/tests/test_filters.py +69 -0
  35. nautobot/extras/tests/test_forms.py +0 -3
  36. nautobot/extras/tests/test_views.py +48 -4
  37. nautobot/extras/utils.py +2 -1
  38. nautobot/extras/views.py +47 -31
  39. nautobot/ipam/forms.py +18 -0
  40. nautobot/ipam/tests/test_views.py +9 -2
  41. nautobot/ipam/views.py +17 -6
  42. nautobot/project-static/docs/404.html +107 -51
  43. nautobot/project-static/docs/apps/index.html +107 -51
  44. nautobot/project-static/docs/apps/nautobot-apps.html +107 -51
  45. nautobot/project-static/docs/assets/_mkdocstrings.css +6 -1
  46. nautobot/project-static/docs/assets/extra.css +7 -0
  47. nautobot/project-static/docs/assets/javascripts/bundle.ebd0bdb7.min.js +29 -0
  48. nautobot/project-static/docs/assets/javascripts/bundle.ebd0bdb7.min.js.map +7 -0
  49. nautobot/project-static/docs/assets/stylesheets/main.6543a935.min.css +1 -0
  50. nautobot/project-static/docs/assets/stylesheets/main.6543a935.min.css.map +1 -0
  51. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +107 -51
  52. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +107 -51
  53. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +107 -51
  54. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +107 -51
  55. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +107 -51
  56. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +107 -51
  57. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +107 -51
  58. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +107 -51
  59. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +107 -51
  60. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +107 -51
  61. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +107 -51
  62. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +107 -51
  63. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +107 -51
  64. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +107 -51
  65. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +107 -51
  66. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +107 -51
  67. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +107 -51
  68. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +107 -51
  69. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +107 -51
  70. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +107 -51
  71. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +107 -51
  72. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +107 -51
  73. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +107 -51
  74. nautobot/project-static/docs/development/apps/api/configuration-view.html +110 -54
  75. nautobot/project-static/docs/development/apps/api/database-backend-config.html +110 -54
  76. nautobot/project-static/docs/development/apps/api/models/django-admin.html +107 -51
  77. nautobot/project-static/docs/development/apps/api/models/global-search.html +110 -54
  78. nautobot/project-static/docs/development/apps/api/models/graphql.html +113 -57
  79. nautobot/project-static/docs/development/apps/api/models/index.html +107 -51
  80. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +113 -57
  81. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +107 -51
  82. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +111 -55
  83. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +107 -51
  84. nautobot/project-static/docs/development/apps/api/platform-features/index.html +107 -51
  85. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +110 -54
  86. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +110 -54
  87. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +110 -54
  88. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +110 -54
  89. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +107 -51
  90. nautobot/project-static/docs/development/apps/api/prometheus.html +110 -54
  91. nautobot/project-static/docs/development/apps/api/setup.html +107 -51
  92. nautobot/project-static/docs/development/apps/api/testing.html +113 -57
  93. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +110 -54
  94. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +110 -54
  95. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +107 -51
  96. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +107 -51
  97. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +113 -57
  98. nautobot/project-static/docs/development/apps/api/views/base-template.html +107 -51
  99. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +110 -54
  100. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +107 -51
  101. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +110 -54
  102. nautobot/project-static/docs/development/apps/api/views/index.html +107 -51
  103. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +113 -57
  104. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +122 -66
  105. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +110 -54
  106. nautobot/project-static/docs/development/apps/api/views/notes.html +110 -54
  107. nautobot/project-static/docs/development/apps/api/views/rest-api.html +107 -51
  108. nautobot/project-static/docs/development/apps/api/views/urls.html +107 -51
  109. nautobot/project-static/docs/development/apps/index.html +128 -72
  110. nautobot/project-static/docs/development/apps/migration/code-updates.html +107 -51
  111. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +107 -51
  112. nautobot/project-static/docs/development/apps/migration/from-v1.html +109 -53
  113. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +107 -51
  114. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +107 -51
  115. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +107 -51
  116. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +107 -51
  117. nautobot/project-static/docs/development/apps/porting-from-netbox.html +110 -54
  118. nautobot/project-static/docs/development/core/application-registry.html +120 -64
  119. nautobot/project-static/docs/development/core/best-practices.html +122 -66
  120. nautobot/project-static/docs/development/core/bootstrap-ui.html +107 -51
  121. nautobot/project-static/docs/development/core/caching.html +107 -51
  122. nautobot/project-static/docs/development/core/controllers.html +107 -51
  123. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +113 -57
  124. nautobot/project-static/docs/development/core/generic-views.html +110 -54
  125. nautobot/project-static/docs/development/core/getting-started.html +137 -81
  126. nautobot/project-static/docs/development/core/homepage.html +110 -54
  127. nautobot/project-static/docs/development/core/index.html +107 -51
  128. nautobot/project-static/docs/development/core/model-checklist.html +107 -51
  129. nautobot/project-static/docs/development/core/model-features.html +107 -51
  130. nautobot/project-static/docs/development/core/natural-keys.html +110 -54
  131. nautobot/project-static/docs/development/core/navigation-menu.html +107 -51
  132. nautobot/project-static/docs/development/core/release-checklist.html +107 -51
  133. nautobot/project-static/docs/development/core/role-internals.html +107 -51
  134. nautobot/project-static/docs/development/core/settings.html +107 -51
  135. nautobot/project-static/docs/development/core/style-guide.html +110 -54
  136. nautobot/project-static/docs/development/core/templates.html +113 -57
  137. nautobot/project-static/docs/development/core/testing.html +126 -70
  138. nautobot/project-static/docs/development/core/user-preferences.html +107 -51
  139. nautobot/project-static/docs/development/index.html +107 -51
  140. nautobot/project-static/docs/development/jobs/index.html +173 -117
  141. nautobot/project-static/docs/development/jobs/migration/from-v1.html +110 -54
  142. nautobot/project-static/docs/docker/index.html +3 -3
  143. nautobot/project-static/docs/index.html +125 -69
  144. nautobot/project-static/docs/installation/selinux-troubleshooting.html +3 -3
  145. nautobot/project-static/docs/release-notes/index.html +107 -51
  146. nautobot/project-static/docs/release-notes/version-1.0.html +108 -52
  147. nautobot/project-static/docs/release-notes/version-1.1.html +107 -51
  148. nautobot/project-static/docs/release-notes/version-1.2.html +109 -53
  149. nautobot/project-static/docs/release-notes/version-1.3.html +108 -52
  150. nautobot/project-static/docs/release-notes/version-1.4.html +109 -53
  151. nautobot/project-static/docs/release-notes/version-1.5.html +118 -62
  152. nautobot/project-static/docs/release-notes/version-1.6.html +721 -285
  153. nautobot/project-static/docs/release-notes/version-2.0.html +113 -57
  154. nautobot/project-static/docs/release-notes/version-2.1.html +107 -51
  155. nautobot/project-static/docs/release-notes/version-2.2.html +503 -120
  156. nautobot/project-static/docs/requirements.txt +4 -4
  157. nautobot/project-static/docs/search/search_index.json +1 -1
  158. nautobot/project-static/docs/sitemap.xml +262 -262
  159. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  160. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +107 -51
  161. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +107 -51
  162. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +109 -53
  163. nautobot/project-static/docs/user-guide/administration/configuration/index.html +108 -52
  164. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +254 -167
  165. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +113 -57
  166. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +107 -51
  167. nautobot/project-static/docs/user-guide/administration/guides/caching.html +113 -57
  168. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +107 -51
  169. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +107 -51
  170. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +107 -51
  171. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +113 -57
  172. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +108 -52
  173. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +107 -51
  174. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +107 -51
  175. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +171 -112
  176. nautobot/project-static/docs/user-guide/administration/installation/docker.html +13 -8626
  177. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +117 -61
  178. nautobot/project-static/docs/user-guide/administration/installation/health-checks.html +13 -8614
  179. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +252 -165
  180. nautobot/project-static/docs/user-guide/administration/installation/index.html +165 -192
  181. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +411 -691
  182. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +249 -230
  183. nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +13 -8118
  184. nautobot/project-static/docs/user-guide/administration/installation/services.html +351 -241
  185. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +8684 -0
  186. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +8672 -0
  187. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +8176 -0
  188. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +110 -54
  189. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +110 -54
  190. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +155 -99
  191. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +107 -51
  192. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +109 -53
  193. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +107 -51
  194. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +107 -51
  195. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +108 -52
  196. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +107 -51
  197. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +107 -51
  198. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +107 -70
  199. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +115 -59
  200. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +113 -57
  201. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +107 -51
  202. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +107 -51
  203. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +107 -51
  204. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +107 -51
  205. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +110 -54
  206. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +107 -51
  207. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +110 -54
  208. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +110 -54
  209. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +110 -54
  210. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +110 -54
  211. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +107 -51
  212. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +107 -51
  213. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +115 -59
  214. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +110 -54
  215. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +110 -54
  216. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +110 -54
  217. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +110 -54
  218. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +117 -61
  219. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +110 -54
  220. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +110 -54
  221. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +119 -63
  222. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +110 -54
  223. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +110 -54
  224. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +113 -57
  225. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +113 -57
  226. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +113 -57
  227. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +107 -51
  228. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +113 -57
  229. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +107 -51
  230. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +110 -54
  231. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +110 -54
  232. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +107 -51
  233. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +110 -54
  234. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +110 -54
  235. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +107 -51
  236. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +107 -51
  237. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +107 -51
  238. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +110 -54
  239. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +110 -54
  240. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +110 -54
  241. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +110 -54
  242. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +107 -51
  243. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +113 -57
  244. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +110 -54
  245. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +110 -54
  246. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +110 -54
  247. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +125 -69
  248. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +113 -57
  249. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +128 -72
  250. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +110 -54
  251. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +107 -51
  252. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +110 -54
  253. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +116 -60
  254. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +107 -51
  255. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +113 -57
  256. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +107 -51
  257. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +110 -54
  258. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +107 -51
  259. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +107 -51
  260. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +107 -51
  261. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +107 -51
  262. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +113 -57
  263. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +113 -57
  264. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +107 -51
  265. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +113 -57
  266. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +110 -54
  267. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +107 -51
  268. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +107 -51
  269. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +108 -52
  270. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +107 -51
  271. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +107 -51
  272. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +107 -51
  273. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +107 -51
  274. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +108 -52
  275. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +110 -54
  276. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +113 -57
  277. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +107 -51
  278. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +110 -54
  279. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +107 -51
  280. nautobot/project-static/docs/user-guide/index.html +109 -53
  281. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +107 -51
  282. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +113 -57
  283. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +128 -72
  284. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +107 -51
  285. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +125 -69
  286. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +107 -51
  287. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +110 -54
  288. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +125 -69
  289. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +110 -54
  290. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +107 -51
  291. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +107 -51
  292. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +128 -72
  293. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +114 -58
  294. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +113 -57
  295. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +110 -54
  296. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +121 -65
  297. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +109 -53
  298. nautobot/project-static/docs/user-guide/platform-functionality/note.html +110 -54
  299. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +116 -60
  300. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +110 -54
  301. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +131 -75
  302. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +149 -93
  303. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +110 -54
  304. nautobot/project-static/docs/user-guide/platform-functionality/role.html +108 -84
  305. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +116 -60
  306. nautobot/project-static/docs/user-guide/platform-functionality/status.html +119 -63
  307. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +110 -54
  308. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +137 -81
  309. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +110 -54
  310. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +107 -51
  311. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +110 -54
  312. nautobot/project-static/js/forms.js +2 -1
  313. nautobot/tenancy/forms.py +9 -0
  314. nautobot/tenancy/views.py +3 -6
  315. nautobot/virtualization/forms.py +18 -6
  316. nautobot/virtualization/templates/virtualization/clustertype.html +2 -2
  317. nautobot/virtualization/views.py +7 -9
  318. {nautobot-2.2.3.dist-info → nautobot-2.2.5.dist-info}/METADATA +2 -2
  319. {nautobot-2.2.3.dist-info → nautobot-2.2.5.dist-info}/RECORD +323 -320
  320. nautobot/project-static/docs/assets/javascripts/bundle.bd41221c.min.js +0 -29
  321. nautobot/project-static/docs/assets/javascripts/bundle.bd41221c.min.js.map +0 -7
  322. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css +0 -1
  323. nautobot/project-static/docs/assets/stylesheets/main.bcfcd587.min.css.map +0 -1
  324. {nautobot-2.2.3.dist-info → nautobot-2.2.5.dist-info}/LICENSE.txt +0 -0
  325. {nautobot-2.2.3.dist-info → nautobot-2.2.5.dist-info}/NOTICE +0 -0
  326. {nautobot-2.2.3.dist-info → nautobot-2.2.5.dist-info}/WHEEL +0 -0
  327. {nautobot-2.2.3.dist-info → nautobot-2.2.5.dist-info}/entry_points.txt +0 -0
@@ -145,6 +145,12 @@ class CircuitTypeForm(NautobotModelForm):
145
145
  ]
146
146
 
147
147
 
148
+ class CircuitTypeFilterForm(NautobotFilterForm):
149
+ model = CircuitType
150
+ q = forms.CharField(required=False, label="Search")
151
+ name = forms.CharField(required=False)
152
+
153
+
148
154
  #
149
155
  # Circuits
150
156
  #
@@ -262,3 +268,12 @@ class CircuitTerminationForm(LocatableModelFormMixin, NautobotModelForm):
262
268
  widgets = {
263
269
  "term_side": forms.HiddenInput(),
264
270
  }
271
+
272
+
273
+ class CircuitTerminationFilterForm(LocatableModelFilterFormMixin, NautobotFilterForm):
274
+ model = CircuitTermination
275
+ q = forms.CharField(required=False, label="Search")
276
+ circuit = DynamicModelMultipleChoiceField(queryset=Circuit.objects.all(), to_field_name="cid", required=False)
277
+ provider_network = DynamicModelMultipleChoiceField(
278
+ queryset=ProviderNetwork.objects.all(), to_field_name="name", required=False
279
+ )
@@ -33,10 +33,18 @@ menu_items = (
33
33
  ),
34
34
  ),
35
35
  ),
36
+ NavMenuItem(
37
+ link="circuits:circuittermination_list",
38
+ name="Circuit Terminations",
39
+ weight=200,
40
+ permissions=[
41
+ "circuits.view_circuittermination",
42
+ ],
43
+ ),
36
44
  NavMenuItem(
37
45
  link="circuits:circuittype_list",
38
46
  name="Circuit Types",
39
- weight=200,
47
+ weight=300,
40
48
  permissions=[
41
49
  "circuits.view_circuittype",
42
50
  ],
@@ -27,6 +27,7 @@ class CircuitTypeUIViewSet(
27
27
  view_mixins.ObjectNotesViewMixin,
28
28
  ):
29
29
  filterset_class = filters.CircuitTypeFilterSet
30
+ filterset_form_class = forms.CircuitTypeFilterForm
30
31
  form_class = forms.CircuitTypeForm
31
32
  queryset = CircuitType.objects.annotate(circuit_count=count_related(Circuit, "circuit_type"))
32
33
  serializer_class = serializers.CircuitTypeSerializer
@@ -67,6 +68,7 @@ class CircuitTerminationUIViewSet(
67
68
  ):
68
69
  action_buttons = ("import", "export")
69
70
  filterset_class = filters.CircuitTerminationFilterSet
71
+ filterset_form_class = forms.CircuitTerminationFilterForm
70
72
  form_class = forms.CircuitTerminationForm
71
73
  queryset = CircuitTermination.objects.all()
72
74
  serializer_class = serializers.CircuitTerminationSerializer
nautobot/core/filters.py CHANGED
@@ -176,6 +176,9 @@ class ContentTypeFilterMixin:
176
176
  if value in EMPTY_VALUES:
177
177
  return qs
178
178
 
179
+ if value.isdigit():
180
+ return qs.filter(**{f"{self.field_name}__pk": value})
181
+
179
182
  try:
180
183
  app_label, model = value.lower().split(".")
181
184
  except ValueError:
@@ -242,6 +245,9 @@ class ContentTypeMultipleChoiceFilter(django_filters.MultipleChoiceFilter):
242
245
  if self.conjoined:
243
246
  qs = ContentTypeFilter.filter(self, qs, v)
244
247
  else:
248
+ if v.isdigit():
249
+ q |= models.Q(**{f"{self.field_name}__pk": value})
250
+ continue
245
251
  # Similar to the ContentTypeFilter.filter() call above, but instead of narrowing the query each time
246
252
  # (a AND b AND c ...) we broaden the query each time (a OR b OR c ...).
247
253
  # Specifically, we're mapping a value like ['dcim.device', 'ipam.vlan'] to a query like
@@ -716,6 +722,11 @@ class BaseFilterSet(django_filters.FilterSet):
716
722
  """
717
723
  filters = super().get_filters()
718
724
 
725
+ # Remove any filters that may have been auto-generated from private model attributes
726
+ for filter_name in list(filters.keys()):
727
+ if filter_name.startswith("_"):
728
+ del filters[filter_name]
729
+
719
730
  # django-filters has no concept of "abstract" filtersets, so we have to fake it
720
731
  if cls._meta.model is not None:
721
732
  new_filters = {}
nautobot/core/settings.py CHANGED
@@ -69,7 +69,7 @@ ALLOWED_URL_SCHEMES = [
69
69
  "xmpp",
70
70
  ]
71
71
 
72
- # Banners to display to users. HTML is allowed.
72
+ # Banners to display to users. Markdown and limited HTML are allowed.
73
73
  if "NAUTOBOT_BANNER_BOTTOM" in os.environ and os.environ["NAUTOBOT_BANNER_BOTTOM"] != "":
74
74
  BANNER_BOTTOM = os.environ["NAUTOBOT_BANNER_BOTTOM"]
75
75
  if "NAUTOBOT_BANNER_LOGIN" in os.environ and os.environ["NAUTOBOT_BANNER_LOGIN"] != "":
@@ -686,15 +686,15 @@ CONSTANCE_CONFIG = {
686
686
  ),
687
687
  "BANNER_BOTTOM": ConstanceConfigItem(
688
688
  default="",
689
- help_text="Custom HTML to display in a banner at the bottom of all pages.",
689
+ help_text="Custom Markdown or limited HTML to display in a banner at the bottom of all pages.",
690
690
  ),
691
691
  "BANNER_LOGIN": ConstanceConfigItem(
692
692
  default="",
693
- help_text="Custom HTML to display in a banner at the top of the login page.",
693
+ help_text="Custom Markdown or limited HTML to display in a banner at the top of the login page.",
694
694
  ),
695
695
  "BANNER_TOP": ConstanceConfigItem(
696
696
  default="",
697
- help_text="Custom HTML to display in a banner at the top of all pages.",
697
+ help_text="Custom Markdown or limited HTML to display in a banner at the top of all pages.",
698
698
  ),
699
699
  "CHANGELOG_RETENTION": ConstanceConfigItem(
700
700
  default=90,
@@ -972,6 +972,8 @@ BRANDING_FILEPATHS = {
972
972
  "NAUTOBOT_BRANDING_FILEPATHS_HEADER_BULLET", None
973
973
  ), # bullet image used for various view headers
974
974
  "nav_bullet": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_NAV_BULLET", None), # bullet image used for nav menu headers
975
+ "css": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_CSS", None), # Custom global CSS
976
+ "javascript": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_JAVASCRIPT", None), # Custom global JavaScript
975
977
  }
976
978
 
977
979
  # Title to use in place of "Nautobot"
@@ -128,24 +128,40 @@ properties:
128
128
  type: "array"
129
129
  BANNER_BOTTOM:
130
130
  default: ""
131
- description: "Custom content to be displayed in a banner at the bottom of the page. HTML is allowed."
131
+ description: >-
132
+ Custom content to be displayed in a banner at the bottom of all Nautobot pages.
133
+ details: |-
134
+ +/- 2.2.4
135
+ Markdown formatting is supported within this message, as well as
136
+ [a limited subset of HTML](../../platform-functionality/template-filters.md#render_markdown).
132
137
  environment_variable: "NAUTOBOT_BANNER_BOTTOM"
133
138
  is_constance_config: true
134
139
  type: "string"
135
140
  BANNER_LOGIN:
136
141
  default: ""
137
- description: "Custom content to be displayed on the login page above the login form. HTML is allowed."
142
+ description: >-
143
+ Custom content to be displayed in a banner on the login page above the login form.
144
+ details: |-
145
+ +/- 2.2.4
146
+ Markdown formatting is supported within this message, as well as
147
+ [a limited subset of HTML](../../platform-functionality/template-filters.md#render_markdown).
138
148
  environment_variable: "NAUTOBOT_BANNER_LOGIN"
139
149
  is_constance_config: true
140
150
  type: "string"
141
151
  BANNER_TOP:
142
152
  default: ""
143
- description: "Custom content to be displayed in a banner at the top of the page. HTML is allowed."
153
+ description: >-
154
+ Custom content to be displayed in a banner at the top of all Nautobot pages.
155
+ details: |-
156
+ +/- 2.2.4
157
+ Markdown formatting is supported within this message, as well as
158
+ [a limited subset of HTML](../../platform-functionality/template-filters.md#render_markdown).
144
159
  environment_variable: "NAUTOBOT_BANNER_TOP"
145
160
  is_constance_config: true
146
161
  type: "string"
147
162
  BRANDING_FILEPATHS:
148
163
  default:
164
+ css: null
149
165
  favicon: null
150
166
  header_bullet: null
151
167
  icon_16: null
@@ -153,57 +169,76 @@ properties:
153
169
  icon_180: null
154
170
  icon_192: null
155
171
  icon_mask: null
172
+ javascript: null
156
173
  logo: null
157
174
  nav_bullet: null
158
175
  description: >-
159
- A set of filepaths relative to the [`MEDIA_ROOT`](#media_root) which locate image assets used for
160
- custom branding. Each of these assets takes the place of the corresponding stock Nautobot asset.
176
+ A set of filepaths relative to the [`MEDIA_ROOT`](#media_root) which locate assets used for
177
+ custom branding of your Nautobot instance.
178
+ With the exception of `css` and `javascript`, which provide the option to add an _additional_ file to Nautobot
179
+ page content, each of the other assets takes the place of the corresponding stock Nautobot asset.
161
180
  This allows for, for instance, providing your own navbar logo and favicon.
162
- If a custom image asset is not provided for any of the above options, the stock Nautobot asset is used.
181
+ If a custom asset is not provided for any of the above options, the stock Nautobot asset is used.
182
+ details: |-
183
+ +++ 2.1.0
184
+ The `header_bullet` and `nav_bullet` assets were added as options.
185
+
186
+ +++ 2.2.4
187
+ The `css` and `javascript` assets were added as options.
163
188
  properties:
189
+ css:
190
+ "$ref": "#/definitions/relative_path"
191
+ default: null
192
+ description: "Custom global CSS file"
193
+ environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_CSS"
164
194
  favicon:
165
195
  "$ref": "#/definitions/relative_path"
166
- default: ""
196
+ default: null
167
197
  description: "Browser favicon"
168
198
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_FAVICON"
169
199
  header_bullet:
170
200
  "$ref": "#/definitions/relative_path"
171
- default: ""
201
+ default: null
172
202
  description: "Bullet image used for various view headers"
173
203
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_HEADER_BULLET"
174
204
  icon_16:
175
205
  "$ref": "#/definitions/relative_path"
176
- default: ""
206
+ default: null
177
207
  description: "16x16px icon"
178
208
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_16"
179
209
  icon_180:
180
210
  "$ref": "#/definitions/relative_path"
181
- default: ""
211
+ default: null
182
212
  description: "180x180px icon - used for the apple-touch-icon header"
183
213
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_180"
184
214
  icon_192:
185
215
  "$ref": "#/definitions/relative_path"
186
- default: ""
216
+ default: null
187
217
  description: "192x192px icon"
188
218
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_192"
189
219
  icon_32:
190
220
  "$ref": "#/definitions/relative_path"
191
- default: ""
221
+ default: null
192
222
  description: "32x32px icon"
193
223
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_32"
194
224
  icon_mask:
195
225
  "$ref": "#/definitions/relative_path"
196
- default: ""
226
+ default: null
197
227
  description: "Mono-chrome icon used for the mask-icon header"
198
228
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_ICON_MASK"
229
+ javascript:
230
+ "$ref": "#/definitions/relative_path"
231
+ default: null
232
+ description: "Custom global JavaScript file"
233
+ environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_JAVASCRIPT"
199
234
  logo:
200
235
  "$ref": "#/definitions/relative_path"
201
- default: ""
236
+ default: null
202
237
  description: "Navbar logo"
203
238
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_LOGO"
204
239
  nav_bullet:
205
240
  "$ref": "#/definitions/relative_path"
206
- default: ""
241
+ default: null
207
242
  description: "Bullet image used for nav menu headers"
208
243
  environment_variable: "NAUTOBOT_BRANDING_FILEPATHS_NAV_BULLET"
209
244
  type: "object"
@@ -738,7 +773,7 @@ properties:
738
773
  description: "A mapping of permissions to assign a new user account when created using SSO authentication."
739
774
  details: |-
740
775
  Each key in the dictionary will be the permission name specified as `<app_label>.<action>_<model>`,
741
- and the value should be set to the permission [constraints](../guides/permissions.md#constraints),
776
+ and the value should be set to the permission [constraints](../guides/permissions.md#example-constraint-definitions),
742
777
  or `None` to allow all objects.
743
778
 
744
779
  Example:
@@ -1135,7 +1170,7 @@ properties:
1135
1170
  !!! note
1136
1171
  The Docker container normally attempts to run migrations on startup; however, if the database is
1137
1172
  in a read-only state the Docker container will fail to start. Setting the environment variable
1138
- [`NAUTOBOT_DOCKER_SKIP_INIT`](../installation/docker.md#nautobot_docker_skip_init) to `true`
1173
+ [`NAUTOBOT_DOCKER_SKIP_INIT`](../installation-extras/docker.md#nautobot_docker_skip_init) to `true`
1139
1174
  will prevent the migrations from occurring.
1140
1175
 
1141
1176
  !!! note
@@ -1243,7 +1278,7 @@ properties:
1243
1278
 
1244
1279
  !!! note
1245
1280
  If a given device has an appropriately populated
1246
- [secrets group](../../platform-functionality/secret.md#secretsgroup) assigned to it,
1281
+ [secrets group](../../platform-functionality/secret.md#secrets-groups) assigned to it,
1247
1282
  the [secrets](../../platform-functionality/secret.md) defined in that group will take precedence
1248
1283
  over these default values.
1249
1284
  environment_variable: "NAUTOBOT_NAPALM_PASSWORD"
@@ -1265,7 +1300,7 @@ properties:
1265
1300
 
1266
1301
  !!! note
1267
1302
  If a given device has an appropriately populated
1268
- [secrets group](../../platform-functionality/secret.md#secretsgroup) assigned to it,
1303
+ [secrets group](../../platform-functionality/secret.md#secrets-groups) assigned to it,
1269
1304
  the [secrets](../../platform-functionality/secret.md) defined in that group will take precedence
1270
1305
  over these default values.
1271
1306
  environment_variable: "NAUTOBOT_NAPALM_USERNAME"
@@ -56,7 +56,7 @@
56
56
  {% if not is_popup %}
57
57
  {% if "BANNER_TOP"|settings_or_config %}
58
58
  <div class="alert alert-info text-center" role="alert">
59
- {{ "BANNER_TOP"|settings_or_config|safe }}
59
+ {{ "BANNER_TOP"|settings_or_config|render_markdown }}
60
60
  </div>
61
61
  {% endif %}
62
62
  {% if settings.MAINTENANCE_MODE %}
@@ -107,7 +107,7 @@
107
107
  <div class="push"></div>
108
108
  {% if "BANNER_BOTTOM"|settings_or_config %}
109
109
  <div class="alert alert-info text-center banner-bottom" role="alert">
110
- {{ "BANNER_BOTTOM"|settings_or_config|safe }}
110
+ {{ "BANNER_BOTTOM"|settings_or_config|render_markdown }}
111
111
  </div>
112
112
  {% endif %}
113
113
  </div>
@@ -16,7 +16,7 @@
16
16
  {% if request.user.is_authenticated %}
17
17
  {% if "BANNER_TOP"|settings_or_config %}
18
18
  <div class="alert alert-info text-center" role="alert">
19
- {{ "BANNER_TOP"|settings_or_config|safe }}
19
+ {{ "BANNER_TOP"|settings_or_config|render_markdown }}
20
20
  </div>
21
21
  {% endif %}
22
22
  {% endif %}
@@ -42,7 +42,7 @@
42
42
  {% if request.user.is_authenticated %}
43
43
  {% if "BANNER_BOTTOM"|settings_or_config %}
44
44
  <div class="alert alert-info text-center banner-bottom" role="alert">
45
- {{ "BANNER_BOTTOM"|settings_or_config|safe }}
45
+ {{ "BANNER_BOTTOM"|settings_or_config|render_markdown }}
46
46
  </div>
47
47
  {% endif %}
48
48
  {% endif %}
@@ -1,60 +1,60 @@
1
1
  {% if export_url %}
2
2
  {% if export_templates or include_yaml_option %}
3
- <form style="display: inline-block" action="{{ export_url }}" method="post">
4
- {% csrf_token %}
5
- <input type="hidden" name="content_type" value="{{ content_type.pk }}">
6
- <input type="hidden" name="query_string" value="{{ query_string }}">
7
- <input type="hidden" name="export_format"
8
- value="{% if include_yaml_option %}yaml{% else %}csv{% endif %}">
9
- <input type="hidden" name="_schedule_type" value="immediately">
10
- <div class="btn-group">
11
- <button type="submit" class="btn btn-success">
12
- <span class="mdi mdi-database-export" aria-hidden="true"></span>
13
- Export
14
- </button>
15
- <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
16
- <span class="caret"></span>
17
- <span class="sr-only">Toggle Dropdown</span>
18
- </button>
19
- <ul class="dropdown-menu dropdown-menu-right">
20
- {% if include_yaml_option %}
21
- <li>
22
- <button type="submit" class="btn btn-link">YAML format</button>
23
- </li>
3
+ <div class="btn-group">
4
+ <button type="submit" class="btn btn-success" form="export_default">
5
+ <span class="mdi mdi-database-export" aria-hidden="true"></span>
6
+ Export
7
+ </button>
8
+ <form id="export_default" style="display: inline-block" action="{{ export_url }}" method="post">
9
+ {% csrf_token %}
10
+ <input type="hidden" name="content_type" value="{{ content_type.pk }}">
11
+ <input type="hidden" name="query_string" value="{{ query_string }}">
12
+ <input type="hidden" name="export_format"
13
+ value="{% if include_yaml_option %}yaml{% else %}csv{% endif %}">
14
+ <input type="hidden" name="_schedule_type" value="immediately">
15
+ </form>
16
+ <button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
17
+ <span class="caret"></span>
18
+ <span class="sr-only">Toggle Dropdown</span>
19
+ </button>
20
+ <ul class="dropdown-menu dropdown-menu-right">
21
+ {% if include_yaml_option %}
22
+ <li>
23
+ <button type="submit" class="btn btn-link" form="export_default">YAML format</button>
24
+ </li>
25
+ <li>
26
+ <form action="{{ export_url }}" method="post">
27
+ {% csrf_token %}
28
+ <input type="hidden" name="content_type" value="{{ content_type.pk }}">
29
+ <input type="hidden" name="query_string" value="{{ query_string }}">
30
+ <input type="hidden" name="_schedule_type" value="immediately">
31
+ <button type="submit" class="btn btn-link">CSV format</button>
32
+ </form>
33
+ </li>
34
+ {% else %}
35
+ <li>
36
+ <button type="submit" class="btn btn-link" form="export_default">CSV format</button>
37
+ </li>
38
+ {% endif %}
39
+ {% if export_templates %}
40
+ <li class="divider"></li>
41
+ {% for et in export_templates %}
24
42
  <li>
25
43
  <form action="{{ export_url }}" method="post">
26
44
  {% csrf_token %}
27
45
  <input type="hidden" name="content_type" value="{{ content_type.pk }}">
46
+ <input type="hidden" name="export_template" value="{{ et.pk }}">
28
47
  <input type="hidden" name="query_string" value="{{ query_string }}">
29
48
  <input type="hidden" name="_schedule_type" value="immediately">
30
- <button type="submit" class="btn btn-link">CSV format</button>
49
+ <button type="submit" class="btn btn-link"
50
+ {% if et.description %}title="{{ et.description }}"{% endif %}
51
+ >{{ et.name }}</button>
31
52
  </form>
32
53
  </li>
33
- {% else %}
34
- <li>
35
- <button type="submit" class="btn btn-link">CSV format</button>
36
- </li>
37
- {% endif %}
38
- {% if export_templates %}
39
- <li class="divider"></li>
40
- {% for et in export_templates %}
41
- <li>
42
- <form action="{{ export_url }}" method="post">
43
- {% csrf_token %}
44
- <input type="hidden" name="content_type" value="{{ content_type.pk }}">
45
- <input type="hidden" name="export_template" value="{{ et.pk }}">
46
- <input type="hidden" name="query_string" value="{{ query_string }}">
47
- <input type="hidden" name="_schedule_type" value="immediately">
48
- <button type="submit" class="btn btn-link"
49
- {% if et.description %}title="{{ et.description }}"{% endif %}
50
- >{{ et.name }}</button>
51
- </form>
52
- </li>
53
- {% endfor %}
54
- {% endif %}
55
- </ul>
56
- </div>
57
- </form>
54
+ {% endfor %}
55
+ {% endif %}
56
+ </ul>
57
+ </div>
58
58
  {% else %}
59
59
  <form style="display: inline-block" action="{{ export_url }}" method="post">
60
60
  {% csrf_token %}
@@ -40,3 +40,6 @@
40
40
  hljs.configure({ cssSelector: '.language-graphql, .language-json, .language-xml, .language-yaml' });
41
41
  hljs.highlightAll();
42
42
  </script>
43
+ {% if settings.BRANDING_FILEPATHS.javascript %}
44
+ <script src="{% custom_branding_or_static 'javascript' None %}"></script>
45
+ {% endif %}
@@ -34,6 +34,9 @@
34
34
  <link rel="stylesheet" id="base-theme"
35
35
  href="{% versioned_static 'css/base.css' %}"
36
36
  onerror="window.location='{% url 'media_failure' %}?filename=css/base.css'">
37
+ {% if settings.BRANDING_FILEPATHS.css %}
38
+ <link rel="stylesheet" id="custom-css" href="{% custom_branding_or_static 'css' None %}">
39
+ {% endif %}
37
40
  <link rel="apple-touch-icon" sizes="180x180" href="{% custom_branding_or_static 'icon_180' 'img/nautobot_icon_180x180.png' %}">
38
41
  <link rel="icon" type="image/png" sizes="32x32" href="{% custom_branding_or_static 'icon_32' 'img/nautobot_icon_32x32.png' %}">
39
42
  <link rel="icon" type="image/png" sizes="16x16" href="{% custom_branding_or_static 'icon_16' 'img/nautobot_icon_16x16.png' %}">
@@ -53,8 +53,8 @@
53
53
  <div class="row" style="margin-top: {% if 'BANNER_LOGIN'|settings_or_config %}100{% else %}150{% endif %}px;">
54
54
  <div class="col-sm-4 col-sm-offset-4">
55
55
  {% if "BANNER_LOGIN"|settings_or_config %}
56
- <div style="margin-bottom: 25px">
57
- {{ "BANNER_LOGIN"|settings_or_config|safe }}
56
+ <div class="alert alert-info text-center" role="alert">
57
+ {{ "BANNER_LOGIN"|settings_or_config|render_markdown }}
58
58
  </div>
59
59
  {% endif %}
60
60
  {% if form.non_field_errors %}
@@ -248,6 +248,8 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
248
248
  # "NAUTOBOT_BRANDING_FILEPATHS_HEADER_BULLET", None
249
249
  # ), # bullet image used for various view headers
250
250
  # "nav_bullet": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_NAV_BULLET", None), # bullet image used for nav menu headers
251
+ # "css": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_CSS", None), # Custom global CSS
252
+ # "javascript": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_JAVASCRIPT", None), # Custom global JavaScript
251
253
  # }
252
254
 
253
255
  # Prepended to CSV, YAML and export template filenames (i.e. `nautobot_device.yml`)
@@ -1,12 +1,19 @@
1
1
  import random
2
2
  import string
3
3
 
4
+ from django.contrib.contenttypes.models import ContentType
4
5
  from django.db.models import Count, Q
5
6
  from django.db.models.fields.related import ManyToManyField
6
7
  from django.db.models.fields.reverse_related import ManyToManyRel, ManyToOneRel
7
8
  from django.test import tag
8
9
 
9
- from nautobot.core.filters import RelatedMembershipBooleanFilter, SearchFilter
10
+ from nautobot.core.filters import (
11
+ ContentTypeChoiceFilter,
12
+ ContentTypeFilter,
13
+ ContentTypeMultipleChoiceFilter,
14
+ RelatedMembershipBooleanFilter,
15
+ SearchFilter,
16
+ )
10
17
  from nautobot.core.models.generics import PrimaryModel
11
18
  from nautobot.core.testing import views
12
19
  from nautobot.tenancy import models
@@ -286,6 +293,22 @@ class FilterTestCases:
286
293
  obj, obj_field_name = self._get_nested_related_obj_and_its_field_name(obj, obj_field_name)
287
294
  self._assert_q_filter_predicate_validity(obj, obj_field_name, filter_field_name, lookup_method)
288
295
 
296
+ def test_content_type_related_fields_uses_content_type_filter(self):
297
+ for field in self.queryset.model._meta.fields:
298
+ related_model = getattr(field, "related_model", None)
299
+ if not related_model or related_model != ContentType:
300
+ continue
301
+ with self.subTest(
302
+ f"Assert {self.filterset.__class__.__name__}.{field.name} implements ContentTypeFilter"
303
+ ):
304
+ filter_field = self.filterset.get_filters().get(field.name)
305
+ if not filter_field:
306
+ # This field is not part of the Filterset.
307
+ continue
308
+ self.assertIsInstance(
309
+ filter_field, (ContentTypeFilter, ContentTypeMultipleChoiceFilter, ContentTypeChoiceFilter)
310
+ )
311
+
289
312
  class NameOnlyFilterTestCase(FilterTestCase):
290
313
  """Add simple tests for filtering by name."""
291
314
 
@@ -213,6 +213,8 @@ class ViewTestCases:
213
213
  escape(str(instance.cf.get(custom_field.key) or "")), response_body, msg=response_body
214
214
  )
215
215
 
216
+ return response # for consumption by child test cases if desired
217
+
216
218
  @override_settings(EXEMPT_VIEW_PERMISSIONS=[])
217
219
  def test_get_object_with_constrained_permission(self):
218
220
  instance1, instance2 = self._get_queryset().all()[:2]
@@ -230,11 +232,14 @@ class ViewTestCases:
230
232
  obj_perm.object_types.add(ContentType.objects.get_for_model(self.model))
231
233
 
232
234
  # Try GET to permitted object
233
- self.assertHttpStatus(self.client.get(instance1.get_absolute_url()), 200)
235
+ response = self.client.get(instance1.get_absolute_url())
236
+ self.assertHttpStatus(response, 200)
234
237
 
235
238
  # Try GET to non-permitted object
236
239
  self.assertHttpStatus(self.client.get(instance2.get_absolute_url()), 404)
237
240
 
241
+ return response # for consumption by child test cases if desired
242
+
238
243
  @override_settings(EXEMPT_VIEW_PERMISSIONS=[])
239
244
  def test_has_advanced_tab(self):
240
245
  instance = self._get_queryset().first()
@@ -740,6 +745,13 @@ class ViewTestCases:
740
745
  def get_list_view(self):
741
746
  return lookup.get_view_for_model(self.model, view_type="List")
742
747
 
748
+ def test_list_view_has_filter_form(self):
749
+ view = self.get_list_view()
750
+ if hasattr(view, "filterset_form"): # ObjectListView
751
+ self.assertIsNotNone(view.filterset_form, "List view lacks a FilterForm")
752
+ if hasattr(view, "filterset_form_class"): # ObjectListViewMixin
753
+ self.assertIsNotNone(view.filterset_form_class, "List viewset lacks a FilterForm")
754
+
743
755
  def test_table_with_indentation_is_removed_on_filter_or_sort(self):
744
756
  self.user.is_superuser = True
745
757
  self.user.save()