Flask不同於Django,Django在創建程序時自動得到必要的目錄文件,而Flask則只有一個空文件夾,所以關於Flask項目的目錄我們需要自行配置。
首先利用pycharm創建一個項目,在根目錄下創建一個app文件夾(app文件)、一個utils文件夾(用於放數據庫連接池)、一個manage.py文件和一個settings.py文件。這里我還創建了一個auth文件夾,寫了一個驗證登錄的py文件
首先,我們要在app文件夾下依次創建一下內容:
-
- static文件夾:用於放靜態文件
- templates文件夾:用於放置html模板文件
- views文件夾:用於放置視圖函數
- __init__.py文件:注冊app到啟動文件,一會兒我們會在這里大做文章
- models.py文件:用於放置創建表的類
在__init__.py中,需要做的是引入Flask-SQLAlchemy、創建app、設置配置文件、注冊藍圖和注冊組件

#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask from auth.auth import Auth from flask_session import Session # 1. 引入Flask-SQLAlchemy from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()#實例化SQLAlchemy from .views.account import account from .views.main import main from .views.user import user # 3. 導入models中的表 from .models import * #創建app def create_app(): app = Flask(__name__) app.debug = True app.secret_key = 'sdiusdfsdf'#自定義的session秘鑰 # 設置配置文件 app.config.from_object('settings.DevelopmentConfig') # 注冊藍圖 app.register_blueprint(account) app.register_blueprint(user) app.register_blueprint(main) # 注冊組件 # Session(app) Auth(app) # 2. 注冊 Flask-SQLAlchemy # 這個對象在其他地方想要使用 # SQLAlchemy(app) db.init_app(app) return app #得到了一個app
然后,在啟動文件manage.py中導入創建的app,創建自定義命令后寫下run

#!/usr/bin/env python # -*- coding:utf-8 -*- """ 被斃掉了 # 5. 創建和刪除表 以后執行db.create_all() 以后執行db.drop_all() 新第5步: 安裝 pip3 install Flask-Migrate """ import os from flask_script import Manager, Server # 5.1 導入 from flask_migrate import Migrate, MigrateCommand from app import create_app, db app = create_app() manager = Manager(app) # 5.2 創建migrate示例 migrate = Migrate(app, db) @manager.command def custom(arg): """ 自定義命令 python manage.py custom 123 :param arg: :return: """ print(arg) @manager.option('-n', '--name', dest='name') @manager.option('-u', '--url', dest='url') def cmd(name, url): """ 自定義命令 執行: python manage.py cmd -n wupeiqi -u http://www.oldboyedu.com :param name: :param url: :return: """ print(name, url) @manager.command def import_news(path): """ 批量導入 :param name: :param url: :return: """ import xlrd from xlrd.book import Book from xlrd.sheet import Sheet from xlrd.sheet import Cell workbook = xlrd.open_workbook(path) sheet_names = workbook.sheet_names() # sheet = workbook.sheet_by_name('工作表1') sheet = workbook.sheet_by_index(0) # 循環Excel文件的所有行 for row in sheet.get_rows(): # print(row) # 循環一行的所有列 for col in row: # 獲取一個單元格中的值 print(col.value, end=';') print('') """ # 數據庫遷移命名 python manage.py db init python manage.py db migrate python manage.py db upgrade """ # 5.3 創建db命令,以后在數據庫操作的時候都可使用db manager.add_command('db', MigrateCommand) """ # 自定義命令 python manage.py runserver """ manager.add_command("runserver", Server()) """ 生成當前環境的所有依賴: requirements.txt pip3 freeze > requirements.txt 生成當前程序的所有依賴: requirements.txt pip3 install pipreqs pipreqs ./ """ if __name__ == "__main__": manager.run()
接下來在settings.py文件中配置好相應的數據庫信息,在utils文件夾下創建文件,寫入數據庫連接池的內容

#!/usr/bin/env python # -*- coding:utf-8 -*- import redis class BaseConfig(object): SESSION_TYPE = 'redis' # session類型為redis SESSION_KEY_PREFIX = 'session:' # 保存到session中的值的前綴 SESSION_PERMANENT = False # 如果設置為True,則關閉瀏覽器session就失效。 SESSION_USE_SIGNER = False # 是否對發送到瀏覽器上 session:cookie值進行加密 SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:123@127.0.0.1:3306/flask_cata?charset=utf8" #數據庫用戶名:密碼@host:port/數據庫名?編碼 SQLALCHEMY_POOL_SIZE = 2 SQLALCHEMY_POOL_TIMEOUT = 30 SQLALCHEMY_POOL_RECYCLE = -1 # 追蹤對象的修改並且發送信號 SQLALCHEMY_TRACK_MODIFICATIONS = False class ProductionConfig(BaseConfig): pass class DevelopmentConfig(BaseConfig): pass class TestingConfig(BaseConfig): pass

import time import pymysql import threading from DBUtils.PooledDB import PooledDB, SharedDBConnection POOL = PooledDB( creator=pymysql, # 使用鏈接數據庫的模塊 maxconnections=6, # 連接池允許的最大連接數,0和None表示不限制連接數 mincached=2, # 初始化時,鏈接池中至少創建的空閑的鏈接,0表示不創建 maxcached=5, # 鏈接池中最多閑置的鏈接,0和None不限制 maxshared=3, # 鏈接池中最多共享的鏈接數量,0和None表示全部共享。PS: 無用,因為pymysql和MySQLdb等模塊的 threadsafety都為1,所有值無論設置為多少,_maxcached永遠為0,所以永遠是所有鏈接都共享。 blocking=True, # 連接池中如果沒有可用連接后,是否阻塞等待。True,等待;False,不等待然后報錯 maxusage=None, # 一個鏈接最多被重復使用的次數,None表示無限制 setsession=[], # 開始會話前執行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服務端,檢查是否服務可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always # host='47.93.4.198', host='127.0.0.1',#本機host port=3306,#數據庫默認端口即3306 user='root',#數據庫用戶名 password='123',#數據庫密碼 database='flask_cata',#數據庫名 charset='utf8' )

""" # 方式一 # helper = SQLHelper() # helper.open() # result = helper.fetchone('select * from users where name=%s and pwd = %s',[request.form.get('user'),request.form.get('pwd'),]) # helper.close() # 方式二: # with SQLHelper() as helper: # result = helper.fetchone('select * from users where name=%s and pwd = %s',[request.form.get('user'),request.form.get('pwd'),]) # if result: # current_app.auth_manager.login(result['name']) # return redirect('/index') """ from utils.pool import db_pool import pymysql class SQLHelper(object): def __init__(self): self.conn = None self.cursor = None def open(self, cursor=pymysql.cursors.DictCursor): self.conn = db_pool.POOL.connection() self.cursor = self.conn.cursor(cursor=cursor) def close(self): self.cursor.close() self.conn.close() def fetchone(self, sql, params): cursor = self.cursor cursor.execute(sql, params) result = cursor.fetchone() return result def fetchall(self, sql, params): cursor = self.cursor cursor.execute(sql, params) result = cursor.fetchall() return result def __enter__(self): self.open() return self def __exit__(self, exc_type, exc_val, exc_tb): self.close() # with SQLHelper() as obj: # # print(obj) # print('正在執行')
到這里,程序的基本框架就設定好了。
接下來就是具體項目的內容,這里舉一個簡單的栗子
在models.py中創建表

""" # 方式一 # helper = SQLHelper() # helper.open() # result = helper.fetchone('select * from users where name=%s and pwd = %s',[request.form.get('user'),request.form.get('pwd'),]) # helper.close() # 方式二: # with SQLHelper() as helper: # result = helper.fetchone('select * from users where name=%s and pwd = %s',[request.form.get('user'),request.form.get('pwd'),]) # if result: # current_app.auth_manager.login(result['name']) # return redirect('/index') """ from utils.pool import db_pool import pymysql class SQLHelper(object): def __init__(self): self.conn = None self.cursor = None def open(self, cursor=pymysql.cursors.DictCursor): self.conn = db_pool.POOL.connection() self.cursor = self.conn.cursor(cursor=cursor) def close(self): self.cursor.close() self.conn.close() def fetchone(self, sql, params): cursor = self.cursor cursor.execute(sql, params) result = cursor.fetchone() return result def fetchall(self, sql, params): cursor = self.cursor cursor.execute(sql, params) result = cursor.fetchall() return result def __enter__(self): self.open() return self def __exit__(self, exc_type, exc_val, exc_tb): self.close() # with SQLHelper() as obj: # # print(obj) # print('正在執行')
通過python manage.py db init python manage.py db migrate python manage.py db upgrade三條命令進行數據庫遷移創建表,得到migrations文件夾
在views文件夾下創建視圖函數,並配置路由。在templates文件夾下創建模板html,在static下創建靜態文件,基本項目就成型了
views:

#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Blueprint, request, render_template, redirect, session, current_app from app import models from app import db from sqlalchemy import orm account = Blueprint('account', __name__) @account.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': """ 執行SQL 方式一: result = db.session.query(models.User.id,models.User.name).all() db.session.remove() 方式二: result = models.Users.query.all() """ """ 示例: # 通配符 ret = db.session.query(Users).filter(Users.name.like('e%')).all() ret = db.session.query(Users).filter(~Users.name.like('e%')).all() # 限制 ret = db.session.query(Users)[1:2] # 排序 ret = db.session.query(Users).order_by(Users.name.desc()).all() ret = db.session.query(Users).order_by(Users.name.desc(), Users.id.asc()).all() db.session.remove() """ return render_template('login.html') else: return render_template('login.html')

#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Blueprint, request, render_template, redirect main = Blueprint('main', __name__) @main.route('/index') def index(): # with SQLHelper() as helper: # user_list = helper.fetchall('select * from users',[]) return render_template('index.html')

#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Blueprint user = Blueprint('user', __name__) @user.route('/users') def users(): return 'users'
templates:

{% extends 'layout.html' %} {% block title %}首頁{% endblock %} {% block body %} <table> <h1>歡迎登錄:{{ session.get('user') }}</h1> <ul> {% for row in user_list %} <li>{{ row }}</li> {% endfor %} </ul> </table> {% endblock %}

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <!-- <link rel="stylesheet" href="/static/css/commons.css" /> --> <link rel="stylesheet" href="{{ url_for('static',filename='css/commons.css') }}" /> {% block css %}{% endblock %} </head> <body> <div class="pg-header"></div> <div class="pg-body"> {% block body %}{% endblock %} </div> {% block js %}{% endblock %} </body> </html>

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post"> <input type="text" name="user"> <input type="text" name="pwd"> <input type="submit" value="提交"> </form> </body> </html>
附:

alembic==0.9.6 blinker==1.4 certifi==2017.11.5 chardet==3.0.4 click==6.7 DBUtils==1.2 docopt==0.6.2 Flask==0.12.2 Flask-Migrate==2.1.1 Flask-Script==2.0.6 Flask-Session==0.3.1 Flask-SQLAlchemy==2.3.2 idna==2.6 itsdangerous==0.24 Jinja2==2.10 Mako==1.0.7 MarkupSafe==1.0 pipreqs==0.4.9 PyMySQL==0.8.0 python-dateutil==2.6.1 python-editor==1.0.3 PyTyrion==1.0.1 requests==2.18.4 six==1.11.0 SQLAlchemy==1.2.0 urllib3==1.22 Werkzeug==0.14.1 WTForms==2.1 xlrd==1.1.0 yarg==0.1.9

#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import request, session,redirect # 登錄成功時 _request_ctx_stack.top.user = user class Auth(object): def __init__(self, app=None): self.app = app if app: self.init_app(app) def init_app(self, app): app.auth_manager = self app.before_request(self.check_login) app.context_processor(self.auth_context_processor) def auth_context_processor(self): name = session.get('user') return dict(current_user=name) def check_login(self): # print(request.url) # print(request.path) if request.path == '/login': return None if session.get('user'): return None return redirect('/login') def permission(self): pass def login(self,data): session['user'] = data