一、问题
这两天在学习使用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,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',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()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。