英文:
getting invalid document error while querying mongodb database
问题
@app.route('/request books', methods=['GET', 'POST'])
@app.route('/get books', methods=['GET', 'POST'])
def requesting_for_books():
try:
mydb = mongo.db.mylogin
user_col = mydb.find_one({"email": session['email']})
final = dict(user_col)
verify = final['isVerified']
form = RequestBooks()
if ('email' in session and verify == True) and ('password' in session and request.method == 'GET'):
return render_template('get_books.html', title="Get Books", donated_by=session['username'], form=form)
elif 'email' in session and request.method == 'POST':
requesting = mongo.db.mylogin
request_books = requesting.find({ location: { "$nearSphere": { "$geometry" : {"type" : "Point", "coordinates": [session['lat'], session['lang']] } } } })
x = []
for i in request_books:
x.append(i)
real_data = x
if request_books == None:
flash("Please enter a search query !")
return render_template('get_books.html', title='Get Books', form=form)
else:
return render_template('get_books.html', title="Get Books", request_books=request_books[0], form=form)
else:
flash('Please Login/Sign Up first to Search for books !')
return redirect(url_for('home'))
except KeyError:
flash("Please Sign in first !")
return render_template('index.html', title="Home")
In this code snippet, there's an implementation of a route for requesting and retrieving books from a MongoDB database. The code checks if the user is logged in and verified before allowing them to access the book requests. It fetches books from the database based on location and displays them using the 'get_books.html' template. If the user is not logged in, appropriate messages are flashed. The code also handles exceptions using try-except blocks.
英文:
i am getting this error while querying my mongodb database: bson.errors.InvalidDocument: documents must have only string keys, key was function location at 0x7f50be59ac80, my database collection looks like this(see image below)
Here's the code
@app.route('/request books', methods=['GET', 'POST'])
@app.route('/get books', methods=['GET', 'POST'])
def requesting_for_books():
try:
mydb = mongo.db.mylogin
user_col = mydb.find_one({"email" : session['email']})
final = dict(user_col)
verify = final['isVerified']
form = RequestBooks()
if ('email' in session and verify == True) and ('password' in session and request.method == 'GET'):
return render_template('get_books.html', title="Get Books", donated_by=session['username'], form=form)
elif 'email' in session and request.method == 'POST':
requesting = mongo.db.mylogin
request_books = requesting.find({ location: { "$nearSphere": { "$geometry" : {"type" : "Point", "coordinates": [session['lat'], session['lang']]} } } })
x = []
for i in request_books:
x.append(i)
real_data = x
if request_books == None:
flash("Please enter a search query !")
return render_template('get_books.html', title='Get Books', form=form)
else:
return render_template('get_books.html', title="Get Books", request_books=request_books[0], form=form)
else:
flash('Please Login/Sign Up first to Search for books !')
return redirect(url_for('home'))
except KeyError:
flash("Please Sign in first !")
return render_template('index.html', title="Home")
However if i loop through over request_books variable, i am able to get pymongo cursor value of my document.
Please help !
答案1
得分: 1
在你的查询中,location
应该是一个字符串,请用单引号或双引号括起来。
可能在模块的其他地方(或者在使用 form module_name import *
导入的其他模块中)有一个名为 location
的函数。
您可以通过一些编辑使代码更简单/可读:
# 由于 REST API 将获取和设置动词嵌入到 HTTP 方法中,
# 只需使用 "/books"(这只是个人偏好)
@app.route('/books', methods=['GET', 'POST'])
def requesting_for_books():
mydb = mongo.db.mylogin
# 最好在异常发生时立即处理异常,
# 并附带的好处是您不需要检查会话中是否有电子邮件
try:
user_col = mydb.find_one({"email" : session['email']})
except KeyError:
flash("请先登录!")
return render_template('index.html', title="主页")
# user_col 已经是一个字典,无需转换
verify = user_col['isVerified']
form = RequestBooks()
# 如果代码运行到这里,那么会话中必须有电子邮件,无需检查
# "== True" 可以省略
if verify and 'password' in session and request.method == 'GET':
return render_template(
'get_books.html',
title="获取图书",
donated_by=session['username'],
form=form
)
# 由于您在前面的 if 中返回了,因此不需要 else/elif 语句,只需再次使用 if
if request.method == 'POST':
# 我想这是错误的,
# 它应该指向图书集合而不是 mylogin 集合
requesting = mongo.db.mylogin
# 如果您只需要第一个元素,只需使用 find_one
request_books = requesting.find_one({
"location": {
"$nearSphere": {
"$geometry" : {
"type" : "Point",
"coordinates": [session['lat'], session['lang']]
}
}
}
})
# 即使 request_books 为 None,也可以将其传递给 render_template,
# 并直接在模板中处理数据的存在
return render_template(
'get_books.html',
title="获取图书",
request_books=request_books,
form=form
)
# 不需要使用 "else",因为您已从其他分支返回
flash('请先登录/注册以搜索图书!')
return redirect(url_for('home'))
如果您想要获取请求的图书列表,只需使用 find 函数并将游标转换为列表,这样您将获得一个字典列表:
request_books = list(requesting.find({
"location": {
"$nearSphere": {
"$geometry" : {
"type" : "Point",
"coordinates": [session['lat'], session['lang']]
}
}
}
}))
英文:
The location
in your query should be a string, enclose it in single or double quotes.
Probably you have a function named location
elsewhere in the module (or in other modules called with form module_name import *
).
You can make the code simpler/more readable with some edits:
# since REST APIs have the get and set verb embedded into the HTTP method,
# just use "books" (this is a personal preference, though)
@app.route('/books', methods=['GET', 'POST'])
def requesting_for_books():
mydb = mongo.db.mylogin
# it's better to handle exception as soon as they arise,
# with the added bonus that you don't need to check
# if email is in session in the following statements
try:
user_col = mydb.find_one({"email" : session['email']})
except KeyError:
flash("Please Sign in first !")
return render_template('index.html', title="Home")
# user_col is already a dictionary, no need to transform it
verify = user_col['isVerified']
form = RequestBooks()
# if the code runs until here, then email must be in session, no need to check
# `== True` can be omitted
if verify and 'password' in session and request.method == 'GET':
return render_template(
'get_books.html',
title="Get Books",
donated_by=session['username'],
form=form
)
# since you returned in the previous if,
# there's no need for an else/elif statement, just use if again
if request.method == 'POST':
# I suppose this is wrong,
# it should be point to the books collection and not mylogin collection
requesting = mongo.db.mylogin
# if you need only the first element, just use find_one
request_books = requesting.find_one({
"location": {
"$nearSphere": {
"$geometry" : {
"type" : "Point",
"coordinates": [session['lat'], session['lang']]
}
}
}
})
# you can pass request_books to render_template even if it is None
# and handle the presence of data directly in the template
return render_template(
'get_books.html',
title="Get Books",
request_books=request_books,
form=form
)
# no need to use "else", since you returned from the other branches
flash('Please Login/Sign Up first to Search for books !')
return redirect(url_for('home'))
If you would like to get the list of the requested books, you can simply use the find function and convert the cursor into a list, so you'll get a list of dictionaries:
request_books = list(requesting.find({
"location": {
"$nearSphere": {
"$geometry" : {
"type" : "Point",
"coordinates": [session['lat'], session['lang']]
}
}
}
}))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论