Quickstart - webargs 8.1.0 documentation

Hide navigation sidebar
Hide table of contents sidebar
Back to top
Toggle table of contents sidebar

# 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 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 import flaskparser

    parser = flaskparser.FlaskParser()

    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.