您好,欢迎访问一九零五行业门户网

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

一、问题
这两天在学习使用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.1connection id: 9current database: web12306current user: root@localhostssl: not in usecurrent pager: stdoutusing outfile: ''using delimiter: ;server version: 5.1.73 source distributionprotocol version: 10connection: localhost via unix socketserver characterset: utf8db characterset: utf8client characterset: latin1conn. characterset: latin1unix 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, metadatafrom sqlalchemy.sql.expression import castfrom sqlalchemy.ext.compiler import compilesfrom 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()#将创建的数据库连接关联到这个sessionsession.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()
其它类似信息

推荐信息