django / django/new-features

Add ability to specify `Widget.attrs` as a class var

Open
#72 9 comments 6 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
188
Forks
7
PR merge metrics
No merged PRs in 30d

Description

### Code of Conduct

- [x] 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](https://github.com/codingjoe/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](https://django-select2.readthedocs.io/en/latest/django_select2.html#configuring-select2).

### Implementation Suggestions

I believe this change to `Widget` would be sufficient:

```python
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.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.