0
# Request Parsing
1
2
Request parsing system for handling URL parameters, form data, JSON payloads, and file uploads with validation and type conversion. Flask-RESTPlus provides a comprehensive request parser that integrates with automatic documentation generation.
3
4
## Capabilities
5
6
### RequestParser Class
7
8
Main class for parsing and validating request data from various sources.
9
10
```python { .api }
11
class RequestParser:
12
def __init__(self, argument_class=None, result_class=None, trim=False, bundle_errors=False):
13
"""
14
Initialize the request parser.
15
16
Args:
17
argument_class (class, optional): Custom Argument class
18
result_class (class, optional): Custom result class
19
trim (bool): Automatically trim string values
20
bundle_errors (bool): Return all validation errors at once
21
"""
22
23
def add_argument(self, name, dest=None, type=str, location=('json', 'form', 'args'),
24
required=False, default=None, help=None, action='store',
25
choices=None, ignore=False, case_sensitive=True, store_missing=True,
26
nullable=True, **kwargs):
27
"""
28
Add an argument to the parser.
29
30
Args:
31
name (str): Argument name
32
dest (str, optional): Destination attribute name
33
type (callable): Type conversion function
34
location (tuple or str): Where to look for the argument
35
required (bool): Whether argument is required
36
default: Default value if argument is missing
37
help (str, optional): Help text for documentation
38
action (str): How to handle the argument ('store', 'store_const', 'store_true', 'store_false', 'append', 'append_const', 'count')
39
choices (list, optional): List of allowed values
40
ignore (bool): Ignore parsing errors
41
case_sensitive (bool): Case sensitive argument matching
42
store_missing (bool): Store missing arguments with None value
43
nullable (bool): Allow None values
44
**kwargs: Additional argument options
45
46
Returns:
47
Argument: The added argument instance
48
"""
49
50
def parse_args(self, req=None, strict=False):
51
"""
52
Parse arguments from the request.
53
54
Args:
55
req (Request, optional): Flask request object (uses current request if None)
56
strict (bool): Raise exception on unknown arguments
57
58
Returns:
59
ParseResult: Parsed arguments
60
"""
61
62
def copy(self):
63
"""
64
Create a copy of this parser.
65
66
Returns:
67
RequestParser: Copied parser
68
"""
69
70
def replace_argument(self, name, **kwargs):
71
"""
72
Replace an existing argument.
73
74
Args:
75
name (str): Argument name to replace
76
**kwargs: New argument parameters
77
78
Returns:
79
Argument: The replaced argument
80
"""
81
82
def remove_argument(self, name):
83
"""
84
Remove an argument from the parser.
85
86
Args:
87
name (str): Argument name to remove
88
"""
89
```
90
91
### Argument Class
92
93
Individual argument configuration for request parsing.
94
95
```python { .api }
96
class Argument:
97
def __init__(self, name, default=None, dest=None, required=False, ignore=False,
98
type=str, location=('json', 'form', 'args'), choices=None,
99
action='store', help=None, operators=('=',), case_sensitive=True,
100
store_missing=True, trim=False, nullable=True, **kwargs):
101
"""
102
Initialize an argument.
103
104
Args:
105
name (str): Argument name
106
default: Default value
107
dest (str, optional): Destination attribute name
108
required (bool): Whether argument is required
109
ignore (bool): Ignore parsing errors
110
type (callable): Type conversion function
111
location (tuple or str): Request locations to search
112
choices (list, optional): Allowed values
113
action (str): Parsing action
114
help (str, optional): Help text
115
operators (tuple): Allowed operators for filtering
116
case_sensitive (bool): Case sensitive matching
117
store_missing (bool): Store missing arguments
118
trim (bool): Trim string values
119
nullable (bool): Allow None values
120
**kwargs: Additional options
121
"""
122
123
def source(self, request):
124
"""
125
Extract argument values from request.
126
127
Args:
128
request (Request): Flask request object
129
130
Returns:
131
list: Extracted values
132
"""
133
134
def convert(self, value, op):
135
"""
136
Convert argument value to the specified type.
137
138
Args:
139
value: Raw argument value
140
op (str): Operator used
141
142
Returns:
143
Converted value
144
"""
145
146
def handle_validation_error(self, error, bundle_errors):
147
"""
148
Handle validation errors.
149
150
Args:
151
error (Exception): Validation error
152
bundle_errors (bool): Whether to bundle errors
153
"""
154
155
def parse(self, request, bundle_errors=False):
156
"""
157
Parse this argument from the request.
158
159
Args:
160
request (Request): Flask request object
161
bundle_errors (bool): Bundle all errors
162
163
Returns:
164
tuple: (parsed_value, found_in_request)
165
"""
166
```
167
168
### ParseResult Class
169
170
Container for parsed arguments with attribute-style access.
171
172
```python { .api }
173
class ParseResult(dict):
174
def __init__(self, *args, **kwargs):
175
"""
176
Initialize parse result.
177
178
Args:
179
*args: Dictionary arguments
180
**kwargs: Keyword arguments
181
"""
182
183
def __getattr__(self, name):
184
"""
185
Get parsed argument by attribute access.
186
187
Args:
188
name (str): Argument name
189
190
Returns:
191
Parsed argument value
192
"""
193
194
def __setattr__(self, name, value):
195
"""
196
Set parsed argument by attribute access.
197
198
Args:
199
name (str): Argument name
200
value: Argument value
201
"""
202
```
203
204
### Constants and Helpers
205
206
Request parsing constants and utility mappings.
207
208
```python { .api }
209
LOCATIONS: dict # Maps Flask-RESTPlus locations to Swagger parameter types
210
PY_TYPES: dict # Maps Python types to Swagger types
211
SPLIT_CHAR: str = ',' # Default character for splitting array values
212
```
213
214
## Usage Examples
215
216
### Basic Request Parsing
217
218
```python
219
from flask_restplus import Api, Resource, reqparse
220
221
api = Api()
222
223
# Create a request parser
224
parser = reqparse.RequestParser()
225
226
# Add arguments
227
parser.add_argument('name', type=str, required=True, help='Name is required')
228
parser.add_argument('age', type=int, location='args', help='Age parameter')
229
parser.add_argument('active', type=bool, default=True, help='Active status')
230
231
@api.route('/users')
232
class UserList(Resource):
233
@api.expect(parser)
234
def post(self):
235
# Parse arguments from request
236
args = parser.parse_args()
237
238
# Access parsed values
239
name = args['name'] # or args.name
240
age = args['age']
241
active = args['active']
242
243
# Process the data...
244
return {'message': f'Created user {name}, age {age}, active: {active}'}, 201
245
```
246
247
### Argument Locations
248
249
```python
250
from flask_restplus import reqparse
251
252
parser = reqparse.RequestParser()
253
254
# URL query parameters (?param=value)
255
parser.add_argument('page', type=int, location='args', default=1)
256
257
# Form data (POST form submission)
258
parser.add_argument('username', type=str, location='form', required=True)
259
260
# JSON payload data
261
parser.add_argument('data', type=dict, location='json')
262
263
# HTTP headers
264
parser.add_argument('api-key', location='headers', required=True)
265
266
# File uploads
267
parser.add_argument('upload', location='files', type=FileStorage)
268
269
# Cookies
270
parser.add_argument('session_id', location='cookies')
271
272
# Multiple locations (search in order)
273
parser.add_argument('token', location=['headers', 'args'], required=True)
274
275
# All locations (json, form, args)
276
parser.add_argument('flexible_param', location=('json', 'form', 'args'))
277
```
278
279
### Type Conversion and Validation
280
281
```python
282
from flask_restplus import reqparse
283
from datetime import datetime
284
285
parser = reqparse.RequestParser()
286
287
# Built-in type conversions
288
parser.add_argument('count', type=int, help='Must be an integer')
289
parser.add_argument('rate', type=float, help='Must be a float')
290
parser.add_argument('enabled', type=bool, help='Boolean value')
291
292
# Custom type conversion function
293
def date_type(date_str):
294
"""Convert date string to datetime object."""
295
try:
296
return datetime.strptime(date_str, '%Y-%m-%d')
297
except ValueError:
298
raise ValueError(f"Invalid date format: {date_str}. Use YYYY-MM-DD")
299
300
parser.add_argument('start_date', type=date_type, help='Date in YYYY-MM-DD format')
301
302
# Choices validation
303
parser.add_argument('status',
304
choices=['active', 'inactive', 'pending'],
305
help='Status must be one of: active, inactive, pending')
306
307
# List/array arguments
308
parser.add_argument('tags', action='append', help='Can be specified multiple times')
309
310
# Store constants
311
parser.add_argument('verbose', action='store_true', help='Enable verbose mode')
312
parser.add_argument('quiet', action='store_false', help='Disable quiet mode')
313
```
314
315
### Advanced Parsing Features
316
317
```python
318
from flask_restplus import reqparse
319
320
# Bundle all validation errors
321
parser = reqparse.RequestParser(bundle_errors=True)
322
323
parser.add_argument('name', type=str, required=True, trim=True)
324
parser.add_argument('email', type=str, required=True)
325
parser.add_argument('age', type=int, required=True)
326
327
@api.route('/users')
328
class UserCreate(Resource):
329
@api.expect(parser)
330
def post(self):
331
try:
332
args = parser.parse_args()
333
# All arguments validated successfully
334
return {'message': 'User created', 'data': args}, 201
335
except Exception as e:
336
# Returns all validation errors at once:
337
# {
338
# "message": "Input payload validation failed",
339
# "errors": {
340
# "name": "Name is required",
341
# "email": "Email is required",
342
# "age": "Age must be an integer"
343
# }
344
# }
345
return {'error': str(e)}, 400
346
```
347
348
### Parser Inheritance and Modification
349
350
```python
351
from flask_restplus import reqparse
352
353
# Base parser with common arguments
354
base_parser = reqparse.RequestParser()
355
base_parser.add_argument('page', type=int, location='args', default=1)
356
base_parser.add_argument('per_page', type=int, location='args', default=10)
357
358
# Create specialized parsers by copying
359
user_parser = base_parser.copy()
360
user_parser.add_argument('name', type=str, location='args')
361
user_parser.add_argument('active', type=bool, location='args')
362
363
product_parser = base_parser.copy()
364
product_parser.add_argument('category', type=str, location='args')
365
product_parser.add_argument('min_price', type=float, location='args')
366
product_parser.add_argument('max_price', type=float, location='args')
367
368
# Modify existing arguments
369
user_parser.replace_argument('per_page', type=int, default=20, help='Users per page')
370
371
# Remove arguments
372
user_parser.remove_argument('page') # Remove pagination
373
```
374
375
### File Upload Handling
376
377
```python
378
from flask_restplus import reqparse
379
from werkzeug.datastructures import FileStorage
380
381
upload_parser = reqparse.RequestParser()
382
383
# Single file upload
384
upload_parser.add_argument('file',
385
location='files',
386
type=FileStorage,
387
required=True,
388
help='File to upload')
389
390
# Multiple file uploads
391
upload_parser.add_argument('attachments',
392
location='files',
393
type=FileStorage,
394
action='append',
395
help='Multiple files can be uploaded')
396
397
@api.route('/upload')
398
class FileUpload(Resource):
399
@api.expect(upload_parser)
400
def post(self):
401
args = upload_parser.parse_args()
402
uploaded_file = args['file']
403
404
if uploaded_file and uploaded_file.filename:
405
# Save the file
406
filename = secure_filename(uploaded_file.filename)
407
uploaded_file.save(os.path.join('/uploads', filename))
408
return {'message': f'File {filename} uploaded successfully'}, 201
409
410
return {'error': 'No file provided'}, 400
411
```
412
413
### Integration with API Documentation
414
415
```python
416
from flask_restplus import Api, Resource, reqparse, fields
417
418
api = Api()
419
420
# Parser automatically generates Swagger documentation
421
user_parser = reqparse.RequestParser()
422
user_parser.add_argument('name',
423
type=str,
424
required=True,
425
help='User full name (required)')
426
user_parser.add_argument('email',
427
type=str,
428
required=True,
429
help='User email address (required)')
430
user_parser.add_argument('age',
431
type=int,
432
help='User age (optional)')
433
user_parser.add_argument('active',
434
type=bool,
435
default=True,
436
help='Account status (default: true)')
437
438
@api.route('/users')
439
class UserList(Resource):
440
@api.expect(user_parser) # Documents expected parameters
441
def post(self):
442
"""Create a new user"""
443
args = user_parser.parse_args()
444
# Implementation...
445
return {'message': 'User created'}, 201
446
```
447
448
### Error Handling and Validation
449
450
```python
451
from flask_restplus import reqparse, abort
452
453
parser = reqparse.RequestParser()
454
455
def validate_positive_int(value):
456
"""Custom validator for positive integers."""
457
try:
458
int_value = int(value)
459
if int_value <= 0:
460
raise ValueError("Must be a positive integer")
461
return int_value
462
except (ValueError, TypeError):
463
raise ValueError("Must be a valid positive integer")
464
465
parser.add_argument('quantity',
466
type=validate_positive_int,
467
required=True,
468
help='Quantity must be a positive integer')
469
470
@api.route('/orders')
471
class OrderCreate(Resource):
472
@api.expect(parser)
473
def post(self):
474
try:
475
args = parser.parse_args()
476
quantity = args['quantity']
477
# Process order...
478
return {'message': f'Order created for {quantity} items'}, 201
479
except Exception as e:
480
# Validation errors are automatically handled by Flask-RESTPlus
481
# and return appropriate error responses
482
abort(400, message=str(e))
483
```
484
485
### Complex Nested Parsing
486
487
```python
488
from flask_restplus import reqparse
489
import json
490
491
parser = reqparse.RequestParser()
492
493
def json_type(value):
494
"""Parse JSON string into Python object."""
495
try:
496
return json.loads(value)
497
except (json.JSONDecodeError, TypeError):
498
raise ValueError("Must be valid JSON")
499
500
# Accept complex nested data as JSON strings
501
parser.add_argument('metadata',
502
type=json_type,
503
location='json',
504
help='Metadata as JSON object')
505
506
parser.add_argument('settings',
507
type=json_type,
508
location=['json', 'form'],
509
help='Settings configuration as JSON')
510
511
@api.route('/configure')
512
class Configuration(Resource):
513
@api.expect(parser)
514
def post(self):
515
args = parser.parse_args()
516
metadata = args['metadata'] # Already parsed as dict/list
517
settings = args['settings'] # Already parsed as dict/list
518
519
# Use the parsed objects directly
520
return {
521
'message': 'Configuration updated',
522
'metadata_keys': list(metadata.keys()) if isinstance(metadata, dict) else [],
523
'settings_keys': list(settings.keys()) if isinstance(settings, dict) else []
524
}, 200
525
```