那些年咱們學Flask-SQLAlchemyhtml
實現數據庫操做,分頁等功能 python
Flask-SQLAlchemy庫讓flask更方便的使用SQLALchemy,是一個強大的關係形數據庫框架,既可使用orm方式操做數據庫,也可使用原始的SQL命令.mysql
Flask-Migrate 是一個數據遷移框架,須要經過Flask-script庫來操做.web
程序使用的數據庫地址須要配置在SQLALCHEMY_DATABASE_URI中,SQLALchemy支持多種數據庫,配置格式以下:sql
Postgres:數據庫
postgresql://scott:tiger@localhost/mydatabase
MySQL:flask
mysql://scott:tiger@localhost/mydatabase
Oracle:bootstrap
oracle://scott:tiger@127.0.0.1:1521/sidname
SQLite:api
sqlite:////absolute/path/to/foo.db
db是SQLALchemy類的實例,表示程序使用的數據庫,爲用戶提供Flask-SQLALchemy的全部功能session
from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) #配置數據庫地址 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost:3306/DB_name?charset=utf8' #該配置爲True,則每次請求結束都會自動commit數據庫的變更 app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True db = SQLAlchemy(app) #也能夠db = SQLAlchemy() db.init_app(app)
Flask-SQLALchemy使用繼承至db.Model的類來定義模型,如:
class User(db.Model, UserMixin):#UserMixin是Flask-Login庫中所須要的 __tablename__ = 'users' #每一個屬性定義一個字段 id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(64),unique=True) password = db.Column(db.String(64)) #定製顯示的格式 def __repr__(self): return '<User %r>' % self.username
定義完須要在Python Shell中導入db,調用db.create_all()來建立數據庫
(1)經常使用字段選項:
primary_key 設置主鍵
unique 是否惟一
index 是否建立索引
nullable 是否容許爲空
default 設置默認值,能夠傳入函數的引用 如傳入 datetime.datetime.utcnow 則每次建立時時間都是最新時間
(1) 插入數據:
from app.models import User from app import db #建立一個新用戶 u = User() u.username = 'abc' u.password = 'abc' #將用戶添加到數據庫會話中 db.session.add(u) #將數據庫會話中的變更提交到數據庫中,若是不Commit,數據庫中是沒有改動的 db.session.commit()
(2)查找數據:
#返回全部用戶保存到list中 user_list = User.query.all() #查找username爲abc的第一個用戶,返回用戶實例 u = User.query.filter_by(username='abc').first() #模糊查找用戶名以c結尾的全部用戶 user_list = User.query.filter(username.endswith('c')).all() #查找用戶名不是abc的用戶 u = User.query.filter(username != 'abc').first()
(3)刪除數據:
user = User.query.first() db.session.delete(user) db.session.commit()
(4)修改數據:
u = User.query.first() u.username = 'Mackie' db.session.commit()
個人理解是:在多的一邊定義外鍵,而relathonship()函數是用來創建關係的,能夠只在一邊定義,也能夠兩邊都使用(只在一邊使用時加上了backref選項等同於兩邊都使用)
class Person(db.Model): __tablename__ = 'persons' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50)) #backref將在Address表中建立個名爲persons的Person引用,以後可使用address.persons #訪問這個地址的全部人 addresses = db.relationship('Address', backref='persons',lazy='dynamic') class Address(db.Model): __tablename__ = 'address' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(50)) #在多的一邊使用db.ForeignKey聲明外鍵 person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
多對多關係能夠分解爲原表和關聯表之間兩個多對一關係,以下代碼創建了學生與所選課程之間的關係:
#建立關聯表,兩個字段的外鍵是另兩個表,一個學生對應多個關聯表,一個關聯表對應多個課程 registrations = db.Table('registrations', db.Column('student_id',db.Integer,db.ForeignKey('students.id')), db.Column('class_id',db.Integer,db.ForeignKey('classes.id')) ) class Student(db.Model): __tablename__ = 'students' id = db.Column(db.Integer,primary_key=True,) name = db.Column(db.String) classes = db.relationship('Class', secondary = registrations, #關聯表,只須要在一個表創建關係,sqlalchemy會負責處理好另外一個表 backref = db.backref('students',lazy='dynamic'), lazy = 'dynamic') class Class(db.Model): __tablename__ = 'classes' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String)
多對多的使用:
#學生1增長一門選課
student1.classes.append(class1)
#學生1退選class1
student1.classes.remove(class1)
#學生1所選課程,因爲指定了lazy='dynamic'因此沒有直接返回列表,而須要使用.all()
student1.classes.all()
Flask-SQLALchemy的Pagination對象能夠方便的進行分頁,
對一個查詢對象調用pagenate(page, per_page=20, error_out=True)函數能夠獲得pagination對象,第一個參數表示當前頁,第二個參數表明每頁顯示的數量,error_out=True的狀況下若是指定頁沒有內容將出現404錯誤,不然返回空的列表
#從get方法中取得頁碼 page = request.args.get('page', 1, type = int) #獲取pagination對象 pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=10, error_out = False) #pagination對象的items方法返回當前頁的內容列表 posts = pagination.items
has_next :是否還有下一頁
has_prev :是否還有上一頁
items : 返回當前頁的全部內容
next(error_out=False) : 返回下一頁的Pagination對象
prev(error_out=False) : 返回上一頁的Pagination對象
page : 當前頁的頁碼(從1開始)
pages : 總頁數
per_page : 每頁顯示的數量
prev_num : 上一頁頁碼數
next_num :下一頁頁碼數
query :返回 建立這個Pagination對象的查詢對象
total :查詢返回的記錄總數
iter_pages(left_edge=2, left_current=2, right_current=5, right_edge=2)
方法一:
{% macro render_pagination(pagination, endpoint) %} <div class=pagination> {%- for page in pagination.iter_pages() %} {% if page %} {% if page != pagination.page %} <a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a> {% else %} <strong>{{ page }}</strong> {% endif %} {% else %} <span class=ellipsis>…</span> {% endif %} {%- endfor %} </div> {% endmacro %}
方法二:jinjia2渲染+bootstrap模板
<!-- 建立頁碼--> <ul class="pagination"> {#上一頁#} {% if pagination.has_prev %} <li><a href="{{ url_for('UserAdmin',page=pagination.prev_num) }}">«</a></li> {% endif %} {#頁碼#} {% set page_now = pagination.page %} {% set page_count = pagination.pages %} {% if pagination.pages <= 5 %} {% for p in pagination.iter_pages() %} {% if p == pagination.page %} <li ><a style="background-color: darkgray;opacity: 0.7;color: black" href="{{ url_for('UserAdmin',page=p) }}">{{ p }}</a></li> {% else %} <li ><a href="{{ url_for('UserAdmin',page=p) }}">{{ p }}</a></li> {% endif %} {% endfor %} {% else %} {% if page_now-2 >0 %} <li><a href="{{ url_for('UserAdmin',page=page_now-2) }}">{{ page_now-2 }}</a></li> {% endif %} {% if page_now-1 >0 %} <li><a href="{{ url_for('UserAdmin',page=page_now-1) }}">{{ page_now-1 }}</a></li> {% endif %} <li ><a style="background-color: darkgray;opacity: 0.7;color: black" href="{{ url_for('UserAdmin',page=page_now) }}">{{ page_now }}</a></li> {% if (page_count-page_now) >1 %} <li><a href="{{ url_for('UserAdmin',page=page_now+1) }}">{{ page_now+1 }}</a></li> {% endif %} {% if (page_count - page_now) >2 %} <li><a href="{{ url_for('UserAdmin',page=page_now+1) }}">{{ page_now+2 }}</a></li> {% endif %} {% endif %} {#下一頁#} {% if pagination.has_next %} <li><a href="{{ url_for('UserAdmin',page=pagination.next_num) }}">»</a></li> {% endif %} <li><span style="color: black">頁數 ( {{ page_now }}/{{ page_count }} )</span></li> </ul>
效果展現:
常見的數據類型與配置
類型名稱 | python類型 | 描述 |
Integer | int | 常規×××,一般爲32位 |
SmallInteger | int | 短×××,一般爲16位 |
BigInteger | int或long | 精度不受限××× |
Float | float | 浮點數 |
Numeric | decimal.Decimal | 定點數 |
String | str | 可變長度字符串 |
Text | str | 可變長度字符串,適合大量文本 |
Unicode | unicode | 可變長度Unicode字符串 |
Boolean | bool | 布爾型 |
TIMESTAMP timestamp 日期加時間類型
Date | datetime.date | 日期類型 |
Time | datetime.time | 時間類型 |
Interval | datetime.timedelta | 時間間隔 |
Enum | str | 字符列表 |
PickleType | 任意Python對象 | 自動Pickle序列化 |
LargeBinary | str | 二進制 |
常見的SQLALCHEMY列選項
可選參數 | 描述 |
primary_key | 若是設置爲True,則爲該列表的主鍵 |
unique | 若是設置爲True,該列不容許相同值 |
index | 若是設置爲True,爲該列建立索引,查詢效率會更高 |
nullable | 若是設置爲True,該列容許爲空。若是設置爲False,該列不容許空值 |
default | 定義該列的默認值 |
關係選項: