nautobot 2.4.0__py3-none-any.whl → 2.4.1__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.
- nautobot/core/celery/schedulers.py +1 -1
- nautobot/core/filters.py +48 -21
- nautobot/core/jobs/bulk_actions.py +56 -19
- nautobot/core/models/__init__.py +2 -0
- nautobot/core/tables.py +5 -1
- nautobot/core/testing/filters.py +25 -13
- nautobot/core/testing/integration.py +86 -4
- nautobot/core/tests/test_filters.py +209 -246
- nautobot/core/tests/test_jobs.py +250 -93
- nautobot/core/tests/test_models.py +9 -0
- nautobot/core/views/generic.py +80 -48
- nautobot/core/views/mixins.py +34 -6
- nautobot/dcim/api/serializers.py +2 -2
- nautobot/dcim/constants.py +6 -13
- nautobot/dcim/factory.py +6 -1
- nautobot/dcim/tests/integration/test_device_bulk_delete.py +189 -0
- nautobot/dcim/tests/integration/test_device_bulk_edit.py +181 -0
- nautobot/dcim/tests/test_api.py +0 -2
- nautobot/dcim/tests/test_models.py +42 -28
- nautobot/extras/forms/mixins.py +1 -1
- nautobot/extras/jobs.py +15 -6
- nautobot/extras/templatetags/job_buttons.py +4 -4
- nautobot/extras/tests/test_forms.py +13 -0
- nautobot/extras/tests/test_jobs.py +18 -13
- nautobot/extras/tests/test_models.py +6 -0
- nautobot/extras/tests/test_views.py +4 -3
- nautobot/ipam/tests/test_api.py +20 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +36 -1
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/release-notes/version-2.4.html +108 -0
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +288 -288
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/wireless/tests/test_views.py +22 -1
- {nautobot-2.4.0.dist-info → nautobot-2.4.1.dist-info}/METADATA +2 -2
- {nautobot-2.4.0.dist-info → nautobot-2.4.1.dist-info}/RECORD +40 -38
- {nautobot-2.4.0.dist-info → nautobot-2.4.1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.0.dist-info → nautobot-2.4.1.dist-info}/NOTICE +0 -0
- {nautobot-2.4.0.dist-info → nautobot-2.4.1.dist-info}/WHEEL +0 -0
- {nautobot-2.4.0.dist-info → nautobot-2.4.1.dist-info}/entry_points.txt +0 -0
|
@@ -37,7 +37,7 @@ from nautobot.extras.choices import (
|
|
|
37
37
|
ObjectChangeEventContextChoices,
|
|
38
38
|
)
|
|
39
39
|
from nautobot.extras.context_managers import change_logging, JobHookChangeContext, web_request_context
|
|
40
|
-
from nautobot.extras.jobs import get_job, get_jobs
|
|
40
|
+
from nautobot.extras.jobs import BaseJob, get_job, get_jobs
|
|
41
41
|
from nautobot.extras.models import Job, JobQueue
|
|
42
42
|
from nautobot.extras.models.jobs import JobLogEntry
|
|
43
43
|
|
|
@@ -47,6 +47,11 @@ class JobTest(TestCase):
|
|
|
47
47
|
Test job features that don't require a transaction test case.
|
|
48
48
|
"""
|
|
49
49
|
|
|
50
|
+
def test_as_form_no_job_model(self):
|
|
51
|
+
"""Job.as_form() test with no corresponding job_model (https://github.com/nautobot/nautobot/issues/6773)."""
|
|
52
|
+
form = BaseJob.as_form()
|
|
53
|
+
self.assertSequenceEqual(list(form.fields.keys()), ["_job_queue", "_profile"])
|
|
54
|
+
|
|
50
55
|
def test_field_default(self):
|
|
51
56
|
"""
|
|
52
57
|
Job test with field that is a default value that is falsey.
|
|
@@ -55,7 +60,7 @@ class JobTest(TestCase):
|
|
|
55
60
|
module = "field_default"
|
|
56
61
|
name = "TestFieldDefault"
|
|
57
62
|
job_class = get_job(f"{module}.{name}")
|
|
58
|
-
form = job_class
|
|
63
|
+
form = job_class.as_form()
|
|
59
64
|
|
|
60
65
|
self.assertInHTML(
|
|
61
66
|
"""<tr><th><label for="id_var_int">Var int:</label></th><td>
|
|
@@ -74,7 +79,7 @@ class JobTest(TestCase):
|
|
|
74
79
|
module = "field_order"
|
|
75
80
|
name = "TestFieldOrder"
|
|
76
81
|
job_class = get_job(f"{module}.{name}")
|
|
77
|
-
form = job_class
|
|
82
|
+
form = job_class.as_form()
|
|
78
83
|
self.assertSequenceEqual(list(form.fields.keys()), ["var1", "var2", "var23", "_job_queue", "_profile"])
|
|
79
84
|
|
|
80
85
|
def test_no_field_order(self):
|
|
@@ -84,7 +89,7 @@ class JobTest(TestCase):
|
|
|
84
89
|
module = "no_field_order"
|
|
85
90
|
name = "TestNoFieldOrder"
|
|
86
91
|
job_class = get_job(f"{module}.{name}")
|
|
87
|
-
form = job_class
|
|
92
|
+
form = job_class.as_form()
|
|
88
93
|
self.assertSequenceEqual(list(form.fields.keys()), ["var23", "var2", "_job_queue", "_profile"])
|
|
89
94
|
|
|
90
95
|
def test_no_field_order_inherited_variable(self):
|
|
@@ -94,7 +99,7 @@ class JobTest(TestCase):
|
|
|
94
99
|
module = "no_field_order"
|
|
95
100
|
name = "TestDefaultFieldOrderWithInheritance"
|
|
96
101
|
job_class = get_job(f"{module}.{name}")
|
|
97
|
-
form = job_class
|
|
102
|
+
form = job_class.as_form()
|
|
98
103
|
self.assertSequenceEqual(
|
|
99
104
|
list(form.fields.keys()),
|
|
100
105
|
["testvar1", "b_testvar2", "a_testvar3", "_job_queue", "_profile"],
|
|
@@ -109,14 +114,14 @@ class JobTest(TestCase):
|
|
|
109
114
|
# not overridden on job model, initial form field value should match job class
|
|
110
115
|
job_model.dryrun_default_override = False
|
|
111
116
|
job_model.save()
|
|
112
|
-
form = job_class
|
|
117
|
+
form = job_class.as_form()
|
|
113
118
|
self.assertEqual(form.fields["dryrun"].initial, job_class.dryrun_default)
|
|
114
119
|
|
|
115
120
|
# overridden on job model, initial form field value should match job model
|
|
116
121
|
job_model.dryrun_default_override = True
|
|
117
122
|
job_model.dryrun_default = not job_class.dryrun_default
|
|
118
123
|
job_model.save()
|
|
119
|
-
form = job_class
|
|
124
|
+
form = job_class.as_form()
|
|
120
125
|
self.assertEqual(form.fields["dryrun"].initial, job_model.dryrun_default)
|
|
121
126
|
|
|
122
127
|
def test_job_task_queues_setter(self):
|
|
@@ -145,7 +150,7 @@ class JobTest(TestCase):
|
|
|
145
150
|
name="irrelevant", defaults={"queue_type": JobQueueTypeChoices.TYPE_CELERY}
|
|
146
151
|
)
|
|
147
152
|
job_model.job_queues.set([jq_1, jq_2])
|
|
148
|
-
form = job_class
|
|
153
|
+
form = job_class.as_form()
|
|
149
154
|
self.assertQuerySetEqual(
|
|
150
155
|
form.fields["_job_queue"].queryset,
|
|
151
156
|
models.JobQueue.objects.filter(jobs=job_model),
|
|
@@ -576,7 +581,7 @@ class JobTransactionTest(TransactionTestCase):
|
|
|
576
581
|
"ipv6_with_mask": "2001:db8::1/64",
|
|
577
582
|
"ipv6_network": "2001:db8::/64",
|
|
578
583
|
}
|
|
579
|
-
form = job_class
|
|
584
|
+
form = job_class.as_form(form_data)
|
|
580
585
|
self.assertTrue(form.is_valid())
|
|
581
586
|
|
|
582
587
|
# Prepare the job data
|
|
@@ -786,7 +791,7 @@ class JobFileUploadTest(TransactionTestCase):
|
|
|
786
791
|
|
|
787
792
|
# Serialize the file to FileProxy
|
|
788
793
|
data = {"file": self.test_file}
|
|
789
|
-
form = job_class
|
|
794
|
+
form = job_class.as_form(files=data)
|
|
790
795
|
self.assertTrue(form.is_valid())
|
|
791
796
|
serialized_data = job_class.serialize_data(form.cleaned_data)
|
|
792
797
|
|
|
@@ -816,7 +821,7 @@ class JobFileUploadTest(TransactionTestCase):
|
|
|
816
821
|
|
|
817
822
|
# Serialize the file to FileProxy
|
|
818
823
|
data = {"file": self.test_file}
|
|
819
|
-
form = job_class
|
|
824
|
+
form = job_class.as_form(files=data)
|
|
820
825
|
self.assertTrue(form.is_valid())
|
|
821
826
|
serialized_data = job_class.serialize_data(form.cleaned_data)
|
|
822
827
|
|
|
@@ -1021,7 +1026,7 @@ class JobButtonReceiverTest(TestCase):
|
|
|
1021
1026
|
module = "job_button_receiver"
|
|
1022
1027
|
name = "TestJobButtonReceiverSimple"
|
|
1023
1028
|
job_class, _job_model = get_job_class_and_model(module, name)
|
|
1024
|
-
form = job_class
|
|
1029
|
+
form = job_class.as_form()
|
|
1025
1030
|
self.assertSequenceEqual(list(form.fields.keys()), ["object_pk", "object_model_name", "_job_queue", "_profile"])
|
|
1026
1031
|
|
|
1027
1032
|
def test_hidden(self):
|
|
@@ -1084,7 +1089,7 @@ class JobHookReceiverTest(TestCase):
|
|
|
1084
1089
|
module = "job_hook_receiver"
|
|
1085
1090
|
name = "TestJobHookReceiverLog"
|
|
1086
1091
|
job_class, _job_model = get_job_class_and_model(module, name)
|
|
1087
|
-
form = job_class
|
|
1092
|
+
form = job_class.as_form()
|
|
1088
1093
|
self.assertSequenceEqual(list(form.fields.keys()), ["object_change", "_job_queue", "_profile"])
|
|
1089
1094
|
|
|
1090
1095
|
def test_hidden(self):
|
|
@@ -2146,6 +2146,12 @@ class ScheduledJobTest(ModelTestCases.BaseModelTestCase):
|
|
|
2146
2146
|
# entry = NautobotScheduleEntry(model=sj)
|
|
2147
2147
|
# scheduler = NautobotDatabaseScheduler(app=entry.app)
|
|
2148
2148
|
# scheduler.apply_async(entry=entry, producer=None, advance=False)
|
|
2149
|
+
# Check scheduled job runs correctly with no job queue
|
|
2150
|
+
# sj.job_queue = None
|
|
2151
|
+
# sj.save()
|
|
2152
|
+
# entry = NautobotScheduleEntry(model=sj)
|
|
2153
|
+
# scheduler = NautobotDatabaseScheduler(app=entry.app)
|
|
2154
|
+
# scheduler.apply_async(entry=entry, producer=None, advance=False)
|
|
2149
2155
|
|
|
2150
2156
|
|
|
2151
2157
|
class SecretTest(ModelTestCases.BaseModelTestCase):
|
|
@@ -2955,8 +2955,9 @@ class JobButtonRenderingTestCase(TestCase):
|
|
|
2955
2955
|
response = self.client.get(self.location_type.get_absolute_url(), follow=True)
|
|
2956
2956
|
self.assertEqual(response.status_code, 200)
|
|
2957
2957
|
content = extract_page_body(response.content.decode(response.charset))
|
|
2958
|
-
job_queues = self.job.job_queues.all()
|
|
2959
|
-
|
|
2958
|
+
job_queues = self.job.job_queues.all()
|
|
2959
|
+
_job_queue = job_queues[0]
|
|
2960
|
+
self.assertIn(f'<input type="hidden" name="_job_queue" value="{_job_queue.pk}">', content, content)
|
|
2960
2961
|
|
|
2961
2962
|
self.job.job_queues_override = False
|
|
2962
2963
|
self.job.save()
|
|
@@ -2965,7 +2966,7 @@ class JobButtonRenderingTestCase(TestCase):
|
|
|
2965
2966
|
self.assertEqual(response.status_code, 200)
|
|
2966
2967
|
content = extract_page_body(response.content.decode(response.charset))
|
|
2967
2968
|
self.assertIn(
|
|
2968
|
-
f'<input type="hidden" name="_job_queue" value="{self.job.default_job_queue.
|
|
2969
|
+
f'<input type="hidden" name="_job_queue" value="{self.job.default_job_queue.pk}">', content, content
|
|
2969
2970
|
)
|
|
2970
2971
|
|
|
2971
2972
|
def test_view_object_with_unsafe_text(self):
|
nautobot/ipam/tests/test_api.py
CHANGED
|
@@ -965,6 +965,26 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
965
965
|
self.assertHttpStatus(response, status.HTTP_200_OK)
|
|
966
966
|
self.assertEqual(len(response.data), 0)
|
|
967
967
|
|
|
968
|
+
def test_prefix_type_filter(self):
|
|
969
|
+
url = reverse("ipam-api:prefix-list")
|
|
970
|
+
self.add_permissions("ipam.view_prefix")
|
|
971
|
+
|
|
972
|
+
test_cases = {
|
|
973
|
+
"ic": "WOR",
|
|
974
|
+
"isw": "NET",
|
|
975
|
+
"iew": "WORK",
|
|
976
|
+
"ie": "NETWORK",
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
for type_filter_lookup, type_filter_value in test_cases.items():
|
|
980
|
+
with self.subTest(render_as=type_filter_lookup):
|
|
981
|
+
response = self.client.get(f"{url}?type__{type_filter_lookup}={type_filter_value}", **self.header)
|
|
982
|
+
|
|
983
|
+
# Assert that the prefixes returned match the type filter
|
|
984
|
+
self.assertEqual(response.status_code, 200)
|
|
985
|
+
for result in response.data["results"]:
|
|
986
|
+
self.assertEqual(result["type"]["value"], "network")
|
|
987
|
+
|
|
968
988
|
|
|
969
989
|
class PrefixLocationAssignmentTest(APIViewTestCases.APIViewTestCase):
|
|
970
990
|
model = PrefixLocationAssignment
|
|
@@ -8394,6 +8394,15 @@
|
|
|
8394
8394
|
</span>
|
|
8395
8395
|
</a>
|
|
8396
8396
|
|
|
8397
|
+
</li>
|
|
8398
|
+
|
|
8399
|
+
<li class="md-nav__item">
|
|
8400
|
+
<a href="#nautobot.apps.testing.SeleniumTestCase.fill_filters_select2_field" class="md-nav__link">
|
|
8401
|
+
<span class="md-ellipsis">
|
|
8402
|
+
fill_filters_select2_field
|
|
8403
|
+
</span>
|
|
8404
|
+
</a>
|
|
8405
|
+
|
|
8397
8406
|
</li>
|
|
8398
8407
|
|
|
8399
8408
|
<li class="md-nav__item">
|
|
@@ -11570,6 +11579,15 @@
|
|
|
11570
11579
|
</span>
|
|
11571
11580
|
</a>
|
|
11572
11581
|
|
|
11582
|
+
</li>
|
|
11583
|
+
|
|
11584
|
+
<li class="md-nav__item">
|
|
11585
|
+
<a href="#nautobot.apps.testing.SeleniumTestCase.fill_filters_select2_field" class="md-nav__link">
|
|
11586
|
+
<span class="md-ellipsis">
|
|
11587
|
+
fill_filters_select2_field
|
|
11588
|
+
</span>
|
|
11589
|
+
</a>
|
|
11590
|
+
|
|
11573
11591
|
</li>
|
|
11574
11592
|
|
|
11575
11593
|
<li class="md-nav__item">
|
|
@@ -14769,6 +14787,23 @@ so there is no need to run <code>collectstatic</code> prior to running tests.</p
|
|
|
14769
14787
|
<div class="doc doc-object doc-function">
|
|
14770
14788
|
|
|
14771
14789
|
|
|
14790
|
+
<h3 id="nautobot.apps.testing.SeleniumTestCase.fill_filters_select2_field" class="doc doc-heading">
|
|
14791
|
+
<code class="highlight language-python"><span class="n">fill_filters_select2_field</span><span class="p">(</span><span class="n">field_name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span></code>
|
|
14792
|
+
|
|
14793
|
+
<a href="#nautobot.apps.testing.SeleniumTestCase.fill_filters_select2_field" class="headerlink" title="Permanent link">¶</a></h3>
|
|
14794
|
+
|
|
14795
|
+
|
|
14796
|
+
<div class="doc doc-contents ">
|
|
14797
|
+
|
|
14798
|
+
<p>Helper function to fill a Select2 single selection field on filters modals.</p>
|
|
14799
|
+
|
|
14800
|
+
</div>
|
|
14801
|
+
|
|
14802
|
+
</div>
|
|
14803
|
+
|
|
14804
|
+
<div class="doc doc-object doc-function">
|
|
14805
|
+
|
|
14806
|
+
|
|
14772
14807
|
<h3 id="nautobot.apps.testing.SeleniumTestCase.fill_select2_field" class="doc doc-heading">
|
|
14773
14808
|
<code class="highlight language-python"><span class="n">fill_select2_field</span><span class="p">(</span><span class="n">field_name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span></code>
|
|
14774
14809
|
|
|
@@ -14777,7 +14812,7 @@ so there is no need to run <code>collectstatic</code> prior to running tests.</p
|
|
|
14777
14812
|
|
|
14778
14813
|
<div class="doc doc-contents ">
|
|
14779
14814
|
|
|
14780
|
-
<p>Helper function to fill a Select2 single selection field.</p>
|
|
14815
|
+
<p>Helper function to fill a Select2 single selection field on add/edit forms.</p>
|
|
14781
14816
|
|
|
14782
14817
|
</div>
|
|
14783
14818
|
|
|
Binary file
|
|
@@ -8686,6 +8686,48 @@
|
|
|
8686
8686
|
</ul>
|
|
8687
8687
|
</nav>
|
|
8688
8688
|
|
|
8689
|
+
</li>
|
|
8690
|
+
|
|
8691
|
+
<li class="md-nav__item">
|
|
8692
|
+
<a href="#v241-2025-01-21" class="md-nav__link">
|
|
8693
|
+
<span class="md-ellipsis">
|
|
8694
|
+
v2.4.1 (2025-01-21)
|
|
8695
|
+
</span>
|
|
8696
|
+
</a>
|
|
8697
|
+
|
|
8698
|
+
<nav class="md-nav" aria-label="v2.4.1 (2025-01-21)">
|
|
8699
|
+
<ul class="md-nav__list">
|
|
8700
|
+
|
|
8701
|
+
<li class="md-nav__item">
|
|
8702
|
+
<a href="#security-in-v241" class="md-nav__link">
|
|
8703
|
+
<span class="md-ellipsis">
|
|
8704
|
+
Security in v2.4.1
|
|
8705
|
+
</span>
|
|
8706
|
+
</a>
|
|
8707
|
+
|
|
8708
|
+
</li>
|
|
8709
|
+
|
|
8710
|
+
<li class="md-nav__item">
|
|
8711
|
+
<a href="#fixed-in-v241" class="md-nav__link">
|
|
8712
|
+
<span class="md-ellipsis">
|
|
8713
|
+
Fixed in v2.4.1
|
|
8714
|
+
</span>
|
|
8715
|
+
</a>
|
|
8716
|
+
|
|
8717
|
+
</li>
|
|
8718
|
+
|
|
8719
|
+
<li class="md-nav__item">
|
|
8720
|
+
<a href="#housekeeping-in-v241" class="md-nav__link">
|
|
8721
|
+
<span class="md-ellipsis">
|
|
8722
|
+
Housekeeping in v2.4.1
|
|
8723
|
+
</span>
|
|
8724
|
+
</a>
|
|
8725
|
+
|
|
8726
|
+
</li>
|
|
8727
|
+
|
|
8728
|
+
</ul>
|
|
8729
|
+
</nav>
|
|
8730
|
+
|
|
8689
8731
|
</li>
|
|
8690
8732
|
|
|
8691
8733
|
<li class="md-nav__item">
|
|
@@ -9672,6 +9714,48 @@
|
|
|
9672
9714
|
</ul>
|
|
9673
9715
|
</nav>
|
|
9674
9716
|
|
|
9717
|
+
</li>
|
|
9718
|
+
|
|
9719
|
+
<li class="md-nav__item">
|
|
9720
|
+
<a href="#v241-2025-01-21" class="md-nav__link">
|
|
9721
|
+
<span class="md-ellipsis">
|
|
9722
|
+
v2.4.1 (2025-01-21)
|
|
9723
|
+
</span>
|
|
9724
|
+
</a>
|
|
9725
|
+
|
|
9726
|
+
<nav class="md-nav" aria-label="v2.4.1 (2025-01-21)">
|
|
9727
|
+
<ul class="md-nav__list">
|
|
9728
|
+
|
|
9729
|
+
<li class="md-nav__item">
|
|
9730
|
+
<a href="#security-in-v241" class="md-nav__link">
|
|
9731
|
+
<span class="md-ellipsis">
|
|
9732
|
+
Security in v2.4.1
|
|
9733
|
+
</span>
|
|
9734
|
+
</a>
|
|
9735
|
+
|
|
9736
|
+
</li>
|
|
9737
|
+
|
|
9738
|
+
<li class="md-nav__item">
|
|
9739
|
+
<a href="#fixed-in-v241" class="md-nav__link">
|
|
9740
|
+
<span class="md-ellipsis">
|
|
9741
|
+
Fixed in v2.4.1
|
|
9742
|
+
</span>
|
|
9743
|
+
</a>
|
|
9744
|
+
|
|
9745
|
+
</li>
|
|
9746
|
+
|
|
9747
|
+
<li class="md-nav__item">
|
|
9748
|
+
<a href="#housekeeping-in-v241" class="md-nav__link">
|
|
9749
|
+
<span class="md-ellipsis">
|
|
9750
|
+
Housekeeping in v2.4.1
|
|
9751
|
+
</span>
|
|
9752
|
+
</a>
|
|
9753
|
+
|
|
9754
|
+
</li>
|
|
9755
|
+
|
|
9756
|
+
</ul>
|
|
9757
|
+
</nav>
|
|
9758
|
+
|
|
9675
9759
|
</li>
|
|
9676
9760
|
|
|
9677
9761
|
<li class="md-nav__item">
|
|
@@ -9946,6 +10030,30 @@
|
|
|
9946
10030
|
|
|
9947
10031
|
<!-- towncrier release notes start -->
|
|
9948
10032
|
|
|
10033
|
+
<h2 id="v241-2025-01-21">v2.4.1 (2025-01-21)<a class="headerlink" href="#v241-2025-01-21" title="Permanent link">¶</a></h2>
|
|
10034
|
+
<h3 id="security-in-v241">Security in v2.4.1<a class="headerlink" href="#security-in-v241" title="Permanent link">¶</a></h3>
|
|
10035
|
+
<ul>
|
|
10036
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6780">#6780</a> - Updated <code>Django</code> to <code>4.2.18</code> to address <code>CVE-2024-56374</code>.</li>
|
|
10037
|
+
</ul>
|
|
10038
|
+
<h3 id="fixed-in-v241">Fixed in v2.4.1<a class="headerlink" href="#fixed-in-v241" title="Permanent link">¶</a></h3>
|
|
10039
|
+
<ul>
|
|
10040
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6427">#6427</a> - Fixed a bug which allowed several wireless interface types to accept cables.</li>
|
|
10041
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6489">#6489</a> - Fixed partial-match filters (such as <code>__ic</code> and <code>__isw</code>) on fields that have restricted choices (<code>Prefix.type</code>, <code>Interface.type</code>, etc.) so that partial values are no longer rejected.</li>
|
|
10042
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6763">#6763</a> - Fixed the issue where the Wireless Network detail view fails to render when any record in the Controller Managed Device Groups table is missing a VLAN.</li>
|
|
10043
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6770">#6770</a> - Fixed breakage of JobButton functionality.</li>
|
|
10044
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6771">#6771</a> - Reverted breaking changes to various generic View base class attributes.</li>
|
|
10045
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6773">#6773</a> - Fixed an exception when trying to render a Job class to a form when no corresponding Job database record exists.</li>
|
|
10046
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6776">#6776</a> - Fixed <code>FilterTestCase.generic_filter_tests</code> to again be optional as intended.</li>
|
|
10047
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6779">#6779</a> - Fixed Object Bulk Delete and Object Bulk Edit functionalities.</li>
|
|
10048
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6783">#6783</a> - Fixed <code>NautobotDataBaseScheduler</code> unable to run Scheduled Jobs without job queues assigned.</li>
|
|
10049
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6786">#6786</a> - Fixed incorrect marking of <code>capabilities</code> field as required on Controller and ControllerManagedDeviceGroup REST APIs.</li>
|
|
10050
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6792">#6792</a> - Fixed <code>natural_key_field_lookups</code> for proxy models.</li>
|
|
10051
|
+
</ul>
|
|
10052
|
+
<h3 id="housekeeping-in-v241">Housekeeping in v2.4.1<a class="headerlink" href="#housekeeping-in-v241" title="Permanent link">¶</a></h3>
|
|
10053
|
+
<ul>
|
|
10054
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6768">#6768</a> - Fixed link to changelog fragment documentation.</li>
|
|
10055
|
+
<li><a href="https://github.com/nautobot/nautobot/issues/6794">#6794</a> - Fixed Device factory to ensure that it only selects SoftwareImageFiles that are permitted for a given Device.</li>
|
|
10056
|
+
</ul>
|
|
9949
10057
|
<h2 id="v240-2025-01-10">v2.4.0 (2025-01-10)<a class="headerlink" href="#v240-2025-01-10" title="Permanent link">¶</a></h2>
|
|
9950
10058
|
<h3 id="added-in-v240">Added in v2.4.0<a class="headerlink" href="#added-in-v240" title="Permanent link">¶</a></h3>
|
|
9951
10059
|
<ul>
|