ashleysommer / sanic-restplus

Fully featured framework for fast, easy and documented API development with Sanic
http://flask-restplus.readthedocs.org
Other
104 stars 14 forks source link

Multiple values for "url_prefix" #6

Closed madsenwattiq closed 5 years ago

madsenwattiq commented 5 years ago

I've been having a hard time using Blueprints with sanic_restplus, and am wondering if this is just an area that is in progress? My own code is giving an error about multiple values for the argument "url_prefix" even though it's only defined once, in one blueprint definition.

To rule out my code, I tried to run the example "todo_blueprint", changing Flask to Sanic, and I'm getting the same result:

Traceback (most recent call last): File "test.py", line 4, in api_v1 = Blueprint('api', name, url_prefix='/api/1') TypeError: init() got multiple values for argument 'url_prefix'

Has anyone seen this? Thanks in advance for help you might be able to offer. Sanic-Restplus is clearly the right way to go for building REST APIs on Sanic, but I haven't gotten multiple API versions and blueprints working yet....

ashleysommer commented 5 years ago

Hi @madsenibis

Yes, you're right. This is an area in progress.

Sanic-restplus, while in development for a few years now, was only just released on PyPI recently for others to use (it was just accessible from github before). So its not surprising that others are finding bugs now.

It looks to me like this is a simple parameter ordering bug in the sanic-restplus code. I will check it out. But I'm pretty sure that, even if I fix that bug, Sanic-Restplus still doesn't work on Sanic Blueprints, there are other limitations of sanic blueprints that prevent that. I will double check.

madsenwattiq commented 5 years ago

Thanks for the ultra-quick response! I'll avoid blueprints for the moment, no worries. I am migrating an API from an older design and see no reason to not build on top of an asyncio-capable framework. We have two API versions, and Blueprints and namespaces are nice designs to handling that, but I can do it without blueprints for the moment. the benefits of Sanic and a solid REST framework are more important.

Thanks for your work in porting a great framework to Sanic!

madsenwattiq commented 5 years ago

Apologies, but another issue surrounding "multiple values". I started with your example "complex.py", and made sure that worked as given.

I then migrated a couple of API classes in place of your "cat" and "dog" examples. Each of the two API classes at this point looks like this:

from sanic_restplus import Namespace, Resource, fields
from sanic.response import json

ns = Namespace('utilization', description='Asset utilization data')

@ns.route('/<target_type>')
class UtilizationData(Resource):
    def get(self, target_type):
        return json({"target_type": target_type})

Each has "target_type" as a parameter like your examples have "id" as a parameter. The only difference is that in the init.py for the package with the API classes, I give a "path" parameter to add_namespace calls, so I can indicate the API version:

api = Api(
    title='Prototyping V2',
    version='v2beta1',
    description='Prototyping V2'
)

api.add_namespace(ns_electrical, path="/data/v2/electrical")
api.add_namespace(ns_utilization, path="/data/v2/utilization")`

When I run the server, I get:

[2019-06-15 09:37:54 -0700] [28277] [INFO] Starting worker [28277]
[2019-06-15 09:37:58 -0700] [28277] [ERROR] RestPlus: (<class 'TypeError'>, TypeError("get() got multiple values for argument 'target_type'"), <traceback object at 0x103cb39c8>)
[2019-06-15 09:37:58 -0700] - (sanic.access)[INFO][127.0.0.1:63141]: GET http://localhost:8000/data/v2/electrical/asset  500 42

You had "id" as a parameter in both your cat and dog examples, so identical parameter names across API classes has to work. What is happening above with "multiple values" for the parameter? Is it because I specified a base path? Does specifying a path to mount an API work right now in sanic-restplus?

It would be so much nicer to use sanic-restplus as opposed to simply building on raw sanic for an API. But I'm getting the sense that the library is in a state of great change? Should I wait for it to stabilize?

Thanks for your help and advice.

ashleysommer commented 5 years ago

Hi @madsenibis I noticed you closed this issue, so you might have worked it out yourself. But the problem in that second issue you described is you are missing the request parameter in your get handler. It should look like this:

    def get(self, request, target_type):
        return json({"target_type": target_type})

All route handlers in Sanic, even those provided by plugins like Sanic-restplus, and all other sanic-plugins-framework based plugins, will required their first argument to be request.

ashleysommer commented 5 years ago

@madsenibis I'm trying to replicate your initial problem you were having with blueprints.

When I setup a Sanic Blueprint and add Sanic-Restplus to it, I get: RuntimeError: As of Sanic 0.7.0, you cannot use Sanic-Restplus on a Blueprint. This will likely change in the future. This is a catch I put in place last year to cover the occasions people will try to use it on a Blueprint, when it doesn't currently work. However this is different to what you were seeing. Are you able to post a minimal code example that reproduces the problem you were seeing?