flask實踐

朋克歸零膏發表於2020-10-29

專案結構

│  bbs_demo.py # 檢視檔案
│  config.py # 存放配置檔案
│  exts.py # 解決迴圈引用, 存放db
│  manage.py # 用flask-script管理
│  models.py # ORM
│
├─.idea
│  │  bbs_demo.iml
│  │  misc.xml
│  │  modules.xml
│  │  workspace.xml
│  │
│  └─inspectionProfiles
├─static # 存放靜態檔案,如圖片,css
└─templates # 存放模版

flask_project.py

存放檢視函式

from flask import Flask, render_template, request, redirect, url_for, session
from models import User, Issue, Comment
from exts import db, valiEmail
from decorators import login_required
import config


app = Flask(__name__)
app.config.from_object(config)
db.init_app(app)


@app.route('/', methods=['GET', 'POST'])
def index():
    context = {
        'issues' : Issue.query.order_by(db.desc('create_time')).all()
    }
    return render_template('index.html', **context)


@app.route('/d/<issue_id>')
def d(issue_id):
    res = Issue.query.filter(Issue.id == issue_id).first()
    return render_template('d.html', issue_item = res)


@app.route('/add_comment/', methods=["POST"])
@login_required
def add_comment():
    comment = Comment(comment=request.form.get('comment'))
    issue_id = request.form.get('issue_id')
    user_id = session['user_id']
    user = User.query.filter(User.id==user_id).first()
    issue = Issue.query.filter(Issue.id == issue_id).first()
    comment.author = user
    comment.issue = issue
    db.session.add(comment)
    db.session.commit()

    return redirect(url_for('d', issue_id=issue_id))


@app.route('/issue/', methods=['GET', 'POST'])
@login_required
def issue():
    if request.method == 'GET':
        return render_template('issue.html')
    else:
        title = request.form.get('title')
        content = request.form.get('content')
        issue = Issue(title=title, content=content)
        user_id = session.get('user_id')
        user = User.query.filter(User.id == user_id).first()
        issue.author = user
        db.session.add(issue)
        db.session.commit()

        return redirect(url_for('index'))


@app.route('/login/', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        email = request.form.get('email')
        password = request.form.get('password')
        user = User.query.filter(User.email==email, User.password==password).first()
        if user:
            session['user_id'] = user.id
            return redirect(url_for('index'))
        else:
            return redirect(url_for('login'))


@app.route('/regist/', methods=['GET', 'POST'])
def regist():
    if request.method == 'GET':
        return render_template('regist.html')
    else:
        email = request.form.get('email')
        username = request.form.get('username')
        password1 = request.form.get('password1')
        password2 = request.form.get('password2')

        user = User.query.filter(User.email == email).first()
        if user:
            return u"該郵箱已存在!"
        elif not valiEmail(email):
            return u"請檢查郵箱格式I"
        else:
            if password1 == password2:
                user = User(email=email, username=username, password=password1)
                db.session.add(user)
                db.session.commit()
                return redirect(url_for('login'))

@app.route('/logout/')
def logout():
    # session.pop('user_id')
    # del session['user_id']
    session.clear()
    return redirect(url_for('login'))


@app.context_processor
def valiLogin():
    user_id = session.get('user_id')
    if user_id:
        user = User.query.filter(User.id == user_id).first()
        if user:
            return {'user':user}
    return {}

if __name__ == '__main__':
    app.run()

config.py

import os

#DEBUG = True

# 設定session需要用到的欄位
SECRET_KEY = os.urandom(24)

# dialect+driver://username:password@host:port/database
DIALECT = 'mysql'
DRIVER = 'mysqldb'
USERNAME = 'root'
PASSWORD = 'root'
HOST = '127.0.0.1'
PORT = '3306'
DATABASE = 'bbs_demo'

SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,
                                                                       HOST,PORT,DATABASE)

在主檢視檔案中使用 app.config.from_object(config)引入配置檔案

exts.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

需要注意的是db = SQLAlchemy()使用都需要繫結一個app.不然會導致遷移失敗.這裡在manage.py進行繫結.不然會導致迴圈引用

manage.py

類似django一樣使用manage用命令列方式方便地進行操作,這裡主要是資料庫的遷移工作.

from flask_script import Manager
from flask_migrate import MigrateCommand, Migrate
from bbs_demo import app
from exts import db

# 建立的模型都需要匯入到這個檔案中
# MigrateCommand才會講模型對映到資料庫中去
from models import User

# Manage()需要給定一個app
manager =Manager(app)
# SQLalchemy執行之前需要繫結到當前app
db.init_app(app)
# Migrate繫結app和db
migrate = Migrate(app, db)

# 新增遷移指令碼的命令到manager
manager.add_command('db', MigrateCommand)

if __name__ =="__main__":
    manager.run()

主要操作命令有:
* python manage.py db init
* python manage.py db migrate
* python manage.py db upgrade

模型匯入

在這個指令碼寫完之後,之後需要將模型對映到資料庫中的準備工作:
* 建立模型到models.py中
* manage中匯入建立好的模型
* 使用命令列進行對映

models.py

from exts import db

# 定義一些模型

class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    email = db.Column(db.String(30), nullable=False)
    username = db.Column(db.String(30), nullable=False)
    password = db.Column(db.String(50), nullable=False)

manage.py中匯入模型

from models.py import User

decorators.py

存放一些裝飾器

from functools import wraps
from flask import session, redirect, url_for

def login_required(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if session.get('user_id'):
            return func(*args, **kwargs)
        else:
            return redirect(url_for('login'))

    return wrapper

至此就是專案的全部內容

相關文章