使用Python的Bottle和Bootstrap来制作类似Instagram的网站(第三部)
注意
这篇文章完全是我个人的备忘录。
1. 上次的梗概和本次的目标
第一次版本我們製作了外觀。
第二次版本我們連接了資料庫,接近實際可使用的一步。
之前我們是將圖片保存在靜態資料夾中,但如果繼續這樣部署的話,所有數據都會消失,因此我們決定將圖片保存在mongoDB中。
此外,我們還希望這次能夠實際上進行發布和刪除操作。
2. 完成目标的图表
我想创建一个名为”binaryImage”的集合,并在其中包含名为”filepath”和”binaryImage”的文档。当访问/user/时,将显示该图像。因此,我想将filepath命名为类似于前一次的_的名称。
我想创建一个页面,用户可以输入图像和评论,并且当上传后会显示在用户页面上。
我希望添加一个按钮,当点击它时可以删除相应的条目。
3. 二进制图像集合
我们要创建一个专门用于收集图像的二进制图像集合binaryImage。图像的保存是在创建条目时进行的,所以让我们在那里实现它。我改写的只是最后一部分。
我用一个名为savepath的变量指定了文件名,并将图像本身的二进制数据放入了binaryImage集合中。现在我们已经保存了图像,接下来考虑显示图像。
#エントリー投稿のロジック部分
@app.route("/<userID>/upload" , method = "post")
def addEntry(mongodb , userID) :
#userが存在していなかったらなにもしない
query = mongodb["userinfo"].find({"userID": userID})
img = request.files.get("upload")
comment = request.forms.get("comment") #文字化けしない・・・?
if query.count() == 0 :
return "user not found"
else :
#userが存在するとき。コメントのみなのか画像もあるのかで処理内容区別
userdbID = methods.userdbID_from_userID(userID, mongodb)
if (img == None) & (comment == "") : return "なにもないよ"
elif img == None :
#commentのみ
entryID = mongodb["entry"].insert_one(
{"userdbID": userdbID, "imgfilename": "" , "comment": comment , "userID" : userID}
).inserted_id
else :
print(img.filename) # safeな文字列のみで構成させるので、複数画像をアップロードするときにnameがかぶるかも
entryID = mongodb["entry"].insert_one(
{"userdbID": userdbID, "imgfilename": img.filename, "comment": comment , "userID" : userID}
).inserted_id
#entryIDを付与してimgに格納
savepath = str(entryID) + "_" + img.filename
binaryImage = img.file.read() #これでバイナリーデータになる模様
mongodb["binaryImage"].insert_one({"filepath" : savepath , "binaryImage":binaryImage})
return redirect("/" + userID)
4. 显示图像
我想要在将filepath(文件名)投入到数据库后显示图像。当访问”/img/”时,根据filepath显示图像的程序如下所示。
以前,图像保存在img文件夹中,从那里读取图像。现在,我将其更改为img_static文件夹,并且只在需要调用我准备的图像时使用它。
#IMGs : データベースから読みだしたい
@app.route('/img/<filepath>')
def sample_image(mongodb , filepath):
binaryImage = mongodb["binaryImage"].find_one({"filepath":filepath})["binaryImage"]
resp = HTTPResponse(status=200, body=binaryImage) #200 means OK
resp.content_type = 'image' #'image/*' だとダウンロードになってしまった。
resp.set_header('Content-Length', str(len(binaryImage)))
return resp
@app.route('/img_static/<filepath>')
def static_image(filepath):
return static_file(filepath, root="./img_static")
删除输入实现
这很简单。通过接收entryID,从entry集合中找到并删除该文章。
文章将从数据库中消失,但图片将继续留存在数据库中。
#エントリー削除用のURL
@app.route("/deleteEntry/<userID>/<entryID>")
def deleteEntry(mongodb , userID , entryID) :
#entryが存在していなかったらなにもしない
query = mongodb["entry"].find({"_id": ObjectId(entryID)}) #IDをObjectIdに戻すの忘れがち
if query.count() == 0 :
return "The entry is not found"
elif query.count() > 1 :
return "記事がいくつもある・・・"
else :
#そのエントリーを削除する
mongodb["entry"].delete_one({"_id": ObjectId(entryID)}) #IDをObjectIdに戻すの忘れがち
return redirect("/" + userID)
6. 编辑HTML
我已经修改代码,使其从userinfo集合和entry集合中检索数据。现在,每次部署后都不会丢失图片了。
%for q in reversed(list(entry)):
<div class="col-lg-6 mb-5">
<div class="card lg-6 box-shadow" >
<img class="card-img-top" src="../img/{{str(q['_id'])+'_'+ q['imgfilename']}}" alt = "">
<div class="card-body">
<h5 class="card-title">@{{userinfo['userID']}}</h5>
<p class="card-text">{{q['comment']}}</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<a href="deleteEntry/{{userinfo['userID']}}/{{str(q['_id'])}}" type="button" class="btn btn-sm btn-outline-secondary">Delete</a>
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
</div>
<small class="text-muted">9 mins</small>
</div>
</div>
</div>
</div>
%end
7. 未来
下一步我想要尝试用户注册和与Twitter的连接。我也想要注重外观,所以我希望能学习JavaScript以及相关的库。