FLASK数据库模型

云想衣裳花想容,春风拂槛露华浓。

SQLAlchemy 是一个基于 Python 实现的 ORM 库,是一种 面对对象 的数据库编程框架 (关系对象映射)。


快速入门文档

http://www.pythondoc.com/flask-sqlalchemy/quickstart.html


安装


扫描二维码关注公众号,回复: 12135359 查看本文章

pip install sqlalchemy


在 Flask 项目中的 URI 配置


class Config:
    SECRET_KEY ="abc_caonima_wocao" # 随机 SECRET_KEY
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True # 自动提交
    SQLALCHEMY_TRACK_MODIFICATIONS = True # 自动sql

    DEBUG = True # debug模式
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://%s:%s@%s:%s/%s' % (DB_USERNAME, DB_PASSWORD,DB_HOST, DB_PORT, DB_NAME) #数据库URL


在初始化项目中连接


app = Flask(__name__,template_folder='templates',static_folder='static')
app.config.from_object(Config)

db = SQLAlchemy(app)
db.init_app(app)


这样就把 数据库 和 Flask实例联系起来了,这里使用 Mysql


建立数据库模型


所谓数据库模型,说白了就是建立数据库中所需的具体字段,包括字段名称,类型,限制条件等等


比如在个人博客中,我们需要有文章列表,也需要有文章详情的数据库模型。


编写模型对象

class Article(db.Model):
        __tablename__ = 'article'
        id = db.Column(db.Integer, primary_key=True)
        title = db.Column(db.String(32))
        author = db.Column(db.String(32))
        img_url = db.Column(db.Text, nullable=False)
        content = db.Column(db.Text, nullable=False)
        tag = db.Column(db.String(64), nullable=True)
        uuid = db.Column(db.Text, nullable=False)
        create_time = db.Column(db.DateTime, nullable=True, default=datetime.now)
        uid = db.relationship('Article_Detail', backref='article')

        def __repr__(self):
            return '<Article %r>' % self.title


这样就实现了文章的数据库所需字段

id:数据库id,主键

title:文章标题,字符类型,后面声明长度

author:作者,字符类型

img_url:图片,text类型

content:文章简介

tag:所属标签

uuid:文章唯一标识id

create_time:创建时间,detatime类型

uid反向代理,通过关联的名称表可以得到 article表中的属性


Article_Detail模型

class Article_Detail(db.Model):
    __tablename__ = 'article_detail'
    id = db.Column(db.Integer, primary_key=True)
    d_content=db.Column(db.Text,nullable=False)
    uid = db.Column(db.Integer, db.ForeignKey('article.id'))

    def __repr__(self):
        return '<Article_Detail %r>' % self.title


id:数据库id,主键

d_content:详情文章内容,文本类型

uid外键,关联到 article 表 id


通过 relationship 和 ForeignKey 把文章和文章详情表联系起来,在编写文章详情的时候,通过 uid 选择是哪一篇文章的详情即可。


对于个人博客而言,模型的关联并没有很复杂,一般是 一对多 的操作就可以搞定,当然如果是论坛或者社区的话,会用到 多对一 和 多对多 的数据库操作 ,不做详细介绍。


增删改查


SQLAlchemy  之所以这么流行,在 Flask 中地位如此之高,基于它是面对对象的数据库编程。


所以,对于数据查询,添加等操作也是非常的简单。


查询文章列表:

@home.route('/')
def index():
    init_list= Article.query.order_by(db.desc(Article.create_time)).all()
    return render_template('home/index.html', datas=init_list)


可以看到,查询所有文章的语句,这里是按照创建的时间排序的,注意到desc(Article.create_time),然后将所得列表传给前端页面,渲染完成。


再来看看根据 id 查询文章详情内容的路由实现:

@home.route('/article/<uuid>')
def query_detail(uuid):
    base_path = os.path.abspath('app/templates/article/')
    old_file = os.listdir(base_path)[0]
    old_path = os.path.join(base_path, old_file)
    file_path = os.path.abspath('app/templates/article/{}.html'.format(uuid))
    if not os.path.exists(file_path):
        log_v.debug("[-] File does not exist, renaming !!!")
        os.rename(old_path, file_path)
    form = CommentForm()
    searchForm = SearchForm()
    article_res = Article.query.filter_by(uuid=uuid).first()
    article_detail_res = Article_Detail.query.filter_by(uid=article_res.id).first()
    return render_template('article/{}.html'.format(uuid), a_data=article_res, d_data=article_detail_res, form=form,
                           searchForm=searchForm)



思路设计:

    在templates模板目录中新建一个article 用于存放文章详情页的html文件,并且索引到这个目录中,在这个目录中只有一个 html 文件,我们只需要向这个html文件填入查询回来的数据即可。


    由于文章列表需要根据文章的 uuid 来跳转到详情页,所以这个 html文件的名称需要 rename 为跳转文章的 uuid,才能正确跳转。


    最后,根据 uuid 查询到文章,再由文章的 id 查询到详情文章内容,渲染到详情页。


是不是及其简单,所以前期的工作主要是数据库模型字段的设计,还有迁移到数据库中,也就是创建表,让其工作。


数据库迁移


使用 flask_migrate 扩展可以非常简单的进行数据库的迁移


# coding:utf8
from datetime import datetime
from flask_migrate import Migrate, MigrateCommand
from app import app
from app.models import db
from flask_script import Manager, Server

manage = Manager(app)

# 迁移
Migrate(app,db)
manage.add_command('db',MigrateCommand)

if __name__ == "__main__":
    manage.run()

'''
初始化
python manage.py db init

创建迁移
python manage.py db migrate

执行迁移
python manage.py db upgrade
'''


黑窗口  执行命令  python manage.py db init 


初始化数据库,执行之后会在主 app 目录中生成一个 migrations 目录,里面包含了一些创建的信息,如 版本号 和 操作脚本


然后执行  python manage.py db migrate

迁移数据库,在数据库中真正创建表字段


最后执行  python manage.py db upgrade  让其生效


PS:在往后的每一次更改数据库模型中的字段之后,只需要执行后两个命令即可。


关于数据库回滚


# -*- coding:utf-8 -*-
import os
from datetime import datetime
from sqlalchemy import or_
from app import app,db
from app.Logger.logger import log_v
from app.forms import CommentForm, SearchForm
from app.tools.getIdAddr import getAddr
from app.home.home import home
from flask import render_template, request, redirect
from app.models import Article, Article_Detail, Global_V, Comment,UserIP


@home.route('/postComment/<uuid>', methods=['GET', 'POST'])
def postComment(uuid):
    # app.config.update(SECRET_KEY=os.urandom(24))
    # log_v.debug("[*] UPDATE SECRET_KEY")
    log_v.debug("[+] Add Comment")

    form = CommentForm()
    # 字段必须完整
    if request.method == "POST" and form.validate_on_submit():
        theme = form.theme.data
        content = form.content.data
        email = form.email.data
        csrf_token = form.csrf_token.data
        t_md = request.form.get("t_md","")
        if all([theme, email, content, csrf_token, t_md]):
            try:
                add_comment = Comment(theme=theme, email=email, content=content, uuid=uuid)
                db.session.add(add_comment)
                db.session.commit()
                return "评论成功"
            except Exception as e:
                db.session.rollback()
                return "评论失败"

            finally:
                log_v.debug("Comment Done   " + theme + ' ' + ' ' + content + ' ' + email + ' ' + t_md)

        else:
            return "参数不齐"
    else:
        return redirect('/article/{}'.format(uuid))


数据库的回滚是十分有必要的,用于处理程序或者数据错误,让程序回到上一次的状态,这就是所谓的数据库回滚,否则很可能会造成死锁或者超时,这是非常可怕的。


所以,请回滚!!!

------------------- End -------------------


猜你喜欢

转载自blog.51cto.com/15069488/2578550