基于python flask 的個人博客系統(tǒng)的設計與實現(xiàn)

摘要

博客是典型的CMS(Content Management System姓迅,內容管理系統(tǒng)),通常由兩部分組成:一部分是博客前臺快耿,用來展示開放給所有用戶的博客內容盏袄;另一部分是博客后臺,這部分內容僅開放給博客管理員葱她,用來對博客資源進行添加撩扒、修改和刪除等操作。本文通過分析個人博客的功能需求吨些,采用 python 的web 框架flask實現(xiàn)一個個人博客系統(tǒng)搓谆。

1、引言

本文旨在開發(fā)一個個人博客系統(tǒng)豪墅,采用的程序設計語言是python泉手,web 開發(fā)框架是flask,數(shù)據(jù)庫是 SQLite偶器。

Python是一種跨平臺的計算機程序設計語言斩萌。是一個高層次的結合了解釋性、編譯性状囱、互動性和面向對象的腳本語言术裸。最初被設計用于編寫自動化腳本(shell),隨著版本的不斷更新和語言新功能的添加亭枷,越多被用于獨立的、大型項目的開發(fā)搀崭。

Flask是一個輕量級的可定制框架叨粘,使用Python語言編寫,較其他同類型框架更為靈活瘤睹、輕便升敲、安全且容易上手。它可以很好地結合MVC模式進行開發(fā)轰传,開發(fā)人員分工合作驴党,小型團隊在短時間內就可以完成功能豐富的中小型網站或Web服務的實現(xiàn)。另外获茬,F(xiàn)lask還有很強的定制性港庄,用戶可以根據(jù)自己的需求來添加相應的功能倔既,在保持核心功能簡單的同時實現(xiàn)功能的豐富與擴展,其強大的插件庫可以讓用戶實現(xiàn)個性化的網站定制鹏氧,開發(fā)出功能強大的網站渤涌。

SQLite,是一款輕型的數(shù)據(jù)庫把还,是關系型數(shù)據(jù)庫管理系統(tǒng)实蓬,在 python 中內置了 SQLite庫。本文采用 SQLite 進行快速開發(fā)與測試吊履。

本文結構如下:

  • 第一章安皱, 引言。介紹本文目的艇炎,采用技術介紹和文章結構酌伊。

  • 第二章, 需求分析冕臭,詳細分析了個人博客系統(tǒng)的功能需求腺晾。

  • 第三章, 數(shù)據(jù)庫分析與設計辜贵。詳細介紹了個人博客系統(tǒng)的數(shù)據(jù)庫表設計與實現(xiàn)悯蝉。

  • 第四章, 詳細設計托慨。介紹了個人模塊系統(tǒng)的項目結構鼻由、功能模塊及其代碼實現(xiàn)。

  • 第五章厚棵, 實驗結果蕉世。介紹了個人博客系統(tǒng)的實現(xiàn)效果。

  • 第六章婆硬, 總結和展望狠轻。介紹對項目開發(fā)的經驗總結以及系統(tǒng)的不足與完善目標。

2彬犯、需求分析

2.1 功能需求

個人博客系統(tǒng)主要分為三個模塊向楼,分別為:博客前臺、博客后臺谐区、用戶認證湖蜕。

2.1.1 博客前臺

博客前臺展示博客文章信息,功能如下:

  • 文章列表(主頁):網站主頁顯示-- 博客文章列表宋列。
  • 文章詳情頁面:頁面顯示博客文章的詳情昭抒。
  • 評論列表:在博客文章詳情頁面顯示評論列表。
  • 發(fā)表評論:在博客文章詳情頁面對文章發(fā)表評論。
  • 回復評論:在評論列表中回復評論灭返。

2.1.2 博客后臺

博客后臺為博客管理員對博客進行管理盗迟,功能如下:

  • 文章管理功能,創(chuàng)建文章婆殿,更新文章诈乒,刪除文章。
  • 管理分類功能婆芦,創(chuàng)建分類绒极,更新分類倍宾,刪除分類妄讯。
  • 管理評論功能氢伟,關閉文章評論,刪除文章評論或粮,審核評論导饲,評論篩選。
    博客資料設置氯材,置博客信息渣锦。

2.1.3用戶認證

創(chuàng)建管理源賬戶
用戶登陸功能

2.2 功能結構圖

image

3、數(shù)據(jù)庫設計

3.1 數(shù)據(jù)庫表設計

3.1.1 管理員

字段名 類型 大小 備注
id
username
password
blog_title
blog_subtitle

3.2 E-R 圖

4氢哮、設計實現(xiàn)

4.1 項目結構

blog/
    blueprint/              功能模塊
        - __init__.py
        - blog.py           博客前臺
        - auth.py           用戶認證
        - admin.py          博客后臺
    templates/              頁面模板
        - admin/            后臺頁面
        - auth/         認證頁面
        - blog/         前臺頁面
        - base.html
        - macros.html
    static/                 靜態(tài)資源
    forms.py                表單          
    models.py               數(shù)據(jù)模型
    email.py                郵箱驗證
    utils.py                    輔助
    fakes.py                虛擬數(shù)據(jù)
    extensions.py           擴展

4.2 數(shù)據(jù)模型實現(xiàn)

4.2.1 管理員

class Admin(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20))
    password_hash = db.Column(db.String(128))
    blog_title = db.Column(db.String(60))
    blog_sub_title = db.Column(db.String(100))
    name = db.Column(db.String(30))
    about = db.Column(db.Text)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def validate_password(self, password):
        return check_password_hash(self.password_hash, password)

4.2.2 分類

lass Category(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30), unique=True)

    posts = db.relationship('Post', back_populates='category')

    def delete(self):
        default_category = Category.query.get(1)
        posts = self.posts[:]
        for post in posts:
            post.category = default_category
        db.session.delete(self)
        db.session.commit()

4.2.4 評論

class Comment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    author = db.Column(db.String(30))
    email = db.Column(db.String(254))
    site = db.Column(db.String(255))
    body = db.Column(db.Text)
    from_admin = db.Column(db.Boolean, default=False)
    reviewed = db.Column(db.Boolean, default=False)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow, index=True)

    replied_id = db.Column(db.Integer, db.ForeignKey('comment.id'))
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))

    post = db.relationship('Post', back_populates='comments')
    replies = db.relationship('Comment', back_populates='replied', cascade='all, delete-orphan')
    replied = db.relationship('Comment', back_populates='replies', remote_side=[id])

4.3 功能實現(xiàn)

4.3.1 博客前臺

1袋毙、首頁

@blog_bp.route('/')
def index():
    page = request.args.get('page', 1, type=int)
    per_page = current_app.config['BLUELOG_POST_PER_PAGE']
    pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=per_page)
    posts = pagination.items
    return render_template('blog/index.html', pagination=pagination, posts=posts)
 

2、分類頁面

@blog_bp.route('/category/<int:category_id>')
def show_category(category_id):
    category = Category.query.get_or_404(category_id)
    page = request.args.get('page', 1, type=int)
    per_page = current_app.config['BLUELOG_POST_PER_PAGE']
    pagination = Post.query.with_parent(category).order_by(Post.timestamp.desc()).paginate(page, per_page)
    posts = pagination.items
    return render_template('blog/category.html', category=category, pagination=pagination, posts=posts)

3冗尤、文章頁面

@blog_bp.route('/post/<int:post_id>', methods=['GET', 'POST'])
def show_post(post_id):
    post = Post.query.get_or_404(post_id)
    page = request.args.get('page', 1, type=int)
    per_page = current_app.config['BLUELOG_COMMENT_PER_PAGE']
    pagination = Comment.query.with_parent(post).filter_by(reviewed=True).order_by(Comment.timestamp.asc()).paginate(
        page, per_page)
    comments = pagination.items

    if current_user.is_authenticated:
        form = AdminCommentForm()
        form.author.data = current_user.name
        form.email.data = current_app.config['BLUELOG_EMAIL']
        form.site.data = url_for('.index')
        from_admin = True
        reviewed = True
    else:
        form = CommentForm()
        from_admin = False
        reviewed = False

    if form.validate_on_submit():
        author = form.author.data
        email = form.email.data
        site = form.site.data
        body = form.body.data
        comment = Comment(
            author=author, email=email, site=site, body=body,
            from_admin=from_admin, post=post, reviewed=reviewed)
        replied_id = request.args.get('reply')
        if replied_id:
            replied_comment = Comment.query.get_or_404(replied_id)
            comment.replied = replied_comment
            send_new_reply_email(replied_comment)
        db.session.add(comment)
        db.session.commit()
        if current_user.is_authenticated:  # send message based on authentication status
            flash('Comment published.', 'success')
        else:
            flash('Thanks, your comment will be published after reviewed.', 'info')
            send_new_comment_email(post)  # send notification email to admin
        return redirect(url_for('.show_post', post_id=post_id))
    return render_template('blog/post.html', post=post, pagination=pagination, form=form, comments=comments)

4听盖、評論功能

@blog_bp.route('/reply/comment/<int:comment_id>')
def reply_comment(comment_id):
    comment = Comment.query.get_or_404(comment_id)
    if not comment.post.can_comment:
        flash('Comment is disabled.', 'warning')
        return redirect(url_for('.show_post', post_id=comment.post.id))
    return redirect(
        url_for('.show_post', post_id=comment.post_id, reply=comment_id, author=comment.author) + '#comment-form')

4.3.2 博客后臺

1、文章管理

@admin_bp.route('/post/manage')
@login_required
def manage_post():
    page = request.args.get('page', 1, type=int)
    pagination = Post.query.order_by(Post.timestamp.desc()).paginate(
        page, per_page=current_app.config['BLUELOG_MANAGE_POST_PER_PAGE'])
    posts = pagination.items
    return render_template('admin/manage_post.html', page=page, pagination=pagination, posts=posts)

2裂七、評論管理

@admin_bp.route('/comment/manage')
@login_required
def manage_comment():
    filter_rule = request.args.get('filter', 'all')  # 'all', 'unreviewed', 'admin'
    page = request.args.get('page', 1, type=int)
    per_page = current_app.config['BLUELOG_COMMENT_PER_PAGE']
    if filter_rule == 'unread':
        filtered_comments = Comment.query.filter_by(reviewed=False)
    elif filter_rule == 'admin':
        filtered_comments = Comment.query.filter_by(from_admin=True)
    else:
        filtered_comments = Comment.query

    pagination = filtered_comments.order_by(Comment.timestamp.desc()).paginate(page, per_page=per_page)
    comments = pagination.items
    return render_template('admin/manage_comment.html', comments=comments, pagination=pagination)

3皆看、分類管理

@admin_bp.route('/category/manage')
@login_required
def manage_category():
    return render_template('admin/manage_category.html')

4、博客設置

@admin_bp.route('/settings', methods=['GET', 'POST'])
@login_required
def settings():
    form = SettingForm()
    if form.validate_on_submit():
        current_user.name = form.name.data
        current_user.blog_title = form.blog_title.data
        current_user.blog_sub_title = form.blog_sub_title.data
        current_user.about = form.about.data
        db.session.commit()
        flash('Setting updated.', 'success')
        return redirect(url_for('blog.index'))
    form.name.data = current_user.name
    form.blog_title.data = current_user.blog_title
    form.blog_sub_title.data = current_user.blog_sub_title
    form.about.data = current_user.about
    return render_template('admin/settings.html', form=form)

4.3.3 用戶認證

1背零、登陸

@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('blog.index'))

    form = LoginForm()
    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        remember = form.remember.data
        admin = Admin.query.first()
        if admin:
            if username == admin.username and admin.validate_password(password):
                login_user(admin, remember)
                flash('Welcome back.', 'info')
                return redirect_back()
            flash('Invalid username or password.', 'warning')
        else:
            flash('No account.', 'warning')
    return render_template('auth/login.html', form=form)

2腰吟、登出

@auth_bp.route('/logout')
@login_required
def logout():
    logout_user()
    flash('Logout success.', 'info')
    return redirect_back()

5、 實驗結果

5.1 博客前臺

5.1.1 首頁

5.1.2 文章頁面

5.1.3 評論列表

6徙瓶、總結與展望

6.1 學習總結

在開發(fā)個人博客系統(tǒng)的過程中蝎困,遇到了許多困難,也學習到了許多新的知識倍啥。遇到的困難主要是陌生技術/框架的掌握上,在開發(fā)系統(tǒng)的過程中澎埠,需要引入新的技術/框架虽缕,由于新技術/框架的原理或者知識領域相對陌生,在掌握的過程中存在一些困難蒲稳。在解決這些困難的工程中氮趋,一并掌握了這些新技術/框架的原理和領域知識伍派。

在開發(fā)本系統(tǒng)的過程中,掌握了許多知識剩胁。本系統(tǒng)采用 flask web 開發(fā)框架诉植,由此學習了web 開發(fā)技術,http 原理昵观,B/S架構模式等知識晾腔。系統(tǒng)還使用 fakes 庫產生虛擬數(shù)據(jù),進行數(shù)據(jù)填充啊犬,學習掌握產生虛擬數(shù)據(jù)的方法灼擂。系統(tǒng)使用SQLite數(shù)據(jù)庫進行數(shù)據(jù)存儲,使用 SQLAlchemy 庫進行數(shù)據(jù)庫匹配觉至,掌握了 ORM 知識剔应。

6.2 展望

本系統(tǒng)的不足之處在于,系統(tǒng)并未進行工作環(huán)境的部署并進行上線语御,在未來的開發(fā)中峻贮,需要系統(tǒng)的部署于上線等知識,將系統(tǒng)進行部署上線应闯。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末纤控,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子孽锥,更是在濱河造成了極大的恐慌嚼黔,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惜辑,死亡現(xiàn)場離奇詭異唬涧,居然都是意外死亡,警方通過查閱死者的電腦和手機盛撑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門碎节,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人抵卫,你說我怎么就攤上這事狮荔。” “怎么了介粘?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵殖氏,是天一觀的道長。 經常有香客問我姻采,道長雅采,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮婚瓜,結果婚禮上宝鼓,老公的妹妹穿的比我還像新娘。我一直安慰自己巴刻,他們只是感情好愚铡,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胡陪,像睡著了一般沥寥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上督弓,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天营曼,我揣著相機與錄音,去河邊找鬼愚隧。 笑死蒂阱,一個胖子當著我的面吹牛,可吹牛的內容都是我干的狂塘。 我是一名探鬼主播录煤,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼荞胡!你這毒婦竟也來了妈踊?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤泪漂,失蹤者是張志新(化名)和其女友劉穎廊营,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體萝勤,經...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡露筒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了敌卓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慎式。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖趟径,靈堂內的尸體忽然破棺而出瘪吏,到底是詐尸還是另有隱情,我是刑警寧澤蜗巧,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布掌眠,位于F島的核電站,受9級特大地震影響幕屹,放射性物質發(fā)生泄漏扇救。R本人自食惡果不足惜刑枝,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望迅腔。 院中可真熱鬧,春花似錦靠娱、人聲如沸沧烈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锌雀。三九已至,卻和暖如春迅诬,著一層夾襖步出監(jiān)牢的瞬間腋逆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工侈贷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惩歉,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓俏蛮,卻偏偏與公主長得像撑蚌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子搏屑,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355