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(missing=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 you know where an argument should be parsed from
    "active": fields.Bool(location="query"),
    # When value is keyed on a variable-unsafe name
    # or you want to rename a key
    "content_type": fields.Str(load_from="Content-Type", location="headers"),
    # OR, on marshmallow 3
    # "content_type": fields.Str(data_key="Content-Type", location="headers"),
    # File uploads
    "profile_image": fields.Field(
        location="files", validate=lambda f: f.mimetype in ["image/jpeg", "image/png"]
    ),
}

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 URL query string (e.g. "/?name=foo"), form data, and JSON data (in that order). You can explicitly specify which locations to search, like so:

@app.route("/register")
@use_args(user_args, locations=("json", "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 import flaskparser

parser = flaskparser.FlaskParser()


class CustomError(Exception):
    pass


@parser.error_handler
def handle_error(error, req, schema, status_code, 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

By default, webargs only parses nested fields using the json request location. You can, however, implement your own parser 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.