說明:flask 非常靈活,它沒有一個固定的項目目錄組織結構,以下內容僅供參考。
結果:如圖所示,此目錄結構為本人正在使用的結構。
- conf/default.py:存儲了Flask的一些配置內容。
- main/__init__.py:存儲藍圖的目錄。
- ops/__init__.py:定義程序,初始化一些對象。
- model/db.py: 定義數據庫中數據表。
- static:存儲js、css文件。
- templates:存儲HTML靜態頁面模板。
- run.py:程序入口。
1. conf/default.py注釋:
import os
class Config:
# 使用導入的os模塊來生成隨機秘鑰,此秘鑰用於Flask中的session。 SECRET_KEY = os.urandom(24)
# 數據庫相關定義,將其設為True時,每次請求結束后都會自動提交數據庫中的變動(不過我數據庫做更改還是寫了commit =.=;) SQLALCHEMY_COMMIT_ON_TEARDOWN = True # 將Config類作為參數傳遞到其他函數中,又希望在實例化Config類之前就能提供下列的功能,所以使用staticmethod. @staticmethod def init_app(app): pass # 繼承Config類,下列定義數據庫地址,可以定義多個環境(TestingConfig="測試環境",DevelopmentConfig="開發環境"...) class TestingConfig(Config): SQLALCHEMY_DATABASE_URI = 'mysql://test:test@192.168.xx.xx:3306/test?charset=utf8'
# 如果設置成 True (默認情況),Flask-SQLAlchemy將會追蹤對象的修改並且發送信號.這需要額外的內存,如果不必要的可以禁用它 SQLALCHEMY_TRACK_MODIFICATIONS = False # 同上 class DevelopmentConfig(Config): SQLALCHEMY_DATABASE_URI = 'mysql://dev:dev@192.168.xx.xx:3306/dev?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = False # 定義字典,方便其他.py文件引用 config = { 'default': DevelopmentConfig, 'testing': TestingConfig }
2.main/__init__.py
from flask import Blueprint, jsonify, request, render_template, session, json from ops import db, and_ from model.db import User # 定義藍圖,指定模板位置及static文件位置,下面有說明 users = Blueprint('user',__name__,template_folder='../templates',static_folder='../static')
# 因為定義了藍圖,所以就要寫"@users.xxx". @users.route('/register',methods=['GET','POST']) # 創建用戶 def register(): if request.method == 'POST':
# 這里的data中的數據是獲取的前端的AJAX里邊的數據. data = json.loads(request.form.get('register_data')) if data: user = data['register_user'] passwd = data['register_password'] re_password = data['repeatpassword']
# 前往數據庫查詢數據 alreay = User.query.filter(User.name == user).first()
'''
下列的return jsonify都是返還給AJAX一個字典,前端AJAX調用結果進行彈窗.
''' if alreay: return jsonify({'code': '300', 'data': '用戶已存在!'}) elif passwd != re_password: return jsonify({'code': '100', 'data': '注冊密碼與確認密碼不一致'}) insert = User(name=user,password=passwd,status=0) db.session.add(insert) db.session.commit() return jsonify({'code': '200','data':'用戶創建成功!'}) return render_template('register.html')
# 下列內容與上述內容大同小異,不做過多解釋 @users.route('/forbidden',methods=['POST']) # 禁用用戶 def forbidden(): data = json.loads(request.form.get('data')) web_user = data['user'] forbidden = User.query.filter(and_(User.name == web_user, User.status == '1')).first() if forbidden: if forbidden.status == "1": forbidden.status = 0 db.session.commit() return jsonify({"code": "200", "data": "賬戶禁用完成!"}) return jsonify({"code": "300", "data": "賬戶已被禁用!"}) @users.route('/start_using',methods=['POST']) # 激活用戶 def start_using(): data = json.loads(request.form.get('data')) web_user = data['user'] start_using = User.query.filter(and_(User.name == web_user, User.status == '0')).first() if start_using: if start_using.status == "0": start_using.status = 1 db.session.commit() return jsonify({"code": "300", "data": "賬戶啟用完成!"}) return jsonify({"code": "300", "data": "賬戶已被啟動!"}) @users.route('/del_user',methods=['POST']) def del_user(): data = json.loads(request.form.get('data')) del_user = data['user'] web_user = session['user'] update_pass = User.query.filter(User.name == del_user).first() if update_pass: if web_user == 'admin': db.session.delete(update_pass) db.session.commit() db.session.execute('alter table user_info AUTO_INCREMENT 1') return jsonify({"code": "200","data":"賬戶刪除成功!"}) return jsonify({'code': '500','data':'你無權刪除用戶'}) @users.route('/check') # 頁面展示數據庫中的用戶數據 def check(): count = User.query.count() name = User.query.all() return render_template('user_list.html',name=name,count=count)
3.ops/__init__.py
'''
下列很多模塊實際在這個文件中並沒有用到,導入到這個文件的目的就是防止Python中的循環導入問題.
'''
from flask import Flask,render_template, request, session, redirect, jsonify import os, jsonfrom sqlalchemy import and_ from werkzeug.security import generate_password_hash, check_password_hash from flask_sqlalchemy import SQLAlchemy
# 導入前面定義的Flask的設置. from conf.default import config # 初始化對象,以后續.py引用. db = SQLAlchemy() # 定義個方法,方便引用,接受引用傳參; def app_create(config_name):
# 導入users,因為main文件夾下邊的__init__.py文件中有users,這個users是藍圖 from main import users
'''
初始化程序,定義模板路徑,因為在這里初始化了那么程序就相當於在ops/目錄下,但是
默認情況下"templates"路徑是和程序同級的,但是這里templates和ops同級,所以
模板路徑就要手動定義
一句話就是 模板的位置是相對於程序
static位置同理
''' app = Flask(__name__,template_folder='../templates',static_folder='../static')
# 上面導入了藍圖,這里需要注冊藍圖. app.register_blueprint(users)
# 這里調用前面定義的配置文件的對象 app.config.from_object(config[config_name])
# 初始化配置. config[config_name].init_app(app)
# 初始化數據庫,官方定義. db.init_app(app)
# 將程序返回,使.py文件可調用全部初始化過的程序. return app
4.model/db.py
# 導入ops中創建的db對象
from ops import db # SQLAlchemy固定語法 class User(db.Model): __tablename__ = 'user_info' id = db.Column(db.Integer, primary_key=True) status = db.Column(db.Integer,nullable=False) name = db.Column(db.String(40),unique=True) password = db.Column(db.String(128),nullable=False) # 自定義輸出結果 def __repr__(self): return str('%r') % self.name
5.run.py
# 導入前面創建的"程序創建"方法
from ops import app_create
# 導入模型中的 from model.db import User from ops import render_template, request, session, redirect, jsonify, os, json, generate_password_hash, check_password_hash app = app_create(os.getenv('FLASK_CONFIG') or 'testing') @app.before_request # 判斷用戶是否登錄,是否緩存在session中 def is_login(): if 'user' not in session \ and request.endpoint != 'login' \ and '/static/' not in request.path: return redirect('/login') @app.route('/login',methods=['GET','POST']) # 用戶登錄 def login(): # 如果以GET請求當前url,直接返回html頁面 if request.method == 'GET': return render_template('login.html') ''' 如果以POST請求的話則將前端JS返回的數據與數據庫中的數據進行對比,對比成功后返回結果 ''' if request.method == 'POST': data = json.loads(request.form.get('data')) username = data['username'] passwd = data['password'] result = User.query.filter(User.name==username).first() if result: sql_pass_encrypt = generate_password_hash(result.password) if result.name == username and check_password_hash(sql_pass_encrypt,passwd): session['user'] = username return jsonify({"code": "200","data": ""}) return jsonify({"code": "500","data": "無效的用戶名或密碼!"}) return jsonify({"code":"300","data":"用戶不存在!"}) @app.route('/') # 頁面主頁 def index(): return render_template('index.html',username=session['user']) if __name__ == '__main__': app.run()
調用關系:
# 注冊藍圖
ops/__init__.py -> main/users
#引用配置文件
oss/__init__.py -> conf/default.py
# 加載數據庫配置
run.py -> model/db.py