Flask RESTful API多个复杂端点

 _珊渣渣 发布于 2023-02-08 18:34

在我的Flask-RESTful API中,假设我有两个对象,用户和城市.这是1对多的关系.现在,当我创建API并向其添加资源时,我似乎只能将非常简单的常规URL映射到它们.这是代码(没有包含无用的东西):

class UserAPI(Resource):  # The API class that handles a single user
  def __init__(self):
    # Initialize

  def get(self, id):
    # GET requests

  def put(self, id):
    # PUT requests

  def delete(self, id):
    # DELETE requests

class UserListAPI(Resource):  # The API class that handles the whole group of Users
  def __init__(self):

  def get(self):

  def post(self):

api.add_resource(UserAPI, '/api/user/', endpoint='user')
api.add_resource(UserListAPI, '/api/users/', endpoint='users')

class CityAPI(Resource):
  def __init__(self):

  def get(self, id):

  def put(self, id):

  def delete(self, id):

class CityListAPI(Resource):
  def __init__(self):

  def get(self):

  def post(self):

api.add_resource(CityListAPI, '/api/cities/', endpoint='cities')
api.add_resource(CityAPI, '/api/city/', endpoint='city')

如您所见,我可以做我想要实现的所有基本功能.我可以获取,发布,放置和删除这两个对象.但是,我的目标是双重的:

(1)能够请求城市名称等其他参数,而不仅仅是城市ID.它看起来像:
api.add_resource(CityAPI, '/api/city/', endpoint='city')
除了它不会抛出这个错误:

AssertionError:视图函数映射正在覆盖现有的端点函数

(2)能够在请求中组合两个资源.假设我想让所有用户与某个城市相关联.在REST URL中,它应该类似于:
/api/cities//users

我如何使用Flask做到这一点?我将它映射到哪个端点?

基本上,我正在寻找将API从基本应用到可用的方法.感谢您的任何想法/建议

1 个回答
  • 你犯了两个错误.

    首先,Flask-RESTful会让您认为资源是使用单个URL实现的.实际上,您可以使用许多不同的URL来返回相同类型的资源.在Flask-RESTful中,您需要Resource为每个URL 创建不同的子类,但从概念上讲,这些URL属于同一资源.请注意,事实上,您已经为每个资源创建了两个实例来处理列表和各个请求.

    您所犯的第二个错误是您希望客户端知道API中的所有网址.这不是构建API的好方法,理想情况下,客户端只知道一些顶级URL,然后从顶级URL的响应中发现其余的数据.

    在您的API中,您可能希望公开/api/users/api/cities作为顶级API.各个城市和用户的网址将包含在回复中.例如,如果我调用http://example.com/api/users以获取用户列表,我可能会收到此响应:

    {
        "users": [ 
            {
                "url": "http://example.com/api/user/1",
                "name": "John Smith",
                "city": "http://example.com/api/city/35"
            },
            {
                "url": "http://example.com/api/user/2",
                "name": "Susan Jones",
                "city": "http://example.com/api/city/2"
            }
        ]
    }
    

    请注意,用户的JSON表示包括该用户的URL以及该城市的URL.客户端不需要知道如何构建这些,因为它们是给予它的.

    以他们的名字获取城市

    正如您所定义的那样/api/city/<id>,城市的URL 是,以及获取城市完整列表的URL /api/cities.

    如果您还需要按名称搜索城市,则可以扩展"城市"端点以执行此操作.例如,您可以让表单中的网址/api/cities/<name>返回与给定的搜索字词匹配的城市列表<name>.

    使用Flask-RESTful,您需要为此定义一个新的Resource子类,例如:

        class CitiesByNameAPI(Resource):
            def __init__(self):
                # ...    
            def get(self, name):
                # ...
    
        api.add_resource(CitiesByNameAPI, '/api/cities/<name>', endpoint = 'cities_by_name')
    

    获取属于某个城市的所有用户

    当客户要求一个城市时,它应该得到一个响应,其中包含一个URL以获取该城市的用户.例如,假设从/api/users上面的响应中我想了解第一个用户的城市.所以现在我发送请求http://example/api/city/35,然后我得到以下JSON响应:

    {
        "url": "http://example.com/api/city/35",
        "name": "San Francisco",
        "users": "http://example/com/api/city/35/users"
    }
    

    现在我有了这个城市,这给了我一个URL,我可以使用它来获取该城市的所有用户.

    请注意,您的URL难以构建或难以构建,因为客户端永远不需要从头开始构建大部分URL,它只是从服务器获取它们.这也使您可以在将来更改URL的格式.

    要实现按城市获取用户的URL,请添加另一个Resource子类:

        class UsersByCityAPI(Resource):
            def __init__(self):
                # ...    
            def get(self, id):
                # ...
    
        api.add_resource(UsersByCityAPI, '/api/cities/<int:id>/users', endpoint = 'users_by_city')
    

    我希望这有帮助!

    2023-02-08 18:36 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有