因为在FastAPI相关博客里没有搜到答案,于是分享出来~
最近在用FastAPI给App写一个简单的登录注册系统的API,明明注册请求的时候发送的中文没问题,但是登录后获取用户信息时,返回的就是乱码,如图
我的Sqlalchemy的Model写法如下:
class User(Base):
__tablename__ = "users"
id = 略
phone = 略
hashed_password = Column(String)
name = Column(String) # 此字段乱码
一共尝试了三种方案,其中第一种方案可行:
-
把
Column(String)
改为Column(NVARCHAR)
,可行,参考自《pymssql读取varchar字段中文显示乱码的问题分析》 - 修改排序规则为
Chinese_PRC_CI_AS
,但我之前已经设置了所以没用上,如有需要可参考《sqlserver乱码问题解决》 - 修改pymssql的url,在末尾加上字符集
?charset=utf8
,即create_engine('mssql+pymssql://username:password@hostname:port/dbname?charset=utf8')
,不可行
最后解释一下原理:为什么把Column(String)
改成把Column(NVARCHAR)
就可以?
因为,如果定义Model时用Column(String)
,实际的数据类型是VARCHAR(MAX)
;如果用Column(NVARCHAR)
,数据类型是NVARCHAR(MAX)
,如下图。
NVARCHAR与VARCHAR的区别:
- NVARCHAR:可变长度 Unicode 字符数据(所有的字符都用两个字节表示,即英文字符也是用两个字节表示,可解决题);通过查看源码,它继承的是Unicode类,而Unicode类是在String类基础上增加了一些参数。
- VARCHAR:可变长度非 Unicode 字符数据(英文字符1字节,中文字符2字节);通过查看源码,它继承的是String类。
# sqltypes.py
class Unicode(String):
__visit_name__ = "unicode"
def __init__(self, length=None, **kwargs):
kwargs.setdefault("_expect_unicode", True)
kwargs.setdefault("_warn_on_bytestring", True)
super(Unicode, self).__init__(length=length, **kwargs)
*关于VARCHAR和NVARCHAR,具体可参考这两篇:《varchar和Nvarchar区别》、《char、varchar、text和nchar、nvarchar、ntext的区别》
网友评论