Transforming TextLine Field Value to Uppercase

I have a need to save several TextLine field values entered in a p.a.z3cform form in uppercase. On the frontend, I am already using CSS text-transform. What is needed in the backend to do the transformation on save? My type is defined as follows:

class IApplicationForm(model.Schema):

    last_name = schema.TextLine(
        title="Last Name",
        required=False,
    )

    first_name = schema.TextLine(
        title="First Name",
        required=False,
    )
    
    ...
    

@implementer(IApplicationForm)
class ApplicationForm(Container):

You could use a dataconverter for this. Either apply the conversion to all TextLine fields, or create a UppercaseTextLine field that derives from schema.TextLine.

Maybe you will find some inspiration here: Register different dataconverters for fields in the same schema

Thank you.

If I understand correctly, I will need to create a custom schema if I want to selectively apply the uppercase format. But if I want the format to apply to all TextLine field, I will just need a custom widget data converter? It is not enough to create a custom widget (with appropriate converter) and specify that the field use this custom widget?

I think you might be working with Volto instead of Plone Classic. That is probably the reason for confusion.

In Plone Classic, a structure like the one below (warning, Python 2.7 for Plone 5.0 - deprecated, replace adapts with a decorator) would be enough.

Maybe this documentation is more useful for you (Volto): Forms and widgets — Plone Documentation v6

configure.zcml

    <adapter factory=".converters.NoFormatIntegerDataConverter" />

converters.py

# -*- coding: utf-8 -*-
from zope.component import provideAdapter
from zope.component import adapts
from zope.schema.interfaces import IInt
from z3c.form.converter import IntegerDataConverter


class NoFormatIntegerDataConverter(IntegerDataConverter):

    # adapts the Widget Definition above
    adapts(IInt, IIntNoFormatWidget)

    def toWidgetValue(self, value):
        if value is self.field.missing_value:
            return u''
        return unicode(value)

provideAdapter(NoFormatIntegerDataConverter)

I am using ClassicUI.

Thank you for the tip. I made it work by creating a custom widget and dataconverter. Below is what I did.

interfaces.py

from plone.app.z3cform.interfaces import ITextWidget

class IUppercaseTextWidget(ITextWidget):
    """Marker interface for uppercase text widget"""

uppercase_text.py

from myapp.common.interfaces import IUppercaseTextWidget
from plone.app.z3cform.converters import BaseDataConverter
from z3c.form.browser.text import TextWidget
from z3c.form.interfaces import IFieldWidget
from z3c.form.widget import FieldWidget
from zope.component import adapter
from zope.interface import implementer
from zope.schema.interfaces import ITextLine


@implementer(IUppercaseTextWidget)
class UppercaseTextWidget(TextWidget):
    """Text widget using uppercase"""

    klass = 'uppercase-text-widget'


@implementer(IFieldWidget)
def UppercaseTextFieldWidget(field, request):
    return FieldWidget(field, UppercaseTextWidget(request))


@adapter(ITextLine, IUppercaseTextWidget)
class UppercaseTextDataConverter(BaseDataConverter):

    def toFieldValue(self, value):
        if self._strip_value and isinstance(value, str):
            stripped = value.strip()
            value = stripped.upper()

        if value == '':
            return self.field.missing_value

        return self.field.fromUnicode(value)

configure.zcml

<adapter factory=".uppercase_text.UppercaseTextDataConverter" />

application_form.py

from myapp.common.widgets.uppercase_text import UppercaseTextFieldWidget


class IApplicationForm(model.Schema):

    directives.widget("last_name", UppercaseTextFieldWidget)
    last_name = schema.TextLine(
        title="Last Name",
        required=False,
    )

The uppercase transformation is only applied to fields that are using UppercaseTextFieldWidget. Then in the frontend form, I use text-transformation on the class "uppercase-text-widget"

1 Like