django form 验证end_time不小于start_time

本文介绍了一种在Django中验证表单字段的方法,确保结束时间end_time不会早于开始时间start_time。通过覆写clean_end_time方法并检查两个时间字段的关系来实现这一目的。

django from  验证end_time不小于start_time:

    def clean_end_time(self):
        start_time = self.cleaned_data.get('start_time')
        end_time = self.cleaned_data['end_time']

        if start_time and end_time:
            if end_time <= start_time:
                raise forms.ValidationError("error.")
        return end_time


import os import time import threading import csv from datetime import datetime, timedelta import tkinter as tk from tkinter import messagebox from pynput import mouse, keyboard import pandas as pd import openpyxl from openpyxl import Workbook from openpyxl.styles import Font, PatternFill from openpyxl.utils import get_column_letter import sys import winshell from win32com.client import Dispatch import ctypes import psutil import win32event import win32api import winerror import json import hashlib # 定义基础无操作时间常量 FIRST_LOCK_LIMIT = 5 # 首次锁定的无操作时间(秒) LOCK_LIMIT = 30 # 后续锁定的无操作时间(秒) # 添加报表文件保护密码 REPORT_PASSWORD = "123" # 用于保护生成的Excel文件 REPORT_DIR = "D:/Users/x00707/LCZ_Machine_Time/LCZ_Machine_Time/UseTime_Summary/" REPORT_FILE_PREFIX = "UseTime_Summary_" # 修改为前缀格式 CONFIG_VERSION = "1.6" # 更新版本号 USER_DATA_FILE = "user_data.json" # 添加默认用户列表(包括两个普通账号) DEFAULT_USERS = { "admin": {"password": "123", "role": "admin"}, "001": {"password": "123", "role": "user"}, "002": {"password": "123", "role": "user"}, "102": {"password": "123", "role": "user"} } last_activity_time = time.time() is_locked = False session_start_time = None current_date = datetime.now().date() lock_window = None app_running = True daily_usage = {} first_run = False current_user = None lock_count = 0 # 记录本次启动后的锁定次数 mutex_name = "Global\\MachineTimeMonitor" mutex = win32event.CreateMutex(None, False, mutex_name) last_error = win32api.GetLastError() if last_error == winerror.ERROR_ALREADY_EXISTS: sys.exit(0) def get_inactivity_limit(): global lock_count return FIRST_LOCK_LIMIT if lock_count == 0 else LOCK_LIMIT def hash_password(password): return hashlib.sha256(password.encode()).hexdigest() def load_user_data(): """加载用户数据,自动添加缺失的默认用户""" if os.path.exists(USER_DATA_FILE): try: with open(USER_DATA_FILE, 'r') as f: user_data = json.load(f) except: # 文件损坏时创建默认用户数据 user_data = create_default_user() else: # 文件存在时创建默认用户数据 user_data = create_default_user() # 检查并添加缺失的默认用户 updated = False for username, user_info in DEFAULT_USERS.items(): if username not in user_data["users"]: # 添加缺失的用户 user_data["users"][username] = { "password": hash_password(user_info["password"]), "role": user_info["role"], "first_login": True } updated = True if updated: save_user_data(user_data) # 保存更新后的用户数据 return user_data def create_default_user(): """创建默认用户,使用全局 DEFAULT_USERS""" default_user = {"users": {}} for username, user_info in DEFAULT_USERS.items(): default_user["users"][username] = { "password": hash_password(user_info["password"]), "role": user_info["role"], "first_login": True } save_user_data(default_user) return default_user def save_user_data(user_data): with open(USER_DATA_FILE, 'w') as f: json.dump(user_data, f, indent=2) def add_user(username, password, role="user"): user_data = load_user_data() if username in user_data["users"]: return False, "用户已存在" user_data["users"][username] = {"password": hash_password(password), "role": role, "first_login": True} save_user_data(user_data) return True, "用户添加成功" def change_password(username, old_password, new_password): user_data = load_user_data() if username not in user_data["users"]: return False, "用户存在" user = user_data["users"][username] if user["password"] != hash_password(old_password): return False, "原密码正确" user["password"] = hash_password(new_password) user["first_login"] = False save_user_data(user_data) return True, "密码修改成功" def authenticate(username, password): user_data = load_user_data() if username not in user_data["users"]: return False, "用户存在", None user = user_data["users"][username] if user["password"] != hash_password(password): return False, "密码正确", None return True, "登录成功", user["role"] def create_shortcut(): startup_folder = winshell.startup() shortcut_path = os.path.join(startup_folder, "MachineTimeMonitor.lnk") current_script = os.path.abspath(__file__) if not os.path.exists(shortcut_path) or not is_shortcut_current(shortcut_path, current_script): target = sys.executable wDir = os.path.dirname(current_script) shell = Dispatch('WScript.Shell') shortcut = shell.CreateShortCut(shortcut_path) shortcut.Targetpath = target shortcut.Arguments = f'"{current_script}"' shortcut.WorkingDirectory = wDir shortcut.IconLocation = sys.executable shortcut.Description = f"机台监控 v{CONFIG_VERSION}" shortcut.save() def is_shortcut_current(shortcut_path, current_script): try: shell = Dispatch('WScript.Shell') shortcut = shell.CreateShortCut(shortcut_path) return shortcut.Arguments == f'"{current_script}"' except: return False def terminate_existing_instances(): current_pid = os.getpid() current_script = os.path.basename(__file__) for proc in psutil.process_iter(['pid', 'name', 'cmdline']): try: if proc.info['name'].lower() in ['python.exe', 'pythonw.exe']: cmdline = proc.info['cmdline'] if (cmdline and len(cmdline) > 1 and current_script in cmdline[1] and proc.info['pid'] != current_pid): proc.terminate() time.sleep(0.5) except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): pass def load_historical_data(): """从 Excel 报表文件加载历史数据""" global daily_usage daily_usage.clear() if not os.path.exists(REPORT_DIR): return # 遍历报表目录下的所有 Excel 文件 for filename in os.listdir(REPORT_DIR): if filename.startswith(REPORT_FILE_PREFIX) and filename.endswith(".xlsx"): try: wb = openpyxl.load_workbook(os.path.join(REPORT_DIR, filename)) if "Session Details" in wb.sheetnames: ws = wb["Session Details"] # 从第二行开始读取数据(跳过标题行) for row in range(2, ws.max_row + 1): date_str = ws.cell(row, 1).value # A列:Date user = ws.cell(row, 2).value # B列:Account duration = ws.cell(row, 5).value # E列:Duration(min) if date_str and user and duration: user_key = f"{date_str}_{user}" daily_usage[user_key] = daily_usage.get(user_key, 0) + float(duration) except Exception as e: print(f"加载历史数据时出错({filename}): {e}") def log_session(start_time, end_time, user): """记录会话并生成使用时间报表""" # 处理跨天使用的情况 current_day = start_time.date() end_day = end_time.date() if current_day == end_day: # 记录单日使用情况 duration = (end_time - start_time).total_seconds() / 60 date_str = start_time.strftime("%Y-%m-%d") start_str = start_time.strftime("%H:%M:%S") end_str = end_time.strftime("%H:%M:%S") # 更新每日使用时间 user_key = f"{date_str}_{user}" daily_usage[user_key] = daily_usage.get(user_key, 0) + duration # 生成/更新当天的使用时间报表 generate_daily_report(current_day, [ [date_str, user, start_str, end_str, f"{duration:.1f}"] ]) else: # 处理跨天使用的情况(第一天部分) day1_end = datetime.combine(start_time.date(), datetime.max.time()).replace(microsecond=0) duration1 = (day1_end - start_time).total_seconds() / 60 date_str1 = start_time.strftime("%Y-%m-%d") start_str1 = start_time.strftime("%H:%M:%S") end_str1 = day1_end.strftime("%H:%M:%S") # 第二天部分 day2_start = datetime.combine(end_time.date(), datetime.min.time()) duration2 = (end_time - day2_start).total_seconds() / 60 date_str2 = end_time.strftime("%Y-%m-%d") start_str2 = day2_start.strftime("%H:%M:%S") end_str2 = end_time.strftime("%H:%M:%S") # 更新每日使用时间 user_key1 = f"{date_str1}_{user}" user_key2 = f"{date_str2}_{user}" daily_usage[user_key1] = daily_usage.get(user_key1, 0) + duration1 daily_usage[user_key2] = daily_usage.get(user_key2, 0) + duration2 # 生成/更新两天的使用时间报表 generate_daily_report(start_time.date(),[[date_str1, user, start_str1, end_str1, f"{duration1:.1f}"]]) generate_daily_report(end_time.date(), [[date_str2, user, start_str2, end_str2, f"{duration2:.1f}"]]) def generate_daily_report(report_date, new_records=None): """生成每日使用时间报表,添加 Date 列""" # 提取年份和月份(格式化为两位数) year_str = report_date.strftime("%Y") month_str = report_date.strftime("%m") # 创建年/月子目录路径 report_path = os.path.join(REPORT_DIR, year_str, month_str) # 确保年/月目录存在 os.makedirs(report_path, exist_ok=True) # 创建完整的文件路径 date_str = report_date.strftime("%Y%m%d") report_filename = os.path.join(report_path, f"{REPORT_FILE_PREFIX}{date_str}.xlsx") try: # 如果文件已存在,加载现有工作簿 if os.path.exists(report_filename): wb = openpyxl.load_workbook(report_filename) ws1 = wb["Session Details"] if "Session Details" in wb.sheetnames else wb.create_sheet("Session Details") ws2 = wb["Daily Summary"] if "Daily Summary" in wb.sheetnames else wb.create_sheet("Daily Summary") else: # 创建新工作簿 wb = Workbook() ws1 = wb.active ws1.title = "Session Details" # 添加包含 Date 列的表头 ws1.append(['Date', 'Account', 'StartTime', 'EndTime', 'Duration(min)']) ws2 = wb.create_sheet("Daily Summary") ws2.append(['Account', 'UseTime(minutes)', 'UseTime(hours)']) # 添加新记录(如果有) if new_records: for record in new_records: ws1.append(record) # 处理详细使用记录 user_totals = {} # 从第二行开始读取现有数据(跳过标题行) for row in range(2, ws1.max_row + 1): user = ws1.cell(row, 2).value # B列:Account duration = ws1.cell(row, 5).value # E列:Duration(min) if user and duration: try: # 确保持续时间是数字 duration_val = float(duration) user_totals[user] = user_totals.get(user, 0) + duration_val except (ValueError, TypeError): pass # 清除旧汇总数据(保留标题行) if ws2.max_row > 1: ws2.delete_rows(2, ws2.max_row - 1) # 生成每日汇总 for user, total_minutes in user_totals.items(): ws2.append([user, total_minutes, f"{total_minutes / 60:.2f}"]) # 应用样式 for ws in [ws1, ws2]: for col in ws.columns: max_length = 0 column_letter = get_column_letter(col[0].column) for cell in col: try: if len(str(cell.value)) > max_length: max_length = len(str(cell.value)) except: pass adjusted_width = (max_length + 2) * 1.2 ws.column_dimensions[column_letter].width = adjusted_width # 设置标题样式 header_fill = PatternFill(start_color="4F81BD", end_color="4F81BD", fill_type="solid") header_font = Font(color="FFFFFF", bold=True) for row in ws.iter_rows(min_row=1, max_row=1): for cell in row: cell.fill = header_fill cell.font = header_font # 保存报表 # 设置工作簿保护密码 wb.security = openpyxl.workbook.protection.WorkbookProtection( workbookPassword=REPORT_PASSWORD, lockStructure=False, # 允许修改工作表结构 lockWindows=False # 允许调整窗口大小 ) wb.security.set_workbook_password(REPORT_PASSWORD) # 设置每个工作表的保护 for ws in wb.worksheets: ws.protection.set_password(REPORT_PASSWORD) ws.protection.sheet = True ws.protection.enable() # 保存报表(原有代码) wb.save(report_filename) print(f"已更新日报表: {report_filename}") except Exception as e: print(f"生成每日报表时出错: {e}") def show_change_password_window(parent, username): change_pw_window = tk.Toplevel(parent) change_pw_window.title("修改密码") change_pw_window.geometry("400x300") change_pw_window.resizable(False, False) change_pw_window.grab_set() change_pw_window.transient(parent) change_pw_window.configure(bg="#2c3e50") window_width = 400 window_height = 300 screen_width = change_pw_window.winfo_screenwidth() screen_height = change_pw_window.winfo_screenheight() x = (screen_width - window_width) // 2 y = (screen_height - window_height) // 2 change_pw_window.geometry(f"{window_width}x{window_height}+{x}+{y}") frame = tk.Frame(change_pw_window, bg="#34495e", padx=20, pady=20) frame.pack(fill="both", expand=True, padx=20, pady=20) tk.Label(frame, text=f"修改密码 - {username}", bg="#34495e", fg="#ecf0f1", font=("Arial", 14, "bold")).grid(row=0, column=0, columnspan=2, pady=(0, 15)) tk.Label(frame, text="原密码:", bg="#34495e", fg="#ecf0f1", font=("Arial", 12)).grid(row=1, column=0, sticky="e", pady=5) old_pw_var = tk.StringVar() old_pw_entry = tk.Entry(frame, textvariable=old_pw_var, show="*", font=("Arial", 12), width=20) old_pw_entry.grid(row=1, column=1, padx=10, pady=5) tk.Label(frame, text="新密码:", bg="#34495e", fg="#ecf0f1", font=("Arial", 12)).grid(row=2, column=0, sticky="e", pady=5) new_pw_var = tk.StringVar() new_pw_entry = tk.Entry(frame, textvariable=new_pw_var, show="*", font=("Arial", 12), width=20) new_pw_entry.grid(row=2, column=1, padx=10, pady=5) tk.Label(frame, text="确认新密码:", bg="#34495e", fg="#ecf0f1", font=("Arial", 12)).grid(row=3, column=0, sticky="e", pady=5) confirm_pw_var = tk.StringVar() confirm_pw_entry = tk.Entry(frame, textvariable=confirm_pw_var, show="*", font=("Arial", 12), width=20) confirm_pw_entry.grid(row=3, column=1, padx=10, pady=5) status_var = tk.StringVar() status_label = tk.Label(frame, textvariable=status_var, bg="#34495e", fg="#e74c3c", font=("Arial", 10)) status_label.grid(row=4, column=0, columnspan=2, pady=5) def change_password_action(): old_pw = old_pw_var.get() new_pw = new_pw_var.get() confirm_pw = confirm_pw_var.get() if not old_pw or not new_pw or not confirm_pw: status_var.set("所有字段都必须填写") return if new_pw != confirm_pw: status_var.set("新密码和确认密码匹配") return success, message = change_password(username, old_pw, new_pw) if success: messagebox.showinfo("成功", message, parent=change_pw_window) change_pw_window.destroy() else: status_var.set(message) button_frame = tk.Frame(frame, bg="#34495e") button_frame.grid(row=5, column=0, columnspan=2, pady=(10, 0)) change_btn = tk.Button(button_frame, text="修改密码", command=change_password_action, bg="#3498db", fg="white", font=("Arial", 12), padx=15, pady=5, bd=0) change_btn.pack(side="left", padx=10) cancel_btn = tk.Button(button_frame, text="取消", command=change_pw_window.destroy, bg="#95a5a6", fg="white", font=("Arial", 12), padx=15, pady=5, bd=0) cancel_btn.pack(side="left", padx=10) change_pw_window.bind("<Return>", lambda event: change_password_action()) old_pw_entry.focus_set() def show_lock_window(): global lock_window lock_window = tk.Tk() # 添加以下代码确保窗口获得焦点 lock_window.focus_force() lock_window.grab_set_global() # 捕获所有输入事件 lock_window.after(100, lambda: username_entry.focus_force()) # 延迟100ms确保焦点设置成功 lock_window.title("机台已锁定") lock_window.attributes("-fullscreen", True) lock_window.attributes("-topmost", True) lock_window.configure(bg="#2c3e50") lock_window.option_add("*Font", "Arial 14") main_frame = tk.Frame(lock_window, bg="#2c3e50") main_frame.pack(fill="both", expand=True) center_frame = tk.Frame(main_frame, bg="#34495e", padx=40, pady=40) center_frame.place(relx=0.5, rely=0.5, anchor="center") tk.Label(center_frame, text="机台已锁定", bg="#34495e", fg="#ecf0f1", font=("Arial", 24, "bold")).grid(row=0, column=0, columnspan=2, pady=(0, 20)) tk.Label(center_frame, text="检测到机台长时间未使用", bg="#34495e", fg="#bdc3c7", font=("Arial", 14)).grid(row=1, column=0, columnspan=2, pady=(0, 10)) tk.Label(center_frame, text="账号:", bg="#34495e", fg="#ecf0f1", font=("Arial", 14)).grid(row=2, column=0, padx=5, pady=10, sticky="e") username_var = tk.StringVar() username_entry = tk.Entry(center_frame, textvariable=username_var, font=("Arial", 14), width=20) username_entry.grid(row=2, column=1, padx=5, pady=10, sticky="w") username_entry.focus() tk.Label(center_frame, text="密码:", bg="#34495e", fg="#ecf0f1", font=("Arial", 14)).grid(row=3, column=0, padx=5, pady=10, sticky="e") password_var = tk.StringVar() password_entry = tk.Entry(center_frame, textvariable=password_var, show="*", font=("Arial", 14), width=20) password_entry.grid(row=3, column=1, padx=5, pady=10, sticky="w") status_var = tk.StringVar() status_label = tk.Label(center_frame, textvariable=status_var, bg="#34495e", fg="#e74c3c", font=("Arial", 12)) status_label.grid(row=4, column=0, columnspan=2, pady=10) button_frame = tk.Frame(center_frame, bg="#34495e") button_frame.grid(row=5, column=0, columnspan=2, pady=(20, 10)) def attempt_unlock(): username = username_var.get() password = password_var.get() if not username or not password: status_var.set("账号和密码能为空") return success, message, role = authenticate(username, password) if success: user_data = load_user_data() if user_data["users"][username]["first_login"]: show_change_password_window(lock_window, username) status_var.set("首次登录,请修改密码") return unlock(username) lock_window.destroy() else: status_var.set(message) # 登录失败后重新聚焦到账号输入框 username_entry.focus_force() def change_password_action(): username = username_var.get() if not username: status_var.set("请先输入账号") return user_data = load_user_data() if username not in user_data["users"]: status_var.set("用户存在") return show_change_password_window(lock_window, username) login_btn = tk.Button(button_frame, text="登录", command=attempt_unlock, bg="#3498db", fg="white", font=("Arial", 14), padx=20, pady=5, bd=0) login_btn.pack(side="left", padx=10) change_pw_btn = tk.Button(button_frame, text="修改密码", command=change_password_action, bg="#f39c12", fg="white", font=("Arial", 14), padx=20, pady=5, bd=0) change_pw_btn.pack(side="left", padx=10) password_entry.bind("<Return>", lambda event: attempt_unlock()) tk.Label(main_frame, text=f"机台使用时间监控系统 v{CONFIG_VERSION}", bg="#2c3e50", fg="#7f8c8d", font=("Arial", 10)).pack(side="bottom", pady=10) lock_window.protocol("WM_DELETE_WINDOW", lambda: None) lock_window.mainloop() def unlock(username): global is_locked, session_start_time, last_activity_time, current_user is_locked = False session_start_time = datetime.now() last_activity_time = time.time() current_user = username print(f"用户 {username} 已解锁") def on_activity(): global last_activity_time last_activity_time = time.time() def activity_monitor(): global is_locked, session_start_time, current_date, current_user, lock_count while app_running: today = datetime.now().date() if today != current_date: # 新的一天开始,生成前一天的报表 generate_daily_report(current_date) current_date = today inactivity_limit = get_inactivity_limit() inactive_time = time.time() - last_activity_time if inactive_time > inactivity_limit and not is_locked: lock_count += 1 is_locked = True if session_start_time and current_user: end_time = datetime.now() print(f"记录会话: {current_user} 从 {session_start_time} 到 {end_time}") log_session(session_start_time, end_time, current_user) session_start_time = None current_user = None show_lock_window() time.sleep(1) def start_listeners(): mouse_listener = mouse.Listener(on_move=lambda x, y: on_activity(), on_click=lambda x, y, button, pressed: on_activity()) keyboard_listener = keyboard.Listener(on_press=lambda key: on_activity()) mouse_listener.start() keyboard_listener.start() return mouse_listener, keyboard_listener def hide_console(): if sys.platform == "win32": console_window = ctypes.windll.kernel32.GetConsoleWindow() if console_window: ctypes.windll.user32.ShowWindow(console_window, 0) def is_running_as_background(): try: parent_pid = psutil.Process(os.getpid()).ppid() parent_name = psutil.Process(parent_pid).name().lower() return parent_name == "explorer.exe" except: return False def main(): global session_start_time, app_running, first_run, lock_count terminate_existing_instances() if not ctypes.windll.shell32.IsUserAnAdmin(): ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, f'"{__file__}"', None, 1) sys.exit() hide_console() create_shortcut() os.makedirs(REPORT_DIR, exist_ok=True) load_historical_data() first_run = not any( f.startswith(REPORT_FILE_PREFIX) and f.endswith(".xlsx") for f in os.listdir(REPORT_DIR) ) monitor_thread = threading.Thread(target=activity_monitor, daemon=True) monitor_thread.start() mouse_listener, keyboard_listener = start_listeners() session_start_time = datetime.now() if first_run: root = tk.Tk() root.withdraw() messagebox.showinfo("启动成功", "机台使用时间监控系统已成功启动!") root.destroy() try: import pystray from PIL import Image def exit_action(icon, item): global app_running app_running = False icon.stop() sys.exit() def show_info(): root = tk.Tk() root.withdraw() messagebox.showinfo("程序信息", f"机台使用时间监控系统 v{CONFIG_VERSION}\n" f"首次锁定时间: {FIRST_LOCK_LIMIT}秒\n" f"后续锁定时间: {LOCK_LIMIT}秒") root.destroy() image = Image.new('RGB', (64, 64), color='white') menu = pystray.Menu( pystray.MenuItem("程序信息", show_info), pystray.MenuItem("退出", exit_action) ) icon = pystray.Icon("machine_monitor", image, "机台使用监控", menu) icon.run_detached() except ImportError: if not is_running_as_background() and not hasattr(sys, 'tray_warning_shown'): root = tk.Tk() root.withdraw() messagebox.showinfo("后台运行", "机台监控程序已在后台运行") root.destroy() sys.tray_warning_shown = True try: while app_running: time.sleep(1) except KeyboardInterrupt: app_running = False finally: if session_start_time and not is_locked and current_user: log_session(session_start_time, datetime.now(), current_user) mouse_listener.stop() keyboard_listener.stop() if __name__ == "__main__": main() 上面的test4.py原代码代码是可以初次运行后一直在后台运行的成功监控键盘和鼠标状态进行锁定,然后登录允许的账号和密码解锁,以及修改密码的功能,电脑关机重启后,开机自动开始运行后台监控,根据锁定的次数判断等待时间。 如果我想要写一个专门用于窗口的另一个python代码(在同一个工程里面),这个窗口代码收集到的信息会关联到上面的这个test4.py代码的参数。下面是我想要实现的窗口代码的功能: ①在桌面创建快捷方式——(打开之后有个窗口可以登录管理员的账号,就像原代码锁定界面登录的管理员账号密码一样)——登录管理员账号后可以在窗口里修改一些原test4.py代码的参数(修改什么参数在后面几点我会说明)。然后这个快捷方式的窗口上面(也就是登录管理员账号的上面部分)也可以选择退出登录也就是重新进入锁定(管是管理员账号还是普通账号)。 ②快捷方式的窗口,上面中间部分是选择退出当前登录按键;下面部分是登录管理员账号,可以输入账号和密码,登录后一个新的管理员窗口包含:一个可以修改锁定时间的输入框,一个修改保存的excel的保护密码的输入框,一个选择退出登录管理员账号的按键(右上角),一个可以滑动的子框可以添加多个管理员账号,一个可以滑动的子框可以添加允许登录的普通账号,一个可以重新在cmd里-instal运行修改参数后的原代码的按键,一个确定上面修改的按键,七个部分从上往下依次排。 ③关联原代码参数的说明:在窗口中实时修改原代码的参数(原代码的文件名是test4.py),参数包含:1.选择退出登录按键关联原代码进入锁定界面重新登录;2.管理员账号窗口:2.1修改锁定时间的输入框关联原代码的LOCK_LIMIT (但是这里输入的单位是分钟)。 2.2退出登录管理员账号的按键就返回到快捷方式的窗口。 2.3子框可以添加多个管理员账号和普通账号关联到原代码的user_data允许在锁定界面登录的账号。 2.4修改保存的excel的保护密码的输入框关联到原代码的REPORT_PASSWORD。 2.5重新在cmd里-instal运行修改参数后的原代码的按键关联到原代码修改之后的重新运行(先结束任务后-install运行) ④或者说,这个新的窗口代码关联到原代码的一个配置文件,这样已经在后台运行的原代码就更实时更新到修改的参数呢? 请给我完整的窗口代码的python代码,如果能这样实现的话请参考②中2.5所说的重新运行按键 原代码只用告诉我需要修改的地方,用告诉我完整代码了 注意:其他我没叫你修改的地方的原代码做修改(包括格式)(改变其他代码的功能!特别是开机自动启动后台运行),代码尽量简洁,逻辑复杂,适当的地方添加注释便于看懂 下面这个代码是我尝试实现上述功能的代码,虽然窗口差多是我预设的内容(还需要你稍微修改,添加修改保存的excel的保护密码的输入框),但是能和正在后台运行的test4.py代码及时联动,退出登录按键按了没反应,管理员修改参数的界面:添加用户显示用户存在,添加了,修改等待时间也成功 import os import sys import json import tkinter as tk from tkinter import ttk, messagebox, simpledialog import subprocess import threading import ctypes from datetime import datetime import psutil import winshell from win32com.client import Dispatch # 配置文件路径 CONFIG_FILE = "monitor_config.json" USER_DATA_FILE = "user_data.json" # 默认配置 DEFAULT_CONFIG = { "lock_limit_minutes": 0.5, # 30秒 = 0.5分钟 "admin_users": ["admin"], "regular_users": ["001", "002", "102"], "lock_immediately": False } class AdminTool: def __init__(self): self.root = tk.Tk() self.root.title("机台监控管理工具") self.root.geometry("600x500") self.root.resizable(True, True) self.root.protocol("WM_DELETE_WINDOW", self.on_closing) # 加载配置 self.config = self.load_config() # 创建主界面 self.create_login_frame() # 创建桌面快捷方式 self.create_desktop_shortcut() self.root.mainloop() def load_config(self): """加载配置文件""" if os.path.exists(CONFIG_FILE): try: with open(CONFIG_FILE, 'r') as f: return json.load(f) except: # 如果文件损坏,创建默认配置 self.save_config(DEFAULT_CONFIG) return DEFAULT_CONFIG.copy() # 如果文件存在,创建默认配置 self.save_config(DEFAULT_CONFIG) return DEFAULT_CONFIG.copy() def save_config(self, config): """保存配置文件""" with open(CONFIG_FILE, 'w') as f: json.dump(config, f, indent=2) def create_desktop_shortcut(self): """在桌面创建快捷方式""" desktop = winshell.desktop() shortcut_path = os.path.join(desktop, "机台监控管理工具.lnk") # 获取当前脚本路径 if getattr(sys, 'frozen', False): # 打包后的可执行文件 target = sys.executable else: # 脚本模式 target = sys.executable script_path = os.path.abspath(__file__) if not os.path.exists(shortcut_path): shell = Dispatch('WScript.Shell') shortcut = shell.CreateShortCut(shortcut_path) shortcut.Targetpath = target if not getattr(sys, 'frozen', False): shortcut.Arguments = f'"{script_path}"' shortcut.WorkingDirectory = os.path.dirname(os.path.abspath(__file__)) shortcut.IconLocation = target shortcut.Description = "机台监控管理工具" shortcut.save() def create_login_frame(self): """创建登录界面""" self.clear_window() # 顶部退出登录按钮 logout_frame = tk.Frame(self.root, bg="#f0f0f0", height=40) logout_frame.pack(fill=tk.X, side=tk.TOP) logout_btn = tk.Button( logout_frame, text="退出登录", command=self.lock_system, bg="#e74c3c", fg="white", font=("Arial", 10) ) logout_btn.pack(side=tk.RIGHT, padx=10, pady=5) # 登录表单 login_frame = tk.Frame(self.root, padx=20, pady=20) login_frame.pack(fill=tk.BOTH, expand=True) tk.Label( login_frame, text="管理员登录", font=("Arial", 16, "bold") ).pack(pady=(10, 20)) form_frame = tk.Frame(login_frame) form_frame.pack(fill=tk.X, padx=50) tk.Label(form_frame, text="账号:", font=("Arial", 12)).grid(row=0, column=0, sticky="e", pady=5) self.username_var = tk.StringVar() username_entry = tk.Entry(form_frame, textvariable=self.username_var, font=("Arial", 12)) username_entry.grid(row=0, column=1, padx=5, pady=5, sticky="ew") tk.Label(form_frame, text="密码:", font=("Arial", 12)).grid(row=1, column=0, sticky="e", pady=5) self.password_var = tk.StringVar() password_entry = tk.Entry(form_frame, textvariable=self.password_var, show="*", font=("Arial", 12)) password_entry.grid(row=1, column=1, padx=5, pady=5, sticky="ew") form_frame.columnconfigure(1, weight=1) status_frame = tk.Frame(login_frame) status_frame.pack(fill=tk.X, pady=10) self.login_status = tk.Label(status_frame, text="", fg="red") self.login_status.pack() btn_frame = tk.Frame(login_frame) btn_frame.pack(pady=10) login_btn = tk.Button( btn_frame, text="登录", command=self.authenticate_admin, width=15, bg="#3498db", fg="white", font=("Arial", 12) ) login_btn.pack(pady=10) # 绑定回车键 password_entry.bind("<Return>", lambda event: self.authenticate_admin()) username_entry.focus() def authenticate_admin(self): """验证管理员身份""" username = self.username_var.get().strip() password = self.password_var.get().strip() if not username or not password: self.login_status.config(text="账号和密码能为空") return # 加载用户数据 if not os.path.exists(USER_DATA_FILE): self.login_status.config(text="用户数据文件存在") return try: with open(USER_DATA_FILE, 'r') as f: user_data = json.load(f) except: self.login_status.config(text="无法读取用户数据") return # 检查用户是否存在 if username not in user_data.get("users", {}): self.login_status.config(text="用户存在") return user = user_data["users"][username] # 验证密码 import hashlib hashed_password = hashlib.sha256(password.encode()).hexdigest() if user["password"] != hashed_password: self.login_status.config(text="密码正确") return # 检查是否为管理员 if user.get("role") != "admin": self.login_status.config(text="该账号是管理员") return # 登录成功,进入管理界面 self.create_admin_panel() def lock_system(self): """锁定系统""" # 更新配置文件设置立即锁定标志 self.config["lock_immediately"] = True self.save_config(self.config) # 创建锁定标志文件 with open("lock_now.flag", "w") as f: f.write(str(datetime.now())) messagebox.showinfo("系统锁定", "系统将在后台监控程序中锁定") # 退出管理员界面 self.create_login_frame() def create_admin_panel(self): """创建管理员面板""" self.clear_window() # 创建主容器 main_container = tk.Frame(self.root) main_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) # 顶部标题和退出按钮 header_frame = tk.Frame(main_container, bg="#34495e", height=40) header_frame.pack(fill=tk.X, side=tk.TOP, pady=(0, 10)) tk.Label( header_frame, text="机台监控管理面板", fg="white", bg="#34495e", font=("Arial", 14, "bold") ).pack(side=tk.LEFT, padx=20) logout_btn = tk.Button( header_frame, text="退出管理员", command=self.create_login_frame, bg="#e74c3c", fg="white", font=("Arial", 10) ) logout_btn.pack(side=tk.RIGHT, padx=10, pady=5) # 锁定时间设置 lock_frame = tk.LabelFrame(main_container, text="锁定时间设置", padx=10, pady=10) lock_frame.pack(fill=tk.X, pady=5) lock_setting_frame = tk.Frame(lock_frame) lock_setting_frame.pack(fill=tk.X, padx=5, pady=5) tk.Label( lock_setting_frame, text="无操作锁定时间(分钟):", font=("Arial", 11) ).pack(side=tk.LEFT, padx=5) self.lock_time_var = tk.DoubleVar(value=self.config["lock_limit_minutes"]) lock_entry = tk.Entry( lock_setting_frame, textvariable=self.lock_time_var, width=8, font=("Arial", 11) ) lock_entry.pack(side=tk.LEFT, padx=5) save_btn = tk.Button( lock_setting_frame, text="保存设置", command=self.save_lock_time, bg="#27ae60", fg="white", width=10 ) save_btn.pack(side=tk.LEFT, padx=10) # 用户管理容器 user_container = tk.Frame(main_container) user_container.pack(fill=tk.BOTH, expand=True, pady=5) # 管理员用户列表 admin_frame = tk.LabelFrame(user_container, text="管理员账号", padx=10, pady=10) admin_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5)) admin_list_frame = tk.Frame(admin_frame) admin_list_frame.pack(fill=tk.BOTH, expand=True) # 滚动条 admin_scroll = tk.Scrollbar(admin_list_frame) admin_scroll.pack(side=tk.RIGHT, fill=tk.Y) self.admin_listbox = tk.Listbox( admin_list_frame, yscrollcommand=admin_scroll.set, height=6 ) self.admin_listbox.pack(fill=tk.BOTH, expand=True) admin_scroll.config(command=self.admin_listbox.yview) # 加载管理员用户 self.load_admin_users() # 管理员操作按钮 admin_btn_frame = tk.Frame(admin_frame) admin_btn_frame.pack(fill=tk.X, pady=(5, 0)) add_admin_btn = tk.Button( admin_btn_frame, text="添加", command=self.add_admin_user, width=8 ) add_admin_btn.pack(side=tk.LEFT, padx=2) remove_admin_btn = tk.Button( admin_btn_frame, text="移除", command=self.remove_admin_user, width=8 ) remove_admin_btn.pack(side=tk.LEFT, padx=2) # 普通用户列表 user_frame = tk.LabelFrame(user_container, text="普通用户账号", padx=10, pady=10) user_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0)) user_list_frame = tk.Frame(user_frame) user_list_frame.pack(fill=tk.BOTH, expand=True) # 滚动条 user_scroll = tk.Scrollbar(user_list_frame) user_scroll.pack(side=tk.RIGHT, fill=tk.Y) self.user_listbox = tk.Listbox( user_list_frame, yscrollcommand=user_scroll.set, height=6 ) self.user_listbox.pack(fill=tk.BOTH, expand=True) user_scroll.config(command=self.user_listbox.yview) # 加载普通用户 self.load_regular_users() # 普通用户操作按钮 user_btn_frame = tk.Frame(user_frame) user_btn_frame.pack(fill=tk.X, pady=(5, 0)) add_user_btn = tk.Button( user_btn_frame, text="添加", command=self.add_regular_user, width=8 ) add_user_btn.pack(side=tk.LEFT, padx=2) remove_user_btn = tk.Button( user_btn_frame, text="移除", command=self.remove_regular_user, width=8 ) remove_user_btn.pack(side=tk.LEFT, padx=2) # 重启服务按钮 restart_frame = tk.Frame(main_container) restart_frame.pack(fill=tk.X, pady=10) restart_btn = tk.Button( restart_frame, text="重启监控服务", command=self.restart_monitor_service, bg="#e67e22", fg="white", font=("Arial", 12), height=2 ) restart_btn.pack(fill=tk.X, padx=20) def load_admin_users(self): """加载管理员用户到列表""" self.admin_listbox.delete(0, tk.END) for user in self.config["admin_users"]: self.admin_listbox.insert(tk.END, user) def load_regular_users(self): """加载普通用户到列表""" self.user_listbox.delete(0, tk.END) for user in self.config["regular_users"]: self.user_listbox.insert(tk.END, user) def save_lock_time(self): """保存锁定时间设置""" try: lock_time = float(self.lock_time_var.get()) if lock_time <= 0: raise ValueError("锁定时间必须大于0") # 更新配置 self.config["lock_limit_minutes"] = lock_time self.save_config(self.config) messagebox.showinfo("成功", "锁定时间设置已保存") except ValueError as e: messagebox.showerror("错误", f"无效的输入: {str(e)}") def add_admin_user(self): """添加管理员用户""" username = simpledialog.askstring("添加管理员", "请输入管理员账号:") if username: if username in self.config["admin_users"]: messagebox.showerror("错误", "该用户已是管理员") return # 检查用户是否存在 if not os.path.exists(USER_DATA_FILE): messagebox.showerror("错误", "用户数据文件存在") return try: with open(USER_DATA_FILE, 'r') as f: user_data = json.load(f) except: messagebox.showerror("错误", "无法读取用户数据") return if username not in user_data.get("users", {}): messagebox.showerror("错误", "该用户存在") return # 添加到管理员列表 self.config["admin_users"].append(username) self.save_config(self.config) self.load_admin_users() def remove_admin_user(self): """移除管理员用户""" selection = self.admin_listbox.curselection() if not selection: messagebox.showerror("错误", "请选择要移除的管理员") return username = self.admin_listbox.get(selection[0]) if username == "admin": messagebox.showerror("错误", "能移除默认管理员账号") return self.config["admin_users"].remove(username) self.save_config(self.config) self.load_admin_users() def add_regular_user(self): """添加普通用户""" username = simpledialog.askstring("添加普通用户", "请输入普通用户账号:") if username: if username in self.config["regular_users"]: messagebox.showerror("错误", "该用户已是普通用户") return # 检查用户是否存在 if not os.path.exists(USER_DATA_FILE): messagebox.showerror("错误", "用户数据文件存在") return try: with open(USER_DATA_FILE, 'r') as f: user_data = json.load(f) except: messagebox.showerror("错误", "无法读取用户数据") return if username not in user_data.get("users", {}): messagebox.showerror("错误", "该用户存在") return # 添加到普通用户列表 self.config["regular_users"].append(username) self.save_config(self.config) self.load_regular_users() def remove_regular_user(self): """移除普通用户""" selection = self.user_listbox.curselection() if not selection: messagebox.showerror("错误", "请选择要移除的用户") return username = self.user_listbox.get(selection[0]) self.config["regular_users"].remove(username) self.save_config(self.config) self.load_regular_users() def restart_monitor_service(self): """重启监控服务""" # 查找并终止现有监控进程 current_pid = os.getpid() script_name = "test4.py" # 原代码文件名 terminated = False for proc in psutil.process_iter(['pid', 'name', 'cmdline']): try: cmdline = proc.info['cmdline'] if cmdline and len(cmdline) > 1 and script_name in cmdline[1] and proc.info['pid'] != current_pid: proc.terminate() terminated = True except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): pass # 稍等片刻让进程终止 if terminated: import time time.sleep(1) # 重新启动监控服务 script_path = os.path.abspath(script_name) if os.path.exists(script_path): # 根据运行环境决定如何启动 if getattr(sys, 'frozen', False): # 打包后的可执行文件 subprocess.Popen([sys.executable, script_path]) else: # 脚本模式 subprocess.Popen([sys.executable, script_path]) messagebox.showinfo("成功", "监控服务已重启") else: messagebox.showerror("错误", f"找到文件: {script_name}") def clear_window(self): """清除窗口中的所有组件""" for widget in self.root.winfo_children(): widget.destroy() def on_closing(self): """关闭窗口时的处理""" self.root.destroy() if __name__ == "__main__": # 检查是否以管理员权限运行 if ctypes.windll.shell32.IsUserAnAdmin() == 0: # 重新以管理员权限运行 ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, f'"{__file__}"', None, 1) sys.exit() app = AdminTool()
最新发布
10-31
<think>我们有一个后台脚本test4.py,它可能是一个Django应用或其他类型的后台服务。用户希望修改现有的窗口(GUI)代码,使其能够与test4.py实时联动,实现以下功能: 1. 退出登录 2. 添加用户 3. 修改锁定时间 4. 修改Excel保护密码(通过添加输入框) 根据引用[1],我们看到Django框架中处理登录和用户认证的方式。特别是使用了`authenticate`和`login`函数。因此,我们可以推断test4.py可能是一个基于Django的后台应用。 我们需要设计一个GUI(可能是Tkinter或其他)来与后台交互。交互方式可能是通过HTTP请求(如果Django提供了API)或者通过数据库(但这样安全,推荐)或者通过消息队列、RPC等。但考虑到实时联动,且Django通常提供HTTP接口,我们假设后台已经提供或我们可以添加相应的API。 由于用户提到“现有窗口代码”,我们需要在现有代码基础上修改。由于没有提供现有代码,我们将假设一个结构,并给出修改建议。 步骤: 1. 确定与后台交互的接口:我们需要在test4.py(Django应用)中创建相应的API来处理退出登录、添加用户、修改锁定时间和修改Excel密码的功能。 2. 修改GUI代码,添加必要的控件(例如,对于修改锁定时间,添加输入框和按钮;对于修改Excel密码,添加输入框等),并为这些控件绑定事件处理函数。 3. 在事件处理函数中,通过发送HTTP请求(或其他方式)调用后台API。 注意:由于后台是Django,我们建议使用Django REST framework来构建API,但也可以使用普通的Django视图。 下面,我们将分别描述两部分:后台API的修改和GUI代码的修改。 ### 后台API(test4.py中的Django应用)修改 我们需要在Django应用中创建以下API端点(假设应用名为`myapp`): 1. 退出登录:需要一个视图来处理退出登录(使用Django的logout函数)。 2. 添加用户:使用Django的User模型创建用户。 3. 修改锁定时间:假设锁定时间存储在用户模型的某个字段(如`last_lock_time`)或自定义用户模型中,我们需要一个视图来修改它。 4. 修改Excel保护密码:这个密码可能存储在某个模型(例如UserProfile)中,因此需要一个视图来修改。 #### 示例视图代码(views.py): ```python from django.contrib.auth import logout as auth_logout from django.contrib.auth.models import User from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt # 为了方便,暂时禁用CSRF,生产环境应考虑安全 def logout_api(request): if request.method == 'POST': auth_logout(request) return JsonResponse({'status': 'success'}) @csrf_exempt def add_user_api(request): if request.method == 'POST': # 从POST数据中获取用户名和密码 username = request.POST.get('username') password = request.POST.get('password') if not username or not password: return JsonResponse({'status': 'error', 'message': 'Missing username or password'}, status=400) try: user = User.objects.create_user(username=username, password=password) # 可以设置其他字段 user.save() return JsonResponse({'status': 'success', 'user_id': user.id}) except Exception as e: return JsonResponse({'status': 'error', 'message': str(e)}, status=400) @csrf_exempt def update_lock_time_api(request): if request.method == 'POST': # 假设锁定时间字段在User模型中,实际上可能需要自定义用户模型 # 或者我们使用另一个模型存储配置 # 这里假设每个用户有一个关联的UserProfile模型,其中包含lock_time字段 user_id = request.POST.get('user_id') lock_time = request.POST.get('lock_time') # 根据实际模型修改 # 示例:profile = UserProfile.objects.get(user_id=user_id) # profile.lock_time = lock_time # profile.save() return JsonResponse({'status': 'success'}) @csrf_exempt def update_excel_password_api(request): if request.method == 'POST': # 同样,假设Excel密码存储在UserProfile中 user_id = request.POST.get('user_id') excel_password = request.POST.get('excel_password') # 更新操作 return JsonResponse({'status': 'success'}) ``` 然后,在urls.py中添加路由。 ### GUI代码修改 假设现有GUI使用Tkinter,我们需要添加: 1. 退出登录按钮:点击后调用后台的退出登录API。 2. 添加用户部分:输入用户名和密码的输入框,以及添加按钮。 3. 修改锁定时间:输入锁定时间的输入框和按钮(可能需要选择用户)。 4. 修改Excel保护密码:输入新密码的输入框和按钮。 #### 示例代码片段(在现有窗口中添加): ```python import tkinter as tk import requests class MyWindow: def __init__(self, master): self.master = master # ... 现有控件 ... # 添加退出登录按钮 self.logout_btn = tk.Button(master, text="退出登录", command=self.logout) self.logout_btn.pack() # 添加用户部分 tk.Label(master, text="用户名").pack() self.new_username = tk.Entry(master) self.new_username.pack() tk.Label(master, text="密码").pack() self.new_password = tk.Entry(master, show="*") self.new_password.pack() self.add_user_btn = tk.Button(master, text="添加用户", command=self.add_user) self.add_user_btn.pack() # 修改锁定时间 tk.Label(master, text="锁定时间(分钟)").pack() self.lock_time = tk.Entry(master) self.lock_time.pack() self.update_lock_btn = tk.Button(master, text="更新锁定时间", command=self.update_lock_time) self.update_lock_btn.pack() # 修改Excel密码 tk.Label(master, text="Excel保护密码").pack() self.excel_password = tk.Entry(master, show="*") self.excel_password.pack() self.update_excel_btn = tk.Button(master, text="更新Excel密码", command=self.update_excel_password) self.update_excel_btn.pack() def logout(self): # 发送退出登录请求 response = requests.post('http://localhost:8000/logout_api/') if response.json().get('status') == 'success': # 退出成功,关闭窗口或清理 self.master.destroy() def add_user(self): username = self.new_username.get() password = self.new_password.get() data = {'username': username, 'password': password} response = requests.post('http://localhost:8000/add_user_api/', data=data) # 处理响应 def update_lock_time(self): lock_time = self.lock_time.get() # 注意:实际中可能需要指定用户(如当前用户),这里假设从界面获取user_id或当前会话已包含 # 如果后台需要user_id,我们可以从当前登录状态获取或通过输入框 # 这里假设后台视图通过request.user获取,但我们的API没有使用认证,需要改进(例如传递sessionid) # 为了简单,假设传递当前登录用户的id(需要先存储) # 更安全的方式是使用会话认证(携带cookie) # 由于我们在GUI中可能已经登录,所以requests会话会保持cookie data = {'lock_time': lock_time} response = requests.post('http://localhost:8000/update_lock_time_api/', data=data) def update_excel_password(self): password = self.excel_password.get() data = {'excel_password': password} response = requests.post('http://localhost:8000/update_excel_password_api/', data=data) # 主窗口 root = tk.Tk() app = MyWindow(root) root.mainloop() ``` 注意:上述GUI代码中,我们假设Django服务运行在http://localhost:8000/。在实际应用中,需要确保GUI在登录后保存了session(即使用requests.Session()),这样后续请求才会携带认证cookie(因为Django的login会在session中记录用户)。 ### 关于认证的说明 在Django中,`login(request, user)`会设置session。因此,在GUI中,我们需要先登录(比如在启动GUI时登录),然后使用同一个requests.Session实例来发送请求,这样才会自动携带sessionid。 修改:在GUI初始化时创建一个session对象,并在所有请求中使用这个session。 ```python class MyWindow: def __init__(self, master): self.session = requests.Session() # 使用同一个会话 # ... 其他初始化 ... def logout(self): response = self.session.post('http://localhost:8000/logout_api/') # ... # 其他方法也使用self.session.post ``` ### 修改Excel保护密码的说明 修改Excel保护密码的功能,我们假设后台已经有一个存储密码的地方(比如用户配置表)。在后台视图中,我们更新这个密码。然后,在保存Excel时使用这个密码(这部分逻辑在后台)。 ### 总结 1. 在后台Django应用中创建必要的API。 2. 在GUI中,使用requests库(特别是Session)与后台交互。 3. 在GUI中添加相应的控件和事件处理函数。 由于现有窗口代码未知,以上代码为示例,需要根据实际情况调整。 §§相关问题§§ 1. 如何在Django中创建安全的API接口? 2. 如何在前端GUI中管理用户会话? 3. 如何设计用户界面以方便管理用户和设置? </think>根据您的需求,我将指导您修改Python窗口代码,实现与后台test4.py的实时联动,包含退出登录、用户管理、锁定时间修改和Excel密码保护功能。以下是具体的解决方案: ### 一、后台API设计(test4.py修改) 在test4.py中需要实现以下API端点: ```python from django.contrib.auth import logout as auth_logout from django.http import JsonResponse def logout_api(request): """退出登录API""" auth_logout(request) return JsonResponse({"status": "success"}) def add_user_api(request): """添加用户API""" username = request.POST.get('username') password = request.POST.get('password') # 创建用户逻辑 return JsonResponse({"status": "user_created"}) def update_lock_time_api(request): """更新锁定时间API""" lock_time = request.POST.get('lock_time') # 更新锁定时间逻辑 return JsonResponse({"status": "lock_time_updated"}) def update_excel_password_api(request): """更新Excel密码API""" excel_pwd = request.POST.get('excel_pwd') # 更新Excel密码逻辑 return JsonResponse({"status": "excel_pwd_updated"}) ``` ### 二、前端窗口代码修改 ```python import tkinter as tk import requests class AdminPanel(tk.Toplevel): def __init__(self, master): super().__init__(master) self.title("系统管理") self.geometry("400x300") # 退出登录按钮 tk.Button(self, text="退出登录", command=self.logout).pack(pady=10) # 添加用户区域 user_frame = tk.LabelFrame(self, text="用户管理") user_frame.pack(fill="x", padx=10, pady=5) tk.Label(user_frame, text="用户名:").grid(row=0, column=0) self.username = tk.Entry(user_frame) self.username.grid(row=0, column=1) tk.Label(user_frame, text="密码:").grid(row=1, column=0) self.password = tk.Entry(user_frame, show="*") self.password.grid(row=1, column=1) tk.Button(user_frame, text="添加用户", command=self.add_user).grid(row=2, columnspan=2) # 锁定时间修改 lock_frame = tk.LabelFrame(self, text="账户锁定设置") lock_frame.pack(fill="x", padx=10, pady=5) tk.Label(lock_frame, text="锁定时间(分钟):").grid(row=0, column=0) self.lock_time = tk.Entry(lock_frame) self.lock_time.insert(0, "30") # 默认值 self.lock_time.grid(row=0, column=1) tk.Button(lock_frame, text="更新", command=self.update_lock_time).grid(row=0, column=2) # Excel密码保护 excel_frame = tk.LabelFrame(self, text="Excel文件保护") excel_frame.pack(fill="x", padx=10, pady=5) tk.Label(excel_frame, text="新密码:").grid(row=0, column=0) self.excel_pwd = tk.Entry(excel_frame, show="*") self.excel_pwd.grid(row=0, column=1) tk.Button(excel_frame, text="更新密码", command=self.update_excel_password).grid(row=0, column=2) def logout(self): """调用退出登录API""" response = requests.post('http://localhost:8000/logout_api/') if response.json().get('status') == 'success': self.master.show_login() # 返回登录界面 self.destroy() def add_user(self): """调用添加用户API""" data = { 'username': self.username.get(), 'password': self.password.get() } requests.post('http://localhost:8000/add_user_api/', data=data) def update_lock_time(self): """更新账户锁定时间""" requests.post('http://localhost:8000/update_lock_time_api/', data={'lock_time': self.lock_time.get()}) def update_excel_password(self): """更新Excel保护密码""" requests.post('http://localhost:8000/update_excel_password_api/', data={'excel_pwd': self.excel_pwd.get()}) ``` ### 三、联动实现关键点 1. **实时通信机制**: - 使用`requests`库发送POST请求到Django后台 - 保持session一致性:`session = requests.Session()` - 错误处理: ```python try: response = session.post(url, data=data, timeout=3) response.raise_for_status() except requests.exceptions.RequestException as e: messagebox.showerror("连接错误", f"后台服务可达: {str(e)}") ``` 2. **会话管理**: ```python # 登录时获取session def login(self): self.session = requests.Session() response = self.session.post(LOGIN_URL, data={ 'username': self.usr.get(), 'password': self.pwd.get() }) if response.ok: AdminPanel(self) # 打开管理面板 ``` 3. **Excel密码处理**: ```python # 后台保存密码到数据库 from django.db import models class ExcelConfig(models.Model): password = models.CharField(max_length=128) updated_at = models.DateTimeField(auto_now=True) ``` ### 四、安全增强建议 1. 使用HTTPS加密通信 2. 密码字段使用PBKDF2加密存储 3. 添加API访问权限控制: ```python from django.contrib.auth.decorators import login_required @login_required def update_excel_password_api(request): # 仅登录用户可访问 ``` 4. 输入验证: ```python # 前端输入验证示例 def validate_password(self): pwd = self.excel_pwd.get() if len(pwd) < 8: messagebox.showwarning("密码强度", "密码至少需要8个字符") return False return True ``` ### 五、部署注意事项 1. 后台服务地址配置: ```python BASE_URL = 'http://localhost:8000' if DEBUG else 'https://your-production-domain.com' ``` 2. 跨域问题解决(如果前后端分离): ```python # settings.py CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", # 前端开发地址 "https://your-frontend-domain.com" ] ``` > 注意:以上代码需要根据您的实际项目结构调整,特别是Django模型定义和URL路由配置部分。确保`test4.py`中已正确配置URL映射到新增的API视图函数[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值