From cba1615750005f48b90b8d255d5b1995f604dd5f Mon Sep 17 00:00:00 2001 From: candifloss Date: Tue, 4 Mar 2025 15:50:31 +0530 Subject: [PATCH] Fixed create & update form validation --- functions/validate_values.py | 58 +++++++++++++----------------------- 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/functions/validate_values.py b/functions/validate_values.py index 064f52b..0dd38ff 100644 --- a/functions/validate_values.py +++ b/functions/validate_values.py @@ -1,6 +1,6 @@ from datetime import datetime import re -from marshmallow import Schema, fields, ValidationError, validates_schema +from marshmallow import Schema, fields, ValidationError from typing import Dict, Any, Optional, Type from config import item_attributes from definitions.attribute import ( @@ -13,31 +13,18 @@ from definitions.attribute import ( def create_dynamic_schema() -> Type[Schema]: """ - Dynamically creates a marshmallow.Schema based on the configuration in item_attributes. + Dynamically creates a Marshmallow Schema based on the configuration in item_attributes. """ - class DynamicSchema(Schema): - class Meta: - strict = False # Ignore unknown fields + schema_fields = {} # Dictionary to store dynamically created fields - @validates_schema - def validate_required_fields(self, data: Dict[str, Any], **kwargs): - """Ensure all required fields are present.""" - for attrib in item_attributes: - if attrib.required and attrib.attrib_name not in data: - raise ValidationError(f"Missing required field: {attrib.display_name}.") - - # Add fields to the schema based on item_attributes for attrib in item_attributes: - print(f"Adding field: {attrib.attrib_name}") # Debugging - field = None - if isinstance(attrib, textAttribute): - field = fields.String( + schema_fields[attrib.attrib_name] = fields.String( required=attrib.required, validate=[ - lambda x: len(x) <= attrib.max_length if attrib.max_length else True, - lambda x: len(x) >= attrib.min_length if attrib.min_length else True, - lambda x: re.match(attrib.regex, x) if attrib.regex else True, + lambda x, attrib=attrib: len(x) <= attrib.max_length if attrib.max_length else True, + lambda x, attrib=attrib: len(x) >= attrib.min_length if attrib.min_length else True, + lambda x, attrib=attrib: re.match(attrib.regex, x) if attrib.regex else True, ], error_messages={ "required": f"{attrib.display_name} is required.", @@ -46,11 +33,11 @@ def create_dynamic_schema() -> Type[Schema]: ) elif isinstance(attrib, intAttribute): - field = fields.Integer( + schema_fields[attrib.attrib_name] = fields.Integer( required=attrib.required, validate=[ - lambda x: x >= attrib.min_val if attrib.min_val is not None else True, - lambda x: x <= attrib.max_val if attrib.max_val is not None else True, + lambda x, attrib=attrib: x >= attrib.min_val if attrib.min_val is not None else True, + lambda x, attrib=attrib: x <= attrib.max_val if attrib.max_val is not None else True, ], error_messages={ "required": f"{attrib.display_name} is required.", @@ -59,11 +46,11 @@ def create_dynamic_schema() -> Type[Schema]: ) elif isinstance(attrib, floatAttribute): - field = fields.Float( + schema_fields[attrib.attrib_name] = fields.Float( required=attrib.required, validate=[ - lambda x: x >= attrib.min_val if attrib.min_val is not None else True, - lambda x: x <= attrib.max_val if attrib.max_val is not None else True, + lambda x, attrib=attrib: x >= attrib.min_val if attrib.min_val is not None else True, + lambda x, attrib=attrib: x <= attrib.max_val if attrib.max_val is not None else True, ], error_messages={ "required": f"{attrib.display_name} is required.", @@ -72,14 +59,14 @@ def create_dynamic_schema() -> Type[Schema]: ) elif isinstance(attrib, dateAttribute): - field = fields.Date( + schema_fields[attrib.attrib_name] = fields.Date( required=attrib.required, format="%Y-%m-%d", validate=[ - lambda x: x >= datetime.strptime(attrib.min_val, "%Y-%m-%d").date() + lambda x, attrib=attrib: x >= datetime.strptime(attrib.min_val, "%Y-%m-%d").date() if attrib.min_val else True, - lambda x: x <= datetime.strptime(attrib.max_val, "%Y-%m-%d").date() + lambda x, attrib=attrib: x <= datetime.strptime(attrib.max_val, "%Y-%m-%d").date() if attrib.max_val else True, ], @@ -90,24 +77,22 @@ def create_dynamic_schema() -> Type[Schema]: ) elif isinstance(attrib, selectAttribute): - field = fields.String( + schema_fields[attrib.attrib_name] = fields.String( required=attrib.required, - validate=[lambda x: x in attrib.options], + validate=[lambda x, attrib=attrib: x in attrib.options], error_messages={ "required": f"{attrib.display_name} is required.", "validator_failed": f"Invalid value for {attrib.display_name}. Must be one of: {', '.join(attrib.options)}.", }, ) - if field: - #print(field) - setattr(DynamicSchema, attrib.attrib_name, field) - + # Dynamically create the schema class + DynamicSchema = type("DynamicSchema", (Schema,), schema_fields) return DynamicSchema def validate_values(form_data: Dict[str, Any]) -> Optional[str]: """ - Validate form data against the configuration in item_attributes using marshmallow. + Validate form data against the configuration in item_attributes using Marshmallow. Returns an error message if invalid, otherwise None. """ DynamicSchema = create_dynamic_schema() @@ -115,7 +100,6 @@ def validate_values(form_data: Dict[str, Any]) -> Optional[str]: try: schema.load(form_data) # Validate the data - print(form_data) return None # No errors except ValidationError as e: # Format the error message for display