You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:50:36