Flask入門之完整項目搭建

  1、建立虛擬環境

  1,新建虛擬環境

  cmd中輸入:mkvirtualenv 環境名html

  2,在虛擬環境安裝項目運行所須要的基本模塊

pip install flask==0.12.4
pip install redis
pip install flask-session
pip install flask-script
pip install flask-mysqldb
pip install flask-sqlalchemy
pip install flask-migrate
pip install flask_wtf

  2、構建項目文件目錄

項目根目錄/
├── application/            # 項目主要邏輯代碼保存目錄
|    ├── apps               #存放藍圖
|    ├── settings/          # 項目配置存儲目錄
│    │   ├ dev.py           # 開發階段的配置文件
│    │   ├ prop.py          # 生產階段的配置文件
|    ├──templates           #存放全局的html文件
│    ├── __init__.py        # 項目初始化文件
├── manage.py               # 項目的終端管理腳本文件
├──logs/                    #存放日誌文件
├──docs/                    #存放文檔文件

  3、配置文件

  settings/__init__.py:python

from redis import StrictRedis

class Config(object):
    """項目配置核心類"""
    # 調試模式
    DEBUG = True

    # todo 配置日誌
    pass

    # mysql數據庫的配置信息
    SQLALCHEMY_DATABASE_URI = "mysql://root:mysql@127.0.0.1:3306/students?charset=utf8"
    # 動態追蹤修改設置,如未設置只會提示警告
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    # 查詢時會顯示原始SQL語句
    SQLALCHEMY_ECHO= False

    # 配置redis
    REDIS_HOST = '127.0.0.1'  # 項目上線之後,這個地址就會被替換成真實IP地址,mysql也是
    REDIS_PORT = 6379

    # 設置密鑰,能夠經過 base64.b64encode(os.urandom(48)) 來生成一個指定長度的隨機字符串
    SECRET_KEY = "ghhBljAa0uzw2afLqJOXrukORE4BlkTY/1vaMuDh6opQ3uwGYtsDUyxcH62Aw3ju"

    # flask_session的配置信息
    SESSION_TYPE = "redis" # 指定 session 保存到 redis 中
    SESSION_USE_SIGNER = True # 讓 cookie 中的 session_id 被加密簽名處理
    SESSION_REDIS = StrictRedis(host=REDIS_HOST, port=REDIS_PORT,db=1) # 使用 redis 的實例
    PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session 的有效期,單位是秒

  settings/dev.py:mysql

from . import Config
class DevelopementConfig(Config):
    """開發模式下的配置"""
    # 查詢時會顯示原始SQL語句
    SQLALCHEMY_ECHO= True

  settings/prop.py:redis

from . import Config
class ProductionConfig(Config):
    """生產模式下的配置"""
    DEBUG = False

  4、項目主應用初始化項目

  application/__init__.py,建立flask應用並加載配置sql

from flask import Flask
from application.settings.dev import DevelopementConfig
from application.settings.prop import ProductionConfig

config = {
    "dev": DevelopementConfig,
    "prop": ProductionConfig,
}

def init_app(config_name):
    """項目的初始化函數"""
    app = Flask(__name__)

    # 設置配置類
    Config = config[config_name]

    # 加載配置
    app.config.from_object(Config)

    return app

  manage.pyz中調用init_app函數,啓動項目數據庫

from application import init_app

app = init_app("dev")

@app.route("/")
def index():
    return "index"

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

  在application/__init__.py項目初始化文件中加載redis或者mysql的初始化代碼django

from flask import Flask
from redis import StrictRedis
from flask_wtf.csrf import CSRFProtect
from flask_session import Session

from application.settings.dev import DevelopementConfig
from application.settings.prop import ProductionConfig

config = {
    "dev": DevelopementConfig,
    "prop": ProductionConfig,
}

# 爲了方便redis的鏈接對象在函數外部可使用,預先設置一個全局變量,接下來在函數中用於保存redis的鏈接
redis_store = None

def init_app(config_name):
    """項目的初始化功能"""
    app = Flask(__name__)

    # 設置配置類
    Config = config[config_name]

    # 加載配置
    app.config.from_object(Config)

    # redis的連接初始化
    global redis_store
    redis_store = StrictRedis(host=Config.REDIS_HOST, port=Config.REDIS_PORT,db=0)

    # 開啓CSRF防範功能
    CSRFProtect(app)

    # 開啓session功能
    Session(app)

    # TODO 註冊藍圖對象到app應用中

    return app

  5、增長數據庫配置

  application/__init__.py增長代碼flask

# from flask import Flask
# from redis import StrictRedis
# from flask_wtf.csrf import CSRFProtect
# from flask_session import Session
from flask_sqlalchemy import SQLAlchemy
# 
# from application.settings.dev import DevelopementConfig
# from application.settings.prop import ProductionConfig
# 
# config = {
#     "dev": DevelopementConfig,
#     "prop": ProductionConfig,
# }
# 
# # 爲了方便redis的鏈接對象在函數外部可使用,預先設置一個全局變量,接下來在函數中用於保存redis的鏈接
# redis_store = None
db = SQLAlchemy()
# 
# def init_app(config_name):
#     """項目的初始化功能"""
#     app = Flask(__name__)
# 
#     # 設置配置類
#     Config = config[config_name]
# 
#     # 加載配置
#     app.config.from_object(Config)
# 
#     # redis的連接初始化
#     global redis_store
#     redis_store = StrictRedis(host=Config.REDIS_HOST, port=Config.REDIS_PORT,db=0)
# 
#     # 開啓CSRF防範功能
#     CSRFProtect(app)
# 
#     # 開啓session功能
#     Session(app)
# 
    # 配置數據庫連接
    db.init_app(app)
# 
#     # TODO 註冊藍圖對象到app應用中
# 
#     return app

  6、在manage啓動文件中新增關於啓動過程當中的相關功能

  manage.pycookie

from application import init_app,db
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand

app = init_app("dev")

# 使用終端腳本工具啓動和管理flask
manager = Manager(app)

# 啓用數據遷移工具
Migrate(app, db)
# 添加數據遷移的命令到終端腳本工具中
manager.add_command('db', MigrateCommand)


@app.route("/")
def index():
    return "index"

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

  7、日誌

  application/__init__.pysession

import logging
from logging.handlers import RotatingFileHandler

# 把日誌相關的配置封裝成一個日誌初始化函數
def setup_log(Config):
    # 設置日誌的記錄等級
    logging.basicConfig(level=Config.LOG_LEVEL)  # 調試debug級
    # 建立日誌記錄器,指明日誌保存的路徑、每一個日誌文件的最大大小、保存的日誌文件個數上限
    file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024 * 1024 * 300, backupCount=10)
    # 建立日誌記錄的格式 日誌等級 輸入日誌信息的文件名 行數 日誌信息
    formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
    # 爲剛建立的日誌記錄器設置日誌記錄格式
    file_log_handler.setFormatter(formatter)
    # 爲全局的日誌工具對象(flaskapp使用的)添加日誌記錄器
    logging.getLogger().addHandler(file_log_handler)

  在init_app方法中電泳上一步建立的方法,並傳入config_name

   # 啓用日誌功能
    setup_log(Config)

  在配置文件seetings/__init__.py中,設置日誌等級

class Config(object):
    """項目配置核心類"""
    # 調試模式
    DEBUG = True

    # todo 配置日誌
    LOG_LEVEL = "DEBUG"

  8、建立藍圖

  application下的apps目錄專門用於存放藍圖的。建立藍圖

  在apps下新建一個包,藍圖名爲index,在包下面的__init.py文件中建立藍圖對象

from flask import Blueprint

index_blu = Blueprint("index_blu",__name__)

  在index藍圖目錄下建立對應的視圖文件,views.py

from . import index_blu

@index_blu.route("/")
def index():
    return "首頁"

  在藍圖下的__init__.py文件中引入視圖中的全部視圖

from flask import Blueprint

index_blu = Blueprint("index_blu",__name__)

from .views import *

  在項目初始化文件application/__init__.py文件中註冊藍圖對象

    # TODO 註冊藍圖對象到app應用中
    # 首頁模塊
    from .apps.index import index_blu
    app.register_blueprint(index_blu,url_prefix='')

  建立模型文件models.py

# coding=utf-8
from application import db

# 建立關係表,再也不建立模型,通常用於表與表之間的多對多場景
"""
表關係變量 = db.Table(
    "關係表表名",
    db.Column('字段名', 字段類型, 字段選項),  # 普通字段
    db.Column("字段名", 字段類型, db.ForeignKey("表名.id")),
    db.Column("字段名", 字段類型, db.ForeignKey("表名.id")),
)
"""
achievement = db.Table(
    "achievement",
    db.Column('score', db.Numeric, comment="分數"),
    db.Column('student_id', db.Integer, db.ForeignKey('student.id')),
    db.Column('course_id', db.Integer, db.ForeignKey('course.id'))
)

class Student(db.Model):
    """學生信息"""
    __tablename__ = "student"
    id = db.Column(db.Integer, primary_key=True, comment="主鍵ID")
    name = db.Column(db.String(64), index=True, comment="姓名" )
    sex = db.Column(db.Boolean, default=True, comment="性別")
    class_number = db.Column(db.String(32), nullable=True, index=True, comment="班級")
    age = db.Column(db.SmallInteger, comment="年齡")
    description = db.Column(db.Text, comment="個性簽名")
    courses = db.relationship(
        'Course', # 模型名稱
        secondary=achievement, # 表關係變量
        backref='students', # 當外鍵反過來獲取主鍵信息時,使用的字段名稱,能夠自定義,接下來的使用例如: course.students 獲取某個課程下全部的學生
        lazy='dynamic'
    )

    def __repr__(self):
        return "%s" % self.name

class Course(db.Model):
    """課程信息"""
    __tablename__ = "course"
    id = db.Column(db.Integer, primary_key=True,comment="主鍵ID")
    name = db.Column(db.String(64), unique=True,comment="課程名稱")
    def __repr__(self):
        return "%s" % self.name

  數據庫遷移:

python manage.py db init

python manage.py db migrate -m 'initial migration'

python manage.py db upgrade 

  完成學生表的增刪改查

  views.py

from . import index_blu
from .models import Student
from flask import render_template,request
from application import db
from flask import flash

@index_blu.route("/")
def index():
    """學生列表"""
    student_list = Student.query.all()
    data = []
    for student in student_list:
        print(student.sex)
        data.append({
            "id":student.id,
            "name":student.name,
            "age":student.age,
            "sex":"" if student.sex else "",
            "description":student.description,
            "class_number":student.class_number,
        })

    return render_template("index.html",students=data)

@index_blu.route("/add",methods=["POST","GET"])
def add_student():
    if request.method == "POST":
        # 接受數據
        name = request.form.get("username")
        age = int( request.form.get("age") )
        sex = True if request.form.get("sex") == '1' else False
        class_number = request.form.get("class_number")
        description = request.form.get("description")
        # 驗證數據
        if age < 0 or age > 120:
            # 閃現信息[用於返回錯誤信息給客戶端,只顯示一次]
            flash("非法的年齡數值")

        # 保存入庫
        student = Student(name=name,age=age,sex=sex,class_number=class_number,description=description)
        try:
            db.session.add(student)
            db.session.commit()
        except:
            # 事務回滾
            db.session.rollback()

    return render_template("add.html")

  在藍圖下創一個templates目錄,用於存放本身的模板

  在index/__init__.py文件中加入

#coding=utf-8
from flask import Blueprint

index_blu = Blueprint("index_blu",__name__,template_folder="templates")

from .views import *

  這個和django同樣的,在查找模板時,先從全局的templates找,而後再去藍圖下面的templates中找

  9、閃現信息

  使用後,只會出現一次的信息,叫‘閃現信息’,用於在驗證數據失敗或者一些只須要顯示一次性提示得場景。

  使用方法:

  在視圖中當驗證有誤時,在顯示模板以前設置flash

# 視圖函數代碼
from flask import flash

flash("對不起,您還沒有登陸,請登陸!")

  模板中代碼:

# 模板代碼
{% for message in get_flashed_messages() %}
    <span>{{message}}</span>
{% endfor %}
相關文章
相關標籤/搜索