• flask开发restful api系列(3)利用alembic进行数据库更改


      上面两章,主要讲基本的配置,今天我们来做一个比较有趣的东西,为每个客户加一个头像图片。如果我们图片保存在自己的服务器,对于服务器要求有点高,每次下载的时候,都会阻塞网络接口,要是1000个人同时访问这张图片,会彻底报废掉整个网络。如果你跟我一样,在小公司,没有自己专业的图片服务器,又想用图片,那就跟我一样,尝试着用七牛吧。这个真的是一款很不错云产品。

      首先,在model里加一个字段,

     1 # coding:utf-8
     2 from sqlalchemy import create_engine, ForeignKey, Column, Integer, String, Text, DateTime,\
     3     and_, or_, SmallInteger, Float, DECIMAL, desc, asc, Table, join, event
     4 from sqlalchemy.orm import relationship, backref, sessionmaker, scoped_session, aliased, mapper
     5 from sqlalchemy.ext.declarative import declarative_base
     6 from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
     7 from sqlalchemy.orm.collections import attribute_mapped_collection
     8 import datetime
     9 
    10 engine = create_engine("mysql://root:a12345678@127.0.0.1:3306/blog01?charset=utf8", pool_recycle=7200)
    11 
    12 Base = declarative_base()
    13 
    14 db_session = scoped_session(sessionmaker(autocommit=False,
    15                                          autoflush=False,
    16                                          bind=engine))
    17 
    18 Base.query = db_session.query_property()
    19 
    20 
    21 class User(Base):
    22     __tablename__ = 'user'
    23 
    24     id = Column('id', Integer, primary_key=True)
    25     phone_number = Column('phone_number', String(11), index=True)
    26     password = Column('password', String(30))
    27     nickname = Column('nickname', String(30), index=True, nullable=True)
    28     head_picture = Column('head_picture', String(100), default='')
    29     register_time = Column('register_time', DateTime, index=True, default=datetime.datetime.now)
    30 
    31 
    32 if __name__ == '__main__':
    33     Base.metadata.create_all(engine)

    增加好了以后,开始整合数据库。该怎么弄呢?flask建议我们,可以使用第三方插件,flask-migrate,其他它的底层就是用的alembic,既然我们知道,就可以直接用alembic。为什么直接用alembic呢?相信大家也看出来了,我这的代码跟其他的flask用sqlalchemy不一样,很多人都直接用flask-sqlalchemy插件,但我不太喜欢。因为这个会束缚着我,为什么要用flask,就是因为它自由,想怎么改就怎么改,以后要是在这个目录下,写点脚本,直接引用即可,没有必要一定要在current_app环境下。这个只是个人喜好,喜欢用flask-sqlalchemy的可以继续使用。

    首先安装alembic,由于之前安装过flask-migrate,所以直接使用apt-get install alembic就可以了。

    先在blog01目录下,

    alembic init my_migration

    这时候,会生成my_migration目录,这时候目录如下:

     这时候编辑一下alembic.ini,这是alembic的配置文件,基本只要修改一处就可以了。

    sqlalchemy.url = mysql://root:a12345678@127.0.0.1:3306/blog01?charset=utf8

    其实就是告诉alembic,我每次修改的时候,你去动哪个数据库

    接下来就是程序,alembic的脚本是放在env.py里面,其实也只是要修改一处,就是告诉alembic,我对应的orm用的是哪个引擎。

    按照正常情况下,我们只要加两行代码就够了,按照理想状况应该是这样

    from model import Base
    target_metadata = Base.metadata

    如果我们仅仅是这样,会出现导入错误,找不到包,它不知道你要怎么引用包,所以我们要把当前目录加入到环境变量中,使之全局可用。

    可是还是导入包错误,一定要把顶部的blog01也放在包里面,代价太大,不如按照标准方式,把所有文件放在app中。

    import os
    import sys
    root = os.path.dirname(__file__) + '/..'
    sys.path.append(root)
    
    from model import Base
    target_metadata = Base.metadata

    然后结构变成这样。


    运行终端,定位到blog01目录下,

    >>alembic revision --autogenerate -m 'add column head_picture'
    INFO  [alembic.runtime.migration] Context impl MySQLImpl.
    INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
    INFO  [alembic.autogenerate.compare] Detected added column 'user.head_picture'
      Generating /home/yudahai/PycharmProjects/blog01/my_migration/versions/9a12387b186_add_column_head_picture.py ... done

    生成编辑脚本,

    再运行

    >>alembic upgrade head

    就可以了,去数据库看看吧,已经多了一个头像列了。

    这边要多说一下,alembic可以增加,删除列,但对改变列有的不自动支持,需要自己稍微修改一下。下面我做一个试验,把head_picture从String(100)修改到String(120),首先我们检查一下数据库实际情况。

    mysql> show create table user;
    +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
    +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | user  | CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `phone_number` varchar(11) DEFAULT NULL,
      `password` varchar(30) DEFAULT NULL,
      `nickname` varchar(30) DEFAULT NULL,
      `register_time` datetime DEFAULT NULL,
      `head_picture` varchar(100) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `ix_user_nickname` (`nickname`),
      KEY `ix_user_phone_number` (`phone_number`),
      KEY `ix_user_register_time` (`register_time`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
    +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> 

    看上面的代码,head_picture是String(100),如果我们按照传统的办法,alembic是没法修改字段的,官方文档也介绍了,截取字段类型和修改字段名字,需要自己手写脚本。不要担心,其实非常非常简单。

    首先,还是把model.py里面的head_picture修改为120

        head_picture = Column('head_picture', String(120), default='')

    然后生成脚本

    $ alembic revision --autogenerate -m 'alter column head_picture string120'

    会生成这个脚本文件,打开它,看代码

    def upgrade():
        ### commands auto generated by Alembic - please adjust! ###
        pass
        ### end Alembic commands ###
    
    
    def downgrade():
        ### commands auto generated by Alembic - please adjust! ###
        pass
        ### end Alembic commands ###

    它什么都没写,这要我们自己写的,也非常非常容易。代码如下。

    from sqlalchemy.dialects import mysql
    
    def upgrade():
        ### commands auto generated by Alembic - please adjust! ###
        op.alter_column('user',  'head_picture', sa.String(length=120), existing_type=mysql.VARCHAR(120))
        ### end Alembic commands ###
    
    
    def downgrade():
        ### commands auto generated by Alembic - please adjust! ###
        op.alter_column('user',  'head_picture', sa.String(length=100), existing_type=mysql.VARCHAR(100))
        ### end Alembic commands ###

    看见没有,如果对mysql稍微熟悉一点,都知道什么意思,就是直接把varchar(100)换成varchar(120),如果以后降级,再换成varchar(100)。是不是非常简单,好了,执行这个脚本吧。

    $ alembic upgrade head

    检查一下效果

    mysql> show create table user;
    +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
    +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | user  | CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `phone_number` varchar(11) DEFAULT NULL,
      `password` varchar(30) DEFAULT NULL,
      `nickname` varchar(30) DEFAULT NULL,
      `register_time` datetime DEFAULT NULL,
      `head_picture` varchar(120) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `ix_user_nickname` (`nickname`),
      KEY `ix_user_phone_number` (`phone_number`),
      KEY `ix_user_register_time` (`register_time`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 |
    +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)

    看head_picture是不是变成120了,是不是很简单?好了,这一章就介绍到这,下一章,我们介绍如何通过七牛上传图片。

  • 相关阅读:
    需要学习的技术
    Building wheel for uwsgi (setup.py) ... error 解决问题
    version `ZLIB_1.2.3.4‘ not found 解决方法
    module 'tensorflow' has no attribute 'space_to_depth'(已解决)
    python语法—命名元祖、偏函数
    python—set集合比较(交集、并集,差集)
    websocket接口测试
    linux根目录扩容方法
    django—问题—中文编码格式报错 、分页warning
    python—使用sorted对字典进行排序
  • 原文地址:https://www.cnblogs.com/yueerwanwan0204/p/5330201.html
Copyright © 2020-2023  润新知