亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

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

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

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

評論數(shù)據(jù)模型

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

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

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表明評論是「第幾樓」,注意這里有個限制,每篇文章樓層不能重復(fù)。

評論展示

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

評論框編輯器使用的是simple-mde,使用起來非常簡單:

<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ù)可能會考慮加上emoji選擇器。markdown保存,后端渲染html,前端取出展示。最后結(jié)果非常漂亮令我滿意,大家可以在本篇文章下面看到效果。

評論管理

對應(yīng)的,在管理員頁面也加上一個評論管理頁面,以及開啟內(nèi)置評論的開關(guān)。因為最初設(shè)計的是評論一經(jīng)發(fā)出,只能刪除,不能修改,所以這種頁面對我這樣的CRUD程序員來說不在話下。

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

上傳文件,導(dǎo)入,成功,Disqus的評論就完美遷移過來了!

評論通知

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

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

這里后臺任務(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端口,害我找了半天原因,只要自己在控制臺解禁一下即可立刻生效。

參考鏈接

源碼倉庫: https://github.com/frostming/Flog
Implementing User Comments with SQLAlchemy - miguelgrinberg.com

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

相關(guān)文章

  • Python字符串格式化輸出代碼實例

    Python字符串格式化輸出代碼實例

    這篇文章主要介紹了Python字符串格式化輸出代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Python 出現(xiàn)錯誤TypeError: ‘NoneType’ object is not iterable解決辦法

    Python 出現(xiàn)錯誤TypeError: ‘NoneType’ object is not iterable解決辦法

    這篇文章主要介紹了Python 出現(xiàn)錯誤TypeError: ‘NoneType’ object is not iterable解決辦法的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • Python更換pip源方法過程解析

    Python更換pip源方法過程解析

    這篇文章主要介紹了Python更換pip源方法過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • Django中數(shù)據(jù)在前后端傳遞的方式之表單、JSON與ajax

    Django中數(shù)據(jù)在前后端傳遞的方式之表單、JSON與ajax

    Django從后臺往前臺傳遞數(shù)據(jù)時有多種方法可以實現(xiàn),下面這篇文章主要給大家介紹了關(guān)于Django中數(shù)據(jù)在前后端傳遞的方式之表單、JSON與ajax的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • 詳解如何使用Python和正則表達(dá)式處理XML表單數(shù)據(jù)

    詳解如何使用Python和正則表達(dá)式處理XML表單數(shù)據(jù)

    在日常的Web開發(fā)中,處理表單數(shù)據(jù)是一個常見的任務(wù),而XML是一種常用的數(shù)據(jù)格式,用于在不同的系統(tǒng)之間傳遞和存儲數(shù)據(jù),本文通過闡述一個技術(shù)問題并給出解答的方式,介紹如何使用Python和正則表達(dá)式處理XML表單數(shù)據(jù),需要的朋友可以參考下
    2023-09-09
  • 通過實例淺析Python對比C語言的編程思想差異

    通過實例淺析Python對比C語言的編程思想差異

    這篇文章主要介紹了通過實例淺析Python對比C語言的編程思想差異,作為面向?qū)ο蠛兔嫦蜻^程的編程語言代表,二者的對比可謂經(jīng)典,需要的朋友可以參考下
    2015-08-08
  • Python中ImportError錯誤的詳細(xì)解決方法

    Python中ImportError錯誤的詳細(xì)解決方法

    最近辛辛苦苦安裝完了python,最后再運行的時候會出現(xiàn)錯誤,所以這篇文章主要給大家介紹了關(guān)于Python中ImportError錯誤的詳細(xì)解決方法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • python中的3種定義類方法

    python中的3種定義類方法

    這篇文章主要給大家分享得是 python中的3種定義類方法,分別是普通方法、類方法(@classmethod)以及類方法(@classmethod),想了解方法具體實現(xiàn)的小伙伴可以參考下面文章內(nèi)容哦,希望對你有所幫助
    2021-11-11
  • Python函數(shù)isalnum用法示例小結(jié)

    Python函數(shù)isalnum用法示例小結(jié)

    isalnum()函數(shù)是Python中的一個內(nèi)置函數(shù),用于判斷字符串是否只由數(shù)字和字母組成,其內(nèi)部實現(xiàn)原理比較簡單,只需遍歷字符串中的每一個字符即可,這篇文章主要介紹了Python函數(shù)isalnum用法介紹,需要的朋友可以參考下
    2024-01-01
  • Django零基礎(chǔ)入門之模板變量詳解

    Django零基礎(chǔ)入門之模板變量詳解

    這篇文章主要介紹了Django零基礎(chǔ)入門之模板變量詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09

最新評論