文档章节

flask使用SQLAlchemy操作mysql

鸿弟
 鸿弟
发布于 2016/11/09 23:20
字数 1205
阅读 103
收藏 1
点赞 0
评论 0

注意:看这篇博客需要先看我之前写的一篇博客,在 https://my.oschina.net/zhuangweihong/blog/780913 (flask获取远程服务器的硬件信息) 这篇博客中有提到,获取远程服务器的硬件信息可以入mysql数据库,现在来实现下。还实现了下分页的功能,如下截图:

 

首先应该了解下SQLAlchemy框架对mysql数据库的操作,使用SQLAlchemy,除了要安装SQLAlchemy外,还需要安装MySQL-python,安装完后看下代码:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://xxx:xxx@192.168.xxx.xxx/xxx'
db = SQLAlchemy(app)
#添加服务器
def server_add(server1):
    db.session.add(server1)
    db.session.commit()

#删除服务器
def server_delete(server1):
    db.session.delete(server1)
    db.session.commit()

#查询服务器(通过ip)
def server_query_from_ip(ip):
    server1 = server.Server.query.filter_by(ip = ip).first()
    return server1

#查询服务器(所有)
def server_query_all():
    server_all = server.Server.query.all()
    return server_all

#查询服务器(分页)
def server_query_page(page_now, page_size):
    server_page = server.Server.query.paginate(page_now, page_size, False)
    return server_page

db.session.add为插入操作,db.session.delete为删除操作,query相关的为查询操作。SQLAlchemy框架底层调用了MySQL-python,并进行封装,不用再使用sql语句对数据库进行操作了。上述代码有使用到一个server类,server类跟数据库的servers表相对应,server类的定义和表的定义如下:

class Server(db.Model):
    __tablename__ = 'servers'
    id = db.Column(db.Integer, primary_key=True)
    ip = db.Column(db.String(128), unique=True)
    hostname = db.Column(db.String(128))
    cpu = db.Column(db.Integer)
    memory = db.Column(db.Integer)
    load = db.Column(db.String(128))
    ulimit = db.Column(db.Integer)
    version = db.Column(db.String(128))
    selinux = db.Column(db.String(128))
CREATE TABLE `servers` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `ip` varchar(128) DEFAULT NULL,
  `hostname` varchar(128) DEFAULT NULL,
  `cpu` int(3) DEFAULT NULL,
  `memory` int(8) DEFAULT NULL,
  `load` varchar(128) DEFAULT NULL,
  `ulimit` int(9) DEFAULT NULL,
  `version` varchar(128) DEFAULT NULL,
  `selinux` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ip` (`ip`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8;

如上定义,基本可完成对数据的操作,但还有很多可优化的地方。

 

前端代码如下,现主要先分为两部分,一个是提交ip用来取ip的数据然后入库的,另外一个是分页展示服务器的硬件信息(分页的一些对象会在最后进行讲解):

{% extends "basic.html" %}
{% block page_content %}
    <form role="form" class="form-inline" method="post" action="/db/server/add">
        <textarea class="form-control" rows="1" name="searchip" placeholder="请输入ip"></textarea>
        <button type="submit" class="btn btn-default">提交</button>
    </form>

    <div style="height: 260px;">
        <table class="table table-bordered">
            <thead>
            <tr>
                <th>服务器ip</th>
                <th>主机名</th>
                <th>cpu内存</th>
                <th>负载</th>
                <th>资源数限制</th>
                <th>系统版本</th>
                <th>selinux状态</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            {% for server1 in object_list %}
                <tr>
                    <td>{{ server1.ip }}</td>
                    <td>{{ server1.hostname }}</td>
                    <td>{{ server1.cpu }}核{{ server1.memory }}M</td>
                    <td>{{ server1.load }}</td>
                    <td>{{ server1.ulimit }}</td>
                    <td>{{ server1.version }}</td>
                    <td>{{ server1.selinux }}</td>
                    <td><a href="/db/server/delete?ip={{ server1.ip }}"><span class="label label-warning">delete</span></a></td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
    </div>
    <ul class="pagination">
        {% if server_page.has_prev %}
            <li><a href="/db/server/query/page?page_now={{ server_page.prev_num }}">&laquo;</a></li>
        {% else %}
            <li class="disabled"><a href="#">&laquo;</a></li>
        {% endif %}

        {% for i in range(1, (server_page.pages + 1)) %}
            {% if i == server_page.page %}
                <li class="disabled"><a href="#">{{ i }}</a></li>
            {% else %}
                <li><a href="/db/server/query/page?page_now={{ i }}">{{ i }}</a></li>
            {% endif %}
        {% endfor %}

        {% if server_page.has_next %}
            <li><a href="/db/server/query/page?page_now={{ server_page.next_num }}">&raquo;</a></li>
        {% else %}
            <li class="disabled"><a href="#">&raquo;</a></li>
        {% endif %}
    </ul>
{% endblock %}

 

输入ip去提取服务器的硬件并入库的操作的代码如下(可输入多个ip,但ip不能重复,这个可以优化做个判断,如果ip已存在,就更新数据库的信息):

#服务器信息入库
@app.route('/db/server/add', methods=['GET', 'POST'])
def db_server_add():
    ip = []
    p = re.compile(r'(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)')
    if request.method == 'POST' and p.findall(request.form['searchip']):
        ip = p.findall(request.form['searchip'])
    for i in range(0, len(ip)):
        info = collect_info(ip[i], 'root', '/root/.ssh/id_rsa', 22)
        server1 = server.Server(ip=info['ip'], hostname = info['hostname'], cpu = info['cpuinfo'], memory = info['meminfo'],
                                 load=info['loadavg'], ulimit = info['ulimit'], version = info['release'], selinux = info['getenforce'])
        modules_db.server_add(server1)
    return render_template('200.html')

此代码就直接使用collect_info收集远程服务器的硬件信息,然后调用SQLAlchemy框架的db.session.add入库。

另外,SQLAlchemy框架把分页的功能弄得比较简单,SQLAlchemy框架自身把当前页,总页数等都进行了封装,分页的代码如下:

#服务器信息查询分页
@app.route('/db/server/query/page', methods=['GET', 'POST'])
def db_server_query_page():
    page_size = 6
    server_page = modules_db.server_query_page(1, page_size)
    page_now = request.values.get('page_now')
    if page_now:
        server_page = modules_db.server_query_page(int(page_now), page_size)
    object_list = server_page.items
    return render_template('db/db_server_query_page.html', object_list  = object_list, server_page = server_page)

SQLAlchemy框架的query.paginate有三个参数,第一个参数为当前页,第二个参数为每个页的数据,第三个参数为超出是否报错。返回的server_page里面包含有分页的信息等,如server_page.items代表的是当前页面的所有内容,需要在前端展示。再回到前端页面可以看到我有用到object_list把当前页面的内容进行展现;server_page.pages提取分页的总页数;server_page.has_prev判断是否有上页,如果有,点击显示上一页server_page.prev_num

目前实现都是先从网上查询到的一些知识,另外,SQLAlchemy官方文档应该有更具体的使用说明可以参考。

© 著作权归作者所有

共有 人打赏支持
鸿弟
粉丝 65
博文 51
码字总数 33082
作品 0
杭州
运维
[flask-SQLAlchemy]关于flask-SQLAlchemy的初级使用教程

鉴于网上关于flask-SQLAlchemy的实例使用教程参差不齐,于此写下工作学习过程中的使用过程,以便分享交流。 对于python关于flask有一定了解的高端玩家来说,请转至flask官方开发文档。 一.安...

yzy121403725 ⋅ 05/24 ⋅ 0

ORM、SQLAlchemy数据库操作

ORM介绍 背景: 用底层的sql写的话,相当于通过pymysql 游标的方式连接“http://blog.51cto.com/jacksoner/2113454 ”,为了避免把sql语句写死在代码里,有没有一种方法直接把原生sql封装好了...

jiekegz ⋅ 05/11 ⋅ 0

Python的Flask框架中前端通过筛选添加动态排序功能

使用flask框架的时,前端通过使用bootstrap的form结构添加多选功能,使用多选的选择时候返回一个筛选后的结果,这样想对结果排序就需要动态排序功能 方法一: 在SQL中非常简单,即语句SELECT ...

走马兰台 ⋅ 05/25 ⋅ 0

flask_sqlalchemy简单用法

说明   SQLAlchemy 是 Python 的 ORM 框架,它的理念是:数据库的量级和性能重要于对象集合,而对象集合的抽象又重要于表和行 1、安装 2.2、创建表文件

812374156 ⋅ 05/18 ⋅ 0

慕课网Flask高级编程实战-9.书籍交易模型(数据库事务、重写Flask中的对象)

9.1 鱼豆 我们的鱼书有一个经济系统,在上传一本书的时候,将获取0.5个鱼豆。赠送一个本书的时候,再获取1个鱼豆。索要一本书的时候,消耗一个鱼豆,其中赠送和索要书籍是用户之间鱼豆互相加...

Meet相识_bfa5 ⋅ 06/14 ⋅ 0

慕课网Flask高级编程实战-3.蓝图、模型与CodeFirst

3.1 应用、蓝图与视图函数 1.Flask的层级关系 Flask最上层是app核心对象 在这个核心对象上可以插入很多蓝图,这个蓝图是不能单独存在的,必须将app作为插板插入app 在每一个蓝图上,可以注册...

Meet相识_bfa5 ⋅ 06/04 ⋅ 0

CMS 内容管理框架 - PFCMS

PFCMS是一个免费开源的cms内容管理框架,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。PFCMS从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性...

@you ⋅ 06/19 ⋅ 0

Flask框架的学习与实战:实战小项目

昨天写了一篇flask开发环境搭建,今天继续,进行一个实战小项目-blog系统。 blog系统很简单,只有一个页面,然而麻雀虽小五脏俱全。这里目的不是为了做项目而做项目,这篇文章本意是通过这次...

yzy121403725 ⋅ 05/24 ⋅ 0

SQLAlchemy 学习(一)

最近用到比较多的Python,当然访问数据库不能用原生的模块直接写Sql语句,这样太累。找了一本SQLAlchemy的教材来研究,记下学习笔记把。 相关的代码的例子在: https://github.com/DoubleSpo...

lemonwater ⋅ 05/14 ⋅ 0

慕课网Flask高级编程实战-4.flask核心机制

4.1 flask中经典错误 working outside application context 在 3.8节我们通过的方式解决了working outside application context的错误,下面我们来深究,这个错误出现的具体原因是什么。 首先...

Meet相识_bfa5 ⋅ 06/04 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

ThreadPoolExecutor

ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

4rnold ⋅ 昨天 ⋅ 0

Java正无穷大、负无穷大以及NaN

问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

young_chen ⋅ 昨天 ⋅ 0

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 昨天 ⋅ 0

实验楼—MySQL基础课程-挑战3实验报告

按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

zhangjin7 ⋅ 昨天 ⋅ 0

VS2015配置并运行汇编(一步一步照图做)【vs2017的链接在最后】

x64: TITLE Add and Subtract (AddSub.asm) ; This program adds and subtracts 32-bit integers. ; Last update: 2/1/02 ;.MODEL flat,stdcall x64 not su......

simpower ⋅ 昨天 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 昨天 ⋅ 0

Java桌球小游戏

其实算不上一个游戏,就是两张图片,不停的重画,改变ball图片的位置。一个左右直线碰撞的,一个有角度碰撞的。 左右直线碰撞 package com.bjsxt.test;import javax.swing.*;import j...

森林之下 ⋅ 昨天 ⋅ 0

你真的明白RPC 吗?一起来探究 RPC 的实质

你真的明白RPC 吗?一起来探究 RPC 的实质 不论你是科班出身还是半路转行,这么优秀的你一定上过小学语文,那么对扩句和缩句你一定不陌生。缩句就是去除各种修饰提炼出一句话的核心,而不失基...

AI9o後 ⋅ 昨天 ⋅ 0

z-index设置失效?

今天碰到了一个问题,就是在给li设置提示框的时候,有用到遮罩效果,本来想把对应的出现在最顶层,可是不管将li设置的z-index值设为多大,li都没有出现在遮罩层之上。 我在网上查了z-index设...

IrisHunag ⋅ 昨天 ⋅ 0

CyclicBarrier、CountDownLatch以及Semaphore使用及其原理分析

CyclicBarrier、CountDownLatch以及Semaphore是Java并发包中几个常用的并发组件,这几个组件特点是功能相识很容易混淆。首先我们分别介绍这几个组件的功能然后再通过实例分析和源码分析其中设...

申文波 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部