首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用RESTful -RestX制作API时遇到困难:“没有在规范中定义的操作!”和“404”

在使用RESTful -RestX制作API时遇到困难:“没有在规范中定义的操作!”和“404”
EN

Stack Overflow用户
提问于 2020-09-06 11:57:47
回答 1查看 3.4K关注 0票数 1

总之,我一直在遵循烧瓶restx教程来创建api,但是我的端点没有出现在swagger页面上(“没有在规范中定义的操作!”)每当我给他们打电话的时候我就会得到404

我创建了我的api,主要遵循这个https://flask-restx.readthedocs.io/en/latest/scaling.html

我正在使用python 3.8.3作为参考。

下面是我正在做的一个简单的例子。

简而言之,我的问题是,我错过了什么?目前空白的原因是这不工作。

目录结构

代码语言:javascript
复制
project/
  - __init__.py
  - views/
    - __init__.py
    - test.py
manage.py
requirements.txt

文件内容

requirements.txt

代码语言:javascript
复制
Flask-RESTX==0.2.0
Flask-Script==2.0.6

manage.py

代码语言:javascript
复制
from flask_script import Manager

from project import app


manager = Manager(app)


if __name__ == '__main__':
    manager.run()

project/init.py

代码语言:javascript
复制
from flask import Flask

from project.views import api


app = Flask(__name__)

api.init_app(app)

project/views/init.py

代码语言:javascript
复制
from flask_restx import Api, Namespace, fields


api = Api(
    title='TEST API',
    version='1.0',
    description='Testing Flask-RestX API.'
)

# Namespaces
ns_test = Namespace('test', description='a test namespace')

# Models
custom_greeting_model = ns_test.model('Custom', {
    'greeting': fields.String(required=True),
})

# Add namespaces
api.add_namespace(ns_test)

project/views/test.py

代码语言:javascript
复制
from flask_restx import Resource

from project.views import ns_test, custom_greeting_model


custom_greetings = list()


@ns_test.route('/')
class Hello(Resource):

    @ns_test.doc('say_hello')
    def get(self):
        return 'hello', 200


@ns_test.route('/custom')
class Custom(Resource):

    @ns_test.doc('custom_hello')
    @ns_test.expect(custom_greeting_model)
    @ns_test.marshal_with(custom_greeting_model)
    def post(self, **kwargs):
        custom_greetings.append(greeting)
        pos = len(custom_greetings) - 1

        return [{'id': pos, 'greeting': greeting}], 200

我是如何测试的&我所期望的

因此,转到swagger页面,我希望定义的两个端点都在那里,但我只看到了前面提到的错误。

仅在shell中使用Ipython,我就尝试跟踪使用请求的调用,然后只返回404。

代码语言:javascript
复制
import json
import requests as r

base_url = 'http://127.0.0.1:5000/'
代码语言:javascript
复制
response = r.get(base_url + 'api/test')
response
代码语言:javascript
复制
response = r.get(base_url + 'api/test/')
response
代码语言:javascript
复制
data = json.dumps({'greeting': 'hi'})
response = r.post(base_url + 'test/custom', data=data)
response
代码语言:javascript
复制
data = json.dumps({'greeting': 'hi'})
response = r.post(base_url + 'test/custom/', data=data)
response
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-10 15:56:57

TL;DR

我在代码和测试中犯了一些错误:

  1. 在声明路由之前注册api。
  2. 对于如何将参数传递给post方法,做了一个简单的假设。
  3. expect装饰器中使用模型而不是请求解析器
  4. 使用错误的api/前缀调用测试中的端点。

全数

我相信这是因为在声明任何路由之前,我在api上注册了名称空间。

我的理解是,当api在应用程序上注册时,应用程序上的“傲慢文档”和“路由”就会在那时设置好。因此,在此之后在api上定义的任何路由都不被认可。我认为这是因为当我在views/test.py文件中声明名称空间(也是避免该文件与views/__init__.py之间的循环引用的模型)时,swagger文档定义了路由,并且我的测试工作正常(在我更正了它们之后)。

在我的应用程序和测试中还有更多的错误,它们是

进一步的错误1

在我的应用程序中,在views/test.py文件中,我做了一个愚蠢的假设:变量将由预期的参数组成(我将神奇地让问候作为某个非局部变量)。查看文档,我了解到了RequestParser,我需要像这样声明一个

代码语言:javascript
复制
from flask_restx import reqparse

# Parser
custom_greeting_parser = reqparse.RequestParser()
custom_greeting_parser.add_argument('greeting', required=True, location='json')

并在expect装饰器中使用这个。然后,我可以在post方法中检索参数的字典。用下面的

代码语言:javascript
复制
...
    def post(self):
        args = custom_greeting_parser.parse_args()
        greeting = args['greeting']
        ...

结果证明,**kwargs是不必要的。

进一步的错误2

在我的测试中,我调用端点api/test,这是不正确的,它只是test。对此端点的校正测试为

test 端点校正测试

代码语言:javascript
复制
import json
import requests as r

base_url = 'http://127.0.0.1:5000/'

response = r.get(base_url + 'test')
print(response)
print(json.loads(response.content.decode()))

进一步的错误3

对于另一个端点post的测试,我需要包含一个声明内容类型的头,以便解析器能够“看到”参数,因为我已经明确地将这个位置指定为json。下面的校正测试。

test/custom 端点的校正测试

代码语言:javascript
复制
import json
import requests as r

base_url = 'http://127.0.0.1:5000/'

data = json.dumps({'greeting': 'hi'})
headers = {'content-type': 'application/json'}
response = r.post(base_url + 'test/custom', data=data, headers=headers)
print(response)
print(json.loads(response.content.decode()))

修正码

对于具有错误代码的文件。

views/init.py

代码语言:javascript
复制
from flask_restx import Api

from project.views.test import ns_test


api = Api(
    title='TEST API',
    version='1.0',
    description='Testing Flask-RestX API.'
)


# Add namespaces
api.add_namespace(ns_test)

views/test.py

代码语言:javascript
复制
from flask_restx import Resource, Namespace, fields, reqparse


# Namespace
ns_test = Namespace('test', description='a test namespace')

# Models
custom_greeting_model = ns_test.model('Custom', {
    'greeting': fields.String(required=True),
    'id': fields.Integer(required=True),
})

# Parser
custom_greeting_parser = reqparse.RequestParser()
custom_greeting_parser.add_argument('greeting', required=True, location='json')


custom_greetings = list()


@ns_test.route('/')
class Hello(Resource):

    @ns_test.doc('say_hello')
    def get(self):
        return 'hello', 200


@ns_test.route('/custom')
class Custom(Resource):

    @ns_test.doc('custom_hello')
    @ns_test.expect(custom_greeting_parser)
    @ns_test.marshal_with(custom_greeting_model)
    def post(self):
        args = custom_greeting_parser.parse_args()
        greeting = args['greeting']

        custom_greetings.append(greeting)
        pos = len(custom_greetings) - 1

        return [{'id': pos, 'greeting': greeting}], 200
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63763884

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档