Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I provide example values for PaginationParameterSchema? #363

Open
replicaJunction opened this issue Jun 2, 2022 · 3 comments
Open

Comments

@replicaJunction
Copy link

I really like adding example data to my OpenAPI spec. It helps some of my users understand my API endpoints more easily, and Rapidoc UI has a convenient "Fill Example" button to autofill example data when playing with the API interactively.

In general, I can add the example= or examples= keyword arguments to blueprint decorators to provide OpenAPI example data for parameters, return values, etc. I've also noticed that I can put these keywords in the marshmallow.field() definition to get the same effect. However, I can't find a way to specify example values for the automatic paging parameters added with the Blueprint.paginate decorator. The decorator itself doesn't expose a **kwargs parameter, and the schema of the generated object is created on the fly in a private helper function.

So far, the only way I've found to add examples to these values is by subclassing Blueprint, copy/pasting both paginate and the helper function _pagination_parameters_schema_factory, and adding example values to the anonymous class in that helper, like this:

def _pagination_parameters_schema_factory(def_page, def_page_size, def_max_page_size):
    """Generate a PaginationParametersSchema"""

    class PaginationParametersSchema(ma.Schema):
        """Deserializes pagination params into PaginationParameters"""

        class Meta:
            ordered = True
            unknown = ma.EXCLUDE

        page = ma.fields.Integer(
            load_default=def_page,
            validate=ma.validate.Range(min=1),
            example=def_page,  # Use the default page parameter as an example value
        )
        page_size = ma.fields.Integer(
            load_default=def_page_size,
            validate=ma.validate.Range(min=1, max=def_max_page_size),
            example=def_page_size,  # Again, use the provided default as an example
        )

        @ma.post_load
        def make_paginator(self, data, **kwargs):
            return PaginationParameters(**data)

    return PaginationParametersSchema

I'm opening this as an issue rather than just submitting a PR for that change because I'm new to flask-smorest and Marshmallow, and I could just be missing something obvious. This seems similar to #327, but not identical.

Is there an easier / better way to provide example data for these pagination fields?

@lafrech
Copy link
Member

lafrech commented Jun 3, 2022

I suppose I could add those two "example" lines to the core, I don't think it would hurt.

This wouldn't address the root issue (#327) which is pagination customization.

Subclassing and overriding _pagination_parameters_schema_factory seem like a fine enough solution to this, at least the best trade-off I can think off. Exposing the schema as class attribute would limit the possibilities to override it in the call to paginate.

Why did you have to duplicate paginate?

@replicaJunction
Copy link
Author

Subclassing and overriding _pagination_parameters_schema_factory seem like a fine enough solution to this, at least the best trade-off I can think off. Exposing the schema as class attribute would limit the possibilities to override it in the call to paginate.

Why did you have to duplicate paginate?

I duplicated paginate because _pagination_parameters_schema_factory isn't a class method. The existing paginate method/decorator has a hardcoded call to flask_smorest.pagination._pagination_parameters_schema_factory, and I couldn't change that reference without overriding the whole paginate method.

If that helper function was converted into an instance method of PaginationMixin, I don't think I'd need to override both, since at that point I could just override the helper function.

@lafrech
Copy link
Member

lafrech commented Jun 4, 2022

Oh, right. My comment above assumed it was a class or instance method.

We should make it a class or instance method, indeed.

I'm open to other suggestions about pagination mixin rework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants