Django执行PrintCSV视图时SQL Server提示master数据库登录失败如何解决
问题结论
该报错核心是代码逻辑错误导致,并非你配置的登录权限有问题,权限配置是正常的。
具体错误原因
- 拼接数据库连接串时错误使用了字典对象转字符串作为库名
你提前把获取到的数据库名存成了{'name': 库名}格式的字典,遍历的时候直接用str(x)拼接,得到的是"{'name': 'master'}"这种字符串,导致程序尝试打开一个名字叫'name': 'master'的不存在的数据库,直接触发登录失败报错。
- 拼接数据库连接串时错误使用了字典对象转字符串作为库名
- 连接串参数写法错误触发无效属性告警
SQL Server的ODBC驱动不支持单独写PORT=xxx参数,正确写法是把端口拼到SERVER字段后,格式为SERVER=IP,端口,你单独加的PORT参数就是报错里Invalid connection string attribute的来源。
- 连接串参数写法错误触发无效属性告警
- 查询用错了数据库连接对象
你遍历每个库的时候新建了connect连接对象,但执行查询的时候仍然用了最开始的cnxn连接(仅连了默认库),即使第一个问题解决,也查不到对应库的数据。
- 查询用错了数据库连接对象
- 字典取值方式错误
你把查询结果存成了键为Account、Balance的字典,但后续取值用了列表的索引写法rdict[0]、rdict[1],运行到这一步也会抛出KeyError报错。
- 字典取值方式错误
修正后的代码示例
import pyodbc import csv from django.http import HttpResponse def PrintCSV(request): # 获取所有数据库名 cnxn = pyodbc.connect('DRIVER={SQL Server};' 'SERVER=serverIP,port;' # 端口写到SERVER后面用逗号分隔 'UID=kyle_dev_ro;' 'PWD=password;') databaseName = 'SELECT name FROM sys.databases' cursor = cnxn.cursor() cursor.execute(databaseName) XdatabaseNames = cursor.fetchall() cursor.close() cnxn.close() # 用完就关连接 dbNames= [row[0] for row in XdatabaseNames] # 直接存库名字符串就行,不用转字典 # 初始化CSV response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="Avonlea_file.csv"' writer = csv.writer(response) writer.writerow(['Unit', 'Balance']) for db_name in dbNames: # 连接对应数据库 connect = pyodbc.connect('DRIVER={SQL Server};' 'SERVER=192.168.1.1,1433;' # 去掉单独的PORT参数 'Database=' + db_name + ';' # 直接用库名字符串 'UID=kyle_dev_ro;' 'PWD=fh$sa#8d#7F8Y3;') XaccAreas = " SELECT Account, DCBalance FROM [dbo].[Client] where iAgeingTermID = '3' AND DCBalance < 0 " cursor = connect.cursor() # 用当前库的连接创建游标 cursor.execute(XaccAreas) accAreas = cursor.fetchall() cursor.close() connect.close() for account, balance in accAreas: # 不需要转字典,直接用元组取值就行 writer.writerow([ '', db_name, '', ]) writer.writerow([ account, balance, ]) return response
额外注意事项
- 你可以根据实际需求调整CSV的行写入逻辑,现在的写法每个账户前面都会多写一行只有库名的空行,确认是否符合你的导出要求。
- 如果有不需要遍历的系统库(比如master、tempdb、model、msdb),可以在遍历dbNames的时候加过滤条件跳过,避免无意义的连接查询。
内容的提问来源于stack exchange,提问作者KyleStranger
相关产品推荐
相关产品推荐

