45 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			45 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """passbook lib fields"""
 | |
| from itertools import chain
 | |
| 
 | |
| from django import forms
 | |
| from django.contrib.postgres.utils import prefix_validation_error
 | |
| 
 | |
| from passbook.lib.widgets import DynamicArrayWidget
 | |
| 
 | |
| 
 | |
| class DynamicArrayField(forms.Field):
 | |
|     """Show array field as a dynamic amount of textboxes"""
 | |
| 
 | |
|     default_error_messages = {"item_invalid": "Item %(nth)s in the array did not validate: "}
 | |
| 
 | |
|     def __init__(self, base_field, **kwargs):
 | |
|         self.base_field = base_field
 | |
|         self.max_length = kwargs.pop("max_length", None)
 | |
|         kwargs.setdefault("widget", DynamicArrayWidget)
 | |
|         super().__init__(**kwargs)
 | |
| 
 | |
|     def clean(self, value):
 | |
|         cleaned_data = []
 | |
|         errors = []
 | |
|         value = [x for x in value if x]
 | |
|         for index, item in enumerate(value):
 | |
|             try:
 | |
|                 cleaned_data.append(self.base_field.clean(item))
 | |
|             except forms.ValidationError as error:
 | |
|                 errors.append(
 | |
|                     prefix_validation_error(
 | |
|                         error, self.error_messages["item_invalid"],
 | |
|                         code="item_invalid", params={"nth": index}
 | |
|                     )
 | |
|                 )
 | |
|         if errors:
 | |
|             raise forms.ValidationError(list(chain.from_iterable(errors)))
 | |
|         if not cleaned_data and self.required:
 | |
|             raise forms.ValidationError(self.error_messages["required"])
 | |
|         return cleaned_data
 | |
| 
 | |
|     def has_changed(self, initial, data):
 | |
|         if not data and not initial:
 | |
|             return False
 | |
|         return super().has_changed(initial, data)
 | 
