nautobot 2.3.15__py3-none-any.whl → 2.3.16__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/circuits/views.py +3 -3
- nautobot/cloud/models.py +1 -1
- nautobot/core/api/fields.py +5 -5
- nautobot/core/api/serializers.py +9 -9
- nautobot/core/api/views.py +3 -2
- nautobot/core/apps/__init__.py +5 -2
- nautobot/core/celery/schedulers.py +1 -1
- nautobot/core/filters.py +19 -16
- nautobot/core/forms/fields.py +5 -5
- nautobot/core/graphql/types.py +1 -1
- nautobot/core/jobs/__init__.py +4 -4
- nautobot/core/jobs/cleanup.py +1 -1
- nautobot/core/jobs/groups.py +1 -1
- nautobot/core/management/commands/validate_models.py +1 -1
- nautobot/core/models/__init__.py +1 -1
- nautobot/core/models/query_functions.py +2 -2
- nautobot/core/models/tree_queries.py +2 -2
- nautobot/core/tables.py +5 -5
- nautobot/core/testing/filters.py +7 -3
- nautobot/core/testing/views.py +5 -0
- nautobot/core/tests/runner.py +1 -1
- nautobot/core/views/generic.py +51 -43
- nautobot/core/views/mixins.py +21 -11
- nautobot/dcim/api/serializers.py +48 -48
- nautobot/dcim/forms.py +2 -0
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/models/device_component_templates.py +2 -2
- nautobot/dcim/models/device_components.py +22 -20
- nautobot/dcim/models/devices.py +1 -1
- nautobot/dcim/models/locations.py +3 -3
- nautobot/dcim/models/power.py +6 -5
- nautobot/dcim/models/racks.py +4 -4
- nautobot/dcim/tables/__init__.py +3 -3
- nautobot/dcim/tables/devicetypes.py +2 -2
- nautobot/dcim/tests/test_filters.py +1 -0
- nautobot/dcim/tests/test_graphql.py +52 -0
- nautobot/dcim/tests/test_models.py +4 -1
- nautobot/dcim/views.py +1 -1
- nautobot/extras/api/customfields.py +2 -2
- nautobot/extras/api/serializers.py +72 -69
- nautobot/extras/api/views.py +4 -4
- nautobot/extras/health_checks.py +1 -2
- nautobot/extras/jobs.py +5 -5
- nautobot/extras/managers.py +3 -1
- nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
- nautobot/extras/models/groups.py +13 -9
- nautobot/extras/models/jobs.py +4 -4
- nautobot/extras/models/models.py +2 -2
- nautobot/extras/plugins/views.py +1 -1
- nautobot/extras/tables.py +5 -5
- nautobot/extras/test_jobs/api_test_job.py +1 -1
- nautobot/extras/test_jobs/atomic_transaction.py +2 -2
- nautobot/extras/test_jobs/dry_run.py +1 -1
- nautobot/extras/test_jobs/fail.py +5 -5
- nautobot/extras/test_jobs/file_output.py +1 -1
- nautobot/extras/test_jobs/file_upload_fail.py +1 -1
- nautobot/extras/test_jobs/file_upload_pass.py +1 -1
- nautobot/extras/test_jobs/ipaddress_vars.py +3 -1
- nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
- nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
- nautobot/extras/test_jobs/log_redaction.py +1 -1
- nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
- nautobot/extras/test_jobs/modify_db.py +1 -1
- nautobot/extras/test_jobs/object_var_optional.py +1 -1
- nautobot/extras/test_jobs/object_var_required.py +1 -1
- nautobot/extras/test_jobs/object_vars.py +1 -1
- nautobot/extras/test_jobs/pass.py +3 -3
- nautobot/extras/test_jobs/profiling.py +1 -1
- nautobot/extras/test_jobs/relative_import.py +3 -3
- nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
- nautobot/extras/test_jobs/task_queues.py +1 -1
- nautobot/extras/tests/test_api.py +13 -13
- nautobot/extras/tests/test_customfields.py +1 -1
- nautobot/extras/tests/test_datasources.py +2 -1
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_filters.py +6 -6
- nautobot/extras/tests/test_jobs.py +11 -11
- nautobot/extras/tests/test_models.py +10 -10
- nautobot/extras/tests/test_relationships.py +1 -1
- nautobot/extras/tests/test_views.py +16 -16
- nautobot/extras/views.py +20 -16
- nautobot/ipam/api/fields.py +3 -3
- nautobot/ipam/api/serializers.py +33 -33
- nautobot/ipam/api/views.py +37 -61
- nautobot/ipam/querysets.py +2 -2
- nautobot/ipam/tests/test_api.py +12 -1
- nautobot/ipam/tests/test_forms.py +51 -47
- nautobot/ipam/tests/test_migrations.py +30 -30
- nautobot/ipam/tests/test_querysets.py +14 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.3.html +181 -99
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +270 -270
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/users/admin.py +1 -1
- nautobot/users/api/serializers.py +4 -4
- nautobot/users/api/views.py +1 -1
- nautobot/virtualization/api/serializers.py +4 -4
- {nautobot-2.3.15.dist-info → nautobot-2.3.16.dist-info}/METADATA +1 -1
- {nautobot-2.3.15.dist-info → nautobot-2.3.16.dist-info}/RECORD +106 -106
- {nautobot-2.3.15.dist-info → nautobot-2.3.16.dist-info}/WHEEL +1 -1
- {nautobot-2.3.15.dist-info → nautobot-2.3.16.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.15.dist-info → nautobot-2.3.16.dist-info}/NOTICE +0 -0
- {nautobot-2.3.15.dist-info → nautobot-2.3.16.dist-info}/entry_points.txt +0 -0
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"""Test IPAM forms."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations # python 3.8
|
|
4
|
+
|
|
5
|
+
from django.forms import Form
|
|
3
6
|
from django.test import TestCase
|
|
4
7
|
|
|
5
8
|
from nautobot.core.testing.forms import FormTestCases
|
|
@@ -9,62 +12,63 @@ from nautobot.ipam.choices import IPAddressTypeChoices
|
|
|
9
12
|
from nautobot.ipam.models import IPAddress, Namespace, Prefix
|
|
10
13
|
|
|
11
14
|
|
|
12
|
-
class
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
15
|
+
class NetworkFormTestCases:
|
|
16
|
+
class BaseNetworkFormTest(TestCase):
|
|
17
|
+
form_class: type[Form]
|
|
18
|
+
field_name: str
|
|
19
|
+
object_name: str
|
|
20
|
+
extra_data = {}
|
|
21
|
+
|
|
22
|
+
def setUp(self):
|
|
23
|
+
super().setUp()
|
|
24
|
+
self.namespace = Namespace.objects.create(name="IPAM Form Test")
|
|
25
|
+
self.status = Status.objects.get(name="Active")
|
|
26
|
+
self.prefix_status = Status.objects.get_for_model(Prefix).first()
|
|
27
|
+
self.ip_status = Status.objects.get_for_model(IPAddress).first()
|
|
28
|
+
self.parent = Prefix.objects.create(
|
|
29
|
+
prefix="192.168.1.0/24", namespace=self.namespace, status=self.prefix_status
|
|
30
|
+
)
|
|
31
|
+
self.parent2 = Prefix.objects.create(
|
|
32
|
+
prefix="192.168.0.0/16", namespace=self.namespace, status=self.prefix_status
|
|
33
|
+
)
|
|
34
|
+
self.parent6 = Prefix.objects.create(
|
|
35
|
+
prefix="2001:0db8::/40", namespace=self.namespace, status=self.prefix_status
|
|
36
|
+
)
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
def test_valid_ip_address(self):
|
|
39
|
+
data = {self.field_name: "192.168.2.0/24", "namespace": self.namespace, "status": self.status}
|
|
40
|
+
data.update(self.extra_data)
|
|
41
|
+
form = self.form_class(data)
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
self.assertTrue(form.is_valid())
|
|
44
|
+
self.assertTrue(form.save())
|
|
41
45
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
def test_address_invalid_ipv4(self):
|
|
47
|
+
data = {self.field_name: "192.168.0.1/64", "namespace": self.namespace, "status": self.status}
|
|
48
|
+
data.update(self.extra_data)
|
|
49
|
+
form = self.form_class(data)
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
self.assertFalse(form.is_valid())
|
|
52
|
+
self.assertEqual("Please specify a valid IPv4 or IPv6 address.", form.errors[self.field_name][0])
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
def test_address_zero_mask(self):
|
|
55
|
+
data = {self.field_name: "192.168.0.1/0", "namespace": self.namespace, "status": self.status}
|
|
56
|
+
data.update(self.extra_data)
|
|
57
|
+
form = self.form_class(data)
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
# With the advent of `Prefix.parent`, it's now possible to create a /0 .
|
|
60
|
+
self.assertTrue(form.is_valid())
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
def test_address_missing_mask(self):
|
|
63
|
+
data = {self.field_name: "192.168.0.1", "namespace": self.namespace, "status": self.status}
|
|
64
|
+
data.update(self.extra_data)
|
|
65
|
+
form = self.form_class(data)
|
|
62
66
|
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
self.assertFalse(form.is_valid())
|
|
68
|
+
self.assertEqual("CIDR mask (e.g. /24) is required.", form.errors[self.field_name][0])
|
|
65
69
|
|
|
66
70
|
|
|
67
|
-
class PrefixFormTest(BaseNetworkFormTest, FormTestCases.BaseFormTestCase):
|
|
71
|
+
class PrefixFormTest(NetworkFormTestCases.BaseNetworkFormTest, FormTestCases.BaseFormTestCase):
|
|
68
72
|
form_class = forms.PrefixForm
|
|
69
73
|
field_name = "prefix"
|
|
70
74
|
object_name = "prefix"
|
|
@@ -79,7 +83,7 @@ class PrefixFormTest(BaseNetworkFormTest, FormTestCases.BaseFormTestCase):
|
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
|
|
82
|
-
class IPAddressFormTest(BaseNetworkFormTest
|
|
86
|
+
class IPAddressFormTest(NetworkFormTestCases.BaseNetworkFormTest):
|
|
83
87
|
form_class = forms.IPAddressForm
|
|
84
88
|
field_name = "address"
|
|
85
89
|
object_name = "IP address"
|
|
@@ -29,29 +29,29 @@ class AggregateToPrefixMigrationTestCase(NautobotDataMigrationTest):
|
|
|
29
29
|
request_id=uuid.uuid4(),
|
|
30
30
|
)
|
|
31
31
|
|
|
32
|
-
def populateDataBeforeMigration(self,
|
|
32
|
+
def populateDataBeforeMigration(self, installed_apps):
|
|
33
33
|
"""Populate Aggregate data before migrating to Prefixes"""
|
|
34
34
|
|
|
35
|
-
self.aggregate =
|
|
35
|
+
self.aggregate = installed_apps.get_model("ipam", "Aggregate")
|
|
36
36
|
# Workaround for django-taggit manager not working in migrations.
|
|
37
37
|
# https://github.com/jazzband/django-taggit/issues/101
|
|
38
38
|
# https://github.com/jazzband/django-taggit/issues/454
|
|
39
39
|
self.aggregate.tags = TagsField()
|
|
40
|
-
self.computed_field =
|
|
41
|
-
self.content_type =
|
|
42
|
-
self.custom_field =
|
|
43
|
-
self.custom_link =
|
|
44
|
-
self.dynamic_group =
|
|
45
|
-
self.note =
|
|
46
|
-
self.object_change =
|
|
47
|
-
self.object_permission =
|
|
48
|
-
self.prefix =
|
|
40
|
+
self.computed_field = installed_apps.get_model("extras", "computedfield")
|
|
41
|
+
self.content_type = installed_apps.get_model("contenttypes", "ContentType")
|
|
42
|
+
self.custom_field = installed_apps.get_model("extras", "customfield")
|
|
43
|
+
self.custom_link = installed_apps.get_model("extras", "customlink")
|
|
44
|
+
self.dynamic_group = installed_apps.get_model("extras", "DynamicGroup")
|
|
45
|
+
self.note = installed_apps.get_model("extras", "note")
|
|
46
|
+
self.object_change = installed_apps.get_model("extras", "objectchange")
|
|
47
|
+
self.object_permission = installed_apps.get_model("users", "objectpermission")
|
|
48
|
+
self.prefix = installed_apps.get_model("ipam", "prefix")
|
|
49
49
|
self.prefix.tags = TagsField()
|
|
50
|
-
self.relationship =
|
|
51
|
-
self.relationship_association =
|
|
52
|
-
self.rir =
|
|
53
|
-
self.status =
|
|
54
|
-
self.tag =
|
|
50
|
+
self.relationship = installed_apps.get_model("extras", "relationship")
|
|
51
|
+
self.relationship_association = installed_apps.get_model("extras", "relationshipassociation")
|
|
52
|
+
self.rir = installed_apps.get_model("ipam", "RIR")
|
|
53
|
+
self.status = installed_apps.get_model("extras", "status")
|
|
54
|
+
self.tag = installed_apps.get_model("extras", "tag")
|
|
55
55
|
|
|
56
56
|
self.aggregate_ct = self.content_type.objects.get_for_model(self.aggregate)
|
|
57
57
|
self.prefix_ct = self.content_type.objects.get_for_model(self.prefix)
|
|
@@ -114,8 +114,8 @@ class AggregateToPrefixMigrationTestCase(NautobotDataMigrationTest):
|
|
|
114
114
|
self.aggregate1.tags.add("AggregateTagA", "AggregateTagB")
|
|
115
115
|
self.aggregate2.tags.add("AggregateTagA")
|
|
116
116
|
self.aggregate3.tags.add("AggregateTagB")
|
|
117
|
-
self.aggregate5.tags.add("AggregateTagA", "AggregateTagB")
|
|
118
|
-
self.aggregate6.tags.add("AggregateTagB")
|
|
117
|
+
self.aggregate5.tags.add("AggregateTagA", "AggregateTagB") # pylint: disable=no-member
|
|
118
|
+
self.aggregate6.tags.add("AggregateTagB") # pylint: disable=no-member
|
|
119
119
|
|
|
120
120
|
# notes
|
|
121
121
|
self.note.objects.create(
|
|
@@ -141,7 +141,7 @@ class AggregateToPrefixMigrationTestCase(NautobotDataMigrationTest):
|
|
|
141
141
|
self.note.objects.create(
|
|
142
142
|
note="Aggregate5 test note",
|
|
143
143
|
assigned_object_type=self.aggregate_ct,
|
|
144
|
-
assigned_object_id=self.aggregate5.id,
|
|
144
|
+
assigned_object_id=self.aggregate5.id, # pylint: disable=no-member
|
|
145
145
|
)
|
|
146
146
|
|
|
147
147
|
# object permissions
|
|
@@ -157,8 +157,8 @@ class AggregateToPrefixMigrationTestCase(NautobotDataMigrationTest):
|
|
|
157
157
|
# object changes
|
|
158
158
|
self._create_objectchange(self.prefix1, "Pre-migration object change for prefix1")
|
|
159
159
|
self._create_objectchange(self.prefix4, "Pre-migration object change for prefix4")
|
|
160
|
-
self._create_objectchange(self.prefix5, "Pre-migration object change for prefix5")
|
|
161
|
-
self._create_objectchange(self.aggregate5, "Pre-migration object change for aggregate5")
|
|
160
|
+
self._create_objectchange(self.prefix5, "Pre-migration object change for prefix5") # pylint: disable=no-member
|
|
161
|
+
self._create_objectchange(self.aggregate5, "Pre-migration object change for aggregate5") # pylint: disable=no-member
|
|
162
162
|
|
|
163
163
|
# custom fields
|
|
164
164
|
prefix_cf1 = self.custom_field.objects.create(name="prefixcf1")
|
|
@@ -179,24 +179,24 @@ class AggregateToPrefixMigrationTestCase(NautobotDataMigrationTest):
|
|
|
179
179
|
|
|
180
180
|
self.aggregate3._custom_field_data["aggregatecf1"] = "testdata aggregatecf1 aggregate3"
|
|
181
181
|
|
|
182
|
-
self.prefix5._custom_field_data["prefixcf1"] = "testdata prefixcf1 prefix5"
|
|
183
|
-
self.prefix5._custom_field_data["prefixaggregatecf1"] = "testdata prefixaggregatecf1 prefix5"
|
|
182
|
+
self.prefix5._custom_field_data["prefixcf1"] = "testdata prefixcf1 prefix5" # pylint: disable=no-member
|
|
183
|
+
self.prefix5._custom_field_data["prefixaggregatecf1"] = "testdata prefixaggregatecf1 prefix5" # pylint: disable=no-member
|
|
184
184
|
|
|
185
|
-
self.aggregate5._custom_field_data["prefixaggregatecf1"] = "testdata prefixaggregatecf1 aggregate5"
|
|
186
|
-
self.aggregate5._custom_field_data["aggregatecf1"] = "testdata aggregatecf1 aggregate5"
|
|
185
|
+
self.aggregate5._custom_field_data["prefixaggregatecf1"] = "testdata prefixaggregatecf1 aggregate5" # pylint: disable=no-member
|
|
186
|
+
self.aggregate5._custom_field_data["aggregatecf1"] = "testdata aggregatecf1 aggregate5" # pylint: disable=no-member
|
|
187
187
|
|
|
188
|
-
self.aggregate6._custom_field_data["prefixaggregatecf1"] = "testdata prefixaggregatecf1 aggregate6"
|
|
188
|
+
self.aggregate6._custom_field_data["prefixaggregatecf1"] = "testdata prefixaggregatecf1 aggregate6" # pylint: disable=no-member
|
|
189
189
|
|
|
190
190
|
self.prefix1.save()
|
|
191
191
|
self.prefix2.save()
|
|
192
192
|
self.prefix3.save()
|
|
193
193
|
self.prefix4.save()
|
|
194
|
-
self.prefix5.save()
|
|
194
|
+
self.prefix5.save() # pylint: disable=no-member
|
|
195
195
|
self.aggregate1.save()
|
|
196
196
|
self.aggregate2.save()
|
|
197
197
|
self.aggregate3.save()
|
|
198
|
-
self.aggregate5.save()
|
|
199
|
-
self.aggregate6.save()
|
|
198
|
+
self.aggregate5.save() # pylint: disable=no-member
|
|
199
|
+
self.aggregate6.save() # pylint: disable=no-member
|
|
200
200
|
|
|
201
201
|
@skipIf(
|
|
202
202
|
connection.vendor != "postgresql",
|
|
@@ -390,7 +390,7 @@ class AggregateToPrefixMigrationTestCase(NautobotDataMigrationTest):
|
|
|
390
390
|
2,
|
|
391
391
|
)
|
|
392
392
|
|
|
393
|
-
for prefix in (self.prefix2, self.prefix3, self.prefix5):
|
|
393
|
+
for prefix in (self.prefix2, self.prefix3, self.prefix5): # pylint: disable=no-member
|
|
394
394
|
self.assertEqual(
|
|
395
395
|
self.object_change.objects.filter(changed_object_id=prefix.id).count(),
|
|
396
396
|
1,
|
|
@@ -478,6 +478,20 @@ class IPAddressQuerySet(TestCase):
|
|
|
478
478
|
[instance for ip, instance in self.ips.items() if re.match(r"2001(.*)1", ip)],
|
|
479
479
|
)
|
|
480
480
|
|
|
481
|
+
def test_get_or_create(self):
|
|
482
|
+
# https://github.com/nautobot/nautobot/issues/6676
|
|
483
|
+
ip_obj, created = IPAddress.objects.update_or_create(
|
|
484
|
+
defaults={
|
|
485
|
+
"status": self.ipaddr_status,
|
|
486
|
+
},
|
|
487
|
+
host="10.0.0.1",
|
|
488
|
+
mask_length="24",
|
|
489
|
+
namespace=self.namespace,
|
|
490
|
+
)
|
|
491
|
+
self.assertFalse(created)
|
|
492
|
+
self.assertEqual(str(ip_obj.address), "10.0.0.1/24")
|
|
493
|
+
self.assertEqual(ip_obj.parent.namespace, self.namespace)
|
|
494
|
+
|
|
481
495
|
|
|
482
496
|
class PrefixQuerysetTestCase(TestCase):
|
|
483
497
|
queryset = Prefix.objects.all()
|
|
@@ -10903,7 +10903,7 @@ as that is now handled by the NautobotCSVParser class and the REST API serialize
|
|
|
10903
10903
|
|
|
10904
10904
|
|
|
10905
10905
|
<h3 id="nautobot.apps.forms.CSVFileField.to_python" class="doc doc-heading">
|
|
10906
|
-
<code class="highlight language-python"><span class="n">to_python</span><span class="p">(</span><span class="n">
|
|
10906
|
+
<code class="highlight language-python"><span class="n">to_python</span><span class="p">(</span><span class="n">data</span><span class="p">)</span></code>
|
|
10907
10907
|
|
|
10908
10908
|
<a href="#nautobot.apps.forms.CSVFileField.to_python" class="headerlink" title="Permanent link">¶</a></h3>
|
|
10909
10909
|
|
|
@@ -12773,7 +12773,7 @@ passed to the queryset's filter(field_name__in=[]) method but will fail to match
|
|
|
12773
12773
|
<tr class="doc-section-item">
|
|
12774
12774
|
<td><code>queryset</code></td>
|
|
12775
12775
|
<td>
|
|
12776
|
-
<code><autoref identifier="QuerySet" optional>QuerySet</autoref></code>
|
|
12776
|
+
<code><autoref identifier="django.db.models.QuerySet" optional hover>QuerySet</autoref></code>
|
|
12777
12777
|
</td>
|
|
12778
12778
|
<td>
|
|
12779
12779
|
<div class="doc-md-description">
|
|
@@ -12081,7 +12081,7 @@ template_name: The name of the template</p>
|
|
|
12081
12081
|
<tr class="doc-section-item">
|
|
12082
12082
|
<td><code>instance</code></td>
|
|
12083
12083
|
<td>
|
|
12084
|
-
<code><autoref identifier="Model" optional>Model</autoref></code>
|
|
12084
|
+
<code><autoref identifier="django.db.models.Model" optional hover>Model</autoref></code>
|
|
12085
12085
|
</td>
|
|
12086
12086
|
<td>
|
|
12087
12087
|
<div class="doc-md-description">
|
|
@@ -12776,7 +12776,7 @@ template_name: Name of the template to use</p>
|
|
|
12776
12776
|
<tr class="doc-section-item">
|
|
12777
12777
|
<td><code>instance</code></td>
|
|
12778
12778
|
<td>
|
|
12779
|
-
<code><autoref identifier="Model" optional>Model</autoref></code>
|
|
12779
|
+
<code><autoref identifier="django.db.models.Model" optional hover>Model</autoref></code>
|
|
12780
12780
|
</td>
|
|
12781
12781
|
<td>
|
|
12782
12782
|
<div class="doc-md-description">
|