nautobot 2.4.3__py3-none-any.whl → 2.4.4__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.
Files changed (175) hide show
  1. nautobot/apps/filters.py +2 -0
  2. nautobot/circuits/filters.py +1 -1
  3. nautobot/circuits/tests/test_models.py +5 -3
  4. nautobot/cloud/filters.py +3 -6
  5. nautobot/cloud/tests/test_filters.py +21 -0
  6. nautobot/core/admin.py +2 -0
  7. nautobot/core/jobs/__init__.py +2 -1
  8. nautobot/core/management/commands/generate_performance_test_endpoints.py +9 -6
  9. nautobot/core/models/utils.py +6 -1
  10. nautobot/core/templates/inc/javascript.html +1 -0
  11. nautobot/core/templatetags/ui_framework.py +20 -4
  12. nautobot/core/testing/forms.py +1 -1
  13. nautobot/core/tests/test_api.py +1 -1
  14. nautobot/core/tests/test_graphql.py +3 -3
  15. nautobot/core/tests/test_jobs.py +4 -1
  16. nautobot/core/ui/object_detail.py +1 -1
  17. nautobot/dcim/api/serializers.py +36 -0
  18. nautobot/dcim/api/views.py +1 -1
  19. nautobot/dcim/elevations.py +17 -4
  20. nautobot/dcim/factory.py +9 -1
  21. nautobot/dcim/filters/__init__.py +27 -1
  22. nautobot/dcim/forms.py +13 -1
  23. nautobot/dcim/models/devices.py +11 -5
  24. nautobot/dcim/signals.py +26 -0
  25. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +0 -62
  26. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +6 -0
  27. nautobot/dcim/tests/test_api.py +176 -0
  28. nautobot/dcim/tests/test_filters.py +56 -3
  29. nautobot/dcim/tests/test_models.py +40 -0
  30. nautobot/dcim/views.py +24 -14
  31. nautobot/extras/api/mixins.py +1 -1
  32. nautobot/extras/api/views.py +2 -2
  33. nautobot/extras/filters/__init__.py +4 -0
  34. nautobot/extras/models/datasources.py +7 -3
  35. nautobot/extras/plugins/__init__.py +26 -1
  36. nautobot/extras/templates/extras/inc/jobresult.html +12 -13
  37. nautobot/extras/templates/extras/objectchange.html +28 -12
  38. nautobot/extras/tests/test_api.py +16 -15
  39. nautobot/extras/tests/test_filters.py +2 -0
  40. nautobot/extras/tests/test_plugins.py +32 -1
  41. nautobot/extras/tests/test_views.py +12 -2
  42. nautobot/extras/views.py +3 -0
  43. nautobot/ipam/api/serializers.py +7 -8
  44. nautobot/ipam/api/views.py +2 -2
  45. nautobot/ipam/factory.py +27 -8
  46. nautobot/ipam/filters.py +67 -29
  47. nautobot/ipam/formfields.py +51 -0
  48. nautobot/ipam/forms.py +13 -1
  49. nautobot/ipam/migrations/0051_added_optional_vrf_relationship_to_vdc.py +41 -0
  50. nautobot/ipam/models.py +63 -5
  51. nautobot/ipam/tables.py +21 -7
  52. nautobot/ipam/tests/test_api.py +107 -66
  53. nautobot/ipam/tests/test_filters.py +145 -5
  54. nautobot/ipam/tests/test_views.py +15 -2
  55. nautobot/project-static/css/base.css +11 -0
  56. nautobot/project-static/css/dark.css +2 -1
  57. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +62 -0
  58. nautobot/project-static/docs/development/apps/api/configuration-view.html +0 -3
  59. nautobot/project-static/docs/development/apps/api/models/graphql.html +0 -4
  60. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +94 -1
  61. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +0 -3
  62. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +0 -3
  63. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +0 -3
  64. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +0 -3
  65. nautobot/project-static/docs/development/apps/api/prometheus.html +0 -3
  66. nautobot/project-static/docs/development/apps/api/testing.html +0 -6
  67. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +0 -3
  68. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +0 -3
  69. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +0 -3
  70. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +0 -3
  71. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +1 -7
  72. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +0 -7
  73. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +0 -4
  74. nautobot/project-static/docs/development/apps/api/views/notes.html +0 -3
  75. nautobot/project-static/docs/development/apps/index.html +2 -35
  76. nautobot/project-static/docs/development/apps/migration/code-updates.html +1 -1
  77. nautobot/project-static/docs/development/core/application-registry.html +0 -6
  78. nautobot/project-static/docs/development/core/best-practices.html +0 -27
  79. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +58 -4
  80. nautobot/project-static/docs/development/core/getting-started.html +12 -16
  81. nautobot/project-static/docs/development/core/homepage.html +0 -3
  82. nautobot/project-static/docs/development/core/style-guide.html +0 -5
  83. nautobot/project-static/docs/development/core/templates.html +0 -3
  84. nautobot/project-static/docs/development/core/testing.html +0 -9
  85. nautobot/project-static/docs/development/jobs/index.html +3 -29
  86. nautobot/project-static/docs/objects.inv +0 -0
  87. nautobot/project-static/docs/overview/application_stack.html +0 -18
  88. nautobot/project-static/docs/release-notes/version-2.4.html +191 -0
  89. nautobot/project-static/docs/requirements.txt +1 -1
  90. nautobot/project-static/docs/search/search_index.json +1 -1
  91. nautobot/project-static/docs/sitemap.xml +290 -290
  92. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  93. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +0 -10
  94. nautobot/project-static/docs/user-guide/administration/guides/docker.html +0 -15
  95. nautobot/project-static/docs/user-guide/administration/installation/index.html +0 -16
  96. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +1 -4
  97. nautobot/project-static/docs/user-guide/administration/installation/services.html +0 -11
  98. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +3 -3
  99. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +5 -35
  100. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-location-changes.yaml +1 -1
  101. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +1 -1
  102. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +0 -4
  103. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +0 -3
  104. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +0 -4
  105. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +0 -4
  106. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +0 -4
  107. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +0 -4
  108. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +0 -4
  109. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +0 -4
  110. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +0 -3
  111. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +0 -4
  112. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +0 -4
  113. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +0 -4
  114. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +1 -17
  115. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +0 -3
  116. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +0 -4
  117. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +0 -4
  118. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +0 -3
  119. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +1 -7
  120. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +0 -4
  121. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +0 -4
  122. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +0 -4
  123. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +0 -4
  124. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +0 -4
  125. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +0 -4
  126. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +0 -4
  127. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +0 -6
  128. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +0 -3
  129. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +0 -4
  130. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +0 -4
  131. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +0 -8
  132. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +3 -3
  133. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +0 -6
  134. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +0 -3
  135. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +3 -15
  136. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +0 -26
  137. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +0 -8
  138. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +0 -3
  139. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +0 -8
  140. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +0 -7
  141. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +0 -3
  142. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +0 -3
  143. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +0 -14
  144. nautobot/project-static/docs/user-guide/platform-functionality/note.html +0 -3
  145. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +1 -10
  146. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +0 -3
  147. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +0 -14
  148. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +0 -19
  149. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +3 -9
  150. nautobot/project-static/docs/user-guide/platform-functionality/status.html +0 -8
  151. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +0 -4
  152. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +1 -13
  153. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +0 -5
  154. nautobot/project-static/js/editor.js +292 -0
  155. nautobot/project-static/monaco-editor-0.52.2/README.md +81 -0
  156. nautobot/project-static/monaco-editor-0.52.2/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  157. nautobot/project-static/monaco-editor-0.52.2/vs/base/worker/workerMain.js +31 -0
  158. nautobot/project-static/monaco-editor-0.52.2/vs/basic-languages/xml/xml.js +10 -0
  159. nautobot/project-static/monaco-editor-0.52.2/vs/basic-languages/yaml/yaml.js +10 -0
  160. nautobot/project-static/monaco-editor-0.52.2/vs/editor/editor.main.css +8 -0
  161. nautobot/project-static/monaco-editor-0.52.2/vs/editor/editor.main.js +798 -0
  162. nautobot/project-static/monaco-editor-0.52.2/vs/language/json/jsonMode.js +19 -0
  163. nautobot/project-static/monaco-editor-0.52.2/vs/language/json/jsonWorker.js +42 -0
  164. nautobot/project-static/monaco-editor-0.52.2/vs/loader.js +11 -0
  165. nautobot/tenancy/filters/__init__.py +3 -5
  166. nautobot/tenancy/tests/test_filters.py +10 -0
  167. nautobot/virtualization/views.py +0 -1
  168. nautobot/wireless/tables.py +9 -4
  169. nautobot/wireless/tests/test_api.py +0 -9
  170. {nautobot-2.4.3.dist-info → nautobot-2.4.4.dist-info}/METADATA +2 -2
  171. {nautobot-2.4.3.dist-info → nautobot-2.4.4.dist-info}/RECORD +175 -163
  172. {nautobot-2.4.3.dist-info → nautobot-2.4.4.dist-info}/LICENSE.txt +0 -0
  173. {nautobot-2.4.3.dist-info → nautobot-2.4.4.dist-info}/NOTICE +0 -0
  174. {nautobot-2.4.3.dist-info → nautobot-2.4.4.dist-info}/WHEEL +0 -0
  175. {nautobot-2.4.3.dist-info → nautobot-2.4.4.dist-info}/entry_points.txt +0 -0
@@ -21,7 +21,8 @@ html[data-theme="dark"] .color-block, /* Colored choices, li
21
21
  html[data-theme="dark"] .select2-selection__choice, /* Colored choices, like statuses */
22
22
  html[data-theme="dark"] #select2-id_color-results, /* Colored choices, like statuses */
23
23
  html[data-theme="dark"] #select2-id_color-container, /* Colored choices, like statuses */
24
- html[data-theme="dark"] .hljs { /* highlight.js maintains its own dark theme */
24
+ html[data-theme="dark"] .hljs, /* highlight.js maintains its own dark theme */
25
+ html[data-theme="dark"] .editor-container { /* Monaco editor maintains its own dark theme */
25
26
  filter: invert(1) hue-rotate(180deg);
26
27
  }
27
28
 
@@ -7487,6 +7487,15 @@
7487
7487
  </span>
7488
7488
  </a>
7489
7489
 
7490
+ </li>
7491
+
7492
+ <li class="md-nav__item">
7493
+ <a href="#nautobot.apps.filters.PrefixFilter" class="md-nav__link">
7494
+ <span class="md-ellipsis">
7495
+ PrefixFilter
7496
+ </span>
7497
+ </a>
7498
+
7490
7499
  </li>
7491
7500
 
7492
7501
  <li class="md-nav__item">
@@ -9724,6 +9733,15 @@
9724
9733
  </span>
9725
9734
  </a>
9726
9735
 
9736
+ </li>
9737
+
9738
+ <li class="md-nav__item">
9739
+ <a href="#nautobot.apps.filters.PrefixFilter" class="md-nav__link">
9740
+ <span class="md-ellipsis">
9741
+ PrefixFilter
9742
+ </span>
9743
+ </a>
9744
+
9727
9745
  </li>
9728
9746
 
9729
9747
  <li class="md-nav__item">
@@ -10755,6 +10773,50 @@ are needed.</p>
10755
10773
 
10756
10774
 
10757
10775
 
10776
+ </div>
10777
+
10778
+ </div>
10779
+
10780
+ </div>
10781
+
10782
+ <div class="doc doc-object doc-class">
10783
+
10784
+
10785
+
10786
+ <h2 id="nautobot.apps.filters.PrefixFilter" class="doc doc-heading">
10787
+ <code>nautobot.apps.filters.PrefixFilter</code>
10788
+
10789
+
10790
+ <a href="#nautobot.apps.filters.PrefixFilter" class="headerlink" title="Permanent link">&para;</a></h2>
10791
+
10792
+
10793
+ <div class="doc doc-contents ">
10794
+ <p class="doc doc-class-bases">
10795
+ Bases: <code><a class="autorefs autorefs-internal" title="nautobot.core.filters.NaturalKeyOrPKMultipleChoiceFilter" href="#nautobot.apps.filters.NaturalKeyOrPKMultipleChoiceFilter">NaturalKeyOrPKMultipleChoiceFilter</a></code></p>
10796
+
10797
+
10798
+ <p>Filter that supports filtering a foreign key to Prefix by either its PK or by a literal <code>prefix</code> string.</p>
10799
+
10800
+
10801
+
10802
+
10803
+
10804
+
10805
+
10806
+
10807
+
10808
+ <div class="doc doc-children">
10809
+
10810
+
10811
+
10812
+
10813
+
10814
+
10815
+
10816
+
10817
+
10818
+
10819
+
10758
10820
  </div>
10759
10821
 
10760
10822
  </div>
@@ -9122,9 +9122,6 @@
9122
9122
 
9123
9123
 
9124
9124
  <h1 id="adding-links-to-the-installed-apps-view">Adding Links to the Installed Apps View<a class="headerlink" href="#adding-links-to-the-installed-apps-view" title="Permanent link">&para;</a></h1>
9125
- <details class="version-added">
9126
- <summary>Added in version 1.2.0</summary>
9127
- </details>
9128
9125
  <p>It's common for many apps to provide an "app configuration" <a href="views/index.html">view</a> used for interactive configuration of aspects of the app that don't necessarily need to be managed by a system administrator via <code>PLUGINS_CONFIG</code>. The <code>NautobotAppConfig</code> setting of <code>config_view_name</code> lets you provide the URL pattern name defined for this view, which will then be accessible via a button on the <strong>Apps -&gt; Installed Apps</strong> UI view.</p>
9129
9126
  <p>For example, if the <code>animal_sounds</code> app provides a configuration view, which is set up in <code>urls.py</code> as follows:</p>
9130
9127
  <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="c1"># urls.py</span>
@@ -9245,10 +9245,6 @@
9245
9245
  <a id="__codelineno-0-15" name="__codelineno-0-15" href="#__codelineno-0-15"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
9246
9246
  </code></pre></div>
9247
9247
  <h2 id="creating-your-own-graphql-type-object">Creating Your Own GraphQL Type Object<a class="headerlink" href="#creating-your-own-graphql-type-object" title="Permanent link">&para;</a></h2>
9248
- <details class="version-changed">
9249
- <summary>Changed in version 1.6.2</summary>
9250
- <p>A new base class was introduced for Nautobot GraphQL object types: <code>nautobot.core.graphql.types.OptimizedNautobotObjectType</code>. This class inherits from <code>graphene_django_optimizer.OptimizedDjangoObjectType</code> and adds generic Nautobot specific functionality.</p>
9251
- </details>
9252
9248
  <p>In some cases, such as when a model is using Generic Foreign Keys, or when a model has constructed fields that should also be reflected in GraphQL, the default GraphQL type definition generated by the <code>@extras_features</code> decorator may not work as the developer intends, and it will be preferable to provide custom GraphQL types.</p>
9253
9249
  <p>By default, Nautobot looks for custom GraphQL types in an iterable named <code>graphql_types</code> within a <code>graphql/types.py</code> file. (This can be overridden by setting <code>graphql_types</code> to a custom value on the app's <code>NautobotAppConfig</code>.) Each type defined in this way must be a class inheriting from <code>graphene_django.DjangoObjectType</code>, <code>graphene_django_optimizer.OptimizedDjangoObjectType</code>, or <code>nautobot.core.graphql.types.OptimizedNautobotObjectType</code> and must follow the <a href="https://docs.graphene-python.org/projects/django/en/latest/queries/">standards defined by <code>graphene-django</code></a>.</p>
9254
9250
  <p>Nautobot uses a library called <a href="https://github.com/tfoxy/graphene-django-optimizer"><code>graphene-django-optimizer</code></a> to decrease the time queries take to process. By inheriting from <code>graphene_django_optimizer</code> type classes are automatically optimized.</p>
@@ -6534,6 +6534,17 @@
6534
6534
 
6535
6535
 
6536
6536
 
6537
+ <label class="md-nav__link md-nav__link--active" for="__toc">
6538
+
6539
+
6540
+ <span class="md-ellipsis">
6541
+ Custom Validators
6542
+ </span>
6543
+
6544
+
6545
+ <span class="md-nav__icon md-icon"></span>
6546
+ </label>
6547
+
6537
6548
  <a href="custom-validators.html" class="md-nav__link md-nav__link--active">
6538
6549
 
6539
6550
 
@@ -6544,6 +6555,34 @@
6544
6555
 
6545
6556
  </a>
6546
6557
 
6558
+
6559
+
6560
+ <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
6561
+
6562
+
6563
+
6564
+
6565
+
6566
+
6567
+ <label class="md-nav__title" for="__toc">
6568
+ <span class="md-nav__icon md-icon"></span>
6569
+ Table of contents
6570
+ </label>
6571
+ <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
6572
+
6573
+ <li class="md-nav__item">
6574
+ <a href="#user-context" class="md-nav__link">
6575
+ <span class="md-ellipsis">
6576
+ User Context
6577
+ </span>
6578
+ </a>
6579
+
6580
+ </li>
6581
+
6582
+ </ul>
6583
+
6584
+ </nav>
6585
+
6547
6586
  </li>
6548
6587
 
6549
6588
 
@@ -9105,6 +9144,23 @@
9105
9144
 
9106
9145
 
9107
9146
 
9147
+ <label class="md-nav__title" for="__toc">
9148
+ <span class="md-nav__icon md-icon"></span>
9149
+ Table of contents
9150
+ </label>
9151
+ <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
9152
+
9153
+ <li class="md-nav__item">
9154
+ <a href="#user-context" class="md-nav__link">
9155
+ <span class="md-ellipsis">
9156
+ User Context
9157
+ </span>
9158
+ </a>
9159
+
9160
+ </li>
9161
+
9162
+ </ul>
9163
+
9108
9164
  </nav>
9109
9165
  </div>
9110
9166
  </div>
@@ -9124,7 +9180,7 @@
9124
9180
  <h1 id="implementing-custom-validators">Implementing Custom Validators<a class="headerlink" href="#implementing-custom-validators" title="Permanent link">&para;</a></h1>
9125
9181
  <p>Apps can register custom validator classes which implement model validation logic to be executed during a model's <code>clean()</code> method. Like template extensions, custom validators are registered to a single model and offer a method which app authors override to implement their validation logic. This is accomplished by subclassing <code>CustomValidator</code> and implementing the <code>clean()</code> method.</p>
9126
9182
  <p>App authors must raise <code>django.core.exceptions.ValidationError</code> within the <code>clean()</code> method to trigger validation error messages which are propagated to the user and prevent saving of the model instance. A convenience method <code>validation_error()</code> may be used to simplify this process. Raising a <code>ValidationError</code> is no different than vanilla Django, and the convenience method will simply pass the provided message through to the exception.</p>
9127
- <p>When a CustomValidator is instantiated, the model instance is assigned to context dictionary using the <code>object</code> key, much like TemplateExtension. E.g. <code>self.context['object']</code>.</p>
9183
+ <p>When a CustomValidator is instantiated, the model instance is assigned to context dictionary using the <code>object</code> key, much like TemplateExtension. E.g. <code>self.context['object']</code>. The context is also populated with the current request user object. E.g. <code>self.context['user']</code>.</p>
9128
9184
  <p>Declared subclasses should be gathered into a list or tuple for integration with Nautobot. By default, Nautobot looks for an iterable named <code>custom_validators</code> within a <code>custom_validators.py</code> file. (This can be overridden by setting <code>custom_validators</code> to a custom value on the app's <code>NautobotAppConfig</code>.) An example is below.</p>
9129
9185
  <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="c1"># custom_validators.py</span>
9130
9186
  <a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="kn">from</span> <span class="nn">nautobot.apps.models</span> <span class="kn">import</span> <span class="n">CustomValidator</span>
@@ -9145,6 +9201,43 @@
9145
9201
  <a id="__codelineno-0-17" name="__codelineno-0-17" href="#__codelineno-0-17"></a>
9146
9202
  <a id="__codelineno-0-18" name="__codelineno-0-18" href="#__codelineno-0-18"></a><span class="n">custom_validators</span> <span class="o">=</span> <span class="p">[</span><span class="n">LocationValidator</span><span class="p">]</span>
9147
9203
  </code></pre></div>
9204
+ <h2 id="user-context">User Context<a class="headerlink" href="#user-context" title="Permanent link">&para;</a></h2>
9205
+ <details class="version-added">
9206
+ <summary>Added in version 2.4.4</summary>
9207
+ </details>
9208
+ <p>Custom validators have access to the current user via <code>self.context['user']</code> whenever the custom validator is invoked within a web request context. This is true for any Web UI, REST API request, Job execution, and anytime the <code>web_request_context</code> context manager is used in <code>nbshell</code> or a out of band script. In the event a custom validator is run outside of a web request context, <code>self.context['user']</code> will be populated with an instance of <code>AnonymousUser</code> from <code>django.contrib.auth</code>. This allows a custom validator author to write code that is durable to cases where a real user is not available.</p>
9209
+ <p>With the user object, you can inspect the groups and permissions that the user has, allowing more granular access related validation.</p>
9210
+ <p>This example shows a custom validator that only allows users in the group "Tenant Managers" to change the tenant of a location:</p>
9211
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a><span class="c1"># custom_validators.py</span>
9212
+ <a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a><span class="kn">from</span> <span class="nn">nautobot.apps.models</span> <span class="kn">import</span> <span class="n">CustomValidator</span>
9213
+ <a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a>
9214
+ <a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a>
9215
+ <a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a><span class="k">class</span> <span class="nc">LocationTenantValidator</span><span class="p">(</span><span class="n">CustomValidator</span><span class="p">):</span>
9216
+ <a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a><span class="w"> </span><span class="sd">&quot;&quot;&quot;Custom validator for Locations to enforce that only some users can update the Tenant.&quot;&quot;&quot;</span>
9217
+ <a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a>
9218
+ <a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a> <span class="n">model</span> <span class="o">=</span> <span class="s1">&#39;dcim.location&#39;</span>
9219
+ <a id="__codelineno-1-9" name="__codelineno-1-9" href="#__codelineno-1-9"></a>
9220
+ <a id="__codelineno-1-10" name="__codelineno-1-10" href="#__codelineno-1-10"></a> <span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
9221
+ <a id="__codelineno-1-11" name="__codelineno-1-11" href="#__codelineno-1-11"></a> <span class="n">new_object_state</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="p">[</span><span class="s2">&quot;object&quot;</span><span class="p">]</span>
9222
+ <a id="__codelineno-1-12" name="__codelineno-1-12" href="#__codelineno-1-12"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">new_object_state</span><span class="o">.</span><span class="n">present_in_database</span><span class="p">:</span>
9223
+ <a id="__codelineno-1-13" name="__codelineno-1-13" href="#__codelineno-1-13"></a> <span class="c1"># This is a brand new Location, so skip the rest of the checks here</span>
9224
+ <a id="__codelineno-1-14" name="__codelineno-1-14" href="#__codelineno-1-14"></a> <span class="k">return</span>
9225
+ <a id="__codelineno-1-15" name="__codelineno-1-15" href="#__codelineno-1-15"></a>
9226
+ <a id="__codelineno-1-16" name="__codelineno-1-16" href="#__codelineno-1-16"></a> <span class="c1"># Get a copy of the object as it currently exists in the database</span>
9227
+ <a id="__codelineno-1-17" name="__codelineno-1-17" href="#__codelineno-1-17"></a> <span class="n">current_object_state</span> <span class="o">=</span> <span class="n">new_object_state</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">new_object_state</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
9228
+ <a id="__codelineno-1-18" name="__codelineno-1-18" href="#__codelineno-1-18"></a>
9229
+ <a id="__codelineno-1-19" name="__codelineno-1-19" href="#__codelineno-1-19"></a> <span class="c1"># Compare the tenant values between the two states</span>
9230
+ <a id="__codelineno-1-20" name="__codelineno-1-20" href="#__codelineno-1-20"></a> <span class="k">if</span> <span class="n">new_object_state</span><span class="o">.</span><span class="n">tenant</span> <span class="o">!=</span> <span class="n">current_object_state</span><span class="o">.</span><span class="n">tenant</span><span class="p">:</span>
9231
+ <a id="__codelineno-1-21" name="__codelineno-1-21" href="#__codelineno-1-21"></a>
9232
+ <a id="__codelineno-1-22" name="__codelineno-1-22" href="#__codelineno-1-22"></a> <span class="c1"># Check if the user has permission to change the tenant, via being a member of &quot;Tenant Managers&quot;</span>
9233
+ <a id="__codelineno-1-23" name="__codelineno-1-23" href="#__codelineno-1-23"></a> <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="p">[</span><span class="s2">&quot;user&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">groups</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;Tenant Managers&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
9234
+ <a id="__codelineno-1-24" name="__codelineno-1-24" href="#__codelineno-1-24"></a> <span class="bp">self</span><span class="o">.</span><span class="n">validation_error</span><span class="p">({</span>
9235
+ <a id="__codelineno-1-25" name="__codelineno-1-25" href="#__codelineno-1-25"></a> <span class="s2">&quot;tenant&quot;</span><span class="p">:</span> <span class="s2">&quot;You do not have permission to change the tenant&quot;</span>
9236
+ <a id="__codelineno-1-26" name="__codelineno-1-26" href="#__codelineno-1-26"></a> <span class="p">})</span>
9237
+ <a id="__codelineno-1-27" name="__codelineno-1-27" href="#__codelineno-1-27"></a>
9238
+ <a id="__codelineno-1-28" name="__codelineno-1-28" href="#__codelineno-1-28"></a>
9239
+ <a id="__codelineno-1-29" name="__codelineno-1-29" href="#__codelineno-1-29"></a><span class="n">custom_validators</span> <span class="o">=</span> <span class="p">[</span><span class="n">LocationTenantValidator</span><span class="p">]</span>
9240
+ </code></pre></div>
9148
9241
 
9149
9242
 
9150
9243
 
@@ -9122,9 +9122,6 @@
9122
9122
 
9123
9123
 
9124
9124
  <h1 id="extending-filters">Extending Filters<a class="headerlink" href="#extending-filters" title="Permanent link">&para;</a></h1>
9125
- <details class="version-added">
9126
- <summary>Added in version 1.3.0</summary>
9127
- </details>
9128
9125
  <p>Apps can extend any model-based <code>FilterSet</code> and <code>FilterForm</code> classes that are provided by the Nautobot core.</p>
9129
9126
  <p>The requirements to extend a filter set or a filter form (or both) are:</p>
9130
9127
  <ul>
@@ -9122,9 +9122,6 @@
9122
9122
 
9123
9123
 
9124
9124
  <h1 id="adding-jinja2-filters">Adding Jinja2 Filters<a class="headerlink" href="#adding-jinja2-filters" title="Permanent link">&para;</a></h1>
9125
- <details class="version-added">
9126
- <summary>Added in version 1.1.0</summary>
9127
- </details>
9128
9125
  <p>Apps can define custom Jinja2 filters to be used when rendering templates defined in computed fields. Check out the <a href="https://jinja.palletsprojects.com/en/3.0.x/api/#custom-filters">official Jinja2 documentation</a> on how to create filter functions.</p>
9129
9126
  <p>In the file that defines your filters (by default <code>jinja_filters.py</code>, but configurable in the <code>NautobotAppConfig</code> if desired), you must import the <code>library</code> module from the <code>django_jinja</code> library. Filters must then be decorated with <code>@library.filter</code>. See an example below that defines a filter called <code>leet_speak</code>.</p>
9130
9127
  <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">from</span> <span class="nn">django_jinja</span> <span class="kn">import</span> <span class="n">library</span>
@@ -9122,9 +9122,6 @@
9122
9122
 
9123
9123
 
9124
9124
  <h1 id="populating-extensibility-features">Populating Extensibility Features<a class="headerlink" href="#populating-extensibility-features" title="Permanent link">&para;</a></h1>
9125
- <details class="version-added">
9126
- <summary>Added in version 1.2.0</summary>
9127
- </details>
9128
9125
  <p>In many cases, an app may wish to make use of Nautobot's various extensibility features, such as <a href="../../../../user-guide/platform-functionality/customfield.html">custom fields</a> or <a href="../../../../user-guide/platform-functionality/relationship.html">relationships</a>. It can be useful for an app to automatically create a custom field definition or relationship definition as a consequence of being installed and activated, so that everyday usage of the app can rely upon these definitions to be present.</p>
9129
9126
  <p>To make this possible, Nautobot provides a custom <a href="https://docs.djangoproject.com/en/stable/topics/signals/">signal</a>, <code>nautobot_database_ready</code>, that apps can register to listen for. This signal is triggered when <code>nautobot-server migrate</code> or <code>nautobot-server post_upgrade</code> is run after installing an app, and provides an opportunity for the app to make any desired additions to the database at this time.</p>
9130
9127
  <p>For example, maybe we want our app to make use of a Relationship allowing each Location to be linked to our Animal model. We would define our callback function that makes sure this Relationship exists, by convention in a <code>signals.py</code> file:</p>
@@ -9122,9 +9122,6 @@
9122
9122
 
9123
9123
 
9124
9124
  <h1 id="implementing-secrets-providers">Implementing Secrets Providers<a class="headerlink" href="#implementing-secrets-providers" title="Permanent link">&para;</a></h1>
9125
- <details class="version-added">
9126
- <summary>Added in version 1.2.0</summary>
9127
- </details>
9128
9125
  <p>An app can define and register additional providers (sources) for <a href="../../../../user-guide/platform-functionality/secret.html">Secrets</a>, allowing Nautobot to retrieve secret values from additional systems or data sources. By default, Nautobot looks for an iterable named <code>secrets_providers</code> within a <code>secrets.py</code> file. (This can be overridden by setting <code>secrets_providers</code> to a custom value on the app's <code>NautobotAppConfig</code>.)</p>
9129
9126
  <p>To define a new <code>SecretsProvider</code> subclass, we must specify the following:</p>
9130
9127
  <ul>
@@ -9122,9 +9122,6 @@
9122
9122
 
9123
9123
 
9124
9124
  <h1 id="prometheus-metrics">Prometheus Metrics<a class="headerlink" href="#prometheus-metrics" title="Permanent link">&para;</a></h1>
9125
- <details class="version-added">
9126
- <summary>Added in version 1.5.13</summary>
9127
- </details>
9128
9125
  <p>It is possible for Nautobot apps to provide their own <a href="../../../user-guide/administration/guides/prometheus-metrics.html">Prometheus metrics</a>. There are two general ways to achieve this:</p>
9129
9126
  <ol>
9130
9127
  <li>Use the <code>prometheus_client</code> library directly in your app code. Depending on whether that code runs in the web server or the worker context, the metric will show up in the respective <code>/metrics</code> endpoint(s) (i.e. metrics generated in the worker context show up in the worker's endpoint and those generated in the web application's context show up in the web application's endpoint).</li>
@@ -9232,14 +9232,8 @@
9232
9232
  <h1 id="testing-apps">Testing Apps<a class="headerlink" href="#testing-apps" title="Permanent link">&para;</a></h1>
9233
9233
  <p>In general apps can be tested like other Django apps. In most cases you'll want to run your automated tests via the <code>nautobot-server test &lt;app_module&gt;</code> command or, if using the <code>coverage</code> Python library, <code>coverage run --module nautobot.core.cli test &lt;app_module&gt;</code>.</p>
9234
9234
  <h2 id="factories">Factories<a class="headerlink" href="#factories" title="Permanent link">&para;</a></h2>
9235
- <details class="version-added">
9236
- <summary>Added in version 1.5.0</summary>
9237
- </details>
9238
9235
  <p>The <a href="../../../user-guide/administration/configuration/settings.html#test_use_factories"><code>TEST_USE_FACTORIES</code></a> setting defaults to <code>False</code> when testing apps, primarily for backwards-compatibility reasons. It can prove a useful way of populating a baseline of Nautobot database data for your tests and save you the trouble of creating a large amount of baseline data yourself. We recommend adding <a href="https://pypi.org/project/factory-boy/"><code>factory-boy</code></a> to your app's development dependencies and settings <code>TEST_USE_FACTORIES = True</code> in your app's development/test <code>nautobot_config.py</code> to take advantage of this.</p>
9239
9236
  <h2 id="performance-tests">Performance Tests<a class="headerlink" href="#performance-tests" title="Permanent link">&para;</a></h2>
9240
- <details class="version-added">
9241
- <summary>Added in version 1.5.0</summary>
9242
- </details>
9243
9237
  <h2 id="running-performance-tests">Running Performance Tests<a class="headerlink" href="#running-performance-tests" title="Permanent link">&para;</a></h2>
9244
9238
  <p>You need to install <code>django-slowtests</code> as a part of your app dev dependency to run performance tests. It has a very intuitive way to measure the performance of your own tests for your app (all you have to do is tag your tests with <code>performance</code>) and do <code>invoke performance-test</code> to get the time to run your tests with <code>NautobotPerformanceTestRunner</code>.</p>
9245
9239
  <p><code>NautobotPerformanceTestRunner</code> is used by adding the flag <code>--testrunner nautobot.core.tests.runner.NautobotPerformanceTestRunner</code> to the <code>coverage run</code> command used for unit tests. This flag will replace the default <code>NautobotTestRunner</code> while retaining all its functionalities with the addition of performance evaluation after test
@@ -9122,9 +9122,6 @@
9122
9122
 
9123
9123
 
9124
9124
  <h1 id="adding-a-banner">Adding a Banner<a class="headerlink" href="#adding-a-banner" title="Permanent link">&para;</a></h1>
9125
- <details class="version-added">
9126
- <summary>Added in version 1.2.0</summary>
9127
- </details>
9128
9125
  <p>An app can provide a function that renders a custom banner on any number of Nautobot views. By default Nautobot looks for a function <code>banner()</code> inside of <code>banner.py</code>. (This can be overridden by setting <code>banner_function</code> to a custom value on the app's <code>NautobotAppConfig</code>.)</p>
9129
9126
  <p>This function currently receives a single argument, <code>context</code>, which is the <a href="https://docs.djangoproject.com/en/stable/ref/templates/api/#using-requestcontext">Django request context</a> in which the current page is being rendered. The function can return <code>None</code> if no banner is needed for a given page view, or can return a <code>Banner</code> object describing the banner contents. Here's a simple example <code>banner.py</code>:</p>
9130
9127
  <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="c1"># banner.py</span>
@@ -9122,9 +9122,6 @@
9122
9122
 
9123
9123
 
9124
9124
  <h1 id="adding-home-page-content">Adding Home Page Content<a class="headerlink" href="#adding-home-page-content" title="Permanent link">&para;</a></h1>
9125
- <details class="version-added">
9126
- <summary>Added in version 1.2.0</summary>
9127
- </details>
9128
9125
  <p>Apps can add content to the Nautobot home page. By default, Nautobot looks for a <code>layout</code> list inside of <code>homepage.py</code>. (This can be overridden by setting <code>homepage_layout</code> to a custom value on the app's <code>NautobotAppConfig</code>.)</p>
9129
9126
  <p>Using a key and weight system, a developer can integrate the app content amongst existing panels, groups, and items and/or create entirely new panels as desired.</p>
9130
9127
  <p>More documentation and examples can be found in the guide on <a href="../../../core/homepage.html">Home Page Panels</a>.</p>
@@ -9457,9 +9457,6 @@
9457
9457
  </code></pre></div>
9458
9458
  <p>Note that a <code>Tab</code> defines its contents directly (as <code>panels</code>) while the <code>DistinctViewTab</code> instead provides a <code>url_name</code> to the related URL that it should link against.</p>
9459
9459
  <h3 id="via-detail_tabs-deprecated">Via <code>detail_tabs()</code> (Deprecated)<a class="headerlink" href="#via-detail_tabs-deprecated" title="Permanent link">&para;</a></h3>
9460
- <details class="version-added">
9461
- <summary>Added in version 1.4.0</summary>
9462
- </details>
9463
9460
  <p>The <code>TemplateExtension.detail_tabs()</code> method should return a list of dicts, each of which has the keys <code>"title"</code> and <code>"url"</code>. In addition, in order for tabs to work properly:</p>
9464
9461
  <ul>
9465
9462
  <li>The <code>"url"</code> key should typically be a URL that includes <code>self.context["object"].pk</code> in some form (so that the URL may know which object is being referenced)</li>
@@ -9124,9 +9124,6 @@
9124
9124
 
9125
9125
 
9126
9126
  <h1 id="replacing-views">Replacing Views<a class="headerlink" href="#replacing-views" title="Permanent link">&para;</a></h1>
9127
- <details class="version-added">
9128
- <summary>Added in version 1.4.0</summary>
9129
- </details>
9130
9127
  <p>You may override any of the core or app views by providing an <code>override_views</code> <code>dict</code> in an app's <code>views.py</code> file.</p>
9131
9128
  <p>To override a view, you must specify the view's fully qualified name as the <code>dict</code> key which consists of the app name followed by the view's name separated by a colon, for instance <code>dcim:device</code>. The <code>dict</code> value should be the overriding view function.</p>
9132
9129
  <p>A simple example to override the device detail view:</p>
@@ -9182,15 +9182,9 @@
9182
9182
  <p class="admonition-title">Warning</p>
9183
9183
  <p>Currently preferred way of implementing views is to use <a href="nautobotuiviewset.html"><code>NautobotUIViewSet</code></a></p>
9184
9184
  </div>
9185
- <details class="version-added">
9186
- <summary>Added in version 1.1.0</summary>
9187
- <p>Via <a href="https://github.com/nautobot/nautobot/issues/14">PR #14</a>, some <code>generic</code> views have been exposed to help aid in App development. These views have some requirements that must be in place in order to work. These can be used by importing them from <code>from nautobot.core.views import generic</code>.</p>
9188
- </details>
9185
+ <p>Some <code>generic</code> views have been exposed to help aid in App development. These views have some requirements that must be in place in order to work. These can be used by importing them from <code>from nautobot.core.views import generic</code>.</p>
9189
9186
  <p>More documentation and examples can be found in <a href="../../../core/generic-views.html">Generic Views</a> guide.</p>
9190
9187
  <h2 id="note-url-endpoint">Note URL Endpoint<a class="headerlink" href="#note-url-endpoint" title="Permanent link">&para;</a></h2>
9191
- <details class="version-added">
9192
- <summary>Added in version 1.4.0</summary>
9193
- </details>
9194
9188
  <p>Models that inherit from <code>PrimaryModel</code> and <code>OrganizationalModel</code> can have notes associated. In order to utilize this new feature you will need to add the endpoint to <code>urls.py</code>. Here is an option to be able to support both 1.4+ and older versions of Nautobot:</p>
9195
9189
  <div class="admonition tip">
9196
9190
  <p class="admonition-title">Tip</p>
@@ -9280,9 +9280,6 @@
9280
9280
 
9281
9281
 
9282
9282
  <h1 id="nautobotuiviewset">NautobotUIViewSet<a class="headerlink" href="#nautobotuiviewset" title="Permanent link">&para;</a></h1>
9283
- <details class="version-added">
9284
- <summary>Added in version 1.4.0</summary>
9285
- </details>
9286
9283
  <p>New in Nautobot 1.4 is the debut of <code>NautobotUIViewSet</code>: A powerful app development tool that can save app developer hundreds of lines of code compared to using legacy <code>generic.views</code>. Using it to gain access to default functionalities previous provided by <code>generic.views</code> such as <code>create()</code>, <code>update()</code>, <code>partial_update()</code>, <code>bulk_update()</code>, <code>destroy()</code>, <code>bulk_destroy()</code>, <code>retrieve()</code> and <code>list()</code> actions.</p>
9287
9284
  <p>Note that this ViewSet is catered specifically to the UI, not the API.</p>
9288
9285
  <p>Concrete examples on how to use <code>NautobotUIViewSet</code> resides in <code>nautobot.circuits.views</code>.</p>
@@ -9443,10 +9440,6 @@ The framework provides many pre-built panel types.</p>
9443
9440
  <p>If you do not provide your own templates in the <code>yourapp/templates/yourapp</code> folder, <code>NautobotUIViewSet</code> will fall back to <code>generic/object_{self.action}.html</code>.</p>
9444
9441
  <p>Since in many cases the <code>create</code> and <code>update</code> templates for a model will be identical, you are not required to create both. If you provide a <code>{app_label}/{model_opts.model_name}_create.html</code> file but not a <code>{app_label}/{model_opts.model_name}_update.html</code> file, then when you update an object, it will fall back to <code>{app_label}/{model_opts.model_name}_create.html</code> and vice versa.</p>
9445
9442
  <h3 id="adding-custom-views-to-nautobotuiviewset-nautobotuiviewsetrouter">Adding Custom Views To NautobotUIViewSet &amp; NautobotUIViewSetRouter<a class="headerlink" href="#adding-custom-views-to-nautobotuiviewset-nautobotuiviewsetrouter" title="Permanent link">&para;</a></h3>
9446
- <details class="version-changed">
9447
- <summary>Changed in version 1.6.0</summary>
9448
- <p>Via <a href="https://github.com/nautobot/nautobot/pull/4045">PR #4045</a>, notes and changelog views provided by mixins have now been moved to this pattern.</p>
9449
- </details>
9450
9443
  <p>Django REST Framework provides the ability to decorate a method on a ViewSet with <code>@action(detail=True)</code> to add the method as a view to the ViewSetRouter. This method must return a fully rendered HTML view.</p>
9451
9444
  <p>Below is an example of adding a custom action view to an App's ViewSet. A few considerations to keep in mind:</p>
9452
9445
  <ul>
@@ -9154,10 +9154,6 @@
9154
9154
  <a id="__codelineno-0-27" name="__codelineno-0-27" href="#__codelineno-0-27"></a><span class="p">]</span>
9155
9155
  <a id="__codelineno-0-28" name="__codelineno-0-28" href="#__codelineno-0-28"></a><span class="n">urlpatterns</span> <span class="o">+=</span> <span class="n">router</span><span class="o">.</span><span class="n">urls</span>
9156
9156
  </code></pre></div>
9157
- <details class="version-added">
9158
- <summary>Added in version 1.5.1</summary>
9159
- <p>Changelog and Notes views and URLs are now provided in the NautobotUIViewSet and NautobotUIViewSetRouter.</p>
9160
- </details>
9161
9157
 
9162
9158
 
9163
9159
 
@@ -9124,9 +9124,6 @@
9124
9124
 
9125
9125
 
9126
9126
  <h1 id="note-url-endpoint">Note URL Endpoint<a class="headerlink" href="#note-url-endpoint" title="Permanent link">&para;</a></h1>
9127
- <details class="version-added">
9128
- <summary>Added in version 1.4.0</summary>
9129
- </details>
9130
9127
  <p>Models that inherit from <code>PrimaryModel</code> and <code>OrganizationalModel</code> can have notes associated. In order to utilize this new feature you will need to add the endpoint to <code>urls.py</code>. Here is an option to be able to support both 1.4+ and older versions of Nautobot:</p>
9131
9128
  <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="n">urlpatterns</span> <span class="o">=</span> <span class="p">[</span>
9132
9129
  <a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a> <span class="n">path</span><span class="p">(</span><span class="s1">&#39;random/&#39;</span><span class="p">,</span> <span class="n">views</span><span class="o">.</span><span class="n">RandomAnimalView</span><span class="o">.</span><span class="n">as_view</span><span class="p">(),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;random_animal&#39;</span><span class="p">),</span>
@@ -9190,10 +9190,6 @@
9190
9190
  <p>This documentation covers the development of custom Apps for Nautobot. Nautobot apps are essentially self-contained <a href="https://docs.djangoproject.com/en/stable/ref/applications/">Django applications</a> which integrate with Nautobot to provide custom functionality. Since the development of Django applications is already very well-documented, this will only be covering the aspects that are specific to Nautobot.</p>
9191
9191
  <p>Apps can <a href="index.html#capabilities">do a lot of different things</a>, all of which will be covered in detail in this document.
9192
9192
  Keep in mind that each piece of functionality is entirely optional. For example, if your app merely adds a piece of middleware or an API endpoint for existing data, there's no need to define any new models.</p>
9193
- <details class="version-changed">
9194
- <summary>Changed in version 1.5.2</summary>
9195
- <p>The <code>nautobot.apps</code> namespace was added in Nautobot 1.5.2. If developing apps to be backwards-compatible with older versions of Nautobot, please refer to the app developer documentation of your required Nautobot version.</p>
9196
- </details>
9197
9193
  <div class="admonition tip">
9198
9194
  <p class="admonition-title">Tip</p>
9199
9195
  <p>The app detail view (<code>/apps/installed-apps/&lt;app_name&gt;/</code>, accessible via <strong>Apps -&gt; Installed Apps</strong> in the navigation menu, then selecting a specific app) provides in-depth information about which features any installed app is implementing or making use of.</p>
@@ -9207,48 +9203,19 @@ Keep in mind that each piece of functionality is entirely optional. For example,
9207
9203
  <li><strong>Add navigation menu items.</strong> An App can extend the navigation menus with new links and buttons or even entirely new menus.</li>
9208
9204
  <li><strong>Add home page content.</strong> An App can add custom items or custom panels to the Nautobot home page.</li>
9209
9205
  <li><strong>Add content to existing model detail views.</strong> An App can inject custom HTML content within the view of a core Nautobot model. This content can appear in the left column, right column, or full width of the page, and can also include custom buttons at the top of the page.</li>
9210
- </ul>
9211
- <details class="version-added">
9212
- <summary>Added in version 1.2.0</summary>
9213
- <ul>
9214
9206
  <li><strong>Add a banner.</strong> An App can add a custom banner to the top of any appropriate views.</li>
9215
- </ul>
9216
- </details>
9217
- <details class="version-added">
9218
- <summary>Added in version 1.4.0</summary>
9219
- <ul>
9220
9207
  <li><strong>Add extra tabs to existing model detail views.</strong> An App can inject additional tabs which will appear at the end of the object detail tabs list.</li>
9221
9208
  </ul>
9222
- </details>
9223
9209
  <h3 id="extend-and-customize-existing-nautobot-functionality">Extend and customize existing Nautobot functionality<a class="headerlink" href="#extend-and-customize-existing-nautobot-functionality" title="Permanent link">&para;</a></h3>
9224
9210
  <ul>
9225
9211
  <li><strong>Add custom validation logic to existing data models.</strong> An App can provide additional logic to customize the rules for validating created/updated data records.</li>
9226
9212
  <li><strong>Provide Jobs.</strong> An App can serve as a convenient way to package and install <a href="../../user-guide/platform-functionality/jobs/index.html">Jobs</a>.</li>
9227
9213
  <li><strong>Add additional Git data types.</strong> An App can add support for processing additional types of data stored in a <a href="../../user-guide/platform-functionality/gitrepository.html">Git repository</a>.</li>
9228
- </ul>
9229
- <details class="version-added">
9230
- <summary>Added in version 1.1.0</summary>
9231
- <ul>
9232
9214
  <li><strong>Register additional Jinja2 filters.</strong> An App can define custom Jinja2 filters to be used in computed fields, webhooks, custom links, and export templates.</li>
9233
- </ul>
9234
- </details>
9235
- <details class="version-added">
9236
- <summary>Added in version 1.2.0</summary>
9237
- <ul>
9238
- <li>
9239
- <p><strong>Populate extensibility features in the database.</strong> An App can add content to the Nautobot database when installed, such as automatically creating new custom fields, relationships, and so forth.</p>
9240
- </li>
9241
- <li>
9242
- <p><strong>Add additional secrets providers.</strong> An App can add support for retrieving <a href="../../user-guide/platform-functionality/secret.html">Secret</a> values from additional sources or external systems.</p>
9243
- </li>
9244
- </ul>
9245
- </details>
9246
- <details class="version-added">
9247
- <summary>Added in version 1.4.0</summary>
9248
- <ul>
9215
+ <li><strong>Populate extensibility features in the database.</strong> An App can add content to the Nautobot database when installed, such as automatically creating new custom fields, relationships, and so forth.</li>
9216
+ <li><strong>Add additional secrets providers.</strong> An App can add support for retrieving <a href="../../user-guide/platform-functionality/secret.html">Secret</a> values from additional sources or external systems.</li>
9249
9217
  <li><strong>Override already-defined views.</strong> An App can define a view which can be set to override a view from the core set of views or another App's view.</li>
9250
9218
  </ul>
9251
- </details>
9252
9219
  <h3 id="add-entirely-new-features">Add entirely new features<a class="headerlink" href="#add-entirely-new-features" title="Permanent link">&para;</a></h3>
9253
9220
  <ul>
9254
9221
  <li><strong>Add new data models.</strong> An App can introduce one or more models to hold data. (A model is essentially a table in the SQL database.) These models can be integrated with core implementations of GraphQL, webhooks, logging, custom relationships, custom fields, and tags.</li>
@@ -9538,7 +9538,7 @@
9538
9538
  </tr>
9539
9539
  <tr>
9540
9540
  <td>nautobot.utilities.utils</td>
9541
- <td>ensure_content_type_and_field_name_inquery_params</td>
9541
+ <td>ensure_content_type_and_field_name_in_query_params</td>
9542
9542
  <td>nautobot.core.utils.requests</td>
9543
9543
  </tr>
9544
9544
  <tr>
@@ -9370,9 +9370,6 @@
9370
9370
  </code></pre></div>
9371
9371
  <p>Apps may extend this dictionary with additional data sources and/or data types by calling <code>extras.registry.register_datasource_contents()</code> as desired.</p>
9372
9372
  <h3 id="homepage_layout"><code>homepage_layout</code><a class="headerlink" href="#homepage_layout" title="Permanent link">&para;</a></h3>
9373
- <details class="version-added">
9374
- <summary>Added in version 1.2.0</summary>
9375
- </details>
9376
9373
  <p>A dictionary holding information about the layout of Nautobot's homepage. Each app may register homepage panels and items using objects from the generic app class. Each object has a weight attribute allowing the developer to define the position of the object.</p>
9377
9374
  <div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="p">{</span>
9378
9375
  <a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a> <span class="s2">&quot;panels&quot;</span><span class="p">:</span> <span class="p">{</span>
@@ -9445,9 +9442,6 @@
9445
9442
  </code></pre></div>
9446
9443
  <p>For more information visit <a href="model-features.html">model-features</a>.</p>
9447
9444
  <h3 id="nav_menu"><code>nav_menu</code><a class="headerlink" href="#nav_menu" title="Permanent link">&para;</a></h3>
9448
- <details class="version-added">
9449
- <summary>Added in version 1.1.0</summary>
9450
- </details>
9451
9445
  <p>Navigation menu items provided by Nautobot applications. Each app may register its navbar configuration inside of the <code>nav_menu</code> dictionary using <code>navigation.py</code>. Tabs are stored in the top level moving down to groups, items and buttons. Tabs, groups and items can be modified by using the key values inside other core applications and Apps. The <code>nav_menu</code> dict should never be modified directly.</p>
9452
9446
  <p>Example:</p>
9453
9447
  <div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="p">{</span>