Quickstart¶
Basic Usage¶
Arguments are specified as a dictionary of name -> Field
pairs.
from webargs import fields, validate
user_args = {
# Required arguments
"username": fields.Str(required=True),
# Validation
"password": fields.Str(validate=lambda p: len(p) >= 6),
# OR use marshmallow's built-in validators
"password": fields.Str(validate=validate.Length(min=6)),
# Default value when argument is missing
"display_per_page": fields.Int(load_default=10),
# Repeated parameter, e.g. "/?nickname=Fred&nickname=Freddie"
"nickname": fields.List(fields.Str()),
# Delimited list, e.g. "/?languages=python,javascript"
"languages": fields.DelimitedList(fields.Str()),
# When value is keyed on a variable-unsafe name
# or you want to rename a key
"user_type": fields.Str(data_key="user-type"),
}
Note
See the marshmallow.fields
documentation for a full reference on available field types.
To parse request arguments, use the parse
method of a Parser
object.
from flask import request
from webargs.flaskparser import parser
@app.route("/register", methods=["POST"])
def register():
args = parser.parse(user_args, request)
return register_user(
args["username"],
args["password"],
fullname=args["fullname"],
per_page=args["display_per_page"],
)
Decorator API¶
As an alternative to Parser.parse
, you can decorate your view with use_args
or use_kwargs
. The parsed arguments dictionary will be injected as a parameter of your view function or as keyword arguments, respectively.
from webargs.flaskparser import use_args, use_kwargs
@app.route("/register", methods=["POST"])
@use_args(user_args) # Injects args dictionary
def register(args):
return register_user(
args["username"],
args["password"],
fullname=args["fullname"],
per_page=args["display_per_page"],
)
@app.route("/settings", methods=["POST"])
@use_kwargs(user_args) # Injects keyword arguments
def user_settings(username, password, fullname, display_per_page, nickname):
return render_template("settings.html", username=username, nickname=nickname)
Note
When using use_kwargs
, any missing values will be omitted from the arguments.
Use **kwargs
to handle optional arguments.
from webargs import fields, missing
@use_kwargs({"name": fields.Str(required=True), "nickname": fields.Str(required=False)})
def myview(name, **kwargs):
if "nickname" not in kwargs:
# ...
pass
Request “Locations”¶
By default, webargs will search for arguments from the request body as JSON. You can specify a different location from which to load data like so:
@app.route("/register")
@use_args(user_args, location="form")
def register(args):
return "registration page"
Available locations include:
'querystring'
(same as'query'
)'json'
'form'
'headers'
'cookies'
'files'
Validation¶
Each Field
object can be validated individually by passing the validate
argument.
from webargs import fields
args = {"age": fields.Int(validate=lambda val: val > 0)}
The validator may return either a boolean
or raise a ValidationError
.
from webargs import fields, ValidationError
def must_exist_in_db(val):
if not User.query.get(val):
# Optionally pass a status_code
raise ValidationError("User does not exist")
args = {"id": fields.Int(validate=must_exist_in_db)}
Note
If a validator returns None
, validation will pass. A validator must return False
or raise a ValidationError
for validation to fail.
There are a number of built-in validators from marshmallow.validate
(re-exported as webargs.validate
).
from webargs import fields, validate
args = {
"name": fields.Str(required=True, validate=[validate.Length(min=1, max=9999)]),
"age": fields.Int(validate=[validate.Range(min=1, max=999)]),
}
The full arguments dictionary can also be validated by passing validate
to Parser.parse
, Parser.use_args
, Parser.use_kwargs
.
from webargs import fields
from webargs.flaskparser import parser
argmap = {"age": fields.Int(), "years_employed": fields.Int()}
# ...
result = parser.parse(
argmap, validate=lambda args: args["years_employed"] < args["age"]
)
Error Handling¶
Each parser has a default error handling method. To override the error handling callback, write a function that
receives an error, the request, the marshmallow.Schema
instance, status code, and headers.
Then decorate that function with Parser.error_handler
.
from webargs.flaskparser import parser
class CustomError(Exception):
pass
@parser.error_handler
def handle_error(error, req, schema, *, error_status_code, error_headers):
raise CustomError(error.messages)
Parsing Lists in Query Strings¶
Use fields.DelimitedList
to parse comma-separated
lists in query parameters, e.g. /?permissions=read,write
from webargs import fields
args = {"permissions": fields.DelimitedList(fields.Str())}
If you expect repeated query parameters, e.g. /?repo=webargs&repo=marshmallow
, use
fields.List
instead.
from webargs import fields
args = {"repo": fields.List(fields.Str())}
Nesting Fields¶
Field
dictionaries can be nested within each other. This can be useful for validating nested data.
from webargs import fields
args = {
"name": fields.Nested(
{"first": fields.Str(required=True), "last": fields.Str(required=True)}
)
}
Note
Of the default supported locations in webargs, only the json
request location supports nested datastructures. You can, however, implement your own data loader to add nested field functionality to the other locations.
Next Steps¶
Go on to Advanced Usage to learn how to add custom location handlers, use marshmallow Schemas, and more.
See the Framework Support page for framework-specific guides.
For example applications, check out the examples directory.