Proposal: Make it easy to add CSS classes to a `BoundField`

You’re discussing API design and not looking at prior art that has solved this issue. That is NIH syndrome.

You know Django’s development process, and stability guarantees. It’s entirely unrealistic that we would rewrite the form layer entirely to address the discussion here. Please can we keep it on topic. (You know this.)

I can see that. When I first saw the BoundField I thought the same thing. Going from the BoundField instance to the form field instance to the widget using ...field.field.widget always felt icky. But it’s where we are now, and there are probably good reasons for that – and even if there were none, we couldn’t change this without breaking a lot of code out there. Also, this proposal doesn’t make the mentioned issue (if it is one) worse, it only continues down the path we chose a long time ago, and it’s not a bad one, even if some people relentlessly insist it is.

Again, it would be great if we could land this.

I think we’re close enough here to proceed to implementation. I reopened the ticket to ask the Fellows to look again.

2 Likes

Yeah, I guess we do have to offer the three level customization. It still feels a bit off but I acknowledge this may just be a personal bias. I’m certainly not objecting!

1 Like

I’m kinda buzzed by Natalia’s comment on the ticket:

I think it would be wise to wait a few more posts before re-opening this ticket.

What do they mean by “a few more posts”? More opinions are required? :thinking:

@christophehenry The last batch of comments are all since then, so I’d not worry too much.

I realise we have two tickets in play here: #35192 and #35521

I think #35521 is the one to progress, renaming to something like Allow overriding BoundField class on forms and fields.

Hello everyone,

I’m working on pushing forward the proposed PR, and there’s still some work left in the docs. Specifically, I’m trying to create a clear example, as requested by @carltongibson, to demonstrate how the div customization request that started this thread can be addressed in an elegant way.

Here’s what I have so far, though I have to admit that the handling of extra_classes doesn’t feel entirely polished. The fact that it can be a string (or any object with a split method) or an iterable makes the override somewhat tricky:

class CustomBoundField(forms.BoundField):
    custom_class = "custom"

    def css_classes(self, extra_classes=None):
        result = super().css_classes(extra_classes)
        if self.custom_class not in result:
            result += f" {self.custom_class}"
        return result.strip()
  1. Is there a better way to define this example for the Django Docs?
  2. Should we consider additional tweaks to the functionality to make these customizations work more smoothly?

Thanks!

PS: From my POV, the proposed example in the PR’s release notes is not a good one since it drops any given extra_classes and that feels incorrect:

    class BoundFieldWithCssClass(BoundField):
        def css_classes(self, extra_classes=None):
            return super().css_classes("user-form")

Thanks @nessita , I hope we haven’t done much duplicate work since I really want to see this happen as well. I have resurrected the PR here Fixed #35192 -- Added possibility to override BoundField at Form level or Field level by matthiask · Pull Request #19043 · django/django · GitHub and have added a test and an example for this.

Something like this seems to work well:

class BoundFieldWithWrappingClass(BoundField):
    def css_classes(self, extra_classes=None):
        return f"field {super().css_classes(extra_classes)}"

css_classes always returns a string, and the deduplication logic for CSS classes isn’t really needed in this case.

Right back up the top, I gave my current template-based approach to this problem. Just as an anecdote-point, in not one case in the WORK project where I’ve needed this have I reused the existing field.css_classes: I don’t think we need to provide anything too clever there. (If it turns out folks need it, then can follow up once they’ve worked out the stable pattern.)

1 Like