def set_max_length_on_fields_where_necessary()

in src/olympia/amo/utils.py [0:0]


    def set_max_length_on_fields_where_necessary(self):
        """
        Automatically set max_length and associated validator on fields that
        map to a model field where it's already set.

        Allow declaring custom fields without having to re-declare the same
        max_length for those fields.

        Should be called at __init__() time."""
        for field_name, field in self.fields.items():
            if getattr(field, 'read_only', False):
                continue
            source = getattr(field, 'source', field_name)
            if getattr(field, 'max_length', None) is None and self.Meta.model:
                try:
                    model_field = self.Meta.model._meta.get_field(source)
                except FieldDoesNotExist:
                    continue
                if (max_length := getattr(model_field, 'max_length', None)) is not None:
                    field.max_length = max_length
                    # Normally setting max_length on the field would be enough,
                    # but because we're late, after the field's __init__(), we
                    # also need to:
                    # - Update the widget attributes again, for form fields
                    if hasattr(field, 'widget'):
                        field.widget.attrs.update(field.widget_attrs(field.widget))
                        # - Update the sub-widgets too if there are any (our
                        #   translations widgets work like that)
                        if hasattr(field.widget, 'widgets'):
                            for widget in field.widget.widgets:
                                widget.attrs.update(field.widget_attrs(widget))
                    # - Convert that max_length into a validator ourselves if
                    #   the field requires it. Unfortunately some fields
                    #   (FileField) do not work like that and instead deal with
                    #   max_length dynamically, with a custom error message
                    #   that is generated dynamically, so we need to avoid
                    #   those. If a compatible error message for max_length is
                    #   set, or no message at all, we're good.
                    message = getattr(field, 'error_messages', {}).get('max_length')
                    if message is None or re.findall(r'\{.*?\}', str(message)) == [
                        '{max_length}'
                    ]:
                        if message:
                            message = lazy_format(
                                field.error_messages['max_length'],
                                max_length=field.max_length,
                            )
                        field.validators.append(
                            MaxLengthValidator(field.max_length, message=message)
                        )