• SQLAlchemy通过models创建数据库表


    原地址:http://blog.csdn.net/jmilk/article/details/53184903

    定义数据模型 models

    SQLAlchemy 允许我们根据数据库的表结构来创建数据模型, 反之亦可. 所以我们一般无须手动的登录到数据库中使用 SQL 语句来创建表, 我们只需把数据模型定义好了之后, 表结构也就有了.

    • 首先要初始化 SQLAlchemy, 在 models.py 中把 app 对象 传入 SQLAlchemy :
      vim JmilkFan-s-Blog/models.py
    from flask.ext.sqlalchemy import SQLAlchemy             
    from main import app
    
    
    # INIT the sqlalchemy object                            
    # Will be load the SQLALCHEMY_DATABASE_URL from config.py
    # SQLAlchemy 会自动的从 app 对象中的 DevConfig 中加载连接数据库的配置项
    db = SQLAlchemy(app)

    db 是 class SQLAlchemy 的实例化对象, 包含了 SQLAlchemy 对数据库操作的支持类集.

    In [7]: db
    Out[7]: <SQLAlchemy engine='mysql+pymysql://root:fanguiju@127.0.0.1:3306/myblog?charset=utf8'>
    • 接下来, 我们就可以在 models.py 中定义 models 类了:
    class User(db.Model):
        """Represents Proected users."""
    
        # Set the name for table
        __tablename__ = 'users'
        id = db.Column(db.String(45), primary_key=True)
        username = db.Column(db.String(255))
        password = db.Column(db.String(255))
    
        def __init__(self, username):
            self.username = username
    
        def __repr__(self):
            """Define the string format for instance of User."""
            return "<Model User `{}`>".format(self.username)

    这样我们就得到了一个 User models, 该模型是基于 users 表的. 该数据表拥有 3 个字段 id/username/password 对应这由 class db.Column 实例化出来的 3 个对象, 当 class User 继承自 db.Model 时, SQLAlchemy 与 数据库的连接通过就已经自动的 Ready 了.

    • db.Column: 其构造器的第一个参数是可选的, 如果传入实参时, 表示创建的字段名. 反之, 则默认使用该实例化对象的名字(即 User 的类属性名); 第二个参数指定了字段的数据类型.

    • __init__(): 其实我们可以省略定义 class User 的构造器. 这样的话 SQLAlchemy 会自动帮我们创建构造器, 并且所有定义的字段名将会成为此构造器的关键字参数名. EXAMPLE:

    def __init__(self, id, username, password):
    • 1
    • __repr__(): 该方法返回一个对象的 字符串表达式. 与 __str__() 不同, 前者返回的是字符串表达式, 能被 eval() 处理;后者返回的是字符串, 不能被 eval() 处理得到原来的对象, 但与 print 语句结合使用时, 会被默认调用. 与 repr() 类似, 将对象转化为便于供 Python 解释器读取的形式, 返回一个可以用来表示对象的可打印字符串.
    In [15]:user = User('JMilkfan')
    
    In [16]:user
    <Model User `JMilkfan`>    
    # 直接调用对象实际上是隐式的调用了 User.__repr__(user) 
    # __repr__() 其定义了类实例化对象的可打印字符串表达式
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建表

    • 在创建表之间需要先创建数据库
    mysql -uroot -pfanguiju -e "CREATE DATABASE myblog default charset utf8 COLLATE utf8_general_ci;"
    mysql -uroot -pfanguiju -e "GRANT ALL ON myblog.* TO 'user'@'127.0.0.1' IDENTIFIED BY 'fanguiju';"
    mysql -uroot -pfanguiju -e "GRANT ALL ON myblog.* TO 'user'@'localhost' IDENTIFIED BY 'fanguiju';"
    mysql -uroot -pfanguiju -e "GRANT ALL ON myblog.* TO 'user'@'%' IDENTIFIED BY 'fanguiju';"

    指定数据库 myblog 的字符集为 utf8.

    • 然后, 我们仍然可以通过 manage.py 来添加创建数据库表的指令:
    # import Flask Script object
    from flask.ext.script import Manager, Server
    import main
    import models
    
    # Init manager object via app object
    manager = Manager(main.app)
    
    # Create some new commands
    manager.add_command("server", Server())
    
    @manager.shell
    def make_shell_context():
        """Create a python CLI.
    
        return: Default import object
        type: `Dict`
        """
        return dict(app=main.app,
                    db=models.db,
                    User=models.User)
    
    if __name__ == '__main__':
        manager.run()

    NOTE: 从现在开始我们每在 models.py 中新定义一个数据模型, 都需要在 manager.py 中导入并添加到返回 dict 中.

    这样我们就可以通过 manager 的 shell 指令行来进行数据库表的创建了:

    (blog)fanguiju@fanguiju:/opt/JmilkFan-s-Blog$ python manage.py shell
    >>> db.create_all()

    注意: 如果在进入 manager shell 时触发 ERROR 没有 flask.ext 这个模块的话, 应该检查 virtualenv 的环境是否正确, 是否有安装所需要的依赖包, 如果没有则执行:

    pip install -r requirements.txt
    • 1
    • 最后, 登录数据库验证数据表表是否由正确创建
    mysql> show tables;
    +------------------+
    | Tables_in_myblog |
    +------------------+
    | users            |
    +------------------+
    1 row in set (0.00 sec)
    
    mysql> desc users;
    +----------+--------------+------+-----+---------+-------+
    | Field    | Type         | Null | Key | Default | Extra |
    +----------+--------------+------+-----+---------+-------+
    | id       | varchar(45)  | NO   | PRI | NULL    |       |
    | username | varchar(255) | YES  |     | NULL    |       |
    | password | varchar(255) | YES  |     | NULL    |       |
    +----------+--------------+------+-----+---------+-------+
    3 rows in set (0.00 sec)

    以同样的方法我们可以创建所和需要的所有数据库表.

    问题:Flask中使用flask-sqlalchemy时db.create_all()无法创建表

    如题,我在学习《Flask Web开发:基于Python的Web应用开发实战》这本书第七章的时候,在shell中使用db.create_all()创建sqlite数据库。但是发现这个命令只能创建出sqlite文件,不能创建数据库table

    (venv) FlaskStudy$ python manage.py shell
    >>> from app import db
    >>> db.create_all()

    几次尝试过后,发现如果在执行db.create_all()前导入我创建的数据库模型,就能正常的创建出表了:

    (venv) FlaskStudy$ python manage.py shell
    >>> from app import db
    >>> from app.models import User, Role
    >>> db.create_all()

    或者在manage.py中导入数据库模型也可以:

    import os
    from app import create_app, db
    # 就是这一句
    from app.models import User, Role
    from flask.ext.script import Manager, Shell
    from flask.ext.migrate import Migrate, MigrateCommand
    
    app = create_app(os.getenv('FLASK_CONFIG') or 'default')
    manager = Manager(app)
    migrate = Migrate(app, db)
    
    manager.add_command('db', MigrateCommand)
    
    if __name__ == '__main__':
        manager.run()

    这是什么原理呢?求大神给讲解一下。

    刚刚看完第7章。我感觉你的manager.py有点问题,缺少shell上下文,所以说你打开的就是一个普通的shell, 并不可以直接使用 app里面的变量,必须手动import。 可以看看下面的代码,加上那几行代码就可以直接使用了。

    #!/usr/bin/env python
    
    from app import create_app, db
    from app.models import User, Role
    from flask.ext.script import Manager, Shell
    
    app = create_app()
    manager = Manager(app)
    
    
    def make_shell_context():
        return dict(app=app, db=db, User=User, Role=Role)
    
    manager.add_command("shell", Shell(make_context=make_shell_context))
    if __name__ == '__main__':
        manager.run()
    
  • 相关阅读:
    WEBSHELL跳板REDUH使用说明
    lcx.exe内网转发命令教程 + LCX免杀下载
    程序只启动一个实例的几种方法
    VS2010中遇到_WIN32_WINNT not defined
    VC编译错误: Nafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12已经在dllmain.obj 中定义
    python(31) enumerate 的用法
    利用余弦定理计算文本的相似度
    Linux命令(24) :sort
    python(30) 获取网页返回的状态码,状态码对应问题查询
    python(29)强大的zip函数
  • 原文地址:https://www.cnblogs.com/yanzi-meng/p/7873894.html
Copyright © 2020-2023  润新知