Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flask_restplus add_namespace keep getting no attribute 'as_view'

Tags:

python

flask

I writing a flask, trying to organize it by using Blueprint with Namespace, following this tutorial

I had faced some problem, and had look around internet and had review solution in 1 and 2. The first one is not relevant to what I doing, and the second one the solution just doesn't fix my problem.

Here are my code:

project/project.py

from flask import Flask, jsonify, url_for
from .apis.apis import api

app = Flask(__name__)

app.register_blueprint(api, url_prefix="/api")

project/apis/apis.py

from flask import Blueprint
from .user.authentication import auth
from flask_restplus import Api, apidoc, Resource

blueprint = Blueprint("api", __name__)

api = Api(blueprint, doc='/docs', ui=False)

api.add_namespace(auth, path="/auth") #Keep getting error at this line

project/apis/user/authentication.py

from flask_restplus import Namespace

auth = Namespace('auth', description='Authentication')

@auth.route("/test")
def authentication():
    return "test"

Stack Trace

    Traceback (most recent call last):
        File "/home/gaara/Python/Flask-Api/project/__init__.py", line 1, in <module>
            from .project import app
        File "/home/gaara/Python/Flask-Api/project/project.py", line 3, in <module>
            from .apis.apis import api
        File "/home/gaara/Python/Flask-Api/project/apis/apis.py", line 13, in <module>
            api.add_namespace(auth, path="/auth")
        File "/home/gaara/Python/Flask-Api/venv/lib/python3.6/site-packages/flask_restplus/api.py", line 413, in add_namespace
            self.register_resource(ns, resource, *self.ns_urls(ns, urls), **kwargs)
        File "/home/gaara/Python/Flask-Api/venv/lib/python3.6/site-packages/flask_restplus/api.py", line 255, in register_resource
            self._register_view(self.app, resource, *urls, **kwargs)
        File "/home/gaara/Python/Flask-Api/venv/lib/python3.6/site-packages/flask_restplus/api.py", line 276, in _register_view
            resource_func = self.output(resource.as_view(endpoint, self, *resource_class_args,
    AttributeError: 'function' object has no attribute 'as_view'

I am not sure why I keep getting this error, had try few approach, include put apis.py all in __init__.py and change the import, but always getting the same error.

What I wish is to code api in an organize way, and when go to localhost:5000/api/auth/test it will output me test

like image 776
Tony Ng Wei Shyang Avatar asked Mar 08 '23 11:03

Tony Ng Wei Shyang


2 Answers

You defined a function, but Flask restplus requires a class, as you can also see in your tutorial.

So it should look like this:

from flask_restplus import Resource

@auth.route("/test") 
class Authentication(Resource):
    def get(self):
        return "test"
like image 130
Anna Lena Avatar answered Apr 06 '23 23:04

Anna Lena


While the approved answer is fully correct, let me dispose why we always say, that if something is possible, does not mean that you should do! So the following to be for everyone a lesson (at 1st place for myself) of an ANTI-PATTERN!

I was a bit tinkering here & there, I found out what is needed for a function like you mentioned in order to be registered and usable by a framework, like F-Restplus (I've used in my case F-RestX==0.5.0, but in reality is a fork of that), and here we go:

def avg(dummy_self_var=''):
    # the dummy_self_var is needed in order to trick and pretend to be as an instance method
    result = 'any-calculation-that-has-to-be-made'
    logging.debug(f'AVG result is: {result}')

    return Response(str(result))


# imitating that this function is a Resource :D
avg.view_class = Resource
avg.as_view = Resource.as_view # at the end, it could be the following function as well: `lambda x,y: avg`
avg.view_class.methods = {'GET', }
avg.view_class.get = avg

api.add_resource(avg, '/asd')

With the help of this I achieved to have the same functionality, it works & gets registered automatically by the Swagger-UI docs:

So, while nearly everything is possible, I could not imagine a situation where someone needs this 'workaround', instead, to be forward-compatible, I would definitely refactor instead of producing this mess in the long-run. Of course, the choice is up to you.

like image 33
Hunor Portik Avatar answered Apr 06 '23 23:04

Hunor Portik