簡體   English   中英

Flask RESTful API多個復雜端點

[英]Flask RESTful API multiple and complex endpoints

在我的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/<int:id>', 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/<int:id>', endpoint='city')

如您所見,我可以做我想要實現的所有基本功能。 我可以獲取,發布,放置和刪除這兩個對象。 但是,我的目標是雙重的:

(1)能夠請求城市名稱等其他參數,而不僅僅是城市ID。 它看起來像:
api.add_resource(CityAPI, '/api/city/<string:name>', endpoint='city')
除了它不會給我這個錯誤:

AssertionError:視圖函數映射正在覆蓋現有的端點函數

(2)能夠在請求中組合兩個資源。 假設我想讓所有用戶與某個城市相關聯。 在REST URL中,它應該類似於:
/api/cities/<int:id>/users

我如何使用Flask做到這一點? 我將它映射到哪個端點?

基本上,我正在尋找將API從基本應用到可用的方法。 感謝您的任何想法/建議

你犯了兩個錯誤。

首先,Flask-RESTful會讓您認為資源是使用單個URL實現的。 實際上,您可以使用許多不同的URL來返回相同類型的資源。 在Flask-RESTful中,您需要為每個URL創建不同的Resource子類,但從概念上講,這些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。 客戶端不需要知道如何構建這些,因為它們是給予它的。

以他們的名字獲取城市

城市的URL是/api/city/<id> ,獲取完整城市列表的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')

我希望這有幫助!

您可以在不重復資源的情況下執行id / name事務:

api.add_resource(CitiesByNameAPI, '/api/cities/<name_or_id>', endpoint = 'cities_by_name')

class CitiesByNameAPI(Resource):
    def get(self, name_or_id):
        if name_or_id.isdigit():
            city = CityModel.find_by_id(name_or_id)
        else:
            city = CityModel.find_by_name(name_or_id)

        if city:
            return city.to_json(), 200
        return {'error': 'not found'}, 404

不確定是否有任何負面影響。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM