flask-migrate,flask-script
阿新 • • 發佈:2018-12-19
Flask-Migrate是一個為Flask應用處理SQLAlchemy資料庫遷移的擴充套件,使得可以通過Flask的命令列介面或者Flask-Scripts對資料庫進行操作。 Flask-Script:用來生成shell命令;為在Flask裡編寫額外的指令碼提供了支援。 這包括執行一個開發伺服器,一個定製的Python命令列,用於執行初始化資料庫、定時任務和其他屬於web應用之外的命令列任務的指令碼。
# 建立遷移倉庫(migrations目錄) python script.py db init # 讀取類的內容, 生成版本檔案, 並沒有真正在資料庫中新增或刪除; python script.py db migrate -m "新增性別" # 在資料庫中曾刪改; python script.py db upgrade # 檢測是否成功? mysql -uroot -phello # 去檢視改變的歷史狀態; python script.py db history # 返回指定的版本狀態; python script.py db downgrade base
Flask-Script:用來生成shell命令;為在Flask裡編寫額外的指令碼提供了支援。 這包括執行一個開發伺服器,一個定製的Python命令列,用於執行 初始化資料庫、定時任務和其他屬於web應用之外的命令列任務的指令碼。
新增自定義命令的3中方式: - 定義Command的子類; - 使用command裝飾器 - 使用option裝飾器
from flask import Flask from flask_script import Manager, Command app = Flask(__name__) # 1. 先例項化物件, Manager類例項化的物件執行/啟動後, 輝跟蹤所有的命令和命令呼叫的引數; manager = Manager(app) # 定義Command的子類; class Hello(Command): """歡迎資訊""" def run(self): print("hello world") # 新增到命令中, 讓馬哪個而進行管理 manager.add_command('hello', Hello) # 使用command裝飾器 @manager.command def add_user(): """新增使用者""" print("新增使用者成功!") # 使用option裝飾器 入符哦命令需要新增引數時 # -n 簡寫, --name, 全稱, @manager.option('-n', '--name', help="刪除使用者的名稱") @manager.option('-p', '--passwd', help="刪除使用者的密碼") def delete_user(name, passwd): """刪除使用者""" if name: print("刪除使用者%s成功, 密碼為%s!" %(name, passwd)) else: print("使用者為空") # 使用option裝飾器 if __name__ == "__main__": manager.run()
Todo manage
from flask_migrate import Migrate, MigrateCommand from flask_script import Shell, Manager from models import app, db, User, Department # 用來管理命令的物件, Manager用來跟蹤所有名林不過並處理他們如何從命令列呼叫; manager = Manager(app) migrate = Migrate(app, db) # 新增一條資料庫遷移管理的命令 manager.add_command('db', MigrateCommand) # 新增一條命令, 可以顯示所有的使用者 @manager.command def showUser(): """顯示所有的使用者""" users = User.query.all() print(users[:5]) # 新增一條命令, 可以顯示所有的使用者 @manager.command def showDepart(): """顯示所有的部門""" deaprts = Department.query.all() print(deaprts) # 新增部門 @manager.option('-n', '--name', help="部門名稱") def add_depart(name): try: depart1 = Department(name=name) db.session.add(depart1) db.session.commit() except Exception: print("建立部門失敗!") else: print("建立部門%s成功!" %(name)) # 實現新增使用者的命令 if __name__ == "__main__": # 準備 manager.run()
models
from datetime import datetime
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:[email protected]/Todo'
# SQLAlchemy 將會追蹤物件的修改並且傳送訊號。
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
bootstrap = Bootstrap(app)
app.config['SECRET_KEY'] = 'westos'
# 1). 面向物件方式建立表
# 2). 分析關係:
# 部門和使用者: 一對多
# 使用者和任務: 一對多的關係
# 使用者和使用者登入日誌: 一對多的關係
# 實現一對多(Role(1): User(n))的關係
# - 多的一端寫外來鍵
# - 少的一端寫反向引用
class User(db.Model):
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
# unique:使用者名稱唯一, nullable=False指使用者名稱不能為空;
name = db.Column(db.String(50), unique=True, nullable=False)
pwd = db.Column(db.String(100))
email = db.Column(db.String(30), unique=True)
phone = db.Column(db.String(30), unique=True)
info = db.Column(db.Text) # 個人簡介
add_time = db.Column(db.DateTime, default=datetime.now()) # 建立時間
department_id = db.Column(db.Integer, db.ForeignKey('department.id'))
todos = db.relationship('Todo', backref='user')
userlogs = db.relationship('Userlog', backref='user')
# 部門id與其他表關聯,不能隨便寫
def __repr__(self):
return '<User: %s>' %(self.name)
# 部門
class Department(db.Model):
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False)
# 反向引用: user就包含一個屬性, department
users = db.relationship('User', backref='department')
todos = db.relationship('Todo', backref='department')
def __repr__(self):
return '<Department: %s>' %(self.name)
class Todo(db.Model):
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
name = db.Column(db.String(200), nullable=False)
add_time = db.Column(db.DateTime, default=datetime.now()) # 建立時間
status = db.Column(db.Boolean, default=False) # 任務狀態, 預設為Flase(未完成)
department_id = db.Column(db.Integer, db.ForeignKey('department.id'))
user_id = db.Column(db.Integer,db.ForeignKey('user.id') )
def __repr__(self):
return '<Todo: %s>' % (self.id)
# 使用者登入日誌
class Userlog(db.Model):
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
add_time = db.Column(db.DateTime, default=datetime.now()) # 建立時間
ip = db.Column(db.String(200), nullable=False) # 登入ip
area = db.Column(db.String(200)) # 使用者登入地點
user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 外來鍵
def __repr__(self):
return '<Userlog: %s>' % (self.ip)
if __name__ == '__main__':
db.create_all()
# # 2). 初始化資料
# parts = ['開發部', '運維部', '人事部']
# partObj = [Department(name=part) for part in parts]
# db.session.add_all(partObj)
# db.session.commit()
u1 = User(name="westos1", pwd='westos', department_id=1)
db.session.add(u1)
db.session.commit()
views
from flask import render_template, request, redirect, url_for
from models import app, Todo, db, Department
@app.route('/')
def index():
return render_template('base.html')
@app.route('/register/')
def register():
pass
@app.route('/login/')
def login():
pass
@app.route('/logout/')
def logout():
pass
# 任務的增刪改查
@app.route('/todo/add/', methods=['POST'])
def todo_add():
# 獲取提交的任務資訊
name = request.form['todo_name']
part = request.form['part']
# 新增完成之後, 返回任務列表顯示頁面
todo = Todo(name=name, department_id=part, user_id=1)
db.session.add(todo)
db.session.commit()
return redirect(url_for('todo_list'))
@app.route('/todo/delete/<int:id>')
def todo_delete(id):
pass
@app.route('/list/')
def todo_list():
# 1). 從資料庫中查詢
todos = Todo.query.all()
parts = Department.query.all()
return render_template('list.html',
todos = todos,
parts=parts)
# 修改任務的狀態(變成已完成狀態/變成未完成狀態)
@app.route('/todo/undo/<int:id>/')
def undo(id):
todo = Todo.query.filter_by(id=id).first()
todo.status = False
db.session.commit()
# 更新狀態後, 返回任務列表頁
return redirect(url_for('todo_list'))
@app.route('/todo/done/<int:id>/')
def done(id):
todo = Todo.query.filter_by(id=id).first()
todo.status = True
db.session.commit()
# 更新狀態後, 返回任務列表頁
return redirect(url_for('todo_list'))
run
# 專案真實執行指令碼
from models import app
# 匯入編寫的檢視函式和路由
from views import *
if __name__ == '__main__':
app.run()
base.html
{#自己編寫一個基類模板#}
{% extends "bootstrap/base.html" %}
{% block styles %}
{{ super() }}
<link rel="stylesheet" href="../static/css/main.css">
{% endblock %}
{% block navbar %}
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html"></a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="#"></a></li>
<li><a href="#"></a></li>
<li><a href="#">首頁<span class="sr-only">(current)</span></a></li>
<li><a href="#">新聞</a></li>
<li><a href="#">國際</a></li>
<li><a href="#">國內</a></li>
<li><a href="/sysinfo/">系統資訊</a></li>
<li><a href="#">登陸使用者</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if 'user' in session %}
<li><a href="login.html"><span class="glyphicon glyphicon-user"></span>
{{ session.user }}</a></li>
<li><a href="/logout/"><span class="glyphicon glyphicon-log-in"></span>
登出 </a></li>
{% else %}
<li><a href="/login/"><span class="glyphicon glyphicon-log-in"></span>
登陸</a></li>
{% endif %}
<li><a href="/register/"><span class="glyphicon glyphicon-log-out"></span>
註冊</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{% endblock %}
{% block content %}
{#定義屬於自己的block#}
{% block newcontent %}
{% endblock %}
{% block footer %}
<div class="footer">
京ICP備11008151號京公網安備11010802014853
</div>
{% endblock %}
{% endblock %}
list.html
{% extends 'base.html' %}
{% block newcontent %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form class="form-horizontal" action="/todo/add/" method="post">
<div class="form-group">
{# 新增框 #}
<div class="col-sm-9">
<input type="text" class="form-control" placeholder="請新增任務" required="required"
name="todo_name">
</div>
{# 選擇框 #}
<div class="col-sm-2">
<select class="form-control" name="part">
{% for part in parts %}
<option value="{{ part.id }}">{{ part.name }}</option>
{% endfor %}
</select>
</div>
{# 新增的按鈕 #}
<div class="col-sm-1">
<input type="submit" class="btn btn-success" value="新增任務">
</div>
</div>
</form>
<h1>新增任務</h1>
<table class="table table-bordered">
<tr>
<td>任務內容</td>
<td>建立時間</td>
<td>狀態</td>
<td>所屬部門</td>
<td>操作</td>
</tr>
{% for todo in todos %}
<tr>
<td>{{ todo.name }}</td>
<td>{{ todo.add_time }}</td>
{# #}
<td>
{% if todo.status %}
<a href="/todo/undo/{{ todo.id }}/" class="btn btn-sm btn-success" role="button"><span
class="glyphicon glyphicon-remove"></span> 已完成</a>
{% else %}
<a href="/todo/done/{{ todo.id }}/" class="btn btn-sm btn-warning" role="button"><span
class="glyphicon glyphicon-remove"></span> 未完成</a>
{% endif %}
</td>
<td>{{ todo.department.name }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}