0
# Validators
1
2
Django Extensions provides custom validation classes for field-level validation including control character prevention, whitespace validation, and hexadecimal string validation. These validators integrate seamlessly with Django's form and model validation system.
3
4
## Capabilities
5
6
### NoControlCharactersValidator
7
8
Validates that control characters like newlines, tabs, and other control characters are not present in the input, with optional whitelist support.
9
10
```python { .api }
11
@deconstructible
12
class NoControlCharactersValidator:
13
message: str = "Control Characters like new lines or tabs are not allowed."
14
code: str = "no_control_characters"
15
whitelist: str | None = None
16
17
def __init__(self, message=None, code=None, whitelist=None):
18
"""
19
Validator that prevents control characters in input.
20
21
Parameters:
22
- message: Custom error message (optional)
23
- code: Custom error code (optional)
24
- whitelist: String of allowed control characters (optional)
25
"""
26
27
def __call__(self, value):
28
"""
29
Validate the input value.
30
31
Parameters:
32
- value: The value to validate
33
34
Raises:
35
- ValidationError: If control characters are found (excluding whitelist)
36
"""
37
38
def __eq__(self, other):
39
"""Check equality with another validator instance."""
40
```
41
42
Usage examples:
43
44
```python
45
from django.db import models
46
from django_extensions.validators import NoControlCharactersValidator
47
48
class CleanTextField(models.Model):
49
# Prevent all control characters
50
clean_text = models.TextField(
51
validators=[NoControlCharactersValidator()]
52
)
53
54
# Allow specific control characters (tabs)
55
text_with_tabs = models.TextField(
56
validators=[NoControlCharactersValidator(whitelist='\t')]
57
)
58
59
# Custom error message
60
strict_text = models.TextField(
61
validators=[NoControlCharactersValidator(
62
message="This field cannot contain control characters like newlines."
63
)]
64
)
65
66
# In forms
67
from django import forms
68
69
class CommentForm(forms.Form):
70
comment = forms.CharField(
71
widget=forms.Textarea,
72
validators=[NoControlCharactersValidator(
73
message="Comments cannot contain control characters.",
74
whitelist='\t' # Allow tabs but not newlines
75
)]
76
)
77
78
# Programmatic validation
79
validator = NoControlCharactersValidator()
80
try:
81
validator("Hello\nWorld") # Raises ValidationError
82
except ValidationError as e:
83
print(e.message) # "Control Characters like new lines or tabs are not allowed."
84
85
# With whitelist
86
validator_with_tabs = NoControlCharactersValidator(whitelist='\t')
87
validator_with_tabs("Hello\tWorld") # OK - tabs are whitelisted
88
```
89
90
### NoWhitespaceValidator
91
92
Validates that input does not have leading or trailing whitespace characters.
93
94
```python { .api }
95
@deconstructible
96
class NoWhitespaceValidator:
97
message: str = "Leading and Trailing whitespaces are not allowed."
98
code: str = "no_whitespace"
99
100
def __init__(self, message=None, code=None, whitelist=None):
101
"""
102
Validator that prevents leading/trailing whitespace.
103
104
Parameters:
105
- message: Custom error message (optional)
106
- code: Custom error code (optional)
107
- whitelist: Not used (for consistency with other validators)
108
"""
109
110
def __call__(self, value):
111
"""
112
Validate the input value.
113
114
Parameters:
115
- value: The value to validate
116
117
Raises:
118
- ValidationError: If leading or trailing whitespace is found
119
"""
120
121
def __eq__(self, other):
122
"""Check equality with another validator instance."""
123
```
124
125
Usage examples:
126
127
```python
128
from django.db import models
129
from django_extensions.validators import NoWhitespaceValidator
130
131
class TrimmedField(models.Model):
132
# Ensure no leading/trailing whitespace
133
username = models.CharField(
134
max_length=50,
135
validators=[NoWhitespaceValidator()]
136
)
137
138
# Custom error message
139
api_key = models.CharField(
140
max_length=100,
141
validators=[NoWhitespaceValidator(
142
message="API keys cannot have leading or trailing spaces."
143
)]
144
)
145
146
# In forms
147
from django import forms
148
149
class UserRegistrationForm(forms.Form):
150
username = forms.CharField(
151
max_length=50,
152
validators=[NoWhitespaceValidator(
153
message="Username cannot start or end with spaces."
154
)]
155
)
156
157
# Programmatic validation
158
validator = NoWhitespaceValidator()
159
validator("username") # OK
160
validator(" username") # Raises ValidationError
161
validator("username ") # Raises ValidationError
162
validator(" username ") # Raises ValidationError
163
164
# Combining validators
165
class StrictUsernameField(models.CharField):
166
def __init__(self, *args, **kwargs):
167
kwargs.setdefault('validators', [])
168
kwargs['validators'].extend([
169
NoWhitespaceValidator(),
170
NoControlCharactersValidator()
171
])
172
super().__init__(*args, **kwargs)
173
```
174
175
### HexValidator
176
177
Validates that input contains only hexadecimal characters with configurable length constraints.
178
179
```python { .api }
180
@deconstructible
181
class HexValidator:
182
messages: dict = {
183
'invalid': "Only a hex string is allowed.",
184
'length': "Invalid length. Must be %(length)d characters.",
185
'min_length': "Ensure that there are more than %(min)s characters.",
186
'max_length': "Ensure that there are no more than %(max)s characters."
187
}
188
code: str = "hex_only"
189
190
def __init__(
191
self,
192
length=None,
193
min_length=None,
194
max_length=None,
195
message=None,
196
code=None
197
):
198
"""
199
Validator for hexadecimal strings with length constraints.
200
201
Parameters:
202
- length: Exact length required (optional)
203
- min_length: Minimum length required (optional)
204
- max_length: Maximum length allowed (optional)
205
- message: Custom error message for invalid hex (optional)
206
- code: Custom error code (optional)
207
"""
208
209
def __call__(self, value):
210
"""
211
Validate the input value.
212
213
Parameters:
214
- value: The value to validate
215
216
Raises:
217
- ValidationError: If value is not valid hexadecimal or wrong length
218
"""
219
220
def __eq__(self, other):
221
"""Check equality with another validator instance."""
222
```
223
224
Usage examples:
225
226
```python
227
from django.db import models
228
from django_extensions.validators import HexValidator
229
230
class CryptoModel(models.Model):
231
# Validate hex string of any length
232
hex_data = models.CharField(
233
max_length=100,
234
validators=[HexValidator()]
235
)
236
237
# Validate hex string of exact length (e.g., MD5 hash)
238
md5_hash = models.CharField(
239
max_length=32,
240
validators=[HexValidator(length=32)]
241
)
242
243
# Validate hex string with min/max length
244
flexible_hex = models.CharField(
245
max_length=64,
246
validators=[HexValidator(min_length=8, max_length=64)]
247
)
248
249
# Color hex code (6 characters)
250
color_code = models.CharField(
251
max_length=6,
252
validators=[HexValidator(
253
length=6,
254
message="Please enter a valid 6-character hex color code."
255
)]
256
)
257
258
# Common use cases
259
class SecurityModel(models.Model):
260
# SHA-256 hash (64 hex characters)
261
sha256_hash = models.CharField(
262
max_length=64,
263
validators=[HexValidator(length=64)]
264
)
265
266
# API key (32 hex characters)
267
api_key = models.CharField(
268
max_length=32,
269
validators=[HexValidator(length=32)]
270
)
271
272
# Session token (variable length, 16-128 characters)
273
session_token = models.CharField(
274
max_length=128,
275
validators=[HexValidator(min_length=16, max_length=128)]
276
)
277
278
# In forms
279
from django import forms
280
281
class ColorForm(forms.Form):
282
background_color = forms.CharField(
283
max_length=6,
284
validators=[HexValidator(
285
length=6,
286
message="Enter a valid 6-digit hex color (e.g., FF0000)"
287
)],
288
widget=forms.TextInput(attrs={'placeholder': 'FF0000'})
289
)
290
291
# Programmatic validation
292
validator = HexValidator(length=8)
293
validator("DEADBEEF") # OK
294
validator("deadbeef") # OK (case insensitive)
295
validator("GGGGGGGG") # Raises ValidationError - invalid hex
296
validator("DEAD") # Raises ValidationError - wrong length
297
298
# Min/max length validation
299
range_validator = HexValidator(min_length=4, max_length=8)
300
range_validator("ABCD") # OK
301
range_validator("ABCDEF12") # OK
302
range_validator("ABC") # Raises ValidationError - too short
303
range_validator("ABCDEF123") # Raises ValidationError - too long
304
```
305
306
## Combining Validators
307
308
Validators can be combined for comprehensive input validation:
309
310
```python
311
from django.db import models
312
from django_extensions.validators import (
313
NoControlCharactersValidator,
314
NoWhitespaceValidator,
315
HexValidator
316
)
317
318
class SecureModel(models.Model):
319
# Username: no control characters, no leading/trailing whitespace
320
username = models.CharField(
321
max_length=50,
322
validators=[
323
NoControlCharactersValidator(),
324
NoWhitespaceValidator()
325
]
326
)
327
328
# API key: must be exactly 32 hex characters
329
api_key = models.CharField(
330
max_length=32,
331
validators=[
332
HexValidator(length=32),
333
NoWhitespaceValidator() # Extra safety
334
]
335
)
336
337
# Description: no control characters except newlines and tabs
338
description = models.TextField(
339
validators=[
340
NoControlCharactersValidator(whitelist='\n\t')
341
]
342
)
343
344
# Custom validator combinations
345
def create_secure_hex_validator(length):
346
"""Create a validator that ensures secure hex strings."""
347
return [
348
HexValidator(length=length),
349
NoWhitespaceValidator(),
350
NoControlCharactersValidator()
351
]
352
353
class CryptoHash(models.Model):
354
sha256 = models.CharField(
355
max_length=64,
356
validators=create_secure_hex_validator(64)
357
)
358
```
359
360
## Custom Error Messages and Codes
361
362
```python
363
from django.core.exceptions import ValidationError
364
from django_extensions.validators import HexValidator
365
366
# Custom validator with specific error codes
367
class StrictHexValidator(HexValidator):
368
def __init__(self, length=None, **kwargs):
369
super().__init__(length=length, **kwargs)
370
self.messages.update({
371
'invalid': 'Value must contain only hexadecimal characters (0-9, A-F).',
372
'length': f'Hex string must be exactly {length} characters long.'
373
})
374
375
# Usage in model
376
class HashModel(models.Model):
377
hash_value = models.CharField(
378
max_length=32,
379
validators=[StrictHexValidator(length=32)]
380
)
381
382
# Testing validators
383
def test_validators():
384
validator = NoControlCharactersValidator(
385
message="No control chars allowed!",
386
code="custom_control_char_error"
387
)
388
389
try:
390
validator("Hello\nWorld")
391
except ValidationError as e:
392
print(e.message) # "No control chars allowed!"
393
print(e.code) # "custom_control_char_error"
394
```
395
396
## Form Integration
397
398
```python
399
from django import forms
400
from django_extensions.validators import (
401
NoControlCharactersValidator,
402
NoWhitespaceValidator,
403
HexValidator
404
)
405
406
class AdvancedForm(forms.Form):
407
username = forms.CharField(
408
validators=[
409
NoWhitespaceValidator(message="Username cannot have leading/trailing spaces"),
410
NoControlCharactersValidator(message="Username cannot contain control characters")
411
]
412
)
413
414
api_key = forms.CharField(
415
validators=[HexValidator(length=32, message="API key must be 32 hex characters")]
416
)
417
418
description = forms.CharField(
419
widget=forms.Textarea,
420
validators=[NoControlCharactersValidator(whitelist='\n\t')]
421
)
422
423
color = forms.CharField(
424
validators=[HexValidator(length=6)],
425
widget=forms.TextInput(attrs={
426
'class': 'color-picker',
427
'pattern': '[0-9A-Fa-f]{6}'
428
})
429
)
430
```