Skip to content

Add ability to specify Widget.attrs as a class var #72

@coredumperror

Description

@coredumperror

Code of Conduct

  • I agree to follow Django's Code of Conduct

Feature Description

I'd like to be able to specify the attrs value for a subclass of Widget as a class var, in order to make it possible to fully specify a custom widget as a reusable class. Currently, you have to specify attrs as a keyword arg, which is redundant any time you want to use the same Widget subclass multiple times.

Problem

Right now, the only way to specify custom attrs on a Widget is via sending the attrs keyword arg to __init__(self, attrs=None). This makes it impossible to build a reusable widget subclass that specifies custom attrs without doing a fairly gross hack (converting the class var to the attrs keyword arg in the subclass's call to super().__init__()).

The reason you can't just specify WidgetSubclass.attrs right now is that the code in Widget.__init__() overwrites the attrs instance var with whatever was sent to __init__() as the attrs keyword arg.

Request or proposal

proposal

Additional Details

The reason this issue with Widget came up is that I've recently started using django-select2, which allows you to specify quite a bit about your custom select2 widgets via class vars... but you can't specify attrs that way because of what Widget.__init__() does. And you need to specify attrs to send configuration to the select2 javascript library.

Implementation Suggestions

I believe this change to Widget would be sufficient:

class Widget(metaclass=MediaDefiningClass):
    ...
    attrs = {}

    def __init__(self, attrs=None):
        self.attrs = self.attrs | (attrs or {})

The new __init__() will assign to the instance variable attrs a new dictionary which is a union of the class variable attrs and the value sent as the attrs keyword arg (if a value was sent). This allows keyword-provided keys to override those provided in the class var, and also ensures that Widget.attrs, itself, is never modified via changes to instance.attrs.

Note that the dict Union operator was added in Python 3.9, which is before the earliest Python that Django currently supports.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Idea

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions