在完成对同一资源的请求的过程中向Flask资源发出请求

时间:2017-05-29 15:39:52

标签: python mongodb rest api flask

我正在为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我也认为问题更多的是我的设计结构。我有很多麻烦突破这个任何帮助将不胜感激。谢谢

0 个答案:

没有答案