diff --git a/eav/models/attribute.py b/eav/models/attribute.py index 9eefeb6..b59af6c 100644 --- a/eav/models/attribute.py +++ b/eav/models/attribute.py @@ -291,6 +291,26 @@ class Attribute(models.Model): _('You can only assign a choice group to multiple choice attributes'), ) + def clean_fields(self, exclude=None): + """Perform field-specific validation on the model's fields. + + This method extends the default field cleaning process to include + custom validation for the slug field. + + Args: + exclude (list): Fields to exclude from cleaning. + + Raises: + ValidationError: If the slug is not a valid Python identifier. + """ + super().clean_fields(exclude=exclude) + + if not self.slug.isidentifier(): + raise ValidationError({ + 'slug': _("Slug must be a valid Python identifier (no spaces, " + "special characters, or leading digits).") + }) + def get_choices(self): """ Returns a query set of :class:`EnumValue` objects for this attribute. diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 1347eb2..d17a8f5 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -1,12 +1,13 @@ -import uuid import string +import uuid +import pytest +from django.conf import settings as django_settings from django.core.exceptions import ValidationError from django.test import TestCase from hypothesis import given, settings -from hypothesis.extra import django -from django.conf import settings as django_settings from hypothesis import strategies as st +from hypothesis.extra import django from hypothesis.strategies import just import eav @@ -15,7 +16,6 @@ from eav.models import Attribute, Value from eav.registry import EavConfig from test_project.models import Doctor, Encounter, Patient, RegisterTestModel - if django_settings.EAV2_PRIMARY_KEY_FIELD == "django.db.models.UUIDField": auto_field_strategy = st.builds(uuid.uuid4, version=4, max_length=32) elif django_settings.EAV2_PRIMARY_KEY_FIELD == "django.db.models.CharField": @@ -162,3 +162,13 @@ class TestAttributeModel(django.TestCase): ) assert isinstance(instance, Attribute) + + +@pytest.mark.django_db +def test_attribute_create_with_invalid_slug(): + with pytest.raises(ValidationError): + Attribute.objects.create( + name="Test Attribute", + slug="123-invalid", + datatype=Attribute.TYPE_TEXT + )