Home > front end >  Flask App with Mongo Gives Error on Passable Argument
Flask App with Mongo Gives Error on Passable Argument

Time:12-09

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))
  • Related