[Python] WriteError in pymongo through using test in Postman

Discussão em 'Python' iniciado por Stack, Fevereiro 22, 2025.

  1. Stack

    Stack Membro Participativo

    I am getting this error in my application:

    [​IMG]

    after trying to do a test case like this:

    [​IMG]

    Here is my application code, I am quite unsure as to why python is throwing this error at me. It seems to not like me trying to add a new review through Postman which is in this format here:

    [​IMG]

    from flask import Flask, request, jsonify, make_response
    from pymongo import MongoClient
    from bson import ObjectId
    import json
    import jwt
    import datetime
    from functools import wraps
    import bcrypt

    def jwt_required(func):
    @wraps(func)
    def jwt_required_wrapper(*args, **kwargs):
    token = None
    if 'x-access-token' in request.headers:
    token = request.headers['x-access-token']
    if not token:
    return jsonify( { 'message' : 'Token is missing' }), 401
    try:
    data = jwt.decode(token, app.config['SECRET_KEY'])
    except:
    return jsonify({ 'message' : 'Token is invalid' }), 401
    bl_token = blacklist.find_one( { "token" : token })
    if bl_token is not None:
    return make_response( jsonify ( { "message" : "Token has been cancelled "}), 401)
    return func(*args, **kwargs)
    return jwt_required_wrapper

    def admin_required(func):
    @wraps(func)
    def admin_required_wrapper(*args, **kwargs):
    token = request.headers['x-access-token']
    data = jwt.decode(token, app.config['SECRET_KEY'])
    if data["admin"]:
    return func(*args, **kwargs)
    else:
    return make_response( jsonify ( { "message" : "Admin access required"}), 401)
    return admin_required_wrapper

    class MyEncoder(json.JSONEncoder):

    def default(self, obj):
    if isinstance(obj, ObjectId):
    return str(obj)
    return super(MyEncoder, self).default(obj)

    app = Flask(__name__)

    app.config['SECRET_KEY'] = 'password123'

    client = MongoClient("mongodb://127.0.0.1:27017")
    db = client.bizDB
    businesses = db.biz
    users = db.users
    blacklist = db.blacklist
    app.json_encoder = MyEncoder


    with app.test_request_context():
    db.mycollection.insert_one({'a': 1})
    doc = db.mycollection.find_one({'a': 1})

    print(jsonify(doc).response)

    @app.route("/api/v1.0/businesses", methods=["GET"])
    def show_all_businesses():
    page_num, page_size = 1, 10
    if request.args.get("pn"):
    page_num = int(request.args.get("pn"))
    if request.args.get("ps"):
    page_size = int(request.args.get("ps"))
    page_start = page_size * (page_num - 1)

    data_to_return = []
    for business in businesses.find().skip(page_start).limit(page_size):
    business["_id"] = str(business["_id"])
    for review in business["reviews"]:
    review["_id"] = str(review["_id"])
    data_to_return.append(business)

    return make_response( jsonify( data_to_return ), 200 )


    @app.route("/api/v1.0/businesses/<string:id>", methods=["GET"])
    @jwt_required
    def show_one_business(id):
    business = businesses.find_one({"_id":ObjectId(id)})
    if business is not None:
    business["_id"] = str(business["_id"])
    for review in business["reviews"]:
    review["_id"] = str(review["_id"])
    return make_response ( jsonify ( business ), 200)
    else:
    return make_response (jsonify({ "error" : "Invalid Business ID" } ), 404)

    @app.route("/api/v1.0/businesses", methods=["POST"])
    @jwt_required
    def add_business():
    if "name" in request.form and "town" in request.form and "rating" in request.form:
    new_business = { "name" : request.form["name"],
    "town" : request.form["town"],
    "rating" : request.form["rating"],
    "reviews" : {}
    }
    new_business_id = businesses.insert_one(new_business)
    new_business_link = "http://localhost:5000/api/v1.0/businesses/" + str(new_business_id.inserted_id)

    return make_response( jsonify( { "url" : new_business_link } ), 201 )
    else:
    return make_response ( jsonify( { "error" : "Missing form data" } ), 404 )


    @app.route("/api/v1.0/businesses/<string:id>", methods=["PUT"])
    def edit_business(id):
    if "name" in request.form and "town" in request.form and "rating" in request.form:
    result = businesses.update_one(
    {"_id" : ObjectId(id)},
    {
    "$set": {
    "name" : request.form["name"],
    "town" : request.form["town"],
    "rating" : request.form["rating"]
    }
    }
    )
    if result.matched_count == 1:
    edited_business_link = "http://localhost:5000/api/v1.0/businesses/" + id
    return make_response( jsonify( { "url": edited_business_link } ), 200 )
    else:
    return make_response ( jsonify( { "error" : "Invalid business ID" } ), 404 )
    else:
    return make_response ( jsonify( { "error" : "Missing form data" } ), 404 )


    @app.route("/api/v1.0/businesses/<string:id>", methods=["DELETE"])
    @jwt_required
    @admin_required
    def delete_business(id):
    result = businesses.delete_one( { "_id" : ObjectId(id) })
    if result.deleted_count == 1:
    return make_response( jsonify( {} ), 204)
    else:
    return make_response ( jsonify( { "error" : "Invalid business ID" } ), 404 )



    @app.route("/api/v1.0/businesses/<string:id>/reviews", methods=["POST"])
    @jwt_required
    def add_new_review(id):
    new_review = {
    "_id" : ObjectId(),
    "username" : request.form["username"],
    "comment" : request.form["comment"],
    "stars" : request.form["stars"]
    }
    businesses.update_one( { "_id" : ObjectId(id)} , {"$push" : { "reviews" : new_review}})
    new_review_link = "http://localhost:5000/api/v1.0/businesses/" + id + "/reviews/" + str(new_review["_id"])
    return make_response( jsonify( { "url" : new_review_link } ), 201 )


    @app.route("/api/v1.0/businesses/<string:id>/reviews", methods=["GET"])
    def fetch_all_reviews(id):
    data_to_return = []
    business = businesses.find_one( {"_id" : ObjectId(id) }, { "reviews" : 1, "_id" : 0})
    for review in business["reviews"]:
    review["_id"] = str(review["_id"])
    data_to_return.append(review)
    return make_response( jsonify( data_to_return), 200 )

    @app.route("/api/v1.0/businesses/<string:business_id>/reviews/<string:review_id>", methods=["GET"])
    def fetch_one_review(business_id, review_id):
    business = businesses.find_one( { "reviews._id" : ObjectId(review_id)}, {"_id" : 0, "reviews.$" : 1} )
    if business is None:
    return make_response ( jsonify( { "error" : "Invalid business ID or Review ID" } ), 404 )
    business["reviews"][0]["_id"] = str(business["reviews"][0]["_id"])
    return make_response( jsonify( business["reviews"][0] ), 200)

    @app.route("/api/v1.0/businesses/<string:id>/reviews/<string:review_id>", methods=["PUT"])
    def edit_review(id, review_id):
    edited_review = {
    "reviews.$.username" : request.form["username"],
    "reviews.$.comment" : request.form["comment"],
    "reviews.$.stars" : request.form["stars"]
    }
    businesses.update_one( { "reviews._id" : ObjectId(review_id) }, {"$set" : edited_review })
    edit_review_url = "http://localhost:5000/api/v1.0/businesses/" + id + "/reviews/" + review_id
    return make_response( jsonify({ "url" : edit_review_url } ), 200 )



    @app.route("/api/v1.0/businesses/<string:id>/reviews/<string:review_id>", methods=["DELETE"])
    @jwt_required
    @admin_required
    def delete_review(id, review_id):
    businesses.update_one( { "_id" : ObjectId(id) }, { "$pull" : {"reviews" : { "_id" : ObjectId(review_id) } } } )
    return make_response( jsonify( {} ), 204)



    @app.route("/api/v1.0/login", methods = ["GET"])
    def login():
    auth = request.authorization
    if auth:
    user = users.find_one( { "username" : auth.username } )
    if user is not None:
    if bcrypt.checkpw(bytes(auth.password, 'UTF-8'), user["password"]):
    token = jwt.encode( {
    'user' : auth.username,
    'admin' : user["admin"],
    'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
    }, app.config['SECRET_KEY'])
    return make_response (jsonify({ 'token' : token.decode('UTF-8') }), 200)
    else:
    return make_response(jsonify({ "message" : "Bad password" } ), 401 )
    else:
    return make_response(jsonify({ "message" : "Bad username" } ), 401 )

    return make_response(jsonify({ "message" : "Authentication required" } ), 401 )

    @app.route("/api/v1.0/logout", methods=["GET"])
    @jwt_required
    def logout():
    token = None
    if 'x-access-token' in request.headers:
    token = request.headers['x-access-token']
    if not token:
    return make_response(jsonify({ "message" : "Token is missing" } ), 401 )
    else:
    blacklist.insert_one( { "token" : token } )
    return make_response(jsonify({ "message" : "Logout Successful" } ), 200 )




    if __name__ == "__main__":
    app.run(debug=True)



    The error I get back is simply:


    pymongo.errors.WriteError: The field 'reviews' must be an array but is of type object in document {_id: ObjectId('5ff3b9a145f6d9013ddb7586')}, full error: {'index': 0, 'code': 2, 'errmsg': "The field 'reviews' must be an array but is of type object in document {_id: ObjectId('5ff3b9a145f6d9013ddb7586')}"}
    ​

    Continue reading...

Compartilhe esta Página