Sunday, April 30, 2023

default_renderer is not accessible in BaseForm

Hi all,

I upgraded from Django 3.2 to Django 4.2 and somewhere along the way, access to an overridden default_renderer in my ModelForm has been lost.

settings.py:

FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
 
my_app/forms.py:

class MyModelForm(forms.ModelForm):
    default_renderer = CustomRenderer
   
    class Meta:
        model = MyModel

The custom renderer adds some extra divs and formatting with row and column css classes and I only apply it to certain widgets on certain forms within one of my apps. I just point specific widgets to a custom html file.

This worked prior to the upgrade. I think the issue is in the forms api. Each time the code hits the following block in BaseForm.__init__(), renderer is always not none, regardless of if FORM_RENDERER is set explicitly or not:

(line 120 in forms/forms.py)
        # Initialize form renderer. Use a global default if not specified
        # either as an argument or as self.default_renderer.
        if renderer is None:
            if self.default_renderer is None:
                renderer = get_default_renderer()
            else:
                renderer = self.default_renderer
                if isinstance(self.default_renderer, type):
                    renderer = renderer()
        self.renderer = renderer

The code inside the if statement is never reached (granted I have only tried some non-exhaustive combinations).

I can see three solutions to this
1. Override the init in my model form and set renderer = None explicitly, so that the default_renderer is picked up instead (shameless dirty hack)

2. Make pr with a change to look for the default_renderer first:
        # Initialize form renderer. Use a global default if not specified
        # either as an argument or as self.default_renderer.
        if self.default_renderer:
            if isinstance(self.default_renderer, type):
                renderer = self.default_renderer()
            else:
                renderer = self.default_renderer
        elif renderer is None:
                renderer = get_default_renderer()
        self.renderer = renderer

3. change the project settings in the event that I have missed some crucial change between 3.2 and 4.2 that explains why the renderer is always not not in the BaseForm init.

I'd appreciate any help from any forms api experts that can point me in the right direction.

Cheers,
Ryan.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/ef5146e1-4ee4-408e-967f-33e748b1092an%40googlegroups.com.

No comments:

Post a Comment