最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用 Flask 做一個(gè)評(píng)論系統(tǒng)

 更新時(shí)間:2020年11月27日 10:22:37   作者:Frost''s Blog  
這篇文章主要介紹了如何使用 Flask 做一個(gè)評(píng)論系統(tǒng),幫助大家更好的理解和使用flask框架進(jìn)行python web開(kāi)發(fā),感興趣的朋友可以了解下

因?yàn)槲也┛褪褂玫腄isqus代理服務(wù)下線,博客的評(píng)論系統(tǒng)可能有一陣子沒(méi)有工作了。慚愧的是我竟然最近才發(fā)現(xiàn),我的工作環(huán)境一直是沒(méi)有GFW存在的,發(fā)現(xiàn)是因?yàn)橛袀€(gè)朋友為了留言給我不惜通過(guò)贊賞1元錢的方式。贊賞功能也是我最近才上的功能,但我怎么是這么一個(gè)無(wú)良的博主呢,我認(rèn)為一個(gè)好的評(píng)論交流環(huán)境還是非常有必要的。但是自建評(píng)論還是換用其他墻內(nèi)友好的評(píng)論系統(tǒng),我還是糾結(jié)了一陣的,大致上我有這么幾個(gè)要求:

  1. 主要服務(wù)墻內(nèi),Disqus雖香但墻內(nèi)用不了啊
  2. 顏值,要能匹配當(dāng)前博客的主色調(diào),或者能方便地自定義皮膚
  3. 評(píng)論要支持markdown語(yǔ)法
  4. 評(píng)論數(shù)據(jù)要有地方可管理、歸檔、導(dǎo)入導(dǎo)出等
  5. 外部用戶使用評(píng)論的門檻要低
  6. 用戶收到回復(fù)時(shí)能通過(guò)他「常用的」聯(lián)系方式收到通知

評(píng)論系統(tǒng)大致有這么幾個(gè)選擇方向:一是使用類似Disqus這樣的三方平臺(tái),這樣數(shù)據(jù)托管不用操心,但服務(wù)隨時(shí)有掛掉的風(fēng)險(xiǎn),而且外觀上也不夠自由;二是使用Github Issue作為后端的評(píng)論系統(tǒng),比如Gitment,utterances 好處是你不必?fù)?dān)心Github掛掉,而且不用收錢。但不方便后續(xù)打包遷移,而且我一直反對(duì)過(guò)度利用Github;那么剩下的選擇就是自己擼一個(gè)了,簡(jiǎn)單的構(gòu)思評(píng)估以后我列出以下列功能大綱:

  • 評(píng)論數(shù)據(jù)模型
  • 評(píng)論展示
  • 評(píng)論管理
  • 導(dǎo)入disqus評(píng)論
  • 新評(píng)論通知
  • 第三方登錄
  • 評(píng)論導(dǎo)出(低優(yōu)先)

類比Workpress提供的評(píng)論功能,用戶只需要填用戶姓名和電子郵件這兩個(gè)信息就夠了,前者用來(lái)顯示作者名,后者用來(lái)接收通知,個(gè)人網(wǎng)站用來(lái)推廣自己,但不是必填的。我在這個(gè)基礎(chǔ)上,希望增加第三方登錄的功能,這樣用戶就不用填寫這些信息,點(diǎn)一個(gè)按鈕就好了。關(guān)于第三方登錄的開(kāi)發(fā)實(shí)現(xiàn),我會(huì)留到下一篇文章中。

評(píng)論數(shù)據(jù)模型

首先是評(píng)論數(shù)據(jù)模型的設(shè)計(jì),我的理念是夠用就好,不用太多太復(fù)雜的東西,畢竟我的文章平均0.2條評(píng)論。所以,點(diǎn)贊什么的就不要了,評(píng)論刪除直接刪數(shù)據(jù)就好了,也不需要什么狀態(tài)。

其中分別有一個(gè)外鍵指向作者用戶以及文章記錄,User里面會(huì)記錄這個(gè)用戶的Email, 名稱,頭像信息。另外會(huì)有一個(gè)parent_id指向評(píng)論回復(fù)的對(duì)象(也是一條評(píng)論),這里有一個(gè)指向自身的外鍵,使用Flask-SQLAlchemy寫起來(lái)是這樣的:

class Comment(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  post_id = db.Column(db.Integer, db.ForeignKey("post.id"))
  author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
  floor = db.Column(db.Integer)
  content = db.Column(db.Text())
  html = db.Column(db.Text())
  create_at = db.Column(db.DateTime(), default=datetime.utcnow)
  parent_id = db.Column(db.Integer, db.ForeignKey("comment.id"))
  replies = db.relationship(
    "Comment", backref=db.backref("parent", remote_side=[id]), lazy="dynamic"
  )

  __table_args__ = (db.UniqueConstraint("post_id", "floor", name="_post_floor"),)

floor表明評(píng)論是「第幾樓」,注意這里有個(gè)限制,每篇文章樓層不能重復(fù)。

評(píng)論展示

接下來(lái)看看如何展示評(píng)論。每條評(píng)論都可能有若干回復(fù),回復(fù)評(píng)論又有回復(fù),所以這是一個(gè)樹(shù)形的結(jié)構(gòu),最極端的,如果把所有樹(shù)形都嵌套顯示出來(lái),就會(huì)像網(wǎng)易新聞評(píng)論蓋樓那樣。另一個(gè)極端,是把所有評(píng)論都展平,按回復(fù)時(shí)間排序顯示,這樣又會(huì)失去回復(fù)的上下文信息。還是那句話,夠用就好,我選擇了一條折中的方式:兩層樹(shù)形展示。直接評(píng)論的是第一層節(jié)點(diǎn),然后回復(fù)這些評(píng)論的,和回復(fù)這些回復(fù)的,都展平成一層節(jié)點(diǎn),算作這條評(píng)論的子節(jié)點(diǎn)。外層評(píng)論和子節(jié)點(diǎn)都按時(shí)間排序顯示,但只有外層評(píng)論具有樓層屬性。且子節(jié)點(diǎn)應(yīng)該展示回復(fù)的是哪位作者,這樣就大大減小了上下文混淆的可能(雖然我覺(jué)得我這評(píng)論的量,全顯示成一層也不會(huì)怎樣)。

評(píng)論框編輯器使用的是simple-mde,使用起來(lái)非常簡(jiǎn)單:

<link rel="stylesheet"  rel="external nofollow" >
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
...
<textarea name="content"></textarea>
...
<script>
var simplemde = new SimpleMDE();
</script>

完事!后續(xù)可能會(huì)考慮加上emoji選擇器。markdown保存,后端渲染html,前端取出展示。最后結(jié)果非常漂亮令我滿意,大家可以在本篇文章下面看到效果。

評(píng)論管理

對(duì)應(yīng)的,在管理員頁(yè)面也加上一個(gè)評(píng)論管理頁(yè)面,以及開(kāi)啟內(nèi)置評(píng)論的開(kāi)關(guān)。因?yàn)樽畛踉O(shè)計(jì)的是評(píng)論一經(jīng)發(fā)出,只能刪除,不能修改,所以這種頁(yè)面對(duì)我這樣的CRUD程序員來(lái)說(shuō)不在話下。

現(xiàn)在就到了激動(dòng)人心的時(shí)刻了,把Disqus的評(píng)論數(shù)據(jù)遷移過(guò)來(lái)!我到Disqus頁(yè)面上去看,發(fā)現(xiàn)Disqus支持導(dǎo)出評(píng)論數(shù)據(jù)為特定的結(jié)構(gòu),是一個(gè)xml,只要是結(jié)構(gòu)化的數(shù)據(jù),那就問(wèn)題不大了。主要分為兩個(gè)部分,前半部分是thread的列表,表示有哪些文章開(kāi)啟了Disqus的評(píng)論,包含文章的url等信息(取決于你如何開(kāi)啟的Disqus),后半部分是評(píng)論列表,每條評(píng)論有評(píng)論內(nèi)容、作者信息、回復(fù)的上級(jí)評(píng)論ID,還好數(shù)據(jù)模型設(shè)計(jì)得好,這些都在射程范圍內(nèi)。于是寫了一個(gè)函數(shù)解析,導(dǎo)入這些數(shù)據(jù),注意有些已刪除的或者垃圾評(píng)論直接過(guò)濾掉即可,函數(shù)放在這里了。

上傳文件,導(dǎo)入,成功,Disqus的評(píng)論就完美遷移過(guò)來(lái)了!

評(píng)論通知

評(píng)論通知需要拿到用戶的聯(lián)系方式,所以表單中電子郵件是必填的,接入第三方登錄時(shí),我也要考慮哪些服務(wù)是可以獲得聯(lián)系方式的,目前決定是用Github,Google兩種方式,至于新浪微博,雖然國(guó)人常用,但好像沒(méi)有誰(shuí)會(huì)在微博上留聯(lián)系方式,所以排除,微信倒是很好,但微信的第三方登錄好像很麻煩的樣子,暫不考慮。所以最后就是郵件通知。那就簡(jiǎn)單了,用Flask的擴(kuò)展Flask-Mail全都搞定,但在使用中我遇到兩個(gè)坑:

如果在后臺(tái)任務(wù)中做發(fā)送郵件的操作,注意獲取g對(duì)象需要應(yīng)用上下文,獲取請(qǐng)求信息需要請(qǐng)求上下文,而光用Flask提供的copy_current_request_context只復(fù)制請(qǐng)求上下文,而會(huì)創(chuàng)建新的應(yīng)用上下文,我寫了兩個(gè)函數(shù),一個(gè)是添加應(yīng)用和請(qǐng)求上下文到一個(gè)函數(shù),另一個(gè)是將函數(shù)轉(zhuǎn)換成后臺(tái)任務(wù):

def with_app_context(f):
  ctx = _app_ctx_stack.top
  req_ctx = _request_ctx_stack.top.copy()

  def wrapper(*args, **kwargs):
    with ctx:
      with req_ctx:
        return f(*args, **kwargs)
  return update_wrapper(wrapper, f)


def background_task(f):
  def wrapper(*args, **kwargs):
    future = gevent.spawn(with_app_context(f), *args, **kwargs)

    def callback(result):
      exc = result.exception
      current_app.log_exception((type(exc), exc, exc.__traceback__))

    future.link_exception(with_app_context(callback))
    return future

  return update_wrapper(wrapper, f)

這里后臺(tái)任務(wù)用了gevent,如果用線程方式,則改成

from concurrent.futures import ThreadPoolExecutor

def background_task(f):
  def wrapper(*args, **kwargs):
    with ThreadPoolExecutor() as pool:
      future = pool.submit(with_app_context(f), *args, **kwargs)

    def callback(result):
      exc = result.exception()
      if exc is not None:
        current_app.log_exception((type(exc), exc, exc.__traceback__))

    future.add_done_callback(with_app_context(callback))
    return future

  return update_wrapper(wrapper, f)

騰訊云的主機(jī)默認(rèn)禁掉了25端口,害我找了半天原因,只要自己在控制臺(tái)解禁一下即可立刻生效。

參考鏈接

源碼倉(cāng)庫(kù): https://github.com/frostming/Flog
Implementing User Comments with SQLAlchemy - miguelgrinberg.com

以上就是如何使用 Flask 做一個(gè)評(píng)論系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于flask 做評(píng)論系統(tǒng)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python深拷貝與淺拷貝用法實(shí)例分析

    Python深拷貝與淺拷貝用法實(shí)例分析

    這篇文章主要介紹了Python深拷貝與淺拷貝用法,結(jié)合實(shí)例形式分析了Python對(duì)象的復(fù)制、深拷貝、淺拷貝等操作原理、用法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2019-05-05
  • python如何求解兩數(shù)的最大公約數(shù)

    python如何求解兩數(shù)的最大公約數(shù)

    這篇文章主要為大家詳細(xì)介紹了python如何求解兩數(shù)的最大公約數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • 基于python的ini配置文件操作工具類

    基于python的ini配置文件操作工具類

    這篇文章主要為大家詳細(xì)介紹了基于python的ini配置文件操作工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • 使用PyTorch構(gòu)建神經(jīng)網(wǎng)絡(luò)的操作指南

    使用PyTorch構(gòu)建神經(jīng)網(wǎng)絡(luò)的操作指南

    PyTorch 是一個(gè)在研究領(lǐng)域廣泛使用的深度學(xué)習(xí)框架,提供了大量的靈活性和效率,本文將向你介紹如何使用 PyTorch 構(gòu)建你的第一個(gè)神經(jīng)網(wǎng)絡(luò),感興趣的小伙伴可以參考閱讀
    2023-07-07
  • python3常用的數(shù)據(jù)清洗方法(小結(jié))

    python3常用的數(shù)據(jù)清洗方法(小結(jié))

    這篇文章主要介紹了python3常用的數(shù)據(jù)清洗方法(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Python實(shí)現(xiàn)統(tǒng)計(jì)圖像連通域的示例詳解

    Python實(shí)現(xiàn)統(tǒng)計(jì)圖像連通域的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用Python實(shí)現(xiàn)統(tǒng)計(jì)圖像連通域的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-04-04
  • Python3.9.1中使用match方法詳解

    Python3.9.1中使用match方法詳解

    這篇文章主要介紹了Python3.9.1中使用match方法詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Python入門教程 超詳細(xì)1小時(shí)學(xué)會(huì)Python

    Python入門教程 超詳細(xì)1小時(shí)學(xué)會(huì)Python

    本文適合有經(jīng)驗(yàn)的程序員盡快進(jìn)入Python世界.特別地,如果你掌握J(rèn)ava和Javascript,不用1小時(shí)你就可以用Python快速流暢地寫有用的Python程序.
    2006-09-09
  • Python數(shù)據(jù)可視化中的時(shí)間序列圖表功能(實(shí)例展示其強(qiáng)大功能)

    Python數(shù)據(jù)可視化中的時(shí)間序列圖表功能(實(shí)例展示其強(qiáng)大功能)

    時(shí)間序列圖表在多個(gè)領(lǐng)域中都有廣泛的應(yīng)用,通過(guò)Python中的各種繪圖庫(kù)和數(shù)據(jù)分析工具,我們可以方便地對(duì)時(shí)間序列數(shù)據(jù)進(jìn)行可視化和分析,本文提供的示例代碼和方法能夠?yàn)槟臅r(shí)間序列數(shù)據(jù)分析工作提供有益的參考,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • YOLOv5車牌識(shí)別實(shí)戰(zhàn)教程(五)字符分割與識(shí)別

    YOLOv5車牌識(shí)別實(shí)戰(zhàn)教程(五)字符分割與識(shí)別

    這篇文章主要介紹了YOLOv5車牌識(shí)別實(shí)戰(zhàn)教程(五)字符分割與識(shí)別,在這個(gè)教程中,我們將一步步教你如何使用YOLOv5進(jìn)行車牌識(shí)別,幫助你快速掌握YOLOv5車牌識(shí)別技能,需要的朋友可以參考下
    2023-04-04

最新評(píng)論

万州区| 伊吾县| 中牟县| 迭部县| 深州市| 深水埗区| 夏河县| 大姚县| 桐梓县| 津市市| 温宿县| 宁安市| 广元市| 镇坪县| 遂川县| 璧山县| 克拉玛依市| 建湖县| 桐柏县| 麻城市| 凭祥市| 梓潼县| 武陟县| 溧水县| 铁岭县| 牟定县| 平武县| 宁国市| 晋州市| 恩施市| 怀柔区| 甘孜县| 准格尔旗| 斗六市| 来安县| 元谋县| 海安县| 石渠县| 原平市| 花垣县| 霍林郭勒市|