flask-restplus-server-example icon indicating copy to clipboard operation
flask-restplus-server-example copied to clipboard

Decorate with multiple/chained parameters

Open jdjodrey opened this issue 7 years ago • 8 comments

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...

jdjodrey avatar Jan 31 '17 20:01 jdjodrey

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!

frol avatar Jan 31 '17 21:01 frol

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 avatar Feb 01 '17 01:02 jdjodrey

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!

jdjodrey avatar Feb 02 '17 14:02 jdjodrey

@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.

frol avatar Feb 02 '17 15:02 frol

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.

soundstripe avatar Dec 18 '17 17:12 soundstripe

👍 on this

joeyorlando avatar Feb 09 '18 16:02 joeyorlando

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

bitfinity avatar May 09 '18 14:05 bitfinity

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

Hatuw avatar Nov 17 '20 08:11 Hatuw