diff --git a/netbox/extras/tests/test_customvalidation.py b/netbox/extras/tests/test_customvalidators.py similarity index 91% rename from netbox/extras/tests/test_customvalidation.py rename to netbox/extras/tests/test_customvalidators.py index 7dca8a2702..217fddd184 100644 --- a/netbox/extras/tests/test_customvalidation.py +++ b/netbox/extras/tests/test_customvalidators.py @@ -4,7 +4,7 @@ from django.test import TestCase, override_settings from dcim.choices import SiteStatusChoices -from dcim.models import Site +from dcim.models import Site, Region from extras.validators import CustomValidator from ipam.models import ASN, RIR from users.models import User @@ -82,6 +82,13 @@ def validate(self, instance): }) +region_validator = CustomValidator({ + 'region.name': { + 'eq': 'Bar', + } +}) + + request_validator = CustomValidator({ 'request.user.username': { 'eq': 'Bob' @@ -154,6 +161,20 @@ def test_prohibited(self): def test_valid(self): Site(name='abcdef123', slug='abcdef123').clean() + @override_settings(CUSTOM_VALIDATORS={'dcim.site': [region_validator]}) + def test_valid(self): + region1 = Region(name='Foo', slug='foo') + region1.save() + region2 = Region(name='Bar', slug='bar') + region2.save() + + # Invalid region + with self.assertRaises(ValidationError): + Site(name='abcdef123', slug='abcdef123', region=region1).clean() + + # Valid region + Site(name='abcdef123', slug='abcdef123', region=region2).clean() + @override_settings(CUSTOM_VALIDATORS={'dcim.site': [custom_validator]}) def test_custom_invalid(self): with self.assertRaises(ValidationError): @@ -207,7 +228,7 @@ def test_plain_data(self): @override_settings( CUSTOM_VALIDATORS={ 'dcim.site': ( - 'extras.tests.test_customvalidation.MyValidator', + 'extras.tests.test_customvalidators.MyValidator', ) } ) @@ -254,7 +275,7 @@ def test_plain_data(self): @override_settings( PROTECTION_RULES={ 'dcim.site': ( - 'extras.tests.test_customvalidation.MyValidator', + 'extras.tests.test_customvalidators.MyValidator', ) } ) diff --git a/netbox/extras/validators.py b/netbox/extras/validators.py index 8d91ca66bc..082f87d642 100644 --- a/netbox/extras/validators.py +++ b/netbox/extras/validators.py @@ -151,14 +151,14 @@ def _get_instance_attr(instance, name): return [] # Raise a ValidationError for unknown attributes - if not hasattr(instance, name): + try: + return operator.attrgetter(name)(instance) + except AttributeError: raise ValidationError(_('Invalid attribute "{name}" for {model}').format( name=name, model=instance.__class__.__name__ )) - return getattr(instance, name) - def get_validator(self, descriptor, value): """ Instantiate and return the appropriate validator based on the descriptor given. For