49 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			49 lines
		
	
	
		
			1.6 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)
 |