nautobot 2.4.2__py3-none-any.whl → 2.4.3__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 (132) hide show
  1. nautobot/circuits/templates/circuits/inc/circuit_termination.html +1 -1
  2. nautobot/circuits/tests/integration/test_circuit.py +135 -0
  3. nautobot/circuits/views.py +4 -1
  4. nautobot/cloud/api/views.py +3 -3
  5. nautobot/core/constants.py +0 -1
  6. nautobot/core/forms/__init__.py +2 -0
  7. nautobot/core/forms/forms.py +2 -1
  8. nautobot/core/forms/widgets.py +8 -0
  9. nautobot/core/management/commands/generate_performance_test_endpoints.py +268 -0
  10. nautobot/core/templates/generic/object_bulk_delete.html +1 -1
  11. nautobot/core/templates/generic/object_bulk_edit.html +1 -1
  12. nautobot/core/templates/generic/object_bulk_import.html +1 -1
  13. nautobot/core/templates/generic/object_create.html +5 -0
  14. nautobot/core/templates/generic/object_delete.html +1 -1
  15. nautobot/core/templates/generic/object_detail.html +1 -1
  16. nautobot/core/templates/generic/object_edit.html +1 -1
  17. nautobot/core/templates/inc/javascript.html +2 -0
  18. nautobot/core/templates/widgets/clearable_file.html +5 -0
  19. nautobot/core/templatetags/helpers.py +3 -3
  20. nautobot/core/testing/integration.py +37 -7
  21. nautobot/core/tests/test_commands.py +31 -0
  22. nautobot/core/tests/test_utils.py +17 -2
  23. nautobot/core/utils/lookup.py +12 -1
  24. nautobot/core/views/generic.py +9 -1
  25. nautobot/core/views/mixins.py +9 -1
  26. nautobot/dcim/api/views.py +11 -10
  27. nautobot/dcim/forms.py +3 -6
  28. nautobot/dcim/models/devices.py +1 -2
  29. nautobot/dcim/templates/dcim/cable_trace.html +4 -4
  30. nautobot/dcim/templates/dcim/consoleport.html +14 -4
  31. nautobot/dcim/templates/dcim/consoleserverport.html +14 -4
  32. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +3 -3
  33. nautobot/dcim/templates/dcim/frontport.html +7 -2
  34. nautobot/dcim/templates/dcim/interface.html +9 -4
  35. nautobot/dcim/templates/dcim/powerfeed.html +8 -3
  36. nautobot/dcim/templates/dcim/poweroutlet.html +14 -4
  37. nautobot/dcim/templates/dcim/powerport.html +14 -4
  38. nautobot/dcim/templates/dcim/rearport.html +7 -2
  39. nautobot/dcim/tests/integration/test_fileinputpicker.py +87 -0
  40. nautobot/dcim/tests/test_models.py +1 -1
  41. nautobot/extras/api/views.py +2 -2
  42. nautobot/extras/forms/forms.py +4 -0
  43. nautobot/extras/jobs.py +8 -1
  44. nautobot/extras/templates/extras/job.html +1 -0
  45. nautobot/extras/tests/test_dynamicgroups.py +14 -0
  46. nautobot/extras/tests/test_views.py +197 -9
  47. nautobot/extras/utils.py +30 -0
  48. nautobot/extras/views.py +29 -14
  49. nautobot/ipam/api/views.py +3 -3
  50. nautobot/ipam/forms.py +2 -6
  51. nautobot/project-static/bootstrap-filestyle-1.2.3/bootstrap-filestyle.min.js +11 -0
  52. nautobot/project-static/docs/apps/index.html +1 -1
  53. nautobot/project-static/docs/apps/nautobot-apps.html +1 -1
  54. nautobot/project-static/docs/development/apps/api/models/graphql.html +9 -9
  55. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +2 -2
  56. nautobot/project-static/docs/development/apps/api/setup.html +1 -1
  57. nautobot/project-static/docs/development/apps/migration/code-updates.html +6 -5
  58. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +2 -2
  59. nautobot/project-static/docs/development/apps/migration/from-v1.html +3 -3
  60. nautobot/project-static/docs/development/core/best-practices.html +1 -1
  61. nautobot/project-static/docs/development/core/bootstrap-ui.html +1 -1
  62. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +7 -7
  63. nautobot/project-static/docs/development/core/getting-started.html +2 -2
  64. nautobot/project-static/docs/development/core/index.html +1 -1
  65. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +3 -3
  66. nautobot/project-static/docs/development/core/model-checklist.html +1 -1
  67. nautobot/project-static/docs/development/core/navigation-menu.html +1 -1
  68. nautobot/project-static/docs/development/core/release-checklist.html +1 -1
  69. nautobot/project-static/docs/development/core/settings.html +1 -1
  70. nautobot/project-static/docs/development/core/style-guide.html +4 -4
  71. nautobot/project-static/docs/development/jobs/index.html +8 -1
  72. nautobot/project-static/docs/development/jobs/migration/from-v1.html +3 -2
  73. nautobot/project-static/docs/index.html +3 -2
  74. nautobot/project-static/docs/objects.inv +0 -0
  75. nautobot/project-static/docs/overview/application_stack.html +2 -2
  76. nautobot/project-static/docs/release-notes/version-1.0.html +2 -2
  77. nautobot/project-static/docs/release-notes/version-1.1.html +2 -2
  78. nautobot/project-static/docs/release-notes/version-1.2.html +3 -3
  79. nautobot/project-static/docs/release-notes/version-1.3.html +1 -1
  80. nautobot/project-static/docs/release-notes/version-1.4.html +17 -17
  81. nautobot/project-static/docs/release-notes/version-1.5.html +8 -8
  82. nautobot/project-static/docs/release-notes/version-1.6.html +4 -4
  83. nautobot/project-static/docs/release-notes/version-2.0.html +10 -10
  84. nautobot/project-static/docs/release-notes/version-2.1.html +7 -7
  85. nautobot/project-static/docs/release-notes/version-2.2.html +1 -1
  86. nautobot/project-static/docs/release-notes/version-2.3.html +4 -4
  87. nautobot/project-static/docs/release-notes/version-2.4.html +188 -0
  88. nautobot/project-static/docs/search/search_index.json +1 -1
  89. nautobot/project-static/docs/sitemap.xml +290 -290
  90. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  91. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +3 -3
  92. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +4 -4
  93. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +1 -1
  94. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +3 -3
  95. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +5 -5
  96. nautobot/project-static/docs/user-guide/administration/guides/docker.html +3 -3
  97. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +1 -1
  98. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +4 -4
  99. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +15 -15
  100. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +2 -2
  101. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +1 -1
  102. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +1 -1
  103. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +6 -6
  104. nautobot/project-static/docs/user-guide/administration/installation/services.html +1 -1
  105. nautobot/project-static/docs/user-guide/administration/security/index.html +1 -1
  106. nautobot/project-static/docs/user-guide/administration/security/notices.html +1 -0
  107. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +1 -1
  108. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +11 -8
  109. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +12 -12
  110. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +1 -1
  111. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1 -1
  112. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +3 -3
  113. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +2 -2
  114. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +6 -6
  115. nautobot/project-static/js/dropdown.js +28 -0
  116. nautobot/tenancy/forms.py +9 -0
  117. nautobot/tenancy/templates/tenancy/tenant_create.html +21 -0
  118. nautobot/tenancy/templates/tenancy/tenant_edit.html +2 -21
  119. nautobot/tenancy/templates/tenancy/tenantgroup.html +2 -44
  120. nautobot/tenancy/templates/tenancy/tenantgroup_retrieve.html +1 -0
  121. nautobot/tenancy/tests/test_views.py +5 -1
  122. nautobot/tenancy/urls.py +7 -79
  123. nautobot/tenancy/views.py +51 -80
  124. nautobot/wireless/api/serializers.py +6 -1
  125. nautobot/wireless/api/views.py +3 -3
  126. nautobot/wireless/tests/test_api.py +5 -0
  127. {nautobot-2.4.2.dist-info → nautobot-2.4.3.dist-info}/METADATA +8 -8
  128. {nautobot-2.4.2.dist-info → nautobot-2.4.3.dist-info}/RECORD +132 -123
  129. {nautobot-2.4.2.dist-info → nautobot-2.4.3.dist-info}/LICENSE.txt +0 -0
  130. {nautobot-2.4.2.dist-info → nautobot-2.4.3.dist-info}/NOTICE +0 -0
  131. {nautobot-2.4.2.dist-info → nautobot-2.4.3.dist-info}/WHEEL +0 -0
  132. {nautobot-2.4.2.dist-info → nautobot-2.4.3.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,11 @@
1
+ /*
2
+ * bootstrap-filestyle
3
+ * doc: http://markusslima.github.io/bootstrap-filestyle/
4
+ * github: https://github.com/markusslima/bootstrap-filestyle
5
+ * fork additions: https://github.com/msheiny/bootstrap-filestyle
6
+ *
7
+ * Copyright (c) 2017 Markus Vinicius da Silva Lima
8
+ * Version 1.2.3
9
+ * Licensed under the MIT license.
10
+ */
11
+ (function($){"use strict";var nextId=0;var Filestyle=function(element,options){this.options=options;this.$elementFilestyle=[];this.$element=$(element)};Filestyle.prototype={clear:function(){this.$element.val("");this.$elementFilestyle.find(":text").val("");this.$elementFilestyle.find(".badge").remove()},destroy:function(){this.$element.removeAttr("style").removeData("filestyle");this.$elementFilestyle.remove()},disabled:function(value){if(value===true){if(!this.options.disabled){this.$element.attr("disabled","true");this.$elementFilestyle.find("label").attr("disabled","true");this.options.disabled=true}}else if(value===false){if(this.options.disabled){this.$element.removeAttr("disabled");this.$elementFilestyle.find("label").removeAttr("disabled");this.options.disabled=false}}else{return this.options.disabled}},clearButton:function(value){if(value===true){if(!this.options.clearButton){this.options.clearButton=true;if(this.options.input){this.$elementFilestyle.remove();this.constructor();this.pushNameFiles()}}}else if(value===false){if(this.options.clearButton){this.options.clearButton=false;if(this.options.input){this.$elementFilestyle.remove();this.constructor();this.pushNameFiles()}}}else{return this.options.clearButton}},buttonBefore:function(value){if(value===true){if(!this.options.buttonBefore){this.options.buttonBefore=true;if(this.options.input){this.$elementFilestyle.remove();this.constructor();this.pushNameFiles()}}}else if(value===false){if(this.options.buttonBefore){this.options.buttonBefore=false;if(this.options.input){this.$elementFilestyle.remove();this.constructor();this.pushNameFiles()}}}else{return this.options.buttonBefore}},icon:function(value){if(value===true){if(!this.options.icon){this.options.icon=true;this.$elementFilestyle.find("label").prepend(this.htmlIcon())}}else if(value===false){if(this.options.icon){this.options.icon=false;this.$elementFilestyle.find(".icon-span-filestyle").remove()}}else{return this.options.icon}},input:function(value){if(value===true){if(!this.options.input){this.options.input=true;if(this.options.buttonBefore){this.$elementFilestyle.append(this.htmlInput())}else{this.$elementFilestyle.prepend(this.htmlInput())}this.$elementFilestyle.find(".badge").remove();this.pushNameFiles();this.$elementFilestyle.find(".group-span-filestyle").addClass("input-group-btn")}}else if(value===false){if(this.options.input){this.options.input=false;this.$elementFilestyle.find(":text").remove();var files=this.pushNameFiles();if(files.length>0&&this.options.badge){this.$elementFilestyle.find("label").append(' <span class="badge">'+files.length+"</span>")}this.$elementFilestyle.find(".group-span-filestyle").removeClass("input-group-btn")}}else{return this.options.input}},size:function(value){if(value!==undefined){var btn=this.$elementFilestyle.find("label"),input=this.$elementFilestyle.find("input");btn.removeClass("btn-lg btn-sm");input.removeClass("input-lg input-sm");if(value!="nr"){btn.addClass("btn-"+value);input.addClass("input-"+value)}}else{return this.options.size}},placeholder:function(value){if(value!==undefined){this.options.placeholder=value;this.$elementFilestyle.find("input").attr("placeholder",value)}else{return this.options.placeholder}},buttonText:function(value){if(value!==undefined){this.options.buttonText=value;this.$elementFilestyle.find("label .buttonText").html(this.options.buttonText)}else{return this.options.buttonText}},buttonName:function(value){if(value!==undefined){this.options.buttonName=value;this.$elementFilestyle.find("label").attr({class:"btn "+this.options.buttonName})}else{return this.options.buttonName}},iconName:function(value){if(value!==undefined){this.$elementFilestyle.find(".icon-span-filestyle").attr({class:"icon-span-filestyle "+this.options.iconName})}else{return this.options.iconName}},inputText:function(value){if(value!==undefined){this.options.inputText=value;this.$elementFilestyle.find("input").text(this.options.inputText)}else{return this.options.inputText}},htmlIcon:function(){if(this.options.icon){return'<span style="margin-right: 3px;" class="icon-span-filestyle '+this.options.iconName+'"></span> '}else{return""}},htmlInput:function(){if(this.options.input){return'<input type="text" class="form-control '+(this.options.size=="nr"?"":"input-"+this.options.size)+'" placeholder="'+this.options.placeholder+'" '+(this.options.inputText?'value="'+this.options.inputText+'" ':"")+'" disabled> '}else{return""}},pushNameFiles:function(){var content="",files=[];if(this.$element[0].files===undefined){files[0]={name:this.$element[0]&&this.$element[0].value}}else{files=this.$element[0].files}for(var i=0;i<files.length;i++){content+=files[i].name.split("\\").pop()+", "}if(content!==""){this.$elementFilestyle.find(":text").val(content.replace(/\, $/g,""));this.$elementFilestyle.find(".clear-button").removeClass("hidden")}else{this.$elementFilestyle.find(":text").val("");this.$elementFilestyle.find(".clear-button").addClass("hidden")}return files},constructor:function(){var _self=this,html="",id=_self.$element.attr("id"),files=[],btn="",clearBtn="",$label;if(id===""||!id){id="filestyle-"+nextId;_self.$element.attr({id:id});nextId++}btn='<span class="group-span-filestyle '+(_self.options.input?"input-group-btn":"")+'">'+'<label for="'+id+'" class="btn '+_self.options.buttonName+" "+(_self.options.size=="nr"?"":"btn-"+_self.options.size)+'" '+(_self.options.disabled?'disabled="true"':"")+">"+_self.htmlIcon()+'<span class="buttonText">'+_self.options.buttonText+"</span>"+"</label>"+"</span>";clearBtn=_self.options.clearButton?'<span class="input-group-btn"><button class="btn btn-default clear-button'+(_self.options.inputText?"":" hidden")+'" type="button">x</button></span>':"";html=_self.options.buttonBefore?btn+_self.htmlInput()+clearBtn:clearBtn+_self.htmlInput()+btn;_self.$elementFilestyle=$('<div class="bootstrap-filestyle input-group">'+html+"</div>");_self.$elementFilestyle.find(".group-span-filestyle").attr("tabindex","0").keypress(function(e){if(e.keyCode===13||e.charCode===32){_self.$elementFilestyle.find("label").click();return false}});_self.$element.css({position:"absolute",clip:"rect(0px 0px 0px 0px)"}).attr("tabindex","-1").after(_self.$elementFilestyle);if(_self.options.disabled||_self.$element.attr("disabled")){_self.$element.attr("disabled","true")}_self.$element.change(function(){var files=_self.pushNameFiles();if(_self.options.input==false&&_self.options.badge){if(_self.$elementFilestyle.find(".badge").length==0){_self.$elementFilestyle.find("label").append(' <span class="badge">'+files.length+"</span>")}else if(files.length==0){_self.$elementFilestyle.find(".badge").remove()}else{_self.$elementFilestyle.find(".badge").html(files.length)}}else{_self.$elementFilestyle.find(".badge").remove()}});if(window.navigator.userAgent.search(/firefox/i)>-1){_self.$elementFilestyle.find("label").click(function(){_self.$element.click();return false})}if(_self.options.clearButton){var $clearButton=_self.$elementFilestyle.find(".clear-button");$clearButton.on("click",function(e){var $input=_self.$element,input=$input[0];try{$input.val("");if(input.value){input.type="text";input.type="file"}$clearButton.addClass("hidden");$input.trigger("change")}catch(e){}})}}};var old=$.fn.filestyle;$.fn.filestyle=function(option,value){var get="",element=this.each(function(){if($(this).attr("type")==="file"){var $this=$(this),data=$this.data("filestyle"),options=$.extend({},$.fn.filestyle.defaults,option,typeof option==="object"&&option);if(!data){$this.data("filestyle",data=new Filestyle(this,options));data.constructor()}if(typeof option==="string"){get=data[option](value)}}});if(typeof get!==undefined){return get}else{return element}};$.fn.filestyle.defaults={buttonText:"Choose file",iconName:"glyphicon glyphicon-folder-open",buttonName:"btn-default",size:"nr",input:true,inputText:"",badge:true,icon:true,buttonBefore:false,disabled:false,clearButton:true};$.fn.filestyle.noConflict=function(){$.fn.filestyle=old;return this};$(function(){$(".filestyle").each(function(){var $this=$(this),options={input:$this.attr("data-input")!=="false",icon:$this.attr("data-icon")!=="false",buttonBefore:$this.attr("data-buttonBefore")==="true",disabled:$this.attr("data-disabled")==="true",size:$this.attr("data-size"),buttonText:$this.attr("data-buttonText"),buttonName:$this.attr("data-buttonName"),iconName:$this.attr("data-iconName"),badge:$this.attr("data-badge")!=="false",placeholder:$this.attr("data-placeholder")};$this.filestyle(options)})})})(window.jQuery);
@@ -9181,7 +9181,7 @@
9181
9181
  <tr>
9182
9182
  <td><img alt="Logo" src="../assets/app-icons/icon-NautobotPluginNornir.png" /></td>
9183
9183
  <td><a href="https://docs.nautobot.com/projects/plugin-nornir/en/latest/">Nautobot Plugin Nornir</a></td>
9184
- <td>Provides a small shim layer between <a href="https://github.com/nautobot/nornir-nautobot">nornir-nautobot</a> and other plugins. The primary abilities that the plugin provides are a native Nornir ORM based inventory and a credential manager.</td>
9184
+ <td>Provides a small shim layer between <a href="https://github.com/nautobot/nornir-nautobot"><code>nornir-nautobot</code></a> and other plugins. The primary abilities that the plugin provides are a native Nornir ORM based inventory and a credential manager.</td>
9185
9185
  </tr>
9186
9186
  <tr>
9187
9187
  <td><img alt="Logo" src="../assets/app-icons/icon-SSoT.png" /></td>
@@ -9117,7 +9117,7 @@
9117
9117
 
9118
9118
  <h1 id="nautobot-community-apps">Nautobot Community Apps<a class="headerlink" href="#nautobot-community-apps" title="Permanent link">&para;</a></h1>
9119
9119
  <p>The following is a manually curated list of Apps from the wider Nautobot community, which have some sort of documentation.</p>
9120
- <!-- pyml disable-num-lines 4 no-inline-html -->
9120
+ <!-- pyml disable-num-lines 4 no-inline-html,proper-names -->
9121
9121
  <table>
9122
9122
  <thead>
9123
9123
  <tr>
@@ -9250,7 +9250,7 @@
9250
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
9251
  </details>
9252
9252
  <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
- <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 graphene-django</a>.</p>
9253
+ <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
9254
  <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>
9255
9255
  <div class="admonition warning">
9256
9256
  <p class="admonition-title">Warning</p>
@@ -9288,17 +9288,17 @@
9288
9288
  <p>Arguments:</p>
9289
9289
  <ul>
9290
9290
  <li><code>execute_query()</code>:<ul>
9291
- <li><code>query</code> (str): String with GraphQL query.</li>
9292
- <li><code>variables</code> (dict, optional): If the query has variables they need to be passed in as a dictionary.</li>
9293
- <li><code>request</code> (django.test.client.RequestFactory, optional): Used to authenticate.</li>
9294
- <li><code>user</code> (django.contrib.auth.models.User, optional): Used to authenticate.</li>
9291
+ <li><code>query</code> (<code>str</code>): String with GraphQL query.</li>
9292
+ <li><code>variables</code> (<code>dict</code>, optional): If the query has variables they need to be passed in as a dictionary.</li>
9293
+ <li><code>request</code> (<code>django.test.client.RequestFactory</code>, optional): Used to authenticate.</li>
9294
+ <li><code>user</code> (<code>django.contrib.auth.models.User</code>, optional): Used to authenticate.</li>
9295
9295
  </ul>
9296
9296
  </li>
9297
9297
  <li><code>execute_saved_query()</code>:<ul>
9298
- <li><code>saved_query_name</code> (str): Name of a saved GraphQL query.</li>
9299
- <li><code>variables</code> (dict, optional): If the query has variables they need to be passed in as a dictionary.</li>
9300
- <li><code>request</code> (django.test.client.RequestFactory, optional): Used to authenticate.</li>
9301
- <li><code>user</code> (django.contrib.auth.models.User, optional): Used to authenticate.</li>
9298
+ <li><code>saved_query_name</code> (<code>str</code>): Name of a saved GraphQL query.</li>
9299
+ <li><code>variables</code> (<code>dict</code>, optional): If the query has variables they need to be passed in as a dictionary.</li>
9300
+ <li><code>request</code> (<code>django.test.client.RequestFactory</code>, optional): Used to authenticate.</li>
9301
+ <li><code>user</code> (<code>django.contrib.auth.models.User</code>, optional): Used to authenticate.</li>
9302
9302
  </ul>
9303
9303
  </li>
9304
9304
  </ul>
@@ -9133,7 +9133,7 @@
9133
9133
  <li>The <code>model</code> attribute of each <code>FilterExtension</code> subclass must be set to a valid model name in the dotted pair format (<code>{app_label}.{model}</code>, e.g. <code>tenant.tenant</code> or <code>dcim.device</code>)</li>
9134
9134
  </ul>
9135
9135
  <p>Nautobot dynamically creates many additional filters based upon the defined filter type. Specifically, there are additional lookup expressions (referred to in code as <code>lookup_expr</code>) that are created for each filter, when there is neither a <code>lookup_expr</code> nor <code>method</code> parameter already set. These dynamically-added lookup expressions are added using a shorthand notation (e.g. <code>icontains</code> is <code>ic</code>). Nautobot will also add the negation of each, for example, so <code>icontains</code> will be added along with <em>not</em> <code>icontains</code> using the <code>ic</code> and <code>nic</code> expressions respectively.</p>
9136
- <p>The dynamically-added lookup expressions can be found in the source code at <a href="https://github.com/nautobot/nautobot/blob/main/nautobot/core/constants.py">nautobot/core/constants.py</a> and the mapping logic can be found in <a href="https://github.com/nautobot/nautobot/blob/main/nautobot/core/filters.py">nautobot/core/filters.py</a>. Please see the documentation on <a href="../../../../user-guide/platform-functionality/rest-api/filtering.html#lookup-expressions">filtering</a> for more information.</p>
9136
+ <p>The dynamically-added lookup expressions can be found in the source code at <a href="https://github.com/nautobot/nautobot/blob/main/nautobot/core/constants.py"><code>nautobot/core/constants.py</code></a> and the mapping logic can be found in <a href="https://github.com/nautobot/nautobot/blob/main/nautobot/core/filters.py"><code>nautobot/core/filters.py</code></a>. Please see the documentation on <a href="../../../../user-guide/platform-functionality/rest-api/filtering.html#lookup-expressions">filtering</a> for more information.</p>
9137
9137
  <div class="admonition tip">
9138
9138
  <p class="admonition-title">Tip</p>
9139
9139
  <p>For developers of apps that define their own model filters, note that the above are added dynamically, as long as the class inherits from <code>nautobot.apps.filters.BaseFilterSet</code>.</p>
@@ -9147,7 +9147,7 @@
9147
9147
  <p>There are several conditions that must be met in order to extend a filter:</p>
9148
9148
  <ul>
9149
9149
  <li>The original FilterSet must follow the pattern: <code>f"{model.__name__}FilterSet"</code> e.g. <code>TenantFilterSet</code></li>
9150
- <li>The <code>FilterExtension.filterset_fields</code> attribute must be a valid dict, with each key being the filter name (which must start with the App's <code>name</code> + <code>_</code>, e.g. <code>"example_app_description"</code>, not merely <code>"description"</code>) and each value being a valid <a href="https://django-filter.readthedocs.io/en/main/">django-filter</a> filter</li>
9150
+ <li>The <code>FilterExtension.filterset_fields</code> attribute must be a valid dict, with each key being the filter name (which must start with the App's <code>name</code> + <code>_</code>, e.g. <code>"example_app_description"</code>, not merely <code>"description"</code>) and each value being a valid <a href="https://django-filter.readthedocs.io/en/main/"><code>django-filter</code></a> filter.</li>
9151
9151
  </ul>
9152
9152
  <p>Nautobot will dynamically generate the additional relevant lookup expressions of an app's defined custom FilterSet field, so no need to additionally register <code>example_app_description__ic</code>, etc.</p>
9153
9153
  <p>Similar to <code>FilterSet</code> fields, Nautobot provides a default filter form for each model, however that does not cover every possible use case. To list a few examples of why one may want to extend a filter form:</p>
@@ -9182,7 +9182,7 @@
9182
9182
  </div>
9183
9183
  <div class="admonition note">
9184
9184
  <p class="admonition-title">Note</p>
9185
- <p>The Nautobot organization provides a Python <a href="https://cookiecutter.readthedocs.io/en/stable/">CookieCutter</a> to help get started with your applications. Get started at <a href="https://github.com/nautobot/cookiecutter-nautobot-app">https://github.com/nautobot/cookiecutter-nautobot-app</a>.</p>
9185
+ <p>The Nautobot organization provides a Python <a href="https://cookiecutter.readthedocs.io/en/stable/">CookieCutter</a> to help get started with your applications. Get started at <a href="https://github.com/nautobot/cookiecutter-nautobot-app"><code>https://github.com/nautobot/cookiecutter-nautobot-app</code></a>.</p>
9186
9186
  </div>
9187
9187
  <h2 id="app-structure">App Structure<a class="headerlink" href="#app-structure" title="Permanent link">&para;</a></h2>
9188
9188
  <p>Although the specific structure of an app is largely left to the discretion of its authors, a Nautobot app that makes use of all available app features described in this document could potentially look something like this:</p>
@@ -7673,7 +7673,7 @@
7673
7673
  <li class="md-nav__item">
7674
7674
  <a href="#revamp-rest-api-serializers" class="md-nav__link">
7675
7675
  <span class="md-ellipsis">
7676
- Revamp Rest API Serializers
7676
+ Revamp REST API Serializers
7677
7677
  </span>
7678
7678
  </a>
7679
7679
 
@@ -9264,7 +9264,7 @@
9264
9264
  <li class="md-nav__item">
9265
9265
  <a href="#revamp-rest-api-serializers" class="md-nav__link">
9266
9266
  <span class="md-ellipsis">
9267
- Revamp Rest API Serializers
9267
+ Revamp REST API Serializers
9268
9268
  </span>
9269
9269
  </a>
9270
9270
 
@@ -9715,8 +9715,9 @@
9715
9715
  </table>
9716
9716
  </details>
9717
9717
  <p>Other than models, most other imports from Nautobot should be imported from <code>nautobot.apps.*</code> as described here.</p>
9718
+ <!-- pyml disable-num-lines 2 proper-names -->
9718
9719
  <details class="info">
9719
- <summary>Full table of nautobot.app code locations</summary>
9720
+ <summary>Full table of <code>nautobot.apps</code> code locations</summary>
9720
9721
  <table>
9721
9722
  <thead>
9722
9723
  <tr>
@@ -11772,7 +11773,7 @@
11772
11773
  <p>App Model Serializers for any models that could have a Generic Foreign Key or a Many to Many relationship from a Nautobot Core model <strong>must</strong> inherit from BaseModelSerializer at a minimum so that they have a properly generated <code>object_type</code> field. This also applies to the case where your model is a subclass of <code>ChangeLoggedModel</code> and you will have a Generic Foreign Key from <code>ObjectChange</code>'s <code>changed_object</code> field. Otherwise drf-spectacular schema generation will throw an error:</p>
11773
11774
  <div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a>(drf_spectacular.E001) Schema generation threw exception &quot;Field name `object_type` is not valid for model `YourAppModel`.
11774
11775
  </code></pre></div>
11775
- <h2 id="revamp-rest-api-serializers">Revamp Rest API Serializers<a class="headerlink" href="#revamp-rest-api-serializers" title="Permanent link">&para;</a></h2>
11776
+ <h2 id="revamp-rest-api-serializers">Revamp REST API Serializers<a class="headerlink" href="#revamp-rest-api-serializers" title="Permanent link">&para;</a></h2>
11776
11777
  <p><code>NestedSerializer</code> classes are no longer needed in Nautobot 2.0. If any <code>NestedSerializers</code> exist for your models, you should just remove their class definitions and references.</p>
11777
11778
  <p>After removing existing <code>NestedSerializers</code>, you can change the <code>fields</code> attribute in your serializers' <code>class Meta</code> to <code>__all__</code> and that will automatically include all the model's fields in the serializer, including related-model fields that would previously have required a reference to a <code>NestedSerializer</code>. If you want to exclude certain fields of the model, you can specify a list of fields you want to display in the <code>fields</code> attribute instead.</p>
11778
11779
  <div class="admonition warning">
@@ -11802,7 +11803,7 @@
11802
11803
  </code></pre></div>
11803
11804
  <p>In addition, the <code>?brief=</code> API query parameter is replaced by <code>?depth=&lt;0-10&gt;</code>. As a result, the ability to specify <code>brief_mode</code> in <code>DynamicModelChoiceField</code>, <code>DynamicModelMultipleChoiceField</code>, and <code>MultiMatchModelMultipleChoiceField</code> has also been removed. For every occurrence of the aforementioned fields where you have <code>brief_mode</code> set to <code>True/False</code> (e.g. <code>brief_mode=True</code>), please remove the statement, leaving other occurrences of the fields where you do not have <code>brief_mode</code> specified as they are. Check out our <a href="../../../user-guide/platform-functionality/rest-api/overview.html#depth-query-parameter">API documentation</a> for this change.</p>
11804
11805
  <h2 id="revamp-csv-import-and-export">Revamp CSV Import and Export<a class="headerlink" href="#revamp-csv-import-and-export" title="Permanent link">&para;</a></h2>
11805
- <p>CSV Import for models are now done automatically via the Rest API. As a result of this change, <code>CSVForm</code> classes are no longer needed and should be deleted. In addition, the Model <code>csv_headers</code> attribute and <code>to_csv</code> method are no longer needed or used in CSV generation, and should be removed from your model definitions. Check out our <a href="../../../release-notes/version-2.0.html#revamped-csv-import-and-export-254">release notes</a> for this specific change.</p>
11806
+ <p>CSV Import for models are now done automatically via the REST API. As a result of this change, <code>CSVForm</code> classes are no longer needed and should be deleted. In addition, the Model <code>csv_headers</code> attribute and <code>to_csv</code> method are no longer needed or used in CSV generation, and should be removed from your model definitions. Check out our <a href="../../../release-notes/version-2.0.html#revamped-csv-import-and-export-254">release notes</a> for this specific change.</p>
11806
11807
 
11807
11808
 
11808
11809
 
@@ -9218,8 +9218,8 @@
9218
9218
  <p>Change your Nautobot to the latest/v2.0 release.</p>
9219
9219
  <h2 id="python-version">Python Version<a class="headerlink" href="#python-version" title="Permanent link">&para;</a></h2>
9220
9220
  <p>Python 3.8 support is dropped for Nautobot v2.4 and Python 3.9 is the minimum version for Nautobot and its apps.</p>
9221
- <h2 id="pylint-nautobot">pylint-nautobot<a class="headerlink" href="#pylint-nautobot" title="Permanent link">&para;</a></h2>
9222
- <p>pylint-nautobot is now a required dev-dependency. Make sure you add <code>pylint-nautobot = "*"</code> under <code>tool.poetry.dev-dependencies</code> section in your <code>pyproject.toml</code>.</p>
9221
+ <h2 id="pylint-nautobot"><code>pylint-nautobot</code><a class="headerlink" href="#pylint-nautobot" title="Permanent link">&para;</a></h2>
9222
+ <p><code>pylint-nautobot</code> is now a required dev-dependency. Make sure you add <code>pylint-nautobot = "*"</code> under <code>tool.poetry.dev-dependencies</code> section in your <code>pyproject.toml</code>.</p>
9223
9223
 
9224
9224
 
9225
9225
 
@@ -9204,14 +9204,14 @@
9204
9204
  <li>Steps to Migrate an App from V1<ul>
9205
9205
  <li>Preliminary Steps:<ul>
9206
9206
  <li>Add <a href="https://github.com/nautobot/pylint-nautobot"><code>pylint-nautobot</code></a> as a development dependency</li>
9207
- <li>Run <code>pylint -v --disable=all --enable=nautobot-code-location-changes,nautobot-replaced-models *</code> in order to parse your development environment for changes that need to be fixed before pylint-django can successfully run.</li>
9207
+ <li>Run <code>pylint -v --disable=all --enable=nautobot-code-location-changes,nautobot-replaced-models *</code> in order to parse your development environment for changes that need to be fixed before <code>pylint-django</code> can successfully run.</li>
9208
9208
  <li>Specific steps to install and run <code>pylint-nautobot</code> in your development environment is available <a href="https://docs.nautobot.com/projects/pylint-nautobot/en/latest/getting_started/">here</a></li>
9209
9209
  </ul>
9210
9210
  </li>
9211
9211
  <li><a href="dependency-updates.html">Dependency Updates</a><ul>
9212
9212
  <li><a href="dependency-updates.html#nautobot-version">Nautobot Version</a></li>
9213
9213
  <li><a href="dependency-updates.html#python-version">Python Version</a></li>
9214
- <li><a href="dependency-updates.html#pylint-nautobot">pylint-nautobot</a></li>
9214
+ <li><a href="dependency-updates.html#pylint-nautobot"><code>pylint-nautobot</code></a></li>
9215
9215
  </ul>
9216
9216
  </li>
9217
9217
  <li><a href="code-updates.html">Code Updates</a><ul>
@@ -9220,7 +9220,7 @@
9220
9220
  <li><a href="code-updates.html#remove-tagtags-filter-from-filterset-definitions">Remove Tag/Tags Filter Field from FilterSet Definitions</a></li>
9221
9221
  <li><a href="code-updates.html#replace-djangofilterbackend-with-nautobotfilterbackend">Replace DjangoFilterBackend with NautobotFilterBackend</a></li>
9222
9222
  <li><a href="code-updates.html#app-model-serializer-inheritance">App Model Serializer Inheritance</a></li>
9223
- <li><a href="code-updates.html#revamp-rest-api-serializers">Revamp Rest API Serializers</a></li>
9223
+ <li><a href="code-updates.html#revamp-rest-api-serializers">Revamp REST API Serializers</a></li>
9224
9224
  <li><a href="code-updates.html#revamp-csv-import-and-export">Revamp CSV Import and Export</a></li>
9225
9225
  </ul>
9226
9226
  </li>
@@ -9993,7 +9993,7 @@ For most purposes, this is not the case you are intending to check!</p>
9993
9993
  <a id="__codelineno-22-11" name="__codelineno-22-11" href="#__codelineno-22-11"></a> <span class="nb">breakpoint</span><span class="p">()</span> <span class="c1"># This was added to illustrate debugging with pdb below</span>
9994
9994
  <a id="__codelineno-22-12" name="__codelineno-22-12" href="#__codelineno-22-12"></a> <span class="k">return</span> <span class="n">queryset</span><span class="o">.</span><span class="n">exclude</span><span class="p">(</span><span class="n">frontports__isnull</span><span class="o">=</span><span class="n">value</span><span class="p">,</span> <span class="n">rearports__isnull</span><span class="o">=</span><span class="n">value</span><span class="p">)</span>
9995
9995
  </code></pre></div>
9996
- <p>The default <code>lookup_expr</code> unless otherwise specified is “exact”, as seen in <a href="https://github.com/carltongibson/django-filter/blob/main/django_filters/conf.py#L10">django_filters.conf</a>:</p>
9996
+ <p>The default <code>lookup_expr</code> unless otherwise specified is “exact”, as seen in the <a href="https://github.com/carltongibson/django-filter/blob/main/django_filters/conf.py#L10"><code>django_filters.conf</code></a> module:</p>
9997
9997
  <div class="highlight"><pre><span></span><code><a id="__codelineno-23-1" name="__codelineno-23-1" href="#__codelineno-23-1"></a> <span class="s1">&#39;DEFAULT_LOOKUP_EXPR&#39;</span><span class="p">:</span> <span class="s1">&#39;exact&#39;</span><span class="p">,</span>
9998
9998
  </code></pre></div>
9999
9999
  <p>When this method is called, the internal state is default, making reverse introspection impossible, because the <code>lookup_expr</code> is defaulting to “exact”:</p>
@@ -9213,7 +9213,7 @@
9213
9213
 
9214
9214
  <h1 id="developing-the-bootstrap-3-ui">Developing the Bootstrap 3 UI<a class="headerlink" href="#developing-the-bootstrap-3-ui" title="Permanent link">&para;</a></h1>
9215
9215
  <h2 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Permanent link">&para;</a></h2>
9216
- <p>Nautobot's current primary UI is based on <a href="https://getbootstrap.com/docs/3.4/">Bootstrap 3</a>. Since Nautobot 2.1.0, this UI has used a Nautobot-specific custom Bootstrap theme built in the <a href="https://github.com/nautobot/nautobot-bootstrap/">nautobot-bootstrap</a> GitHub repository and then customized further in the main <a href="https://github.com/nautobot/nautobot/">nautobot</a> GitHub repository.</p>
9216
+ <p>Nautobot's current primary UI is based on <a href="https://getbootstrap.com/docs/3.4/">Bootstrap 3</a>. Since Nautobot 2.1.0, this UI has used a Nautobot-specific custom Bootstrap theme built in the <a href="https://github.com/nautobot/nautobot-bootstrap/"><code>nautobot-bootstrap</code></a> GitHub repository and then customized further in the main <a href="https://github.com/nautobot/nautobot/"><code>nautobot</code></a> GitHub repository.</p>
9217
9217
  <h2 id="theme-files">Theme Files<a class="headerlink" href="#theme-files" title="Permanent link">&para;</a></h2>
9218
9218
  <ul>
9219
9219
  <li><code>nautobot/project-static/bootstrap-3.4.1-dist/css/</code> - the base Nautobot-themed Bootstrap CSS definitions, directly as compiled from <code>nautobot-bootstrap</code>. <em>These should never be edited manually, only recompiled from <code>nautobot-bootstrap</code> and copied as-is into <code>nautobot</code>.</em></li>
@@ -9580,11 +9580,11 @@
9580
9580
  <p>Once all steps are completed Nautobot should now have the <code>Continue to SSO</code> button on the login screen and should immediately redirect the user to sign in with Keycloak.</p>
9581
9581
  <h4 id="keycloak-login-credentials">Keycloak Login Credentials<a class="headerlink" href="#keycloak-login-credentials" title="Permanent link">&para;</a></h4>
9582
9582
  <p>Keycloak admin console is reachable via <code>http://localhost:8087/admin/</code> with user <code>admin</code> and password <code>admin</code>. The below users are pre-configured within Keycloak, at this time their permissions are not directly mapped to any permissions provided by default by Nautobot. This will be a later enhancement to the local development environment.</p>
9583
- <p>| Username | Password |
9584
- +------------------+-----------+
9585
- | nautobot_unpriv | unpriv123 |
9586
- | nautobot_admin | admin123 |
9587
- | nautobot_auditor | audit123 |</p>
9583
+ <p>| Username | Password |
9584
+ +--------------------+-------------+
9585
+ | <code>nautobot_unpriv</code> | <code>unpriv123</code> |
9586
+ | <code>nautobot_admin</code> | <code>admin123</code> |
9587
+ | <code>nautobot_auditor</code> | <code>audit123</code> |</p>
9588
9588
  <h2 id="microsoft-visual-studio-code-integration">Microsoft Visual Studio Code Integration<a class="headerlink" href="#microsoft-visual-studio-code-integration" title="Permanent link">&para;</a></h2>
9589
9589
  <p>For users of Microsoft Visual Studio Code, several files are included to ease development and integrate with the <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers">VS Code Remote - Containers extension</a>. The following related files are found relative to the root of the project:</p>
9590
9590
  <ul>
@@ -9596,7 +9596,7 @@
9596
9596
  <details class="version-changed">
9597
9597
  <summary>Changed in version 2.1.2</summary>
9598
9598
  </details>
9599
- <h4 id="python_ver-environment-variable">PYTHON_VER Environment Variable<a class="headerlink" href="#python_ver-environment-variable" title="Permanent link">&para;</a></h4>
9599
+ <h4 id="python_ver-environment-variable"><code>PYTHON_VER</code> Environment Variable<a class="headerlink" href="#python_ver-environment-variable" title="Permanent link">&para;</a></h4>
9600
9600
  <p>The <code>PYTHON_VER</code> environment variable must be set in the <code>development/.env</code> file or the container build will fail.</p>
9601
9601
  <p>You can run <code>invoke</code> with the <code>vscode</code> target to generate this file and re-open the VSCode session under the workspace.</p>
9602
9602
  <div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a>invoke<span class="w"> </span>vscode
@@ -9643,7 +9643,7 @@
9643
9643
  <p><strong>VS Code debug configuration.</strong></p>
9644
9644
  <p>If you have opened the workspace file <code>nautobot.code-workspace</code> then there are two debug
9645
9645
  configurations for remote debugging already available.</p>
9646
- <p>If you add nautobot to an existing VS Code workspace (Menu: <em>File &gt; Add Folder to Workspace...</em>)
9646
+ <p>If you add <code>nautobot</code> to an existing VS Code workspace (Menu: <em>File &gt; Add Folder to Workspace...</em>)
9647
9647
  then copy the <code>launch:</code> values to the <code>.vscode/launch.json</code> file.</p>
9648
9648
  <ul>
9649
9649
  <li>Debug Configurations for Remote Debugging:</li>
@@ -10552,7 +10552,7 @@
10552
10552
  <p>You can connect to the development server at <code>localhost:8080</code>.</p>
10553
10553
  <h3 id="starting-the-worker-server">Starting the Worker Server<a class="headerlink" href="#starting-the-worker-server" title="Permanent link">&para;</a></h3>
10554
10554
  <p>In order to run Nautobot Jobs or anything that requires a worker you must start a Celery worker.</p>
10555
- <p>The worker is started in Docker Workflow with <a href="https://pythonhosted.org/watchdog/">watchdog</a> and can be setup to be started with watchdog in the Virtual Environment Workflow. Watchdog provides a similar experience to the Django lightweight HTTP/WSGI for restarting your application automatically. Watchdog can watch for changes on your filesystem, this is helpful when adjusting existing Python files to not have to restart the celery worker when testing jobs.</p>
10555
+ <p>The worker is started in Docker Workflow with <a href="https://pythonhosted.org/watchdog/">watchdog</a> and can be setup to be started with watchdog in the Virtual Environment Workflow. Watchdog provides a similar experience to the Django lightweight HTTP/WSGI for restarting your application automatically. Watchdog can watch for changes on your filesystem, this is helpful when adjusting existing Python files to not have to restart the Celery worker when testing jobs.</p>
10556
10556
  <table>
10557
10557
  <thead>
10558
10558
  <tr>
@@ -10569,7 +10569,7 @@
10569
10569
  </table>
10570
10570
  <div class="admonition tip">
10571
10571
  <p class="admonition-title">Tip</p>
10572
- <p>You can leverage watchdog for your celery worker as described above, with the following watchmedo command in your development environment <code>watchmedo auto-restart --directory './' --pattern '*.py' --recursive -- nautobot-server celery worker -l INFO --events</code>.</p>
10572
+ <p>You can leverage watchdog for your Celery worker as described above, with the following watchmedo command in your development environment <code>watchmedo auto-restart --directory './' --pattern '*.py' --recursive -- nautobot-server celery worker -l INFO --events</code>.</p>
10573
10573
  </div>
10574
10574
  <h3 id="starting-the-interactive-shell">Starting the Interactive Shell<a class="headerlink" href="#starting-the-interactive-shell" title="Permanent link">&para;</a></h3>
10575
10575
  <p>Nautobot provides an <a href="../../user-guide/administration/tools/nautobot-shell.html">interactive Python shell</a> that sets up the server environment and gives you direct access to the database models for debugging. Nautobot extends this slightly to automatically import models and other utilities.</p>
@@ -9561,7 +9561,7 @@
9561
9561
  <p>Communication among the contributors should always occur via public channels. The following outlines the best ways to communicate and engage on all things Nautobot.</p>
9562
9562
  <h3 id="slack">Slack<a class="headerlink" href="#slack" title="Permanent link">&para;</a></h3>
9563
9563
  <ul>
9564
- <li><a href="http://slack.networktocode.com/"><strong>#nautobot</strong> on Network to Code Slack</a> - Good for quick chats. Avoid any discussion that might need to be referenced later on, as the chat history is not retained long.</li>
9564
+ <li><a href="http://slack.networktocode.com/"><code>#nautobot</code> on Network to Code Slack</a> - Good for quick chats. Avoid any discussion that might need to be referenced later on, as the chat history is not retained long.</li>
9565
9565
  </ul>
9566
9566
  <h3 id="github">GitHub<a class="headerlink" href="#github" title="Permanent link">&para;</a></h3>
9567
9567
  <ul>
@@ -9487,7 +9487,7 @@
9487
9487
  <p>Run the following command to point your terminal to use the docker daemon inside minikube. This will ensure that your up-to-date local image named <code>local/nautobot-final-dev:local-${NAUTOBOT_VER}-py${PYTHON_VER}</code> is used when you build your kubernetes deployments.</p>
9488
9488
  <div class="highlight"><pre><span></span><code><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="nb">eval</span><span class="w"> </span><span class="k">$(</span>minikube<span class="w"> </span>docker-env<span class="k">)</span>
9489
9489
  </code></pre></div>
9490
- <p>Now you can build your nautobot image locally using the <code>invoke build</code> command. After the build is complete, you are ready to build your kubernetes deployments.</p>
9490
+ <p>Now you can build your Nautobot image locally using the <code>invoke build</code> command. After the build is complete, you are ready to build your kubernetes deployments.</p>
9491
9491
  <h3 id="starting-the-deployments-and-services">Starting the Deployments and Services<a class="headerlink" href="#starting-the-deployments-and-services" title="Permanent link">&para;</a></h3>
9492
9492
  <p>Once you have confirmed that you have all the files listed above. You can start the required deployments and services:</p>
9493
9493
  <p>To start all deployments:</p>
@@ -9620,7 +9620,7 @@ Check the override default value checkbox on the <code>Default Job Queue</code>
9620
9620
  <p>You can inspect the job result and the job logs in this page. Notice the two job log entries that reads something like "Creating job pod (pod-name) in namespace default" and "Reading job pod (pod-name) in namespace default". Those entries indicate that a Kubernetes Job pod was executing the job for you.</p>
9621
9621
  <p><img alt="K8s Job Result Completed" src="../../media/development/core/kubernetes/k8s_job_result_completed.png" /></p>
9622
9622
  <h3 id="running-a-scheduled-job">Running a Scheduled Job<a class="headerlink" href="#running-a-scheduled-job" title="Permanent link">&para;</a></h3>
9623
- <p>You can run scheduled jobs as well. In order to run scheduled jobs, you do need celery beat which should already be running from previous steps. To confirm that the celery beat is running, you need to retrieve the celery beat pod name by running the command <code>kubectl get pods</code>. You should see the following output or something similar, copy the pod name with prefix <code>celery-beat-*</code>.</p>
9623
+ <p>You can run scheduled jobs as well. In order to run scheduled jobs, you do need Celery Beat which should already be running from previous steps. To confirm that the Celery Beat is running, you need to retrieve the Celery Beat pod name by running the command <code>kubectl get pods</code>. You should see the following output or something similar, copy the pod name with prefix <code>celery-beat-*</code>.</p>
9624
9624
  <div class="highlight"><pre><span></span><code><a id="__codelineno-29-1" name="__codelineno-29-1" href="#__codelineno-29-1"></a>NAME<span class="w"> </span>READY<span class="w"> </span>STATUS<span class="w"> </span>RESTARTS<span class="w"> </span>AGE
9625
9625
  <a id="__codelineno-29-2" name="__codelineno-29-2" href="#__codelineno-29-2"></a>celery-beat-6fb67477b7-rsw62<span class="w"> </span><span class="m">1</span>/1<span class="w"> </span>Running<span class="w"> </span><span class="m">0</span><span class="w"> </span>10m
9626
9626
  <a id="__codelineno-29-3" name="__codelineno-29-3" href="#__codelineno-29-3"></a>db-8687b48964-gtvtc<span class="w"> </span><span class="m">1</span>/1<span class="w"> </span>Running<span class="w"> </span><span class="m">0</span><span class="w"> </span>10m
@@ -9645,7 +9645,7 @@ Check the override default value checkbox on the <code>Default Job Queue</code>
9645
9645
  <p><img alt="K8s Run Job" src="../../media/development/core/kubernetes/k8s_run_job.png" /></p>
9646
9646
  <p>Fill in the data shown below (for the "Starting date and time" field, pick a date and time that is close to the current date and time) and click on the "Schedule Job" button on the bottom right.</p>
9647
9647
  <p><img alt="K8s Run Scheduled Job Form" src="../../media/development/core/kubernetes/k8s_run_scheduled_job_form.png" /></p>
9648
- <p>To confirm that the Scheduled Job is running, you go back to the terminal that was logging celery beat. You should see the following logs or something similar:</p>
9648
+ <p>To confirm that the Scheduled Job is running, you go back to the terminal that was logging Celery Beat. You should see the following logs or something similar:</p>
9649
9649
  <div class="highlight"><pre><span></span><code><a id="__codelineno-31-1" name="__codelineno-31-1" href="#__codelineno-31-1"></a><span class="o">[</span><span class="m">2024</span>-11-21<span class="w"> </span><span class="m">02</span>:09:57,756:<span class="w"> </span>INFO/MainProcess<span class="o">]</span><span class="w"> </span>DatabaseScheduler:<span class="w"> </span>Schedule<span class="w"> </span>changed.
9650
9650
  <a id="__codelineno-31-2" name="__codelineno-31-2" href="#__codelineno-31-2"></a><span class="o">[</span><span class="m">2024</span>-11-21<span class="w"> </span><span class="m">02</span>:09:57,774:<span class="w"> </span>INFO/MainProcess<span class="o">]</span><span class="w"> </span>Scheduler:<span class="w"> </span>Sending<span class="w"> </span>due<span class="w"> </span>task<span class="w"> </span>Export<span class="w"> </span>Object<span class="w"> </span>List<span class="w"> </span>Hourly_85413d3f-1342-4adf-8d80-11e740ebb907<span class="w"> </span><span class="o">(</span>nautobot.extras.jobs.run_job<span class="o">)</span>
9651
9651
  <a id="__codelineno-31-3" name="__codelineno-31-3" href="#__codelineno-31-3"></a><span class="m">02</span>:09:57.782<span class="w"> </span>INFO<span class="w"> </span>nautobot.extras.utils<span class="w"> </span>utils.py<span class="w"> </span>run_kubernetes_job_and_return_job_result<span class="o">()</span><span class="w"> </span>:
@@ -9588,7 +9588,7 @@ article ul li {
9588
9588
  </ul>
9589
9589
  </li>
9590
9590
  <li>Validate that the field appears correctly in GraphQL<ul>
9591
- <li>If the field is not compatible with GraphQL or shouldn't be included in GraphQL it's possible to exclude a specific field in the GraphQL Type Object associated with this specific model. You can refer to the <a href="https://docs.graphene-python.org/projects/django/en/latest/queries/#specifying-which-fields-to-include">graphene-django documentation</a> for additional information.</li>
9591
+ <li>If the field is not compatible with GraphQL or shouldn't be included in GraphQL it's possible to exclude a specific field in the GraphQL Type Object associated with this specific model. You can refer to the <a href="https://docs.graphene-python.org/projects/django/en/latest/queries/#specifying-which-fields-to-include"><code>graphene-django</code> documentation</a> for additional information.</li>
9592
9592
  </ul>
9593
9593
  </li>
9594
9594
  <li>Add field to model documentation with an appropriate version annotation</li>
@@ -9218,7 +9218,7 @@
9218
9218
  <p>A tab object is being created with the same identifier as an existing object using the <code>name</code> attribute. Then a group is being created with a weight of <code>150</code>, which means it will appear between the already defined <code>Circuits</code> and <code>Provider</code> groups.</p>
9219
9219
  <div class="admonition tip">
9220
9220
  <p class="admonition-title">Tip</p>
9221
- <p>Weights for already existing items can be found in the nautobot source code (in <code>navigation.py</code>) or with a web session open to your nautobot instance, you can inspect an element of the navbar using the developer tools. Each type of element will have an attribute <code>data-{type}-weight</code>. The type can be <code>tab</code>, <code>group</code>, <code>item</code> or <code>button</code>.</p>
9221
+ <p>Weights for already existing items can be found in the Nautobot source code (in <code>navigation.py</code>) or with a web session open to your Nautobot instance, you can inspect an element of the navbar using the developer tools. Each type of element will have an attribute <code>data-{type}-weight</code>. The type can be <code>tab</code>, <code>group</code>, <code>item</code> or <code>button</code>.</p>
9222
9222
  </div>
9223
9223
  <p>This pattern works for modifying all objects in the tree. New items can be added to existing groups and new buttons can be added to existing items.</p>
9224
9224
  <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="n">menu_tabs</span> <span class="o">=</span> <span class="p">(</span>
@@ -9647,7 +9647,7 @@
9647
9647
  <p>Do not squash merge this branch into <code>main</code>. Make sure to select <code>Create a merge commit</code> when merging in GitHub.</p>
9648
9648
  </div>
9649
9649
  <h3 id="create-a-new-release-tag">Create a New Release Tag<a class="headerlink" href="#create-a-new-release-tag" title="Permanent link">&para;</a></h3>
9650
- <p>You need to create a release tag locally so that you can use it later when you draft the new release for nautobot, for example, <code>v1.4.3</code>.
9650
+ <p>You need to create a release tag locally so that you can use it later when you draft the new release for Nautobot, for example, <code>v1.4.3</code>.
9651
9651
  To create the tag locally:</p>
9652
9652
  <div class="highlight"><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a>git<span class="w"> </span>tag<span class="w"> </span>v1.4.3
9653
9653
  </code></pre></div>
@@ -9292,7 +9292,7 @@
9292
9292
  <h1 id="adding-and-updating-nautobot-settings">Adding and Updating Nautobot Settings<a class="headerlink" href="#adding-and-updating-nautobot-settings" title="Permanent link">&para;</a></h1>
9293
9293
  <p>Best practices when adding, updating, and deprecating/removing Nautobot configuration settings.</p>
9294
9294
  <h2 id="consider-constance">Consider Constance<a class="headerlink" href="#consider-constance" title="Permanent link">&para;</a></h2>
9295
- <p>If the setting is one that would be desirable to configure at run time rather than install time, and the nature of the setting is such that it <em>can</em> be changed at run time without requiring a server reload or similar operations to fully take effect, consider implementing it as a <a href="https://django-constance.readthedocs.io/en/latest/">django-constance</a> setting.</p>
9295
+ <p>If the setting is one that would be desirable to configure at run time rather than install time, and the nature of the setting is such that it <em>can</em> be changed at run time without requiring a server reload or similar operations to fully take effect, consider implementing it as a <a href="https://django-constance.readthedocs.io/en/latest/"><code>django-constance</code></a> setting.</p>
9296
9296
  <h3 id="constance-advantages">Constance Advantages<a class="headerlink" href="#constance-advantages" title="Permanent link">&para;</a></h3>
9297
9297
  <ul>
9298
9298
  <li>Constance-enabled settings can be configured through the UI by any user with admin privileges, rather than requiring filesystem access to the Nautobot installation to modify.</li>
@@ -9494,14 +9494,14 @@
9494
9494
  </details>
9495
9495
  <h2 id="branding">Branding<a class="headerlink" href="#branding" title="Permanent link">&para;</a></h2>
9496
9496
  <ul>
9497
- <li>When referring to Nautobot in writing, use the proper form "Nautobot," with the letter N. The lowercase form "nautobot" should be used in code, filenames, etc.</li>
9497
+ <li>When referring to Nautobot in writing, use the proper form "<code>Nautobot</code>," with the letter N. The lowercase form "<code>nautobot</code>" should be used in code, filenames, etc.</li>
9498
9498
  </ul>
9499
9499
  <!-- pyml disable-next-line NAU001 -->
9500
9500
  <ul>
9501
- <li>There is an SVG form of the Nautobot logo at <a href="../../nautobot_logo.svg">nautobot/docs/nautobot_logo.svg</a>. It is preferred to use this logo for all purposes as it scales to arbitrary sizes without loss of resolution. If a raster image is required, the SVG logo should be converted to a PNG image of the prescribed size.</li>
9501
+ <li>There is an SVG form of the Nautobot logo at <a href="../../nautobot_logo.svg"><code>nautobot/docs/nautobot_logo.svg</code></a>. It is preferred to use this logo for all purposes as it scales to arbitrary sizes without loss of resolution. If a raster image is required, the SVG logo should be converted to a PNG image of the prescribed size.</li>
9502
9502
  </ul>
9503
9503
  <h2 id="importing-python-packages">Importing Python Packages<a class="headerlink" href="#importing-python-packages" title="Permanent link">&para;</a></h2>
9504
- <p>To prevent circular dependency errors and improve code readability, the following standards should be followed when importing from other python modules.</p>
9504
+ <p>To prevent circular dependency errors and improve code readability, the following standards should be followed when importing from other Python modules.</p>
9505
9505
  <div class="admonition tip">
9506
9506
  <p class="admonition-title">Tip</p>
9507
9507
  <p>Some of the below rules will be applied automatically when running the <code>ruff</code> linter/formatter against your code. Specifically, you can run <code>invoke ruff --fix</code> to automatically reorder imports.</p>
@@ -9585,7 +9585,7 @@
9585
9585
  </code></pre></div>
9586
9586
  </div>
9587
9587
  <h4 id="convenience-imports">Convenience Imports<a class="headerlink" href="#convenience-imports" title="Permanent link">&para;</a></h4>
9588
- <p>Nautobot uses convenience imports in the same way that <a href="https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/#imports">django</a> implements them. These should be leveraged whenever possible.</p>
9588
+ <p>Nautobot uses convenience imports in the same way that <a href="https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/#imports">Django</a> implements them. These should be leveraged whenever possible.</p>
9589
9589
  <div class="admonition example">
9590
9590
  <p class="admonition-title">Example</p>
9591
9591
  <div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="kn">from</span> <span class="nn">nautobot.extras</span> <span class="kn">import</span> <span class="n">forms</span>
@@ -10427,6 +10427,7 @@ Another example of using the nested reference would be to access <a href="../../
10427
10427
  <li><code>skip_db_logging</code> - Log the message to the console but not to the database</li>
10428
10428
  </ul>
10429
10429
  <p>If a <code>grouping</code> is not provided it will default to the function name that logged the message. The <code>object</code> will default to <code>None</code>.</p>
10430
+ <!-- pyml disable-num-lines 10 proper-names -->
10430
10431
  <div class="admonition example">
10431
10432
  <p class="admonition-title">Example</p>
10432
10433
  <div class="highlight"><pre><span></span><code><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span>
@@ -10437,6 +10438,7 @@ Another example of using the nested reference would be to access <a href="../../
10437
10438
  </code></pre></div>
10438
10439
  </div>
10439
10440
  <p>To skip writing a log entry to the database, set the <code>skip_db_logging</code> key in the "extra" kwarg to <code>True</code> when calling the log function. The output will still be written to the console.</p>
10441
+ <!-- pyml disable-num-lines 10 proper-names -->
10440
10442
  <div class="admonition example">
10441
10443
  <p class="admonition-title">Example</p>
10442
10444
  <div class="highlight"><pre><span></span><code><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="kn">from</span> <span class="nn">nautobot.apps.jobs</span> <span class="kn">import</span> <span class="n">Job</span>
@@ -10526,7 +10528,7 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10526
10528
  <a id="__codelineno-24-5" name="__codelineno-24-5" href="#__codelineno-24-5"></a><span class="k">class</span> <span class="nc">MyJobTestCase</span><span class="p">(</span><span class="n">TransactionTestCase</span><span class="p">):</span>
10527
10529
  <a id="__codelineno-24-6" name="__codelineno-24-6" href="#__codelineno-24-6"></a> <span class="k">def</span> <span class="nf">test_my_job</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
10528
10530
  <a id="__codelineno-24-7" name="__codelineno-24-7" href="#__codelineno-24-7"></a> <span class="c1"># Testing of Job &quot;MyJob&quot; in file &quot;my_job_file.py&quot; in $JOBS_ROOT</span>
10529
- <a id="__codelineno-24-8" name="__codelineno-24-8" href="#__codelineno-24-8"></a> <span class="n">job</span> <span class="o">=</span> <span class="n">Job</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="n">job_class_name</span><span class="o">=</span><span class="s2">&quot;MyJob&quot;</span><span class="p">,</span> <span class="n">module_name</span><span class="o">=</span><span class="s2">&quot;my_job_file&quot;</span><span class="p">,</span> <span class="n">source</span><span class="o">=</span><span class="s2">&quot;local&quot;</span><span class="p">)</span>
10531
+ <a id="__codelineno-24-8" name="__codelineno-24-8" href="#__codelineno-24-8"></a> <span class="n">job</span> <span class="o">=</span> <span class="n">Job</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="n">job_class_name</span><span class="o">=</span><span class="s2">&quot;MyJob&quot;</span><span class="p">,</span> <span class="n">module_name</span><span class="o">=</span><span class="s2">&quot;my_job_file&quot;</span><span class="p">)</span>
10530
10532
  <a id="__codelineno-24-9" name="__codelineno-24-9" href="#__codelineno-24-9"></a> <span class="c1"># or, job = Job.objects.get_for_class_path(&quot;local/my_job_file/MyJob&quot;)</span>
10531
10533
  <a id="__codelineno-24-10" name="__codelineno-24-10" href="#__codelineno-24-10"></a> <span class="n">job_result</span> <span class="o">=</span> <span class="n">run_job_for_testing</span><span class="p">(</span><span class="n">job</span><span class="p">,</span> <span class="n">var1</span><span class="o">=</span><span class="s2">&quot;abc&quot;</span><span class="p">,</span> <span class="n">var2</span><span class="o">=</span><span class="mi">123</span><span class="p">)</span>
10532
10534
  <a id="__codelineno-24-11" name="__codelineno-24-11" href="#__codelineno-24-11"></a>
@@ -10535,6 +10537,11 @@ However the import paths used in the examples requires 1.5.2 and newer.</p>
10535
10537
  <a id="__codelineno-24-14" name="__codelineno-24-14" href="#__codelineno-24-14"></a> <span class="k">for</span> <span class="n">log_entry</span> <span class="ow">in</span> <span class="n">log_entries</span><span class="p">:</span>
10536
10538
  <a id="__codelineno-24-15" name="__codelineno-24-15" href="#__codelineno-24-15"></a> <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">log_entry</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="s2">&quot;...&quot;</span><span class="p">)</span>
10537
10539
  </code></pre></div>
10540
+ <p>The test files should be placed under the <code>tests</code> folder in the app's directory or under JOBS_ROOT. The test can be run via <code>nautobot-server test [path to test in dotted directory format]</code> or <code>pytest [path to test in slash directory format]</code>.</p>
10541
+ <div class="admonition tip">
10542
+ <p class="admonition-title">Tip</p>
10543
+ <p>For running tests directly in the JOBS_ROOT, make sure the <code>JOBS_ROOT</code> environment variable is set.</p>
10544
+ </div>
10538
10545
  <div class="admonition tip">
10539
10546
  <p class="admonition-title">Tip</p>
10540
10547
  <p>For more advanced examples refer to the Nautobot source code, specifically <code>nautobot/extras/tests/test_jobs.py</code>.</p>
@@ -9518,10 +9518,10 @@
9518
9518
  <li><a href="#test_-and-post_run-methods"><code>self.test_*</code> and <code>self.post_run()</code> methods were removed</a></li>
9519
9519
  <li><a href="#read-only-meta-attribute"><code>read_only</code> no longer changes the behavior of Nautobot core</a></li>
9520
9520
  <li><a href="#tracking-job-state"><code>self.job_result</code> should no longer be modified or saved from within a Job</a></li>
9521
- <li><a href="#job-registration">Jobs must be registered in the celery task registry</a></li>
9521
+ <li><a href="#job-registration">Jobs must be registered in the Celery task registry</a></li>
9522
9522
  <li><a href="#tracking-job-state"><code>self.failed</code> removed</a></li>
9523
9523
  <li><a href="#job-logging">The job logging methods have been renamed and their signature changed</a></li>
9524
- <li><a href="#request-property">The <code>request</code> property has been changed to a celery request instead of a Django request</a></li>
9524
+ <li><a href="#request-property">The <code>request</code> property has been changed to a Celery request instead of a Django request</a></li>
9525
9525
  </ul>
9526
9526
  <h2 id="overview">Overview<a class="headerlink" href="#overview" title="Permanent link">&para;</a></h2>
9527
9527
  <p>Some fundamental changes were made to Jobs in Nautobot v2.0. This document outlines the changes that were made and how to migrate your existing Jobs to work in Nautobot v2.0. For more information about the changes made to the Job class and Job model in Nautobot v2.0 see the <a href="../../../user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html#job-changes">Upgrading From Nautobot v1</a> documentation.</p>
@@ -9575,6 +9575,7 @@
9575
9575
  </div>
9576
9576
  <h3 id="database-transaction-handling">Database Transaction Handling<a class="headerlink" href="#database-transaction-handling" title="Permanent link">&para;</a></h3>
9577
9577
  <p>Jobs no longer run in a single atomic <a href="https://docs.djangoproject.com/en/stable/topics/db/transactions/">database transaction</a> by default. If a Job needs to run in a database transaction, you can use the <code>@transaction.atomic</code> decorator on the <code>run()</code> method or wrap parts of your Job code in the <code>with transaction.atomic()</code> context manager.</p>
9578
+ <!-- pyml disable-num-lines 10 proper-names -->
9578
9579
  <div class="admonition example">
9579
9580
  <p class="admonition-title">Example</p>
9580
9581
  <div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">transaction</span>
@@ -9183,12 +9183,13 @@
9183
9183
 
9184
9184
 
9185
9185
  <h1 id="nautobot">Nautobot<a class="headerlink" href="#nautobot" title="Permanent link">&para;</a></h1>
9186
- <!-- pyml disable-num-lines 3 no-inline-html -->
9186
+ <!-- pyml disable-num-lines 5 no-inline-html,proper-names -->
9187
9187
  <figure>
9188
9188
  <img alt="Nautobot Logo" src="assets/nautobot_logo.svg" title="Welcome" width="400" />
9189
9189
  </figure>
9190
9190
  <h2 id="what-is-nautobot">What is Nautobot?<a class="headerlink" href="#what-is-nautobot" title="Permanent link">&para;</a></h2>
9191
9191
  <p>Nautobot is an open source Network Source of Truth and Network Automation Platform built as a web application atop the <a href="https://www.djangoproject.com/">Django</a> Python framework with a <a href="https://www.postgresql.org/">PostgreSQL</a> or <a href="https://www.mysql.com">MySQL</a> database.</p>
9192
+ <!-- pyml disable-next-line proper-names -->
9192
9193
  <p>Try out a live demo at <a href="https://demo.nautobot.com">https://demo.nautobot.com</a></p>
9193
9194
  <h2 id="key-use-cases">Key Use Cases<a class="headerlink" href="#key-use-cases" title="Permanent link">&para;</a></h2>
9194
9195
  <p>Nautobot enables three (3) key use cases.</p>
@@ -9204,7 +9205,7 @@
9204
9205
  </li>
9205
9206
  </ol>
9206
9207
  <h2 id="getting-started">Getting Started<a class="headerlink" href="#getting-started" title="Permanent link">&para;</a></h2>
9207
- <!-- pyml disable-num-lines 30 no-inline-html -->
9208
+ <!-- pyml disable-num-lines 30 no-inline-html,proper-names -->
9208
9209
  <div class="grid cards">
9209
9210
  <ul>
9210
9211
  <li>
Binary file
@@ -9248,7 +9248,7 @@
9248
9248
  <h1 id="application-stack">Application Stack<a class="headerlink" href="#application-stack" title="Permanent link">&para;</a></h1>
9249
9249
  <p>Nautobot is built on the <a href="https://djangoproject.com/">Django</a> Python Web framework and requires either a <a href="https://www.postgresql.org/">PostgreSQL</a> or <a href="https://www.mysql.com">MySQL</a> database backend. It runs as a WSGI service behind your choice of HTTP server.</p>
9250
9250
  <h2 id="components">Components<a class="headerlink" href="#components" title="Permanent link">&para;</a></h2>
9251
- <!-- pyml disable-num-lines 9 no-inline-html -->
9251
+ <!-- pyml disable-num-lines 9 no-inline-html,proper-names -->
9252
9252
  <table>
9253
9253
  <thead>
9254
9254
  <tr>
@@ -9312,7 +9312,7 @@
9312
9312
  </ul>
9313
9313
  </details>
9314
9314
  <details class="version-removed">
9315
- <summary>Removed in version 2.0.0 — django-rq and django-cacheops</summary>
9315
+ <summary>Removed in version 2.0.0 — <code>django-rq</code> and <code>django-cacheops</code></summary>
9316
9316
  <ul>
9317
9317
  <li><code>django-rq</code> support was removed.</li>
9318
9318
  <li><code>django-cacheops</code> usage was removed and replaced with Django's native caching features.</li>