or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-django-widget-tweaks

Django template tags and filters for customizing form field rendering without modifying Python form definitions.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/django-widget-tweaks@1.5.x

To install, run

npx @tessl/cli install tessl/pypi-django-widget-tweaks@1.5.0

0

# Django Widget Tweaks

1

2

Django Widget Tweaks provides template-level control over form field rendering without requiring Python-level form definitions. It offers template tags and filters for customizing HTML attributes, CSS classes, and field properties directly in Django templates, enabling clean separation between presentation logic and business logic.

3

4

## Package Information

5

6

- **Package Name**: django-widget-tweaks

7

- **Package Type**: pypi

8

- **Language**: Python

9

- **Installation**: `pip install django-widget-tweaks`

10

- **Django Setup**: Add `'widget_tweaks'` to `INSTALLED_APPS` in settings.py

11

12

## Core Imports

13

14

```python

15

# Load in Django templates

16

{% load widget_tweaks %}

17

```

18

19

## Basic Usage

20

21

```html

22

{% load widget_tweaks %}

23

24

<!-- Basic attribute modification -->

25

{{ form.name|attr:"placeholder:Enter your name" }}

26

27

<!-- Add CSS classes -->

28

{{ form.email|add_class:"form-control email-input" }}

29

30

<!-- Use render_field tag for HTML-like syntax -->

31

{% render_field form.message rows="5" cols="40" placeholder="Your message" %}

32

33

<!-- Conditional styling based on field state -->

34

{{ form.password|add_error_class:"error-border"|add_required_class:"required-field" }}

35

```

36

37

## Architecture

38

39

Django Widget Tweaks operates through Django's template system using two main approaches:

40

41

- **Template Filters**: Modify form fields by chaining filters that manipulate widget attributes

42

- **Template Tags**: Use HTML-like syntax with the `render_field` tag for more intuitive field customization

43

44

The library works by copying Django BoundField objects and decorating their `as_widget` method to inject custom attributes, ensuring the original form definitions remain unchanged.

45

46

## Capabilities

47

48

### Attribute Manipulation

49

50

Core functionality for setting, appending, and removing HTML attributes on Django form fields.

51

52

```python { .api }

53

# Template filters for attribute manipulation

54

{{ field|attr:"attribute:value" }} # Set or replace HTML attribute

55

{{ field|append_attr:"attribute:value" }} # Append to existing attribute

56

{{ field|remove_attr:"attribute" }} # Remove HTML attribute

57

{{ field|set_data:"key:value" }} # Set HTML5 data attribute (data-key="value")

58

```

59

60

**Usage Examples:**

61

62

```html

63

<!-- Set input type -->

64

{{ form.search|attr:"type:search" }}

65

66

<!-- Add placeholder and set multiple attributes -->

67

{{ form.email|attr:"placeholder:user@example.com"|attr:"autocomplete:email" }}

68

69

<!-- Remove unwanted attributes -->

70

{{ form.field|remove_attr:"readonly" }}

71

72

<!-- Set data attributes for JavaScript -->

73

{{ form.price|set_data:"validation:currency"|set_data:"min:0" }}

74

75

<!-- Append to existing classes or attributes -->

76

{{ form.description|append_attr:"class:large-text"|append_attr:"style:min-height: 100px;" }}

77

```

78

79

### CSS Class Management

80

81

Specialized filters for managing CSS classes with conditional application based on field state.

82

83

```python { .api }

84

# CSS class manipulation filters

85

{{ field|add_class:"css_class" }} # Add CSS class(es)

86

{{ field|add_label_class:"css_class" }} # Add CSS class to field label

87

{{ field|add_error_class:"css_class" }} # Add class only if field has errors

88

{{ field|add_required_class:"css_class" }} # Add class only if field is required

89

{{ field|add_error_attr:"attribute:value" }} # Set attribute only if field has errors

90

```

91

92

**Usage Examples:**

93

94

```html

95

<!-- Basic class addition -->

96

{{ form.username|add_class:"form-control" }}

97

98

<!-- Multiple classes -->

99

{{ form.title|add_class:"form-control large-input highlighted" }}

100

101

<!-- Conditional classes based on field state -->

102

{{ form.email|add_error_class:"is-invalid"|add_required_class:"required" }}

103

104

<!-- Style labels -->

105

{{ form.description|add_label_class:"form-label text-bold" }}

106

107

<!-- Accessibility attributes on errors -->

108

{{ form.password|add_error_attr:"aria-invalid:true" }}

109

```

110

111

### HTML-like Field Rendering

112

113

Template tag providing intuitive HTML-like syntax for field customization with support for both assignment and appending operations.

114

115

```python { .api }

116

# render_field template tag

117

{% render_field field attribute="value" attribute+="append_value" %}

118

```

119

120

**Usage Examples:**

121

122

```html

123

<!-- Basic field rendering with attributes -->

124

{% render_field form.title class="form-control" placeholder="Enter title" %}

125

126

<!-- Append to existing attributes -->

127

{% render_field form.description class+=" large-textarea" rows="8" %}

128

129

<!-- Change input types -->

130

{% render_field form.search type="search" %}

131

{% render_field form.phone type="tel" %}

132

133

<!-- Template variables as values -->

134

{% render_field form.message placeholder=form.message.label %}

135

136

<!-- Vue.js style attributes with double colon -->

137

{% render_field form.status v-bind::class="{active:isActive}" %}

138

139

<!-- Mix of assignment and appending -->

140

{% render_field form.tags class="tag-input" class+=" autocomplete" data-source="/api/tags" %}

141

```

142

143

**Context Variables for render_field:**

144

145

```python { .api }

146

# Special template context variables that affect render_field behavior

147

WIDGET_ERROR_CLASS # CSS class automatically applied to fields with errors

148

WIDGET_REQUIRED_CLASS # CSS class automatically applied to required fields

149

```

150

151

**Context Variable Usage:**

152

153

```html

154

{% with WIDGET_ERROR_CLASS='error-field' WIDGET_REQUIRED_CLASS='required-field' %}

155

{% render_field form.email type="email" class="form-control" %}

156

{% render_field form.password type="password" class="form-control" %}

157

{% render_field form.confirm_password type="password" class="form-control" %}

158

{% endwith %}

159

```

160

161

### Field Introspection

162

163

Utility filters for determining field and widget types, useful for conditional template logic and CSS styling.

164

165

```python { .api }

166

# Field type inspection filters

167

{{ field|field_type }} # Returns field class name in lowercase (e.g., "charfield")

168

{{ field|widget_type }} # Returns widget class name in lowercase (e.g., "textinput")

169

```

170

171

**Usage Examples:**

172

173

```html

174

<!-- Dynamic CSS classes based on field type -->

175

<div class="field {{ field|field_type }} {{ field|widget_type }} {{ field.html_name }}">

176

{{ field }}

177

</div>

178

179

<!-- Conditional logic based on field type -->

180

{% if field|field_type == "charfield" %}

181

{{ field|attr:"maxlength:255" }}

182

{% elif field|field_type == "emailfield" %}

183

{{ field|attr:"type:email" }}

184

{% endif %}

185

186

<!-- Widget-specific styling -->

187

{% if field|widget_type == "textarea" %}

188

{{ field|add_class:"auto-resize" }}

189

{% elif field|widget_type == "select" %}

190

{{ field|add_class:"custom-select" }}

191

{% endif %}

192

```

193

194

## Advanced Usage Patterns

195

196

### Filter Chaining

197

198

Django Widget Tweaks filters can be chained together, with leftmost filters taking precedence (useful for creating reusable templates with overridable defaults):

199

200

```html

201

<!-- Leftmost filter wins -->

202

{{ form.title|attr:"class:default-class"|attr:"class:override-class" }}

203

<!-- Result: class="default-class" -->

204

205

<!-- Reusable field template with defaults -->

206

{# inc/field.html #}

207

{% load widget_tweaks %}

208

<div class="field-wrapper">

209

{{ field|add_class:"form-control"|attr:"data-default:true" }}

210

</div>

211

212

{# Usage with overrides #}

213

{% include "inc/field.html" with field=form.email|attr:"data-default:false"|add_class:"email-field" %}

214

```

215

216

### Mixing render_field with Filters

217

218

The `render_field` tag can be combined with filters for complex field customization:

219

220

```html

221

{% render_field form.category|append_attr:"readonly:readonly" type="text" placeholder="Category" %}

222

```

223

224

### Form Validation Integration

225

226

Leverage Django's form validation states for dynamic styling:

227

228

```html

229

<!-- Comprehensive field with all states -->

230

{{ form.username|add_class:"form-control"|add_error_class:"is-invalid"|add_required_class:"required"|add_error_attr:"aria-describedby:username-error" }}

231

232

{% if form.username.errors %}

233

<div id="username-error" class="invalid-feedback">

234

{{ form.username.errors.0 }}

235

</div>

236

{% endif %}

237

```

238

239

## Package Metadata

240

241

```python { .api }

242

# Package version (available after installation)

243

import widget_tweaks

244

widget_tweaks.__version__ # String version or None if not installed

245

```

246

247

## Limitations

248

249

- **MultiWidgets**: SplitDateTimeWidget and SplitHiddenDateTimeWidget are not supported

250

- **Filter Order**: Filter chaining follows leftmost-wins precedence which may be counter-intuitive

251

- **Field State**: Filters create copies of BoundField objects, so multiple applications may not reflect the most recent state changes