使用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以及相关的库。

广告
将在 10 秒后关闭
bannerAds