Python的Flask框架中SQLAlchemy使用时的乱码问题解决

1289次阅读  |  发布于5年以前

一、问题

这两天在学习使用flask + SQLAlchemy 定制一个web查询页面的demo ,在测试时,发现查询到的结果显示乱码 。这里将解决方法记录下。

二、解决思路

1、flask 程序上定位

flask的文档中提到可以通过设置SQLALCHEMY_NATIVE_UNICODE来禁止使用SQLAlchemy默认的Unicode编码。有可能是SQLAlchemy默认的Unicode编码不是UTF-8,抱着这样的想法,在程序中指定了"SQLALCHEMY_NATIVE_UNICODE=False",执行程序,报错。

flask中还提到"use_native_unicode"为目标编码来指定编码方式,尝试将"db = SQLAlchemy(app)"改为"db = SQLAlchemy(app, use_native_unicode="utf8")"。这回虽然没报错,但还是乱码。

2、mysql 上定位

突然想到有可能是建表的时候,没有指定字符集,使用的是数据库默认的字符集的导致的。继续找了一段时间的如何指定建表时使用字符集的方法,未果。

数据库该不会使用的不是UTF-8吧?抱着这个想法,进入数据库,输入"status",在输出的信息上显示默认是latin-1。搞了半天,原来问题在这。


    mysql> status
    --------------
    mysql Ver 14.14 Distrib 5.1.73, for redhat-linux-gnu (x86_64) using readline 5.1
    Connection id:     9
    Current database:   web12306
    Current user:      root@localhost
    SSL:          Not in use
    Current pager:     stdout
    Using outfile:     ''
    Using delimiter:    ;
    Server version:     5.1.73 Source distribution
    Protocol version:    10
    Connection:       Localhost via UNIX socket
    Server characterset:  utf8
    Db   characterset:  utf8
    Client characterset:  latin1
    Conn. characterset:  latin1
    UNIX socket:      /var/lib/mysql/mysql.sock

3、解决问题

即然找到了,问题就在mysql 的my.cnf 上增加相关配置,并重启mysql 服务:


    # 进入mysql的配置文件目录
    cd /etc/mysql/
    # 编辑my.cnf配置文件
    vim my.cnf
    # 在文件中的[mysqld]下面增加一行内容
    character_set_server = utf8
    # 在[client]和[mysql]下面分别增加一行内容
    default-character-set = utf8
    # 保存。然后重启MySQL的服务,设置就生效了
    service mysqld restart

注:需要注意的是,之前已经存在的数据,在上面修改过后,通过mysql select查询时会是乱码,需要重新导入。

PS:Python下SQLAlchemy真的是super好用,不太了解的童鞋可以尝试一下下面这个MySQL的例子:


    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    from sqlalchemy.orm import mapper, sessionmaker

    __author__ = 'tan9le'

    from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData
    from sqlalchemy.sql.expression import Cast
    from sqlalchemy.ext.compiler import compiles
    from sqlalchemy.dialects.mysql import \
        BIGINT, BINARY, BIT, BLOB, BOOLEAN, CHAR, DATE, \
        DATETIME, DECIMAL, DECIMAL, DOUBLE, ENUM, FLOAT, INTEGER, \
        LONGBLOB, LONGTEXT, MEDIUMBLOB, MEDIUMINT, MEDIUMTEXT, NCHAR, \
        NUMERIC, NVARCHAR, REAL, SET, SMALLINT, TEXT, TIME, TIMESTAMP, \
        TINYBLOB, TINYINT, TINYTEXT, VARBINARY, VARCHAR, YEAR

    #表的属性描述对象
    metadata = MetaData()
    userTable = Table(
      "wzp_user",metadata,
      Column('user_id', Integer, primary_key=True),
      Column('user_name', VARCHAR(50), unique=True, nullable=False),
      Column('password', VARCHAR(40), nullable=True)
    )
    #创建数据库连接,MySQLdb连接方式
    mysql_db = create_engine('mysql://用户名:密码@ip:port/dbname')
    #创建数据库连接,使用 mysql-connector-python连接方式
    #mysql_db = create_engine("mysql+mysqlconnector://用户名:密码@ip:port/dbname")
    #生成表
    metadata.create_all(mysql_db)


    #创建一个映射类
    class User(object):
      pass
    #把表映射到类
    mapper(User, userTable)
    #创建了一个自定义了的 Session类
    Session = sessionmaker()
    #将创建的数据库连接关联到这个session
    Session.configure(bind=mysql_db)
    session = Session()


    def main():
      u = User()
      #给映射类添加以下必要的属性,因为上面创建表指定这个字段不能为空,且唯一
      u.user_name='tan9le测试'
      #按照上面创建表的相关代码,这个字段允许为空
      u.password='123456'
      #在session中添加内容
      session.add(u)
      #保存数据
      session.flush()
      #数据库事务的提交,sisson自动过期而不需要关闭
      session.commit()

      #query() 简单的理解就是select() 的支持 ORM 的替代方法,可以接受任意组合的 class/column 表达式
      query = session.query(User)
      #列出所有user
      print list(query)
      #根据主键显示
      print query.get(1)
      #类似于SQL的where,打印其中的第一个
      print query.filter_by(user_name='tan9le测试').first()
      u = query.filter_by(user_name='tan9le测试').first()
      #修改其密码字段
      u.password = '654321'
      #提交事务
      session.commit()
      #打印会出现新密码
      print query.get(1).password
      #根据id字段排序,打印其中的用户名和密码
      for instance in session.query(User).order_by(User.user_id):
        print instance.user_name, instance.password
      #释放资源
      session.close()



    if __name__ == '__main__':
      main()

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8