如何用Python结合HTML模板将用户输入打印至普通打印机(支票)
问题:如何将Python支票录入系统与HTML打印模板关联?
我正在开发一款用普通打印机打印银行支票的软件,已完成以下工作:
- 编写了带GUI的Python脚本,可收集用户输入并存储到MySQL数据库,也能在应用内调取展示
- 制作了匹配银行支票精确坐标的HTML模板
但完全不清楚如何将二者关联,实现把用户输入的内容填充到HTML模板并打印到银行支票上。
现有Python脚本代码
import PySimpleGUI as sg import mysql.connector # MySQL Connection dbms = mysql.connector.connect( host='127.0.0.1', user='root', password='password', database='app') myCursor = dbms.cursor() # Add some color to the window sg.theme('Default1') sg.set_options(font='Courier 16') RecordsData = [] myCursor.execute("SELECT * FROM app.inputs") for i in myCursor: RecordsData.append(list(i)) headersRecords = ['pay_to', 'amount_words', 'amount', 'address', 'purpose', 'drawer', 'issue_date', 'company'] # Functions to update new data on the display tables on refreshing def refresh_records(): dbms2 = mysql.connector.connect(host="127.0.0.1", user="root", password="password", database="app") myCursor2 = dbms2.cursor() data = [] myCursor2.execute("SELECT * FROM app.inputs;") for j in myCursor2: data.append(list(j)) window1['-table1-'].Update(values=data) sg.popup("Records Updated!") # Clearing from functions def clear_records(): for key in values: window1['pay_to'].update('') window1['amount_words'].update('') window1['amount'].update('') window1['address'].update('') window1['purpose'].update('') window1['drawer'].update('') window1['issue_date'].update('') window1['company'].update('') return None # Submitting functions def submit_records(): pay_to = values['pay_to'] if pay_to == '': sg.popup_error('Missing Pay_to') amount_words = values['amount_words'] if amount_words == '': sg.popup_error('Missing amount in words') amount = values['amount'] if amount == '': sg.popup_error('Missing amount') address = values['address'] if address == '': sg.popup_error('Missing address') purpose = values['purpose'] if purpose == '': sg.popup_error('Missing purpose') drawer = values['drawer'] if drawer == '': sg.popup_error('Missing drawer') issue_date = values['issue_date'] if issue_date == '': sg.popup_error('Missing issue_date') company = values['company'] if company == '': sg.popup_error('Missing company') else: try: # 修正:execute直接执行SQL,不需要再调用一次execute(command) myCursor.execute("INSERT INTO app.inputs (pay_to, amount_words, amount, address, purpose, drawer, issue_date, company) VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",(pay_to, amount_words, amount, address, purpose, drawer, issue_date, company)) dbms.commit() choice = sg.popup_ok_cancel("Please confirm entry") if choice == 'OK': clear_records() sg.popup_quick('records entered') else: sg.popup_ok('Edit Entry') except: sg.popup('Please check your inputs. Something is wrong!') # GUI Layout recordsTable_layout = [ [sg.T('RECORDS')], [sg.Table(headings=headersRecords, values=RecordsData, display_row_numbers=True, enable_events=True, justification='center', key='-table1-')], [sg.Button("Refresh Records", key='-refreshR-', expand_x=True)], [sg.Button("Exit", expand_x=True)] ] RecordsForm_layout = [ [sg.T('Records File')], [sg.T('pay_to'), sg.Push(), sg.I(size=(30, 5), key='pay_to')], [sg.T('amount_words'), sg.Push(), sg.I(size=(30, 5), key='amount_words')], [sg.T('amount'), sg.Push(), sg.I(size=(30, 5), key='amount')], [sg.T('address'), sg.Push(), sg.I(size=(30, 5), key='address')], [sg.T('purpose'), sg.Push(), sg.I(size=(30, 5), key='purpose')], [sg.T('drawer'), sg.Push(), sg.I(size=(30, 5), key='drawer')], [sg.T('issue_date'), sg.Push(), sg.I(size=(30, 5), key='issue_date')], [sg.T('company'), sg.Push(), sg.Combo(size=(30, 5), values=['Medivet', 'Agri-Master'], key='company')], [sg.Button('Submit', key='-submit-', expand_x=True), sg.Button('Clear', key='-clear-', expand_x=True), sg.Button('Exit', key='-exit-', expand_x=True)] ] main_layout = [ [sg.Button('View RECORDS', key='-viewR-')], [sg.Button('Enter RECORDS', key='-enterR-')], [sg.Button('Exit', key='-exit-')] ] window= sg.Window("Medivet Check", main_layout) # MAIN while True: event, values = window.read() if event in (sg.WIN_CLOSED, '-exit-'): break if event == '-viewR-': window1 = sg.Window("", recordsTable_layout) event, values = window1.read() if event == 'Exit': window1.close() if event == '-refreshR-': refresh_records() if event == '-enterR-': window1 = sg.Window("Records Form", RecordsForm_layout) event, values = window1.read() if event == '-submit-': submit_records() if event == '-clear-': clear_records() if event == '-exit-': window1.close() window.close()
现有HTML模板代码
<div class="check"> <div class="border"> <div class="container"> <div class="content"> <div class="one"> <div class="title"> <div class="number">DATE:| 15 | 12 | 2022|</div> <table class="add"> <td class="lines"><input type="text" PLACEHOLDER="PAY" name="address" size="13"></td> <tr> <td class="amountwords"><input type="text" PLACEHOLDER="AMOUNT IN WORDS" name="citystate" size="13"></td> <tr> </table> <table class="following"> <tr> <tr><td class="empty line"><input type="text" name="reason" placeholder="KHR" size="13"></td> </table> <table class="cookie"> <td class="half"><input type="text"Placeholder="Address again" name="drawdress" size="13"></td> <tr> <td class="half"><input type="text"Placeholder="REASON" name="reason" size="13"></td> </table> </div> </div> </div> </div> </div> </div>
解决方案
1. 修正Python脚本的核心bug
首先修复submit_records函数中的错误:原代码中myCursor.execute()返回None,后续的myCursor.execute(command)会导致报错,直接删除这一行即可。
2. 用Jinja2填充HTML模板(推荐)
Jinja2是轻量灵活的模板引擎,适合将数据库数据填充到HTML中。
步骤1:安装Jinja2
pip install jinja2
步骤2:修改HTML模板(适配Jinja2变量)
将HTML中的占位符替换为Jinja2变量语法,同时调整name属性与数据库字段对应,确保坐标不变:
<div class="check"> <div class="border"> <div class="container"> <div class="content"> <div class="one"> <div class="title"> <div class="number">DATE:| {{ issue_date.split('-')[2] }} | {{ issue_date.split('-')[1] }} | {{ issue_date.split('-')[0] }}|</div> <table class="add"> <td class="lines"><input type="text" value="{{ pay_to }}" size="13" readonly></td> <tr> <td class="amountwords"><input type="text" value="{{ amount_words }}" size="13" readonly></td> <tr> </table> <table class="following"> <tr> <tr><td class="empty line"><input type="text" value="{{ amount }}" size="13" readonly></td> </table> <table class="cookie"> <td class="half"><input type="text" value="{{ address }}" size="13" readonly></td> <tr> <td class="half"><input type="text" value="{{ purpose }}" size="13" readonly></td> </table> </div> </div> </div> </div> </div> </div>
注:添加
readonly防止输入框被编辑,确保打印内容固定。
步骤3:编写填充模板的Python函数
from jinja2 import Environment, FileSystemLoader def fill_check_template(record): # 加载当前目录下的HTML模板 env = Environment(loader=FileSystemLoader('.')) template = env.get_template('check_template.html') # 将数据库记录转为字典,匹配模板变量 record_dict = { 'pay_to': record[0], 'amount_words': record[1], 'amount': record[2], 'address': record[3], 'purpose': record[4], 'drawer': record[5], 'issue_date': record[6], 'company': record[7] } # 渲染模板生成填充后的HTML filled_html = template.render(record_dict) # 保存为本地文件 with open('filled_check.html', 'w', encoding='utf-8') as f: f.write(filled_html) return 'filled_check.html'
3. 实现打印功能
推荐用WeasyPrint将HTML转为PDF后打印,保证格式精确:
步骤1:安装WeasyPrint
pip install weasyprint
注:Windows/Linux可能需要额外安装系统依赖(如libpango1.0-0、libcairo2等)。
步骤2:编写打印函数
from weasyprint import HTML import subprocess import os def print_selected_check(record): # 填充模板得到HTML文件 html_file = fill_check_template(record) # 转换为PDF(格式更稳定) pdf_file = 'filled_check.pdf' HTML(html_file).write_pdf(pdf_file) # 调用系统打印命令 if os.name == 'nt': # Windows subprocess.run(['start', '/wait', pdf_file], shell=True) elif os.name == 'posix': # Linux/macOS subprocess.run(['lp', pdf_file])
4. 集成到现有GUI
在记录查看界面添加打印按钮,并处理打印事件:
修改记录表格布局
recordsTable_layout = [ [sg.T('RECORDS')], [sg.Table(headings=headersRecords, values=RecordsData, display_row_numbers=True, enable_events=True, justification='center', key='-table1-')], [sg.Button("Refresh Records", key='-refreshR-', expand_x=True), sg.Button("Print Selected", key='-print-', expand_x=True)], [sg.Button("Exit", expand_x=True)] ]
修改记录窗口的事件循环
if event == '-viewR-': window1 = sg.Window("Check Records", recordsTable_layout) while True: event_r, values_r = window1.read() if event_r in (sg.WIN_CLOSED, 'Exit'): window1.close() break if event_r == '-refreshR-': refresh_records() if event_r == '-print-': selected_rows = values_r['-table1-'] if not selected_rows: sg.popup_error('请选择一条记录') continue # 获取选中的记录 selected_record = RecordsData[selected_rows[0]] # 执行打印 print_selected_check(selected_record) sg.popup('打印任务已启动')
内容的提问来源于stack exchange,提问作者David Lightman
相关产品推荐
相关产品推荐

