Change Widget in View

I am using a RelationChoice field as follows:

    directives.widget("field_name", SelectFieldWidget)
    field_name = RelationChoice(
        title="Field Name",
        vocabulary="someVocabularyName",
        required=False,
    )

And I use the SelectFieldWidget for the Add and Edit forms. However, for the display or browser view, I want to use another widget which will render the value with a link to the target. I tried using the updateWidgets method below but it does not work.

from plone.dexterity.browser.view import DefaultView


class ItemView(DefaultView):

    def updateWidgets(self, prefix=None):
        super().updateWidgets()
        self.fields["field_name"].widgetFactory = RelatedItemsFieldWidget

Using pdb and setting the widgetFactory, the field still uses the SelectFieldWidget.

(Pdb++) self.fields['field_name'].widgetFactory
{'display': ParameterizedWidget(<function SelectFieldWidget at 0x75122720c9a0>, {})}

In my template, I am calling the widget via:

<span tal:replace="structure widget/@@ploneform-render-widget" />

What is a way to change the widget in a browser view?

Does it matter if you update it in fields instead ?

def updateFields(self):

Thanks! This led me to the not so obvious error:

self.fields.....

It is supposed to be:

self.widgets["field_name"].widgetFactory = RelatedItemsFieldWidget

I spoke too soon. While I can now set the widgetFactory to be a RelatedItemsFieldWidget. The template still renders the SelectFieldWidget display template. I also tried updateFields() but it was not called by the view so I can not set the widgetFactory from there.

use the raw value and create an instance of the widget with that value. Or import the new widget template and use it directly.

Thank you for your suggestion. I actually had a work around via my custom view template already. However, I have several views that needs the same. I wanted a lazy solution. Using the display view of the RelatedItemsFieldWidget is also not the ideal solution for me so I just opted to create a custom widget instead of using different ones.

1 Like