diff --git a/src/servala/core/crd/forms.py b/src/servala/core/crd/forms.py index 71fac67..6eb8c74 100644 --- a/src/servala/core/crd/forms.py +++ b/src/servala/core/crd/forms.py @@ -310,8 +310,10 @@ class CustomFormMixin(FormGeneratorMixin): validators = [] if min_val is not None: validators.append(MinValueValidator(min_val)) + field.widget.attrs["min"] = min_val if max_val is not None: validators.append(MaxValueValidator(max_val)) + field.widget.attrs["max"] = max_val if validators: field.validators.extend(validators) diff --git a/src/tests/test_form_config.py b/src/tests/test_form_config.py index 32c2bb8..3b6a197 100644 --- a/src/tests/test_form_config.py +++ b/src/tests/test_form_config.py @@ -1,6 +1,7 @@ from unittest.mock import Mock import jsonschema +from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from servala.core.crd import generate_custom_form_class @@ -374,7 +375,6 @@ def test_choice_field_validates_against_control_plane_choices(): def test_admin_form_validates_choice_values_against_schema(): - from servala.core.forms import ServiceDefinitionAdminForm form = ServiceDefinitionAdminForm() mock_crd = Mock() @@ -457,3 +457,65 @@ def test_admin_form_validates_choice_values_against_schema(): error_message = str(errors[0]) assert "invalid" in error_message.lower() assert "Environment" in error_message + + +def test_number_field_min_max_sets_widget_attributes(): + class TestModel(models.Model): + name = models.CharField(max_length=100) + port = models.IntegerField() + replica_count = models.IntegerField() + + class Meta: + app_label = "test" + + form_config = { + "fieldsets": [ + { + "title": "General", + "fields": [ + { + "type": "text", + "label": "Name", + "controlplane_field_mapping": "name", + "required": True, + }, + { + "type": "number", + "label": "Port", + "controlplane_field_mapping": "port", + "required": True, + "min_value": 1, + "max_value": 65535, + }, + { + "type": "number", + "label": "Replicas", + "controlplane_field_mapping": "replica_count", + "required": True, + "min_value": 1, + "max_value": 10, + }, + ], + } + ] + } + + form_class = generate_custom_form_class(form_config, TestModel) + form = form_class() + + port_field = form.fields["port"] + assert port_field.widget.attrs.get("min") == 1 + assert port_field.widget.attrs.get("max") == 65535 + + replica_field = form.fields["replica_count"] + assert replica_field.widget.attrs.get("min") == 1 + assert replica_field.widget.attrs.get("max") == 10 + + port_validators = port_field.validators + assert any( + isinstance(v, MinValueValidator) and v.limit_value == 1 for v in port_validators + ) + assert any( + isinstance(v, MaxValueValidator) and v.limit_value == 65535 + for v in port_validators + )