使用Python+Flask開發(fā)博客項(xiàng)目并實(shí)現(xiàn)內(nèi)網(wǎng)穿透
前言
Flask是一個(gè)使用python編寫的輕量級(jí)Web框架,對(duì)比其他相同類型的框架而言,這個(gè)框架更加的靈活輕便。并且具有很強(qiáng)的定制性,用戶可以根據(jù)自己的需求添加功能,有強(qiáng)大的插件庫,這也是為什么這個(gè)框架在python領(lǐng)域一直火熱的原因。這篇文章我們將使用這個(gè)框架編寫一個(gè)屬于自己的博客網(wǎng)站!并教你如何通過使用內(nèi)網(wǎng)穿透工具處理項(xiàng)目,讓本地的項(xiàng)目可以在公網(wǎng)訪問!
🚀首先來看看我們開發(fā)的博客Web項(xiàng)目的一些展示


項(xiàng)目主要包含主要以下功能:個(gè)人注冊(cè)于登錄,首頁文章展示,文章詳情展示,文章發(fā)布模塊,文章添加分類模塊,文章分類管理模塊,用戶信息管理模塊,程序啟動(dòng)模塊。
🚀下面我們對(duì)各個(gè)模塊的代碼進(jìn)行編寫
1.個(gè)人的注冊(cè)與登錄模塊
這個(gè)模塊的主要讓用戶進(jìn)行用戶的注冊(cè),之后判斷輸入的密碼是否一致,并將結(jié)果寫入到數(shù)據(jù)庫。

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請(qǐng)求的話就返回頁面,post請(qǐng)求的話就接收表單數(shù)據(jù)
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加密密碼再存入數(shù)據(jù)庫,拿到md5.hexdigest()加密后的密碼
user.password = md5.hexdigest()
user.password=password
print(username,password)
try:
db.session.add(user)
db.session.commit()
flash('注冊(cè)成功,歡迎訪問我的個(gè)人博客!')
return redirect(url_for('front.register'))
except Exception:
flash('注冊(cè)失敗,請(qǐng)檢查密碼后重新注冊(cè)')
return redirect(url_for('front.register'))
else:
flash('注冊(cè)失敗')
return redirect(url_for('front.register'))
2.首頁文章展示模塊
這個(gè)模塊合并了分頁的功能,當(dāng)發(fā)布文章的數(shù)量在當(dāng)前頁面無法展示完全的時(shí)候就使用增加分頁的方式進(jìn)行展示,并通過bootstrap提供的分頁導(dǎo)航欄進(jìn)行編寫。使用bootstrap進(jìn)行前端頁面的開發(fā),可以讓我們?cè)诓痪邆浜芎玫那岸酥R(shí)的情況下也可以開發(fā)出精美的頁面。

@front.route('/index')
@front.route('/')
# @login_required
def index():
page=int(request.args.get('page',default=1)) #找到傳入的?page=? 參數(shù),沒有的話默認(rèn)就是1,因?yàn)閭骰貋淼氖亲址?,所以需要轉(zhuǎn)化成int
#pre_page=? 這個(gè)是設(shè)置每一頁最多顯示幾條數(shù)據(jù)
paginate=Article.query.order_by(Article.create_time.desc()).paginate(page=page,per_page=5)
article=paginate.items
groups=ArticleGroup.query.all() #拿到模型所有的數(shù)據(jù)
return render_template("index.html",groups=groups,article=article,paginate=paginate)
3.文章詳情展示模塊
這個(gè)模塊主要是拿到文章模型的全部時(shí)間并進(jìn)行展示,并通過文章的id進(jìn)行精準(zhǔn)展示
![[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-H3NWBcYU-1636098859836)(picture/image-20211105153111194.jpg)]](http://img.jbzj.com/file_images/article/202111/2021110809210040.jpg)
@front.route('/article_detail/<int:article_id>')
# @login_required
def article_detail(article_id):
article=Article.query.get(article_id)
groups=ArticleGroup.query.all() #拿到模型所有的數(shù)據(jù)
return render_template("article_detail.html",groups=groups,article=article)
4.文章發(fā)布模塊
這個(gè)模塊引入了md格式的文章編寫模塊,用戶可以根據(jù)md的語法進(jìn)行文章發(fā)編寫與發(fā)布,同時(shí)增加右邊的語法預(yù)覽框方便用戶看到文章的展示情況

@front.route('/add_article',methods=['GET','POST'])
# @login_required
def add_article():
if request.method=='GET':
groups=ArticleGroup.query.all() #拿到模型所有的數(shù)據(jù)
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
# 獲取當(dāng)前時(shí)間,從datetime這個(gè)庫里面
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.文章添加分類模塊
這個(gè)模塊,用戶可以自己輸入要增加的分組的名稱,之后可以選擇分組要展現(xiàn)的顏色進(jìn)行展示,并把相關(guān)數(shù)據(jù)存入數(shù)據(jù)庫

@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.文章分類管理模塊
這個(gè)模塊主要是對(duì)用戶編輯的分組與顏色進(jìn)行編輯與刪除的管理功能

@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"))
# 刪除的 視圖函數(shù)
@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.文章管理模塊
這個(gè)模塊提供了文章的管理功能,用戶如果對(duì)已經(jīng)發(fā)布的文章有繼續(xù)改進(jìn)的想法可以在這個(gè)模塊進(jìn)行編輯,并對(duì)文章進(jìn)行刪除或者編輯重新發(fā)布的操作。

@front.route('/edit_article/<int:article_id>',methods=['GET','POST'])
def edit_article(article_id):
if request.method=='GET':
# 拿到文章內(nèi)容
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.用戶個(gè)人信息注銷模塊
通過這個(gè)模塊用戶可以一鍵注銷當(dāng)前登錄的賬號(hào),并回到登錄頁面
# 注銷登錄,在base寫上
@front.route('/logout')
def logout():
session.clear()
flash("注銷登錄成功")
return redirect(url_for('front.login'))
9.信息管理模塊
對(duì)于上面模塊的信息都需要存入到mysql數(shù)據(jù)庫,首先在本地的MySQL數(shù)據(jù)庫創(chuàng)建一個(gè)blog庫,之后執(zhí)行Web項(xiàng)目,這個(gè)模塊會(huì)把對(duì)于的數(shù)據(jù)庫表信息與數(shù)據(jù)庫表進(jìn)行映射創(chuàng)建,并賦值對(duì)應(yīng)的類型。實(shí)現(xiàn)可以避免手動(dòng)創(chuàng)建數(shù)據(jù)表的繁雜操作。
login_manager = LoginManager()
db=SQLAlchemy() #實(shí)例化sqlalchemy對(duì)象
class User(db.Model,UserMixin):
# __tablename__='login_register'
id = Column(db.Integer,autoincrement=True,primary_key=True)
#autoincrement自增長(zhǎng)
username=Column(db.String(50),nullable=False)
password=Column(db.String(128),nullable=True)
# 沒有這個(gè)的話,使用{{users}}顯示的就是一個(gè)對(duì)象
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)
#下面相當(dāng)于做一個(gè)聯(lián)表查詢。
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):
#對(duì)主鍵的查詢是沒有必要使用filler_by的
user = db.session.query(User).get(user_id)
return user
10.程序啟動(dòng)模塊
這個(gè)模塊為了讓Flask的啟動(dòng)入口更加的簡(jiǎn)潔,我對(duì)啟動(dòng)模塊的代碼進(jìn)行了封裝操作。
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='請(qǐng)先登錄或注冊(cè)'
db.create_all(app=app)
return app
def register_blueprint(app):
from front_back import front
app.register_blueprint(front)
應(yīng)用程序主類

from current import create_app
app=create_app()
if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True,port=83)
到這里我們的博客項(xiàng)目相關(guān)模塊就編寫完成啦,其實(shí)還有很多的功能小伙伴們可以根據(jù)自己的需求添加,這也是Flask極具特色的一個(gè)地方,這里要說明的一點(diǎn)是,由于前端部分的代碼太多啦,這里就不展示出來了,需要的小伙伴可以私聊我拿到整體的代碼喲。
11.內(nèi)網(wǎng)穿透模塊
這個(gè)模塊對(duì)于很多小伙伴來說可能比較陌生,這里舉一個(gè)例子方便小伙伴們理解。
假如說我們要把上面寫好的項(xiàng)目進(jìn)行部署,并讓全部人可以使用的話,很容易想到的一點(diǎn)是,利用服務(wù)器。但是服務(wù)器的成本較高,而且部署的過程也比較繁雜,那么有沒有什么好的方式可以幫我們實(shí)現(xiàn)本地的服務(wù)id映射到公網(wǎng)訪問呢?答案就是內(nèi)網(wǎng)穿透
這里給大家介紹一個(gè)快捷的內(nèi)網(wǎng)穿透工具,花生殼。大家可以直接去搜索下載哦。
下載好之后我們只需要把我們本機(jī)的ip輸入進(jìn)去,他就會(huì)幫我們生成一個(gè)域名,實(shí)現(xiàn)公網(wǎng)可訪問,如下圖。

之后到瀏覽器測(cè)試是否可以訪問,可以成功訪問即代表映射成功:

12.總結(jié)
到此這篇關(guān)于使用Python+Flask開發(fā)博客項(xiàng)目并實(shí)現(xiàn)內(nèi)網(wǎng)穿透的文章就介紹到這了,更多相關(guān)Flask開發(fā)博客項(xiàng)目并內(nèi)網(wǎng)穿透內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pandas實(shí)現(xiàn)datetime64與unix時(shí)間戳互轉(zhuǎn)
這篇文章主要介紹了pandas實(shí)現(xiàn)datetime64與unix時(shí)間戳互轉(zhuǎn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
Pytorch使用MNIST數(shù)據(jù)集實(shí)現(xiàn)基礎(chǔ)GAN和DCGAN詳解
今天小編就為大家分享一篇Pytorch使用MNIST數(shù)據(jù)集實(shí)現(xiàn)基礎(chǔ)GAN和DCGAN詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-01-01
Python使用matplotlib繪制圓形代碼實(shí)例
這篇文章主要介紹了Python使用matplotlib繪制圓形代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
使用Python將圖片轉(zhuǎn)正方形的兩種方法實(shí)例代碼詳解
這篇文章主要介紹了使用Python將圖片轉(zhuǎn)正方形的兩種方法,本文通過實(shí)例代碼給大家給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
對(duì)python numpy.array插入一行或一列的方法詳解
今天小編就為大家分享一篇對(duì)python numpy.array插入一行或一列的方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01
使用Python3實(shí)現(xiàn)判斷函數(shù)的圈復(fù)雜度
編寫函數(shù)最重要的原則就是:別寫太復(fù)雜的函數(shù),那什么樣的函數(shù)才能算是過于復(fù)雜?一般會(huì)通過兩個(gè)標(biāo)準(zhǔn)來判斷,長(zhǎng)度和圈復(fù)雜度,下面我們就來看看如何使用Python判斷函數(shù)的圈復(fù)雜度吧2024-04-04
使用Python對(duì)Syslog信息進(jìn)行分析并繪圖的實(shí)現(xiàn)
這篇文章主要介紹了使用Python對(duì)Syslog信息進(jìn)行分析并繪圖的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

