Opened 9 days ago

Closed 8 days ago

Last modified 2 days ago

#35542 closed Cleanup/optimization (needsinfo)

BoundField's label and help_text and renderer should be properties not class members

Reported by: Christophe Henry Owned by: Christophe Henry
Component: Forms Version: dev
Severity: Normal Keywords:
Cc: Christophe Henry Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

BoundField exposes label help_text and renderer, all of them are copies of underlying members of Field and Form.

This is a bit misleanding since you can modify Fields member in Form's __init__ like documented here but any modification of help_text, label or renderer after super().__init__ won't be reflected on the bound which can leand to incomprehensible behavior in templates

Change History (2)

comment:1 by Natalia Bidart, 8 days ago

Resolution: needsinfo
Status: assignedclosed
Type: UncategorizedCleanup/optimization
Version: 5.0dev

Hello again Christophe Henry! Thank you for your report.

We would need more information to understand your use case. The documentation you linked about "Fields which handle relationships" refers to redefining a field's queryset, not the label/help_text/renderer/etc.

With the information provided so far, I cannot determine whether this is a very specific issue arising from a niche use case or something that applies to the broader ecosystem. Django is a framework designed to provide robust and reliable solutions for common scenarios. Therefore, before accepting any changes to well-established and mature code, it is crucial to demonstrate clear benefits from the proposed modification and ensure there are no risks of breaking existing functionality.

Specifically, we would need a small Django test project or a failing test case that shows the code path or use case that needs fixing. I'll close as needsinfo in the meantime.

in reply to:  1 comment:2 by Christophe Henry, 2 days ago

Replying to Natalia Bidart:

Hello Natalia!

Well the documentation I linked features this as the first example:

class FooMultipleChoiceForm(forms.Form):
    foo_select = forms.ModelMultipleChoiceField(queryset=None)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["foo_select"].queryset = ...

The same way, you can do this, for instance:

class FooMultipleChoiceForm(forms.Form):
    foo_select = forms.CharField()

    def __init__(self, user: User, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["foo_select"].help_text = f"Indicate {user.first_name}'s pet name"

But if you do this, you won't get the result you expect when rendering form with {{ form }} since what will be rendered is self["foo_select"].help_text. (the associated BoundField) and not self.fields["foo_select"].help_text. In order for the help text to correctly be rendered, you need to write:

class FooMultipleChoiceForm(forms.Form):
    foo_select = forms.CharField()

    def __init__(self, user: User, *args, **kwargs):
        super().__init__(*args, **kwargs)
       # Not self.field
        self["foo_select"].help_text = f"Indicate {user.first_name}'s pet name"

This is confusing and is inconsistant with the queryset example of the documentation for anyone who's not very familiar with Django's Form API and looks very much like a bug.

My proposed solution does not introduce any breaking changes and can even be easily reverted to its original behavior with the patch I also proposed for #35192.

Last edited 2 days ago by Christophe Henry (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top