diff --git a/netbox/dcim/models/mixins.py b/netbox/dcim/models/mixins.py index 127dfb9e5..e9484264c 100644 --- a/netbox/dcim/models/mixins.py +++ b/netbox/dcim/models/mixins.py @@ -85,7 +85,7 @@ class CachedScopeMixin(models.Model): abstract = True def clean(self): - if self.scope_type and not self.scope: + if self.scope_type and not (self.scope or self.scope_id): scope_type = self.scope_type.model_class() raise ValidationError({ 'scope': _( diff --git a/netbox/ipam/tests/test_api.py b/netbox/ipam/tests/test_api.py index 6255aaf86..a7562a53b 100644 --- a/netbox/ipam/tests/test_api.py +++ b/netbox/ipam/tests/test_api.py @@ -1,6 +1,7 @@ import json import logging +from django.test import tag from django.urls import reverse from netaddr import IPNetwork from rest_framework import status @@ -383,6 +384,18 @@ class PrefixTest(APIViewTestCases.APIViewTestCase): ) Prefix.objects.bulk_create(prefixes) + @tag('regression') + def test_clean_validates_scope(self): + prefix = Prefix.objects.first() + site = Site.objects.create(name='Test Site', slug='test-site') + + data = {'scope_type': 'dcim.site', 'scope_id': site.id} + url = reverse('ipam-api:prefix-detail', kwargs={'pk': prefix.pk}) + self.add_permissions('ipam.change_prefix') + + response = self.client.patch(url, data, format='json', **self.header) + self.assertHttpStatus(response, status.HTTP_200_OK) + def test_list_available_prefixes(self): """ Test retrieval of all available prefixes within a parent prefix.