那些年咱们学Flask-SQLAlchemy,实现数据库操做,分页等功能

那些年咱们学Flask-SQLAlchemyhtml

实现数据库操做,分页等功能 python



Flask-SQLAlchemy库让flask更方便的使用SQLALchemy,是一个强大的关系形数据库框架,既可使用orm方式操做数据库,也可使用原始的SQL命令.mysql

Flask-Migrate 是一个数据迁移框架,须要经过Flask-script库来操做.web



一.配置Flask-SQLAlchemy

程序使用的数据库地址须要配置在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


pagination对象经常使用方法:

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) }}">&laquo;</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) }}">&raquo;</a></li>
    {% endif %}

    <li><span style="color: black">页数 ( {{ page_now }}/{{ page_count }} )</span></li>
</ul>


效果展现:

wKiom1gOOurSf9olAAAK6xH4iUE659.png

wKiom1gOOs-z9QPuAAAK6xH4iUE840.pngwKioL1gOOs-TWAuWAAAH7jdeSnQ274.png


常见的数据类型与配置



类型名称 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 定义该列的默认值

关系选项:

常见的SQLALCHEMY列类型.配置选项和关系选项

相关文章
相关标签/搜索