I have a flask app and a mongo instance locally, I am using a lav set-up and am wondering why I am getting the following message when I pass an ID to the API endpoint:
the-real-devops-challenge-devopschallenge-1 | Traceback (most recent call last):
the-real-devops-challenge-devopschallenge-1 | File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2073, in wsgi_app
the-real-devops-challenge-devopschallenge-1 | response = self.full_dispatch_request()
the-real-devops-challenge-devopschallenge-1 | File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1518, in full_dispatch_request
the-real-devops-challenge-devopschallenge-1 | rv = self.handle_user_exception(e)
the-real-devops-challenge-devopschallenge-1 | File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1516, in full_dispatch_request
the-real-devops-challenge-devopschallenge-1 | rv = self.dispatch_request()
the-real-devops-challenge-devopschallenge-1 | File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1502, in dispatch_request
the-real-devops-challenge-devopschallenge-1 | return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
the-real-devops-challenge-devopschallenge-1 | File "./app.py", line 25, in restaurant
the-real-devops-challenge-devopschallenge-1 | restaurants = find_restaurants(mongo, _id)
the-real-devops-challenge-devopschallenge-1 | File "/code/src/mongoflask.py", line 30, in find_restaurants
the-real-devops-challenge-devopschallenge-1 | query["_id"] = ObjectId(id)
the-real-devops-challenge-devopschallenge-1 | File "/usr/local/lib/python3.7/site-packages/bson/objectid.py", line 105, in __init__
the-real-devops-challenge-devopschallenge-1 | self.__validate(oid)
the-real-devops-challenge-devopschallenge-1 | File "/usr/local/lib/python3.7/site-packages/bson/objectid.py", line 210, in __validate
the-real-devops-challenge-devopschallenge-1 | "not %s" % (type(oid),))
the-real-devops-challenge-devopschallenge-1 | TypeError: id must be an instance of (bytes, str, ObjectId), not <class 'builtin_function_or_method'>
I have tried numerous things to get it to return the JSON Object, but it does not work.
I know it has something to do with the way I am passing the _id
but I am not sure how to fix it:
Code for app.py:
from os import environ
from bson import json_util
from bson.objectid import ObjectId
from flask import Flask, jsonify
from flask_pymongo import PyMongo
from src.mongoflask import MongoJSONEncoder, ObjectIdConverter, find_restaurants
app = Flask(__name__)
app.config["MONGO_URI"] = environ.get("MONGO_URI")
app.json_encoder = MongoJSONEncoder
app.url_map.converters["objectid"] = ObjectIdConverter
mongo = PyMongo(app)
@app.route("/api/v1/restaurant")
def restaurants():
restaurants = find_restaurants(mongo)
return jsonify(restaurants)
@app.route("/api/v1/restaurant/<_id>")
def restaurant(_id):
restaurants = find_restaurants(mongo, _id)
return jsonify(restaurants)
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=False, port=8080)
Code for mongo.py
from datetime import date, datetime
import isodate as iso
from bson import ObjectId
from flask.json import JSONEncoder
from werkzeug.routing import BaseConverter
class MongoJSONEncoder(JSONEncoder):
def default(self, o):
if isinstance(o, (datetime, date)):
return iso.datetime_isoformat(o)
if isinstance(o, ObjectId):
return str(o)
else:
return super().default(o)
class ObjectIdConverter(BaseConverter):
def to_python(self, value):
return ObjectId(value)
def to_url(self, value):
return str(value)
def find_restaurants(mongo, _id=""):
query = {}
if _id != "":
print(_id)
query["_id"] = ObjectId(id)
return list(mongo.db.restaurant.find(query))
When I curl:
curl localhost:8080/api/v1/restaurant
it works, but when I try:
curl localhost:8080/api/v1/restaurant/55f14313c7447c3da7052485
it fails with this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>
CodePudding user response:
Turns out I had a type in the query["_id"] = ObjectId(id)
it should have been query["_id"] = ObjectId(_id)
:
from datetime import date, datetime
import isodate as iso
from bson import ObjectId
from flask.json import JSONEncoder
from werkzeug.routing import BaseConverter
class MongoJSONEncoder(JSONEncoder):
def default(self, o):
if isinstance(o, (datetime, date)):
return iso.datetime_isoformat(o)
if isinstance(o, ObjectId):
return str(o)
else:
return super().default(o)
class ObjectIdConverter(BaseConverter):
def to_python(self, value):
return ObjectId(value)
def to_url(self, value):
return str(value)
def find_restaurants(mongo, _id=""):
query = {}
if _id != "":
print(_id)
query["_id"] = ObjectId(_id)
return list(mongo.db.restaurant.find(query))