使用Python+Flask手把手教你開發個人博客系統,並進行內網穿透實現全網訪問,超詳細建議收藏


使用Python+Flask手把手教你開發個人博客系統,並進行內網穿透實現全網訪問,超詳細建議收藏

前言

Flask是一個使用python編寫的輕量級Web框架,對比其他相同類型的框架而言,這個框架更加的靈活輕便。並且具有很強的定制性,用戶可以根據自己的需求添加功能,有強大的插件庫,這也是為什么這個框架在python領域一直火熱的原因。這篇文章我們將使用這個框架編寫一個屬於自己的博客網站!並教你如何通過使用內網穿透工具處理項目,讓本地的項目可以在公網訪問!

首先來看看我們開發的博客Web項目的一些展示。

在這里插入圖片描述

 

項目主要包含主要以下功能:個人的注冊與登錄模塊,首頁文章展示模塊,引入MD格式的文章發布模塊,賬號注銷模塊,文章分類與編輯模塊,文章發布修改模塊與文章展示分頁模塊,數據庫管理模塊。

下面我們對各個模塊的代碼進行編寫

1.個人的注冊與登錄模塊

這個模塊的主要讓用戶進行用戶的注冊,之后判斷輸入的密碼是否一致,並將結果寫入到數據庫。

在這里插入圖片描述

from flask import render_template, redirect, url_for, request, flash, session
from front_back import front
from modles.dbmodels import User, db
import hashlib
from utils import login_check


@front.route('/login',methods=['GET','POST'])
def login():
   if request.method=='GET':
       return render_template('login.html')
   elif request.method=='POST':
       username=request.form.get('username')
       password=request.form.get('password')
       user=User.query.filter_by(username=username,password=password).first()
       print(user)
       if user:
           session['user']=username
           print(session['user'])
           flash('登錄成功')
           return redirect(url_for('front.index'))
       else:
           flash('登錄失敗')
           return redirect(url_for('front.login'))

@front.route('/register',methods=['GET','POST'])
def register():
       # 如果是get請求的話就返回頁面,post請求的話就接收表單數據
       if request.method == 'GET':
           return render_template("register.html")
       elif request.method == 'POST':
           username = request.form.get('username')
           password = request.form.get('password')
           check_password = request.form.get('check_password')

           if username and password and password == check_password:
               md5 = hashlib.md5()
               md5.update(password.encode('utf-8'))
               user = User()

               user.username = username
               # 使用hashlib加密密碼再存入數據庫,拿到md5.hexdigest()加密后的密碼
               user.password = md5.hexdigest()
               user.password=password
               print(username,password)
           try:
              db.session.add(user)
              db.session.commit()
              flash('注冊成功,歡迎訪問我的個人博客!')
              return redirect(url_for('front.register'))
           except Exception:
              flash('注冊失敗,請檢查密碼后重新注冊')
              return redirect(url_for('front.register'))
       else:
            flash('注冊失敗')
            return redirect(url_for('front.register'))

2.首頁文章展示模塊

這個模塊合並了分頁的功能,當發布文章的數量在當前頁面無法展示完全的時候就使用增加分頁的方式進行展示,並通過bootstrap提供的分頁導航欄進行編寫。

在這里插入圖片描述

@front.route('/index')
@front.route('/')
# @login_required

def index():
   page=int(request.args.get('page',default=1))   #找到傳入的?page=? 參數,沒有的話默認就是1,因為傳回來的是字符串,所以需要轉化成int
   #pre_page=? 這個是設置每一頁最多顯示幾條數據
   paginate=Article.query.order_by(Article.create_time.desc()).paginate(page=page,per_page=5)
   article=paginate.items
   groups=ArticleGroup.query.all()  #拿到模型所有的數據
   return render_template("index.html",groups=groups,article=article,paginate=paginate)

3.文章詳情展示模塊

這個模塊主要是拿到文章模型的全部時間並進行展示,並通過文章的id進行精准展示

image.png

@front.route('/article_detail/<int:article_id>')
# @login_required
def article_detail(article_id):
   article=Article.query.get(article_id)
   groups=ArticleGroup.query.all()  #拿到模型所有的數據
   return render_template("article_detail.html",groups=groups,article=article)

 

4.文章發布模塊

這個模塊引入了md格式的文章編寫模塊,用戶可以根據md的語法進行文章發編寫與發布,同時增加右邊的語法預覽框方便用戶看到文章的展示情況

在這里插入圖片描述

@front.route('/add_article',methods=['GET','POST'])
# @login_required
def add_article():
   if request.method=='GET':
       groups=ArticleGroup.query.all()  #拿到模型所有的數據
       return render_template("add_article.html",groups=groups)
   elif request.method=='POST':
       title=request.form.get('title')
       content=request.form.get('content')
       gid=request.form.get('gid')

       user=User.query.filter_by(username=session.get('user')).first()
       uid=user.id
       # 獲取當前時間,從datetime這個庫里面
       create_time=datetime.datetime.now()

       article=Article()
       article.title=title
       article.content=content
       article.gid=gid
       article.uid=uid
       article.create_time=create_time
       print(user,title,content,gid,uid,create_time)
       try:
           db.session.add(article)
           db.session.commit()
           flash('添加%s成功' % title)
           return redirect(url_for('front.add_article'))
       except Exception:
           flash('添加%s失敗' % title)
           return redirect(url_for('front.add_article'))

 

5.文章添加分類模塊

這個模塊,用戶可以自己輸入要增加的分組的名稱,之后可以選擇分組要展現的顏色進行展示,並把相關數據存入數據庫

在這里插入圖片描述

@front.route("/add_group",methods=['GET','POST'])
def add_group():
   if request.method=='GET':
       groups = ArticleGroup.query.all()
       colors=['default','primary','success','into','warning','danger']
       return render_template('add_group.html',colors=colors,groups=groups)
   elif request.method=='POST':
       name=request.form.get('name')
       color=request.form.get('color')
       group=ArticleGroup()
       group.name=name
       group.color=color
       try:
           db.session.add(group)
           db.session.commit()
           flash("添加分組成功")
           return redirect(url_for('front.manage'))
       except Exception:
           flash("添加失敗")
           return redirect(url_for('front.manage'))

6.文章分類管理模塊

這個模塊主要是對用戶編輯的分組與顏色進行編輯與刪除的管理功能

在這里插入圖片描述

@front.route("/article_group_manage")

def article_group_manage():
   groups = ArticleGroup.query.all()
   return render_template('article_group_mange.html',groups=groups)
@front.route('/edit_group/<int:gid>',methods=['GET','POST'])
def edit_group(gid):
   if request.method=='GET':
       groups=ArticleGroup.query.all()
       #找到通過id找到分組
       group=ArticleGroup.query.get(gid)
       colors = ['default', 'primary', 'success', 'into', 'warning', 'danger']
       return render_template('edit_group.html',group=group,colors=colors,groups=groups)
   elif request.method=='POST':
       name=request.form.get("name")
       color=request.form.get("color")

       group=ArticleGroup.query.get(gid)
       group.name=name
       group.color=color
       try:
           db.session.add(group)
           db.session.commit()
           flash("修改成功")
           return redirect(url_for("front.article_group_manage"))
       except Exception:
           flash("修改失敗")
           return redirect(url_for("front.article_group_mange"))

# 刪除的 視圖函數
@front.route('/delete_group/<int:gid>')
def delete_group(gid):
   group=ArticleGroup.query.get(gid)
   try:
       db.session.delete(group)
       db.session.commit()
       flash('刪除%s成功' % group.name)
       return redirect(url_for("front.article_group_manage"))
   except Exception:
       flash('刪除%s失敗' % group.name)
       return redirect(url_for("front.article_group_manage"))

7.文章管理模塊

這個模塊提供了文章的管理功能,用戶如果對已經發布的文章有繼續改進的想法可以在這個模塊進行編輯,並對文章進行刪除或者編輯重新發布的操作。

在這里插入圖片描述

@front.route('/edit_article/<int:article_id>',methods=['GET','POST'])
def edit_article(article_id):
   if request.method=='GET':
       # 拿到文章內容
       article=Article.query.get(article_id)
       groups=ArticleGroup.query.all()
       return render_template('edit_article.html',groups=groups,article=article)
   elif request.method=='POST':
       title=request.form.get("title")
       content=request.form.get("content")
       gid=request.form.get("gid")
       update_time=datetime.datetime.now()

       article=Article.query.get(article_id)
       article.title=title
       article.content=content
       print(content)
       article.gid=gid
       article.update_time=update_time

       try:
           db.session.commit()
           return redirect(url_for("front.article_manage"))
       except Exception:
           flash("修改%s失敗" % title)
           return redirect(url_for("front.article_manage"))
@front.route('/delete_article/<int:article_id>')
def delete_article(article_id):
   article=Article.query.get(article_id)
   try:
       db.session.delete(article)
       db.session.commit()
       flash("刪除文章%s成功"%article.title)
       return redirect(url_for("front.article_manage"))
   except Exception:
       flash("刪除文章%s失敗"%article.title)
       return redirect(url_for("front.article_manage"))

8.用戶個人信息注銷模塊

通過這個模塊用戶可以一鍵注銷當前登錄的賬號,並回到登錄頁面

# 注銷登錄,在base寫上
@front.route('/logout')
def logout():
    session.clear()
    flash("注銷登錄成功")
    return redirect(url_for('front.login'))

9.信息管理模塊

對於上面模塊的信息都需要存入到mysql數據庫,首先在本地的MySQL數據庫創建一個blog庫,之后執行Web項目,這個模塊會把對於的數據庫表信息與數據庫表進行映射創建,並賦值對應的類型。

login_manager = LoginManager()

db=SQLAlchemy()    #實例化sqlalchemy對象

class User(db.Model,UserMixin):
    # __tablename__='login_register'
    id = Column(db.Integer,autoincrement=True,primary_key=True)
    #autoincrement自增長
    username=Column(db.String(50),nullable=False)
    password=Column(db.String(128),nullable=True)


    # 沒有這個的話,使用{{users}}顯示的就是一個對象
    def __repr__(self):
        return self.username

    def get_id(self):
        return True

class Article(db.Model):
    __tablename__='article'
    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    title = db.Column(db.String(50), nullable=False,unique=True)
    content=db.Column(db.String(512),nullable=True)
    uid=db.Column(db.Integer,db.ForeignKey('user.id'))
    gid=db.Column(db.Integer,db.ForeignKey('article_group.id'))
    create_time=db.Column(db.DateTime)
    update_time=db.Column(db.DateTime)
    #下面相當於做一個聯表查詢。
    users=db.relationship('User',backref=db.backref('articles'))
    groups=db.relationship('ArticleGroup',backref=db.backref('articles'))


    def __repr__(self):
        return '<Article %s>'%self.title

class ArticleGroup(db.Model):
    __tablename__='article_group'
    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    name = db.Column(db.String(50), nullable=False,unique=True)
    color= db.Column(db.String(50), nullable=False)

    def __repr__(self):
        return '<ArticleGroup %s>'% self.name

@login_manager.user_loader
def get_user(user_id):
    #對主鍵的查詢是沒有必要使用filler_by的
    user = db.session.query(User).get(user_id)
    return user

10.程序啟動模塊

這個模塊為了讓Flask的啟動入口更加的簡介,我對啟動模塊的代碼進行了封裝操作

def create_app():
    app=Flask(__name__)
    app.config.from_object('config')
    register_blueprint(app)
    db.init_app(app)

    login_manager.init_app(app)
    login_manager.login_view="front.login"
    login_manager.login_message_category='請先登錄或注冊'

    db.create_all(app=app)
    return app


def register_blueprint(app):
    from front_back import front
    app.register_blueprint(front)

應用程序主類

image.png

from current import create_app

app=create_app()
if __name__ == '__main__':
    app.run(host='0.0.0.0',debug=True,port=83)

到這里我們的博客項目相關模塊就編寫完成啦,其實還有很多的功能小伙伴們可以根據自己的需求添加,這也是Flask極具特色的一個地方,這里要說明的一點是,由於前端部分的代碼太多啦,這里就不展示出來了,需要的小伙伴可以私我拿到整體的代碼喲。

 

11.內網穿透模塊

這個模塊對於很多小伙伴來說可能比較陌生,這里舉一個例子方便小伙伴們理解。

加入說我們要把上面寫好的項目進行部署,並讓全部人可以使用的話,很容易想到的一點是,利用服務器。但是服務器的成本較高,而且部署的過程也比較繁雜,那么有沒有什么好的方式可以幫我們實現本地的服務id映射到公網訪問呢?答案就是內網穿透

這里給大家介紹一個快捷的內網穿透工具,花生殼。大家可以直接去搜索下載哦。

下載好之后我們只需要把我們本機的ip輸入進去,他就會幫我們生成一個域名,實現公網可訪問,如下圖。

在這里插入圖片描述

之后到瀏覽器測試是否可以訪問:

在這里插入圖片描述

12.總結

到這里對於博客的編寫與內網穿透的實踐就介紹完了!總體來說要上手Flask這個框架的話還是不難的,但重要的是當你想學習一樣東西的時候就要堅持下去,努力了就會有回報!獲取博客源碼請關注下方公眾號,聯系我哦。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM