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.