那些年咱们学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 | 定义该列的默认值 |
关系选项: