join & f.write 行为不符合预期

join & f.write behaviour not as expected

我在 SQL 中有一个查询 运行,它通过循环将结果返回到一个变量,然后将其放入 HTML 文件。当我通过在 Jupyter Notebook 中打印到控制台来测试它时,它按预期打印,日历的接下来 30 天按日期顺序打印。

但是,当我告诉它使用

加入数据时
dates = ''.join(variable)

它似乎不仅重新排列日期,使 8 月 13 日奇怪地位于 7 月 13 日之前,而且它在页面中重复日期 div 4 次。完整代码见下文;

from os import getenv
import pyodbc
import os

cnxn = pyodbc.connect('DRIVER={ODBC Driver 13 for SQL Server};SERVER=MYVM\SQLEXPRESS;DATABASE=MyTables;UID=test;PWD=t')

cursor = cnxn.cursor() #makes connection
cursor.execute('DECLARE @today as date SET @today = GetDate() SELECT style112, day, month, year, dayofweek, showroom_name, isbusy from ShowroomCal where Date Between @today and dateadd(month,1,@today) order by style112') #runs statement


while row is not None:
    inset = inset + ['<div class="'+ str(row.isbusy) + '"><a href="#" id="' + str(row.style112) + '" onclick="parent.updateField(field38, ' + str(row.style112) + ');">' + str(row.day) + '</a></div>']
    row = cursor.fetchone()



dates = ''.join(inset)    
f = open("C:\tes.html",'r') # open file with read permissions
filedata = f.read() # read contents
f.close() # closes file
filedata = filedata.replace("{inset}", dates) 

#os.remove("c:\inetpub\wwwroot\cal\tes.html")



f = open("c:\inetpub\wwwroot\cal\tes.html",'w') 
f.write(filedata) # update it replacing the previous strings 
f.close() # closes the file

cnxn.close()

''.join() 不会以任何方式改变顺序。如果您得到不同的顺序,那么 数据库查询 会以不同的顺序生成行。

我不认为您是在告诉数据库按日期对结果进行排序。您按 style112 排序,数据库可以自由地按照它喜欢的任何顺序对具有相同 style112 列值的值进行排序。如果style112不包含日期信息(固定长度的年月日序列)并且日期顺序很重要,告诉数据库使用正确的顺序!这里至少包括 year, month, day .

我还会重构代码以避免二次性能行为; inset = inset + [....] 表达式每次都必须创建一个新的列表对象,将 inset 中的所有元素和新列表复制到其中。以这种方式将 N 个元素添加到列表时,Python 必须执行 N * N 个步骤。对于 1000 个元素,需要执行 100 万步!使用list.append()添加单个元素,这会将工作量减少到大约N步。

您可以直接在游标上循环;这样效率更高,因为它可以缓冲行,这里 cursor.fetchone() 不能假设您会获取更多数据。 for row in cursor: 循环也更具可读性。

您还可以使用 string formatting 而不是字符串连接,这将有助于避免所有这些 str() 调用和冗余,并进一步减少性能问题;所有这些字符串连接还会创建和重新创建很多您根本不需要创建的中间字符串对象。

所以使用这个:

cnxn = pyodbc.connect(
    'DRIVER={ODBC Driver 13 for SQL Server};SERVER=MYVM\SQLEXPRESS;'
    'DATABASE=MyTables;UID=test;PWD=t')

cursor = cnxn.cursor()
cursor.execute('''
    DECLARE @today as date
    SET @today = GetDate()
    SELECT
        style112, day, month, year, dayofweek, showroom_name, isbusy
    from ShowroomCal
    where Date Between @today and dateadd(month,1,@today)
    order by year, month, day, style112
''')

inset = []
for row in cursor:
    inset.append(
        '<div class="{r.isbusy}">'
        '<a href="#" id="{r.style112}"'
        ' onclick="parent.updateField(field38, {r.style112});">'
        '{r.day}</a></div>'.format(r=row))

with open(r"C:\tes.html") as template:
    template = f.read()

html = template.format(inset=''.join(inset))

with open(r"C:\inetpub\wwwroot\cal\tes.html", 'w') as output:
    output.write(html)

注意:如果您的用户输入了您的任何数据库数据,您必须确保数据被正确转义以包含在内在 HTML first 中,否则你将对 XSS cross-site scripting attacks. Personally, I'd use a HTML templating engine with default escaping support, such as Jinja.

保持开放