一.項目准備
1.新建項目目錄students,並創建虛擬環境
mkvirtualenv students
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
3.在pycharm中打開項目目錄編寫manage.py啟動項目的文件
(記得配置解釋器為我們的虛擬環境解釋器)
from flask import Flask app = Flask(__name__) @app.route('/index') def index(): return 'index' if __name__ == '__main__': app.run()
運行正常說明成功:
4.創建目錄結構:
創建項目目錄結構:
項目根目錄/ ├── application/ # 項目主要邏輯代碼保存目錄 | ├── settings/ # 項目配置存儲目錄 │ │ ├ dev.py # 開發階段的配置文件 │ │ ├ prop.py # 生產階段的配置文件 │ ├── __init__.py # 項目初始化文件 ├── manage.py # 項目的終端管理腳本文件
5.各配置文件的編寫
配置文件
settings/__init__.py
代碼:
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 的有效期,單位是秒
from . import Config class DevelopementConfig(Config): """開發模式下的配置""" # 查詢時會顯示原始SQL語句 SQLALCHEMY_ECHO= True
from . import Config class ProductionConfig(Config): """生產模式下的配置""" DEBUG = False
二.
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.py 中調用 init_app 函數,啟動項目
from application import init_app app = init_app("dev") @app.route("/") def index(): return "index" if __name__ == '__main__': app.run()
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
# 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) # # 配置數據庫鏈接
# 這個init_app是數據庫那個類自身的函數,並不是當前的這個函數
db.init_app(app) # # # TODO 注冊藍圖對象到app應用中 # # return app
因為前面已經在settings中設置了數據庫的配置信息,所以接下來,創建對應的數據庫
create database students charset=utf8;
2.
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()
三.日志的使用
Python 自身提供了一個用於記錄日志的標准庫模塊:logging
FATAL/CRITICAL = 致命的,危險的 ERROR = 錯誤 WARNING = 警告 INFO = 信息 DEBUG = 調試 NOTSET = 沒有設置
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)
# 啟用日志功能 setup_log(Config)
1 class Config(object): 2 """項目配置核心類""" 3 # 調試模式 4 DEBUG = True 5 6 # todo 配置日志 7 LOG_LEVEL = "DEBUG"
新增日志以后的項目目錄結構(logs這個文件需要手動創建,否則會報錯)
項目根目錄/ ├── docs/ # 項目開發相關文檔 ├── logs/ # 項目運行日志保存目錄 | ├── log # 日志文件 ├── application/ # 項目主要邏輯代碼保存目錄 | ├── settings/ # 項目配置存儲目錄 │ │ ├ dev.py # 開發階段的配置文件 │ │ ├ prop.py # 生產階段的配置文件 │ ├── __init__.py # 項目初始化文件 ├── manage.py # 項目的終端管理腳本文件
四.藍圖創建
在applications下創建apps目錄,apps以后專門用於保存每一個項目的藍圖,
並在apps創建index藍圖目錄,並在__init__.py
from flask import Blueprint index_blu = Blueprint("index_blu",__name__)
在index藍圖目錄中新增對應的視圖文件vies.py,代碼:
from . import index_blu @index_blu.route("/") def index(): return "首頁"
from flask import Blueprint index_blu = Blueprint("index_blu",__name__) from .views import *
# TODO 注冊藍圖對象到app應用中 # 首頁模塊 from .apps.index import index_blu app.register_blueprint(index_blu,url_prefix='')
聲明了藍圖目錄以后的項目目錄結構
項目根目錄/ ├── application/ # 項目主要邏輯代碼保存目錄 | ├── settings/ # 項目配置存儲目錄 │ │ ├ dev.py # 開發階段的配置文件 │ │ ├ prop.py # 生產階段的配置文件 │ ├── __init__.py # 項目初始化文件 │ ├── statics/ # 保存項目中所有的靜態資源文件[img/css/js] │ ├── modules/ # 保存項目中所有藍圖的存儲目錄 │ │ ├── index # 藍圖目錄 │ │ │ ├── __init__.py # 藍圖的初始化問年間 │ │ │ └── views.py # 藍圖的視圖函數文件 │ │ ├── __init__.py ├── manage.py # 項目的終端管理腳本文件
index的模型代碼: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' ) 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="課程名稱")
在主應用中帶入模型並遷移數據庫
#!/usr/bin/env python # -*- coding: utf-8 -*- #author tom 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) # 導入模型[為了進行數據遷移] from application.apps.index import models @app.route('/') def index(): return 'index' if __name__ == '__main__': manager.run()
遷移數據庫:
#因為上面已經把數據庫遷移夢里添加了: #所以直接 #初始化 python manage.py init #遷移 python manage.py migrate #生成報表 python manage.py upgrade
添加測試數據
insert into student values (1,"趙華",1,307,22,"對於勤奮的人來說,成功不是偶然;對於懶惰的人來說,失敗卻是必然。"), (2,"程星雲",1,301,20,"人生應該如蠟燭一樣,從頂燃到底,一直都是光明的。"), (3,"陳峰",1,504,21,"在不瘋狂,我們就老了,沒有記憶怎么祭奠呢?"), (4,"蘇禮就",1,502,20,"不要為舊的悲傷,浪費新的眼淚。"), (5,"張小玉",0,306,18,"沒有血和汗水就沒有成功的淚水。"), (6,"吳傑",1,307,19,"以大多數人的努力程度之低,根本輪不到去拼天賦"), (7,"張小辰",0,405,19,"人生的道路有成千上萬條, 每一條路上都有它獨自的風景。")
查看數據:在index.view編寫視圖
from flask import render_template, request, flash from application import db from . import index_blu from .models import Student @index_blu.route('/') def index(): '''學生列表''' student_list=Student.query.all() data=[] for student in student_list: 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.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a href="{{ url_for('index_blu.add') }}">新增學員</a> <table border="1" width="1000" align="center"> <tr> <th>id</th> <th>姓名</th> <th>年齡</th> <th>性別</th> <th>班級</th> <th>個性簽名</th> </tr> {% for student in students %} <tr> <td>{{ student.id }}</td> <td>{{ student.name }}</td> <td>{{ student.age }}</td> <td>{{ student.sex }}</td> <td>{{ student.class_number }}</td> <td>{{ student.description }}</td> </tr> {% endfor %} </table> </body> </html>
添加數據:在index.view編寫視圖
@index_blu.route('/add',methods=['GET','POST']) def add(): 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,sex=sex,class_number=class_number,description=description) try: db.session.add(student) db.session.commit() except Exception as e: db.session.rollback() return render_template('add.html')
add.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for message in get_flashed_messages() %} <span>{{ message }}</span> {% endfor %} <form action="" method="post"> <table border="1" witdth="600" align="center"> <tr> <td>姓名:</td> <td><input type="text" name="username"></td> </tr> <tr> <td>年齡:</td> <td><input type="text" name="age"></td> </tr> <tr> <td>性別:</td> <td> <select name="sex"> <option value="1">男</option> <option value="0">女</option> </select> </td> </tr> <tr> <td>班級:</td> <td><input type="class_number"></td> </tr> <tr> <td>個性簽名:</td> <td><textarea name="description"></textarea></td> </tr> <tr> <td> </td> <td> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> <input type="submit" value="注冊"> </td> </tr> </table> </form> </body> </html>
項目目錄結構圖:
五。
使用后,只會出現一次的信息,叫“閃現信息”,用於在驗證代碼失敗,或者一些只需要顯示一次性提示的場景。
使用步驟:
# 視圖函數代碼
from flask import flash
flash("對不起,您尚未登錄,請登錄!")
模板代碼:
# 模板代碼 {% for message in get_flashed_messages() %} <span>{{message}}</span> {% endfor %}