question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

blueprint.arguments(location="view_args") fails with "view_args is not a valid location"

See original GitHub issue

Besides standard locations (query, json, form, etc), webargs also supports Flask-specific view_args option to validate the URL path parameters.

Here is the simplified example of my code:

@blueprint.route("/update/<string:item_id>/<string:list>", methods=["POST"])
@blueprint.arguments(ItemInputSchema(), location="view_args")
@blueprint.response(ItemSchema())
def move_item(data: ItemInputArgs, item_id: string, list: string):
    """Move an item to the specified list."""
    return move_item_to_list(data.item, data.list)

In this case, I want to validate item_id (check that this is a valid ID of the object existing in the database) and list (check that this is a string matching per-defined list of values) The schema looks like this:

class ItemInputArgs:
    """Arguments for the POST /update/<item>/<list>."""

    def __init__(self, item: Item, list: string):
        self.item = item
        self.list = list

class ItemInputSchema(Schema):

    item_id = fields.Str(required=True)
    list = fields.Str(required=True)

    @validates("item_id")
    def validate_item_id(self, value: str) -> None:
        """Check if item exists in the DB."""
        item = Item.query.filter_by(id=value).one_or_none()
        if item is None:
            raise ValidationError("Item with this id does not exist", "item")

    @validates("list")
    def validate_list(self, value: str) -> None:
        if value not in ['value1', 'value2', 'value3']:
            raise ValidationError('Wrong list value')

    @post_load
    def make_object(self, data: JSON, **kwargs: Any) -> ItemInputArgs:
        return ItemInputArgs(
            Item.query.filter_by(item_id=data["item_id"]).one(),
        )

This fails with an error:

    def arguments(
            self, schema, *, location='json', required=True,
            example=None, examples=None, **kwargs
    ):
        """Decorator specifying the schema used to deserialize parameters
        ...
        """
        try:
            openapi_location = __location_map__[location]
        except KeyError as exc:
            raise InvalidLocationError(
>               "{} is not a valid location".format(location)) from exc
E           flask_rest_api.exceptions.InvalidLocationError: view_args is not a valid location

venv/lib/python3.7/site-packages/flask_rest_api/arguments.py:47: InvalidLocationError

The __location_map__ itself is taken from the apispec package: from apispec.ext.marshmallow.openapi import __location_map__.

The workaround I use is this (just patch the __location_map__ and add view_args):

from apispec.ext.marshmallow.openapi import __location_map__

# The `view_args` location is supported by FlaskParser in webargs, 
# but flask-rest-api looks into the __location_map__ and raises an error, 
# so we patch the map to allow `view_args` as `location` in @blueprint.arguments.
__location_map__["view_args"] = "view_args"

Not sure though if that affects the schema generation (I am not generating it yet, although planning to).

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
lafrechcommented, Aug 29, 2019

Done in 0a70faa115cca26c194a5d8f20f319f4de53f645.

Thanks for the feedback.

1reaction
lafrechcommented, Aug 28, 2019

Hi. Thanks for reporting.

(Note you can specify ```py before your code blocks to get syntax highlighting.)

I don’t use webargs to validate path parameters as flask/werkzeug validation is often enough, so I never investigated this, but I knew it might be a little tricky.

This part of the code is removed in master branch (unreleased). Please give it a try.

You may have to keep your patch. Otherwise, you won’t get errors but the doc will be wrong, with the location defaulting to body.

Here’s what I’d try:

from apispec.ext.marshmallow.openapi import __location_map__
__location_map__["view_args"] = "path"

Please tell us how it goes.

We should find a better way to address this.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Arguments — flask-smorest 0.40.0 documentation
To inject arguments into a view function, use the Blueprint.arguments decorator. It allows to specify a Schema to deserialize and validate the parameters....
Read more >
API — Flask Documentation (2.2.x)
Calls the blueprint's register() method after recording the blueprint in the application's blueprints . Parameters. blueprint (Blueprint) – The blueprint to ...
Read more >
Flask, Marshmallow 3, and webargs use_args fails to parse ...
When I curl an unknown parameter I expect a ValidationError to be raised because it's an unknown parameter. This also does not work...
Read more >
Parsing arguments and building values — Python 3.11.1 ...
This format converts a bytes-like object to a C pointer to a character string; it does not accept Unicode objects. The bytes buffer...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found