0
# Input Validation
1
2
Pre-built validation functions for common input types including emails, URLs, IP addresses, dates, and custom regular expression patterns. Flask-RESTPlus provides a comprehensive set of input validators that can be used with request parsing and field validation.
3
4
## Capabilities
5
6
### Network Address Validation
7
8
Functions for validating IP addresses and network-related inputs.
9
10
```python { .api }
11
def ipv4(value):
12
"""
13
Validate IPv4 addresses.
14
15
Args:
16
value (str): IP address string to validate
17
18
Returns:
19
str: Validated IPv4 address
20
21
Raises:
22
ValueError: If not a valid IPv4 address
23
"""
24
25
def ipv6(value):
26
"""
27
Validate IPv6 addresses.
28
29
Args:
30
value (str): IP address string to validate
31
32
Returns:
33
str: Validated IPv6 address
34
35
Raises:
36
ValueError: If not a valid IPv6 address
37
"""
38
39
def ip(value):
40
"""
41
Validate IP addresses (both IPv4 and IPv6).
42
43
Args:
44
value (str): IP address string to validate
45
46
Returns:
47
str: Validated IP address
48
49
Raises:
50
ValueError: If not a valid IP address
51
"""
52
```
53
54
### Date and Time Validation
55
56
Functions for parsing and validating date and time formats.
57
58
```python { .api }
59
def date(value):
60
"""
61
Parse date strings in YYYY-MM-DD format.
62
63
Args:
64
value (str): Date string to parse
65
66
Returns:
67
datetime.date: Parsed date object
68
69
Raises:
70
ValueError: If not a valid date format
71
"""
72
73
def datetime_from_rfc822(value):
74
"""
75
Parse RFC822 format datetime strings.
76
77
Args:
78
value (str): RFC822 datetime string
79
80
Returns:
81
datetime.datetime: Parsed datetime object
82
83
Raises:
84
ValueError: If not a valid RFC822 datetime
85
"""
86
87
def datetime_from_iso8601(value):
88
"""
89
Parse ISO8601 format datetime strings.
90
91
Args:
92
value (str): ISO8601 datetime string
93
94
Returns:
95
datetime.datetime: Parsed datetime object
96
97
Raises:
98
ValueError: If not a valid ISO8601 datetime
99
"""
100
101
def date_from_iso8601(value):
102
"""
103
Parse ISO8601 format date strings.
104
105
Args:
106
value (str): ISO8601 date string
107
108
Returns:
109
datetime.date: Parsed date object
110
111
Raises:
112
ValueError: If not a valid ISO8601 date
113
"""
114
115
def iso8601interval(value, argument='argument'):
116
"""
117
Parse ISO8601 interval strings.
118
119
Args:
120
value (str): ISO8601 interval string
121
argument (str): Argument name for error messages
122
123
Returns:
124
dict: Parsed interval with 'start' and 'end' datetime objects
125
126
Raises:
127
ValueError: If not a valid ISO8601 interval
128
"""
129
```
130
131
### Numeric Validation
132
133
Functions for validating numeric inputs with constraints.
134
135
```python { .api }
136
def natural(value, argument='argument'):
137
"""
138
Validate natural numbers (non-negative integers >= 0).
139
140
Args:
141
value (str or int): Value to validate
142
argument (str): Argument name for error messages
143
144
Returns:
145
int: Validated natural number
146
147
Raises:
148
ValueError: If not a natural number
149
"""
150
151
def positive(value, argument='argument'):
152
"""
153
Validate positive integers (>= 1).
154
155
Args:
156
value (str or int): Value to validate
157
argument (str): Argument name for error messages
158
159
Returns:
160
int: Validated positive integer
161
162
Raises:
163
ValueError: If not a positive integer
164
"""
165
166
def boolean(value):
167
"""
168
Parse boolean values from various string representations.
169
170
Accepts: 'true', 'false', '1', '0', 'yes', 'no', 'on', 'off' (case insensitive)
171
172
Args:
173
value (str or bool): Value to parse
174
175
Returns:
176
bool: Parsed boolean value
177
178
Raises:
179
ValueError: If not a valid boolean representation
180
"""
181
```
182
183
### Validator Classes
184
185
Configurable validator classes for complex validation scenarios.
186
187
```python { .api }
188
class URL:
189
def __init__(self, check=False, ip=False, local=False, port=False,
190
auth=False, schemes=None, domains=None, exclude=None):
191
"""
192
Configurable URL validator.
193
194
Args:
195
check (bool): Perform additional URL checks
196
ip (bool): Allow IP addresses as hostnames
197
local (bool): Allow local/private URLs
198
port (bool): Require port number
199
auth (bool): Allow authentication in URL
200
schemes (list, optional): Allowed URL schemes
201
domains (list, optional): Allowed domains
202
exclude (list, optional): Excluded domains
203
"""
204
205
def __call__(self, value):
206
"""
207
Validate URL string.
208
209
Args:
210
value (str): URL string to validate
211
212
Returns:
213
str: Validated URL
214
215
Raises:
216
ValueError: If URL doesn't meet validation criteria
217
"""
218
219
class email:
220
def __init__(self, check=False, ip=False, local=False, domains=None, exclude=None):
221
"""
222
Email address validator with domain checking.
223
224
Args:
225
check (bool): Perform additional email checks
226
ip (bool): Allow IP addresses as domains
227
local (bool): Allow local email addresses
228
domains (list, optional): Allowed domains
229
exclude (list, optional): Excluded domains
230
"""
231
232
def __call__(self, value):
233
"""
234
Validate email address.
235
236
Args:
237
value (str): Email address to validate
238
239
Returns:
240
str: Validated email address
241
242
Raises:
243
ValueError: If email doesn't meet validation criteria
244
"""
245
246
class regex:
247
def __init__(self, pattern):
248
"""
249
Regular expression validator.
250
251
Args:
252
pattern (str): Regular expression pattern
253
"""
254
255
def __call__(self, value):
256
"""
257
Validate value against regular expression.
258
259
Args:
260
value (str): Value to validate
261
262
Returns:
263
str: Validated value
264
265
Raises:
266
ValueError: If value doesn't match pattern
267
"""
268
269
class int_range:
270
def __init__(self, low, high, argument='argument'):
271
"""
272
Integer range validator.
273
274
Args:
275
low (int): Minimum value (inclusive)
276
high (int): Maximum value (inclusive)
277
argument (str): Argument name for error messages
278
"""
279
280
def __call__(self, value):
281
"""
282
Validate integer is within range.
283
284
Args:
285
value (str or int): Value to validate
286
287
Returns:
288
int: Validated integer
289
290
Raises:
291
ValueError: If integer is outside range
292
"""
293
```
294
295
### Pre-configured Validators
296
297
Ready-to-use validator instances for common use cases.
298
299
```python { .api }
300
url: URL # Pre-configured URL validator instance
301
```
302
303
### Time Constants
304
305
Constants for time-based validation and processing.
306
307
```python { .api }
308
START_OF_DAY: datetime.time # Time representing start of day (00:00:00)
309
END_OF_DAY: datetime.time # Time representing end of day (23:59:59)
310
```
311
312
## Usage Examples
313
314
### Basic Input Validation
315
316
```python
317
from flask_restplus import Api, Resource, reqparse, inputs
318
319
api = Api()
320
321
parser = reqparse.RequestParser()
322
323
# IP address validation
324
parser.add_argument('server_ip', type=inputs.ipv4, required=True)
325
parser.add_argument('client_ip', type=inputs.ip) # IPv4 or IPv6
326
327
# Date validation
328
parser.add_argument('start_date', type=inputs.date)
329
parser.add_argument('created_at', type=inputs.datetime_from_iso8601)
330
331
# Numeric validation
332
parser.add_argument('page', type=inputs.natural, default=0)
333
parser.add_argument('count', type=inputs.positive, required=True)
334
335
# Boolean validation
336
parser.add_argument('active', type=inputs.boolean, default=True)
337
338
@api.route('/search')
339
class Search(Resource):
340
@api.expect(parser)
341
def get(self):
342
args = parser.parse_args()
343
return {
344
'server_ip': args['server_ip'],
345
'page': args['page'],
346
'count': args['count'],
347
'active': args['active']
348
}
349
```
350
351
### Email and URL Validation
352
353
```python
354
from flask_restplus import reqparse, inputs
355
356
parser = reqparse.RequestParser()
357
358
# Basic email validation
359
parser.add_argument('email', type=inputs.email(), required=True)
360
361
# Email with domain restrictions
362
allowed_email = inputs.email(domains=['company.com', 'partner.org'])
363
parser.add_argument('work_email', type=allowed_email)
364
365
# Email excluding certain domains
366
restricted_email = inputs.email(exclude=['spam.com', 'temp-mail.org'])
367
parser.add_argument('user_email', type=restricted_email)
368
369
# Basic URL validation
370
parser.add_argument('website', type=inputs.url)
371
372
# URL with restrictions
373
secure_url = inputs.URL(schemes=['https'], check=True)
374
parser.add_argument('secure_website', type=secure_url)
375
376
# URL allowing local addresses
377
local_url = inputs.URL(local=True, ip=True)
378
parser.add_argument('internal_url', type=local_url)
379
```
380
381
### Regular Expression Validation
382
383
```python
384
from flask_restplus import reqparse, inputs
385
386
parser = reqparse.RequestParser()
387
388
# Phone number validation (US format)
389
phone_validator = inputs.regex(r'^\+?1?[2-9]\d{2}[2-9]\d{2}\d{4}$')
390
parser.add_argument('phone', type=phone_validator)
391
392
# Username validation (alphanumeric + underscore, 3-20 chars)
393
username_validator = inputs.regex(r'^[a-zA-Z0-9_]{3,20}$')
394
parser.add_argument('username', type=username_validator, required=True)
395
396
# Color hex code validation
397
color_validator = inputs.regex(r'^#[0-9A-Fa-f]{6}$')
398
parser.add_argument('color', type=color_validator)
399
400
# UUID validation
401
uuid_validator = inputs.regex(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$')
402
parser.add_argument('uuid', type=uuid_validator)
403
404
@api.route('/profile')
405
class Profile(Resource):
406
@api.expect(parser)
407
def post(self):
408
args = parser.parse_args()
409
return {'message': 'Profile updated', 'data': args}
410
```
411
412
### Range Validation
413
414
```python
415
from flask_restplus import reqparse, inputs
416
417
parser = reqparse.RequestParser()
418
419
# Age validation (0-150)
420
age_validator = inputs.int_range(0, 150, argument='age')
421
parser.add_argument('age', type=age_validator)
422
423
# Percentage validation (0-100)
424
percentage_validator = inputs.int_range(0, 100, argument='percentage')
425
parser.add_argument('completion', type=percentage_validator)
426
427
# Port number validation (1-65535)
428
port_validator = inputs.int_range(1, 65535, argument='port')
429
parser.add_argument('port', type=port_validator)
430
431
# Priority levels (1-10)
432
priority_validator = inputs.int_range(1, 10, argument='priority')
433
parser.add_argument('priority', type=priority_validator, default=5)
434
```
435
436
### Date and Time Parsing
437
438
```python
439
from flask_restplus import reqparse, inputs
440
from datetime import datetime, date
441
442
parser = reqparse.RequestParser()
443
444
# Simple date parsing (YYYY-MM-DD)
445
parser.add_argument('birth_date', type=inputs.date)
446
447
# ISO8601 datetime parsing
448
parser.add_argument('event_time', type=inputs.datetime_from_iso8601)
449
450
# RFC822 datetime parsing
451
parser.add_argument('mail_date', type=inputs.datetime_from_rfc822)
452
453
# ISO8601 interval parsing
454
parser.add_argument('time_range', type=inputs.iso8601interval)
455
456
@api.route('/events')
457
class Events(Resource):
458
@api.expect(parser)
459
def post(self):
460
args = parser.parse_args()
461
462
# dates are automatically parsed to Python objects
463
birth_date = args['birth_date'] # datetime.date object
464
event_time = args['event_time'] # datetime.datetime object
465
466
return {
467
'birth_date': birth_date.isoformat() if birth_date else None,
468
'event_time': event_time.isoformat() if event_time else None,
469
'age_years': (date.today() - birth_date).days // 365 if birth_date else None
470
}
471
```
472
473
### Custom Validation Functions
474
475
```python
476
from flask_restplus import reqparse
477
import re
478
479
def validate_password(value):
480
"""
481
Validate password strength.
482
483
Requirements:
484
- At least 8 characters
485
- Contains uppercase and lowercase letters
486
- Contains at least one digit
487
- Contains at least one special character
488
"""
489
if len(value) < 8:
490
raise ValueError("Password must be at least 8 characters long")
491
492
if not re.search(r'[A-Z]', value):
493
raise ValueError("Password must contain at least one uppercase letter")
494
495
if not re.search(r'[a-z]', value):
496
raise ValueError("Password must contain at least one lowercase letter")
497
498
if not re.search(r'\d', value):
499
raise ValueError("Password must contain at least one digit")
500
501
if not re.search(r'[!@#$%^&*(),.?":{}|<>]', value):
502
raise ValueError("Password must contain at least one special character")
503
504
return value
505
506
def validate_credit_card(value):
507
"""Validate credit card number using Luhn algorithm."""
508
# Remove spaces and dashes
509
card_number = re.sub(r'[^0-9]', '', value)
510
511
if not card_number.isdigit():
512
raise ValueError("Credit card number must contain only digits")
513
514
if len(card_number) < 13 or len(card_number) > 19:
515
raise ValueError("Credit card number must be 13-19 digits long")
516
517
# Luhn algorithm
518
def luhn_check(card_num):
519
digits = [int(d) for d in card_num]
520
for i in range(len(digits) - 2, -1, -2):
521
digits[i] *= 2
522
if digits[i] > 9:
523
digits[i] -= 9
524
return sum(digits) % 10 == 0
525
526
if not luhn_check(card_number):
527
raise ValueError("Invalid credit card number")
528
529
return card_number
530
531
parser = reqparse.RequestParser()
532
parser.add_argument('password', type=validate_password, required=True)
533
parser.add_argument('card_number', type=validate_credit_card)
534
```
535
536
### Boolean Input Handling
537
538
```python
539
from flask_restplus import reqparse, inputs
540
541
parser = reqparse.RequestParser()
542
543
# Boolean inputs accept various formats
544
parser.add_argument('active', type=inputs.boolean)
545
parser.add_argument('verified', type=inputs.boolean, default=False)
546
parser.add_argument('premium', type=inputs.boolean)
547
548
@api.route('/user-settings')
549
class UserSettings(Resource):
550
@api.expect(parser)
551
def put(self):
552
args = parser.parse_args()
553
554
# These all work for boolean inputs:
555
# active=true, active=True, active=1, active=yes, active=on
556
# active=false, active=False, active=0, active=no, active=off
557
558
return {
559
'settings_updated': True,
560
'active': args['active'],
561
'verified': args['verified'],
562
'premium': args['premium']
563
}
564
```
565
566
### Field Integration
567
568
```python
569
from flask_restplus import Api, fields, inputs
570
571
api = Api()
572
573
# Using validators in field definitions
574
user_model = api.model('User', {
575
'id': fields.Integer(required=True),
576
'email': fields.String(required=True, validate=inputs.email()),
577
'website': fields.String(validate=inputs.url),
578
'age': fields.Integer(validate=inputs.int_range(13, 120, 'age')),
579
'active': fields.Boolean(validate=inputs.boolean)
580
})
581
582
# Custom field with validation
583
class EmailField(fields.String):
584
def __init__(self, **kwargs):
585
super().__init__(**kwargs)
586
self.validate = inputs.email()
587
588
class URLField(fields.String):
589
def __init__(self, **kwargs):
590
super().__init__(**kwargs)
591
self.validate = inputs.URL(schemes=['http', 'https'])
592
593
# Using custom fields
594
profile_model = api.model('Profile', {
595
'name': fields.String(required=True),
596
'email': EmailField(required=True),
597
'website': URLField(),
598
'birth_date': fields.Date(validate=inputs.date)
599
})
600
```