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

Decorate with multiple/chained parameters #48

Open
jdjodrey opened this issue Jan 31, 2017 · 8 comments
Open

Decorate with multiple/chained parameters #48

jdjodrey opened this issue Jan 31, 2017 · 8 comments

Comments

@jdjodrey
Copy link

I would like to add multiple parameters to an endpoint, essentially chaining them as so:

 @api.parameters(SomeParameters())
 @api.parameters(MoreParameters())
 @api.parameters(EvenMoreParameters())
 def get(self, args):
    ...

However, this results in a separate dict for each set of parameters and does not concatenate the arguments as I had expected. Also, Swagger does not seem to parse all of the argument options as only the topmost decorator appears in the docs.

image

I could simply create another Parameters class that combines all of the fields from the others, but I'd like to avoid having to create one for each desired combination of parameters.

Another idea I had was to create a method that would accept any number of Parameter objects and return a new dynamic Schema object with all of the combined fields. Something like:

 @api.parameters(many_params(SomeParameters(), MoreParameters(), EvenMoreParameters()))
 def get(self, args):
    ...

What is the recommended approach to accomplish this? I feel like I must be missing an easier way...

@frol
Copy link
Owner

frol commented Jan 31, 2017

Currently, there are no plans to support chained parameters (simply due to the lack of time, and because implementing it the right way may take more time than it might be expected). Multiple Inheritance is the way to go now. Still, you can implement many_params helper yourself. It would be great if you share your experience and the implementation, so we can consider to include it into this example/boilerplate.

Thank you for your interest and sharing this idea!

@jdjodrey
Copy link
Author

jdjodrey commented Feb 1, 2017

Good to know, thanks @frol. I'm very appreciative of all your hard work on this project, and if I end up going the helper method route, I'll be sure to post my implementation details back here.

@jdjodrey
Copy link
Author

jdjodrey commented Feb 2, 2017

Here's what I ended up going with:

def multi_params(*params):
    m = Parameters()
    for p in params:
        m.fields = dict(m.fields, **p.fields)
    return m

And then you can simply put that callable in the decorate and pass in any number of parameter objects to it:

@api.parameters(multi_params(IncludeParameters(), OnlyParameters()))

It's somewhat crude and is definitely limited in handling more complex objects, but it serves my purpose for simple parameters with one or two fields (and it keeps Swagger happy too).

For anyone looking to do something similar, please feel free to improve/refine it!

@frol
Copy link
Owner

frol commented Feb 2, 2017

@jdjodrey Thanks for sharing. I will just comment an obvious limitation of your implementation: custom validations defined on the classes will be ignored, and the reason I haven't touched it is that I have no idea on how to merge @validates_schema handlers.

@soundstripe
Copy link

soundstripe commented Dec 18, 2017

I'm running across the same problem here. I'd like to add that it would be nice to be able to specify different locations for each set of parameters. Something like:

@api.parameters(AuthenticationParameters(), locations['header', ])
@api.parameters(PaginationParameters(), locations['query', ])
@api.parameters(SearchQueryParameters(), locations=['json', ])
def get():
    return {}

If I come up with anything I'll drop it here.

@joeyorlando
Copy link

👍 on this

@bitfinity
Copy link

@jdjodrey Your method has been working quite well for me.

@Hatuw
Copy link

Hatuw commented Nov 17, 2020

Thanks for @jdjodrey sharing. But it seems that not support locations='path'. I don't know how to adapt your method...Could you help me? pls @jdjodrey

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

No branches or pull requests

6 participants