我正在为MongoDB制作一个Flask REST API,用于在线食品订购服务。我们的数据库有两个集合类别和具有以下格式文档的项目。
category {
href: String,
_id: Number,
name: String,
description: String,
items {
href: String,
}
}
item {
href: String,
_id: Number,
name: String,
description: String,
quantity: Number,
category_id: Number,
offers {
size1: price1,
size2: price2,
}
}
href惯例来自Stormpath CTO https://stormpath.com/blog/linking-and-resource-expansion-rest-api-tips的演讲。它讨论了链接到其他api端点以嵌套可以在加载时扩展的数据。
我的问题是当我从api加载一个类别时,我希望属于它的项目从保存在项目的href元素中的api端点扩展。在我填写原始请求之前,我的请求开始/api/categories
,我成功跟踪了它尝试使用/api/items?category_id=_id
请求填充项目的位置。这是请求挂在服务器中。当我从浏览器取消原始请求/api/categories
时,它会继续向我提供/api/items?category_id=_id
的回复
这是我的Flask服务器的样子......
import requests
from flask import Flask, jsonify, url_for, redirect, request
from flask_pymongo import PyMongo
from flask_restful import Api, Resource
import json
from bson import json_util, ObjectId
app = Flask(__name__)
app.config["MONGO_DBNAME"] = 'AdriansWebsite'
mongo = PyMongo(app, config_prefix='MONGO')
APP_URL = "http://127.0.0.1:5000/"
def expand(document, expand_collections):
for key in document:
value = document[key]
if (key in expand_collections or 'all' in expand_collections):
if isinstance(value, dict) and len(value) == 1 and 'href' in value:
new_data = app.test_client().get(value['href'])
document[key] = new_data
elif isinstance(value, list):
for idx, nested_document in enumerate(value):
if isinstance(nested_document, dict) and len(nested_document) == 1 and 'href' in nested_document:
new_data = app.test_client().get(nested_document['href'])
print(new_data)
document[key][idx] = new_data
return document
class Collection(Resource):
def get(self, collection_name=None, collection_id=None):
all_args = request.args.lists()
expand_collections = []
query_parameters = dict()
for arg in all_args:
field = arg[0]
values = arg[1]
if(field == "expand"):
expand_collections.extend(values)
continue
elif("_id" in field):
for idx in range(len(values)):
if(type(values[idx] is not ObjectId)):
values[idx] = ObjectId(values[idx])
query_value = None
if (len(values) > 1):
query_value = {"$in": values}
else:
query_value = values[0]
query_parameters[field] = query_value
if collection_id:
collection = mongo.db[collection_name]
item = collection.find_one({"_id": ObjectId(collection_id)})
if item:
document_data = expand(item, expand_collections)
json_data = json.dumps(document_data, default=json_util.default)
return json_data
else:
return jsonify({"response": "no collection found for {}".format(collection_id)})
else:
collection = mongo.db[collection_name]
print(query_parameters)
items=collection.find(query_parameters)
data=[]
if items:
for item in items:
data.append(expand(item, expand_collections))
print(data)
return json.dumps(data, default=json_util.default)
else:
return jsonify({"response": "no collections found"})
def post(self, collection_name=None):
data = request.get_json()
if not data:
data = {"response": "ERROR"}
return json.dumps(data, default=json_util.default)
else:
for key in data:
if '_id' in key:
if(type(data[key]) is not ObjectId):
data[key] = ObjectId(data[key])
collection = mongo.db[collection_name]
new_id = collection.save(data)
data = {}
data['href'] = 'api/' + collection_name + '/' + str(new_id)
if(collection_name == 'categories'):
data['items'] = { "href": "api/items?category_id="+str(new_id)}
collection.update({'_id': new_id }, {'$set': data})
return jsonify({"response": "Object " + str(new_id) + " created"})
def put(self, collection_name=None, collection_id=None):
if(type(collection_id) is not ObjectId):
collection_id = ObjectId(collection_id)
data = request.get_json()
if '_id' in data:
del data[_id]
collection = mongo.db[collection_name]
collection.update({'_id': collection_id}, {'$set': data})
return jsonify({"response": "Object " + str(collection_id) + " updated"})
def delete(self, collection_name=None, collection_id=None):
if(type(collection_id) is not ObjectId):
collection_id = ObjectId(collection_id)
collection = mongo.db[collection_name]
collection.remove({'_id': collection_id})
return jsonify({"response": "Object " + str(collection_id) + " deleted"})
api = Api(app)
api.add_resource(Collection, "/api/<collection_name>", endpoint="collections")
api.add_resource(Collection, "/api/<collection_name>/<collection_id>", endpoint="collection")
if __name__ == "__main__":
app.run(debug=True)
问题发生在expand函数中,它传递了一个json文档和一个要扩展的键列表。当expand方法遇到并且实际上尝试扩展元素时会发生这种情况。我相信我的问题是因为我正在尝试向资源提出请求,我正在提交请求。我试图使用请求库和CURL我也认为问题更多的是我的设计结构。我有很多麻烦突破这个任何帮助将不胜感激。谢谢