or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

csrf.mdfields.mdforms.mdi18n.mdindex.mdvalidation.mdwidgets.md

forms.mddocs/

0

# Forms and Processing

1

2

Core form functionality including form definition, data processing, validation, and object population. These classes provide the foundation for all form handling in WTForms.

3

4

## Capabilities

5

6

### Form Classes

7

8

The main form classes that provide declarative form definition and processing capabilities.

9

10

```python { .api }

11

class Form:

12

"""

13

Declarative form class with metaclass support for field definition.

14

15

Parameters:

16

- formdata: Input data from client (multidict interface like request.form)

17

- obj: Object to populate fields from

18

- prefix: Optional prefix for all field names

19

- data: Dict of field data to pre-populate

20

- meta: Meta configuration overrides

21

- **kwargs: Additional field data

22

"""

23

def __init__(self, formdata=None, obj=None, prefix="", data=None, meta=None, **kwargs): ...

24

25

def validate(self, extra_validators=None) -> bool:

26

"""

27

Validate all fields and run validate_<fieldname> methods.

28

29

Parameters:

30

- extra_validators: Dict of field_name -> list of extra validators

31

32

Returns:

33

bool: True if all fields validate successfully

34

"""

35

36

def populate_obj(self, obj):

37

"""

38

Populate object attributes with form field data.

39

40

Parameters:

41

- obj: Object to populate (uses field names as attribute names)

42

"""

43

44

def process(self, formdata=None, obj=None, data=None, extra_filters=None, **kwargs):

45

"""

46

Process form data through all fields.

47

48

Parameters:

49

- formdata: Input data from client

50

- obj: Object to populate fields from

51

- data: Dict of field data

52

- extra_filters: Additional data filters to apply

53

- **kwargs: Additional field data

54

"""

55

56

# Dict-like field access

57

def __iter__(self): ...

58

def __contains__(self, name) -> bool: ...

59

def __getitem__(self, name) -> Field: ...

60

def __setitem__(self, name, value): ...

61

def __delitem__(self, name): ...

62

63

# Properties

64

data: dict # Dict of all field data

65

errors: dict # Dict of field errors

66

form_errors: list # Form-level validation errors

67

68

class BaseForm:

69

"""

70

Base form class providing core form behavior without metaclass.

71

72

Parameters:

73

- fields: Dict or sequence of 2-tuples of partially-constructed fields

74

- prefix: Optional prefix for all field names

75

- meta: Meta instance for configuration

76

"""

77

def __init__(self, fields, prefix="", meta=None): ...

78

79

def validate(self, extra_validators=None) -> bool:

80

"""Validate all fields, returns True if all fields validate."""

81

82

def populate_obj(self, obj):

83

"""Populate object attributes with form data."""

84

85

def process(self, formdata=None, obj=None, data=None, extra_filters=None, **kwargs):

86

"""Process form data through all fields."""

87

88

# Dict-like field access methods (same as Form)

89

def __iter__(self): ...

90

def __contains__(self, name) -> bool: ...

91

def __getitem__(self, name) -> Field: ...

92

def __setitem__(self, name, value): ...

93

def __delitem__(self, name): ...

94

95

# Properties

96

data: dict # Dict of all field data

97

errors: dict # Dict of field errors

98

form_errors: list # Form-level validation errors

99

```

100

101

### Form Usage Examples

102

103

#### Basic Form Definition and Processing

104

105

```python

106

from wtforms import Form, StringField, IntegerField, validators

107

108

class UserRegistrationForm(Form):

109

username = StringField('Username', [

110

validators.DataRequired(),

111

validators.Length(min=4, max=25)

112

])

113

email = StringField('Email Address', [

114

validators.DataRequired(),

115

validators.Email()

116

])

117

age = IntegerField('Age', [

118

validators.NumberRange(min=13, max=120)

119

])

120

121

# Process form submission

122

def handle_registration(request):

123

form = UserRegistrationForm(formdata=request.form)

124

125

if form.validate():

126

# Create user object

127

user = User()

128

form.populate_obj(user) # Sets user.username, user.email, user.age

129

user.save()

130

return redirect('/success')

131

else:

132

# Re-render form with errors

133

return render_template('register.html', form=form)

134

```

135

136

#### Form with Object Population

137

138

```python

139

def edit_user(request, user_id):

140

user = User.get(user_id)

141

form = UserRegistrationForm(formdata=request.form, obj=user)

142

143

if form.validate():

144

form.populate_obj(user)

145

user.save()

146

return redirect('/success')

147

148

return render_template('edit_user.html', form=form)

149

```

150

151

#### Custom Validation Methods

152

153

```python

154

class LoginForm(Form):

155

username = StringField('Username', [validators.DataRequired()])

156

password = StringField('Password', [validators.DataRequired()])

157

158

def validate_username(self, field):

159

"""Custom validation method for username field."""

160

if not User.exists(field.data):

161

raise ValidationError('Username does not exist.')

162

163

def validate_password(self, field):

164

"""Custom validation method for password field."""

165

user = User.get_by_username(self.username.data)

166

if user and not user.check_password(field.data):

167

raise ValidationError('Invalid password.')

168

```

169

170

#### Form with Prefixes

171

172

```python

173

# Useful for multiple forms on one page

174

billing_form = AddressForm(formdata=request.form, prefix='billing')

175

shipping_form = AddressForm(formdata=request.form, prefix='shipping')

176

177

if billing_form.validate() and shipping_form.validate():

178

# Process both forms

179

pass

180

```

181

182

#### Dynamic Field Access

183

184

```python

185

form = MyForm(formdata=request.form)

186

187

# Access fields dynamically

188

for field_name, field in form:

189

print(f"Field {field_name}: {field.data}")

190

191

# Check if field exists

192

if 'username' in form:

193

username_field = form['username']

194

195

# Access field data and errors

196

all_data = form.data # {'username': 'john', 'email': 'john@example.com'}

197

all_errors = form.errors # {'email': ['Invalid email address.']}

198

```

199

200

### Advanced Form Patterns

201

202

#### Form Inheritance

203

204

```python

205

class BaseUserForm(Form):

206

username = StringField('Username', [validators.DataRequired()])

207

email = StringField('Email', [validators.Email()])

208

209

class AdminUserForm(BaseUserForm):

210

is_admin = BooleanField('Admin privileges')

211

permissions = SelectMultipleField('Permissions', choices=[...])

212

```

213

214

#### Form Composition with FormField

215

216

```python

217

class AddressForm(Form):

218

street = StringField('Street')

219

city = StringField('City')

220

zipcode = StringField('Zip Code')

221

222

class UserForm(Form):

223

name = StringField('Name')

224

billing_address = FormField(AddressForm)

225

shipping_address = FormField(AddressForm)

226

227

# Access nested data

228

form = UserForm(formdata=request.form)

229

if form.validate():

230

billing_street = form.billing_address.street.data

231

shipping_city = form.shipping_address.city.data

232

```

233

234

### Error Handling

235

236

Form validation produces structured error information that can be used for display:

237

238

```python

239

form = MyForm(formdata=request.form)

240

if not form.validate():

241

# Field-level errors

242

for field_name, field_errors in form.errors.items():

243

for error in field_errors:

244

print(f"Error in {field_name}: {error}")

245

246

# Form-level errors (from validate_<fieldname> methods)

247

for error in form.form_errors:

248

print(f"Form error: {error}")

249

250

# Individual field errors

251

if form.username.errors:

252

print("Username errors:", form.username.errors)

253

```