使用python的flask框架做一个本地mysql服务器的webui!

能不能不要报错! 2024-07-31 13:33:04 阅读 64

该webui的主要作用是作为一个数据库管理系统对本地mysql数据库进行管理。这里会手把手教学如何实现的,并在文末给出初代完整flask数据库管理系统的完整代码!希望能帮助到有需要的同学。本来是想用来干点其他的,但是想了一下决定还是完整开源出来,各位看官,用的话记得给个鸣谢或者引用呗!Thanks♪(・ω・)ノ

注:本人软工部分也是刚学习不久,代码规范和代码维护上存在欠缺,还需看官多多包涵,恳请批评指正!

这是我的界面截图(背景随便找的)

登录界面:

数据库选择界面:

数据库管理界面:

搜索结果:

现在我们开始

首先,先安装mysql数据库,这里给出一个windows的下载链接,我选择的是mysql8.4.0.lts版本,MySQL :: Download MySQL Community Server

以及mysql workbench-mysql的可视化界面

MySQL :: Download MySQL Workbench

下载后根据安装指引安装即可,记得先给设置一个从用户账户和密码,该账户用来给flask连接数据库。记住保存路径,并勾选world数据库(方便后期调试)

然后设置系统环境变量,右键此电脑→高级系统设置→系统变量设置→系统变量→path→新建→粘贴刚才的保存路径(默认是C:\Program Files\MySQL\MySQL Server 8.4\bin,需要查看该目录下是否存在mysql.exe)

mysql安装好后按道理理论上会自动启动,不过也可以通过win+r输入services.msc查询,找到mysql开头的,我的是MySQL84,右键属性可以看到

这样就可以了。

然后试一下,找一个空白的地方shift+右键,打开powershell,然后键入 mysql -u root账户名 -p,然后输入密码验证。显示<mysql>即成功安装。

然后就是python,python的安装自行搜索,不做过多停留,安装完python后给pip换为国内源,

windows环境下: 比如windows账号是 admin

那么建立 admin主目录下的 pip子目录,在此pip子目录下建立pip的配置文件:pip.ini

位于c:\users\admin\pip\pip.ini

# coding: GBK

[global]

index-url = https://pypi.tuna.tsinghua.edu.cn/simple

[install]

trusted-host = https://pypi.tuna.tsinghua.edu.cn

#清华大学:https://pypi.tuna.tsinghua.edu.cn/simple

#阿里云:http://mirrors.aliyun.com/pypi/simple/

#豆瓣:http://pypi.douban.com/simple/

=================================================================

推荐采用python虚拟环境中执行该系统环境配置

创建一个工程目录,并在该目录下执行powershell(shift + 右键)或者终端(ctrl+alt+T)

python -m venv venv

venv/script/activate

安装flask框架(mysql):

pip install flask

pip install mysql-connector-python

pip install Flask mysql-connector-python

pip install Flask-Session

这样环境就配置好了

然后就是执行python文件,python app.py

如果终端显示

则表示运行成功,并可在浏览器输入http://127.0.0.1:5000访问。

以下是app.py的示例代码:

<code>################################app.py############################

from flask import Flask, request, jsonify, render_template, redirect, url_for, session

from flask_session import Session

import mysql.connector

app = Flask(__name__)

app.secret_key = 'root' # 用于会话管理

app.config['SESSION_TYPE'] = 'filesystem' # 使用文件系统存储会话

Session(app)

# 预定义账号和密码

USERS = {

'admin': 'admin',

'旅馆管理系统': '123456'

}

# 数据库连接配置

db_config = {

'host': 'localhost',

'user': '旅馆管理系统',

'password': '123456'

}

def get_db_connection():

conn = mysql.connector.connect(

host=db_config['host'],

user=db_config['user'],

password=db_config['password']

)

return conn

def get_databases():

conn = get_db_connection()

cursor = conn.cursor()

cursor.execute("SHOW DATABASES")

databases = [database[0] for database in cursor.fetchall() if database[0] != 'information_schema'] # 排除系统数据库

cursor.close()

conn.close()

return databases

def get_tables(database):

conn = get_db_connection()

cursor = conn.cursor()

cursor.execute(f"USE {database}")

cursor.execute("SHOW TABLES")

tables = [table[0] for table in cursor.fetchall()]

cursor.close()

conn.close()

return tables

def get_table_fields(database, table):

conn = get_db_connection()

cursor = conn.cursor()

cursor.execute(f"USE {database}")

cursor.execute(f"SHOW COLUMNS FROM {table}")

fields = [field[0] for field in cursor.fetchall()]

cursor.close()

conn.close()

return fields

def get_table_records(database, table):

conn = get_db_connection()

cursor = conn.cursor(dictionary=True)

cursor.execute(f"USE {database}")

cursor.execute(f"SELECT * FROM {table}")

records = cursor.fetchall()

cursor.close()

conn.close()

return records

# 获取表的主键字段

def get_table_primary_key(database, table):

conn = get_db_connection()

cursor = conn.cursor()

cursor.execute(f"USE {database}")

cursor.execute(f"SHOW KEYS FROM {table} WHERE Key_name = 'PRIMARY'")

primary_key = cursor.fetchone()

cursor.close()

conn.close()

return primary_key[4] if primary_key else None

# 用户登录页

@app.route('/', methods=['GET', 'POST'])

def login():

if request.method == 'POST':

username = request.form['username']

password = request.form['password']

if username in USERS and USERS[username] == password:

session['username'] = username # 将用户名存储在session中

return redirect(url_for('home'))

else:

return 'Invalid username or password', 401

return render_template('login.html')

# 用户登出页

@app.route('/logout')

def logout():

session.pop('username', None) # 清除会话数据

return redirect(url_for('login'))

# 用户管理页

@app.route('/home')

def home():

if 'username' not in session:

return redirect(url_for('login'))

return render_template('index.html', databases=get_databases())

# 进入数据库

@app.route('/enter-database', methods=['POST'])

def enter_database():

if 'username' not in session:

return redirect(url_for('login'))

selected_database = request.form.get('database')

session['selected_database'] = selected_database

return redirect(url_for('database_home'))

# 数据库主页

@app.route('/database_home')

def database_home():

if 'username' not in session or 'selected_database' not in session:

return redirect(url_for('login'))

selected_database = session['selected_database']

tables = get_tables(selected_database)

selected_table = request.args.get('table', tables[0] if tables else None)

fields = get_table_fields(selected_database, selected_table) if selected_table else []

records = get_table_records(selected_database, selected_table) if selected_table else []

primary_key = get_table_primary_key(selected_database, selected_table)

return render_template('database_home.html',

database=selected_database,

tables=tables,

selected_table=selected_table,

fields=fields,

records=records,

field_names=fields,

primary_key=primary_key) # 将主键字段传递给模板

# 获取表的字段

@app.route('/get_table_fields', methods=['POST'])

def get_table_fields_route():

if 'username' not in session or 'selected_database' not in session:

return redirect(url_for('login'))

database = session['selected_database']

table = request.form.get('table')

fields = get_table_fields(database, table)

return jsonify(fields)

# 保存记录

@app.route('/save_record', methods=['POST'])

def save_record():

if 'username' not in session or 'selected_database' not in session:

return jsonify({'success': False, 'error': 'Unauthorized'}), 403

data = request.get_json()

database = data['database']

table = data['table']

record = data['record']

print("Saving record:", record) # 添加调试输出

if 'id' not in record:

return jsonify({'success': False, 'error': 'Missing id'}), 400

conn = get_db_connection()

cursor = conn.cursor()

update_query = f"UPDATE {database}.{table} SET "

update_query += ", ".join([f"{field} = %s" for field in record.keys() if field != 'id'])

update_query += " WHERE id = %s"

params = [record[field] for field in record.keys() if field != 'id'] + [record['id']]

try:

cursor.execute(update_query, params)

conn.commit()

success = True

except Exception as e:

print(e)

success = False

cursor.close()

conn.close()

return jsonify({'success': success})

# 删除记录

@app.route('/delete_record', methods=['POST'])

def delete_record():

if 'username' not in session or 'selected_database' not in session:

return jsonify({'success': False, 'error': 'Unauthorized'}), 403

data = request.get_json()

database = data['database']

table = data['table']

record_name = data['name'] # 修改为 'name' 字段

print("Deleting record with name:", record_name) # 添加调试输出

conn = get_db_connection()

cursor = conn.cursor()

delete_query = f"DELETE FROM {database}.{table} WHERE Name = %s" # 使用 'Name' 字段作为唯一标识

try:

cursor.execute(delete_query, (record_name,))

conn.commit()

success = True

except Exception as e:

print(e)

success = False

cursor.close()

conn.close()

return jsonify({'success': success})

# 保存新记录

@app.route('/save_new_record', methods=['POST'])

def save_new_record():

if 'username' not in session or 'selected_database' not in session:

return jsonify({'success': False, 'error': 'Unauthorized'}), 403

data = request.get_json()

database = data['database']

table = data['table']

record = data['record']

print("Saving new record:", record) # 添加调试输出

# 构造插入记录的 SQL 查询语句

insert_query = f"INSERT INTO {database}.{table} ({', '.join(record.keys())}) VALUES ({', '.join(['%s']*len(record))})"

params = tuple(record.values()) # 将记录的值转换为元组形式

conn = get_db_connection()

cursor = conn.cursor()

try:

cursor.execute(insert_query, params)

conn.commit()

success = True

except Exception as e:

print(e)

success = False

cursor.close()

conn.close()

return jsonify({'success': success})

# 执行搜索并返回结果

def search_records(database, table, keyword):

conn = get_db_connection()

cursor = conn.cursor(dictionary=True)

# 构造模糊搜索的 SQL 查询语句

search_query = f"SELECT * FROM {database}.{table} WHERE "

search_query += " OR ".join([f"{field} LIKE %s" for field in get_table_fields(database, table)])

params = ['%' + keyword + '%'] * len(get_table_fields(database, table))

cursor.execute(search_query, params)

records = cursor.fetchall()

cursor.close()

conn.close()

return records

# 搜索页面

@app.route('/search_results')

def search_results():

if 'username' not in session or 'selected_database' not in session:

return redirect(url_for('login'))

selected_database = session['selected_database']

selected_table = request.args.get('table')

keyword = request.args.get('keyword')

records = search_records(selected_database, selected_table, keyword)

fields = get_table_fields(selected_database, selected_table)

return render_template('search_results.html',

keyword=keyword,

database=selected_database,

selected_table=selected_table,

fields=fields,

records=records)

if __name__ == '__main__':

app.run(debug=True)

以下是一些示例html

####################database_home.html#########################

<!DOCTYPE html>

<html lang="en">code>

<head>

<meta charset="UTF-8">code>

<meta name="viewport" content="width=device-width, initial-scale=1.0">code>

<title>Database Home</title>

<style>

body {

margin: 0;

padding: 0;

font-family: Arial, sans-serif;

background-image: url('/static/background.jpg');

background-size: cover;

background-position: center;

background-attachment: fixed;

height: 100vh;

overflow: auto;

}

.container {

background-color: rgba(255, 255, 255, 0.8);

padding: 20px;

border-radius: 10px;

box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);

margin: 20px;

}

h2 {

margin-bottom: 10px;

font-size: 24px;

}

button {

padding: 12px 24px;

cursor: pointer;

border: none;

border-radius: 5px;

font-size: 18px;

outline: none;

transition: background-color 0.3s ease;

}

.go-back-button {

background-color: #dc3545;

color: #fff;

margin-bottom: 20px;

text-align: right;

font-size: 18px;

}

.go-back-button:hover {

background-color: #c82333;

text-align: right;

}

.search-form-container,

.table-select-container {

text-align: left;

margin-bottom: 50px;

}

input[type="text"],code>

select {

width: calc(100% - 120px);

padding: 10px;

margin-bottom: 10px;

box-sizing: border-box;

border: 1px solid #ccc;

border-radius: 5px;

background-color: #f8f8f8;

font-size: 18px;

outline: none;

}

button[type="submit"] {code>

padding: 12px 24px;

cursor: pointer;

border: none;

border-radius: 5px;

background-color: #007bff;

color: #fff;

font-size: 18px;

outline: none;

transition: background-color 0.3s ease;

}

button[type="submit"]:hover {code>

background-color: #0056b3;

}

table {

width: 100%;

border-collapse: collapse;

margin-top: 10px;

}

th,

td {

border: 1px solid black;

padding: 8px;

text-align: left;

}

th {

background-color: #f2f2f2;

}

.editable {

background-color: #e8f0fe;

}

#new-record-table {

display: none;

margin-top: 20px;

}

#new-record-table td {

width: 150px;

padding: 5px;

}

.icon-button {

background: none;

border: none;

cursor: pointer;

padding: 0;

outline: none;

}

.icon-button img {

width: 48px;

/* 调整SVG图标的尺寸 */

height: 48px;

/* 调整SVG图标的尺寸 */

}

.divider {

border-top: 2px solid #ccc;

margin-top: 20px;

margin-bottom: 20px;

}

.footer {

position: fixed;

bottom: 0;

width: 100%;

background-color: #d6dce1;

padding: 10px 0;

text-align: center;

font-size: 14px;

color: #6c757d;

}

</style>

</head>

<body>

<div class="footer">code>

Version 1.0.0

</div>

<div id="user-info"code>

style="position: absolute; top: 10px; right: 10px; padding: 10px; background-color: #3ec83e; border: 1px solid #007bff; border-radius: 5px;">code>

<span style="color: #0b0808; font-weight: bold;">你好!{ { session['username'] }}</span>code>

</div>

<div class="container">code>

<h2 style="font-size: 50px; font-weight: bold;">当前数据库:{ { database }}</h2>code>

<button class="go-back-button" style="float: right; background-color:#d05d63;"code>

onclick="goBack()">退出当前数据库</button>code>

<div class="search-form-container">code>

<form id="search-form" onsubmit="search(event)">code>

<input type="text" id="keyword" name="keyword" placeholder="搜索..."code>

style="height=45px; padding: 10px; border: 2px solid #ccc; border-radius: 10px; font-size: 16px;">code>

<input type="hidden" name="table" value="{ { selected_table }}">code>

<button type="submit" style="background-color:#a099dd;">搜索</button>code>

</form>

</div>

<div class="table-select-container" style="display: flex; align-items: center; margin-top: 20px;">code>

<label for="table-select" style="font-size: 20px; margin-right: 10px;"><strong>当前访问的表:</strong></label>code>

<select id="table-select" name="table" onchange="updateTable(this.value)"code>

style="font-size: 20px; width: 200px;">code>

{% for table in tables %}

<option value="{ { table }}" {% if table==selected_table %}selected{% endif %}>{ { table }}</option>code>

{% endfor %}

</select>

</div>

<button class="icon-button" onclick="toggleNewRecordForm()" style="text-align: center;">code>

<img src="/static/svg/档案.svg" alt="添加记录" style="vertical-align: middle;">code>

<br>

<span id="toggle-text" style="font-size: 20px; font-weight: bold;">{ { '添加记录明细' if button_new_record_activatecode>

else '添加记录' }}</span>

</button>

<div id="new-record-table">code>

<h3>添加记录</h3>

<table id="new-record-form">code>

<tbody>

{% for field in field_names %}

<tr>

<td>{ { '*' if field == primary_key else '' }}{ { field }}</td>

<td><input type="text" id="new-{ { field }}" name="{ { field }}"></td>code>

</tr>

{% endfor %}

<tr>

<td colspan="2" style="text-align: center;"><button class="icon-button"code>

onclick="saveNewRecord()"><img src="/static/svg/上传.svg" alt="保存"></button></td>code>

</tr>

</tbody>

</table>

</div>

<div class="divider"></div>code>

<h3>记录列表</h3>

<table id="record-list">code>

<thead>

<tr>

{% for field in fields %}

<th>{ { field }}</th>

{% endfor %}

<th>保存修改</th>

<th>删除</th>

</tr>

</thead>

<tbody>

{% for record in records %}

<tr>

{% for field in fields %}

<td contenteditable="true" data-field="{ { field }}">{ { record[field] }}</td>code>

{% endfor %}

<td><button class="icon-button" onclick="saveRecord(this)"><img src="/static/svg/编辑.svg"code>

alt="保存"></button></td>code>

<td><button class="icon-button" onclick="confirmDelete(this)"><img src="/static/svg/删除.svg"code>

alt="删除"></button></td>code>

</tr>

{% endfor %}

</tbody>

</table>

</div>

<script>

let button_new_record_activate = false;

function toggleNewRecordForm() {

button_new_record_activate = !button_new_record_activate;

document.getElementById('new-record-table').style.display = button_new_record_activate ? 'block' : 'none';

}

function updateTable(table) {

const urlParams = new URLSearchParams(window.location.search);

urlParams.set('table', table);

window.location.search = urlParams.toString();

}

function saveRecord(button) {

const row = button.closest('tr');

const fields = {};

row.querySelectorAll('td[data-field]').forEach(td => {

const fieldName = td.getAttribute('data-field');

fields[fieldName.toLowerCase()] = td.innerText;

});

fetch('/save_record', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({

database: '{ { database }}',

table: '{ { selected_table }}',

record: fields

})

})

.then(response => response.json())

.then(data => {

if (data.success) {

alert('记录保存成功');

} else {

alert('记录保存失败');

}

});

}

function confirmDelete(button) {

if (confirm("确定要删除吗?")) {

deleteRecord(button);

} else {

// 用户取消删除操作

}

}

function deleteRecord(button) {

const row = button.closest('tr');

const recordName = row.querySelector('td[data-field="Name"]').innerText;code>

fetch('/delete_record', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({

database: '{ { database }}',

table: '{ { selected_table }}',

name: recordName

})

})

.then(response => response.json())

.then(data => {

if (data.success) {

alert('记录删除成功');

row.remove();

} else {

alert('记录删除失败');

}

});

}

function search(event) {

event.preventDefault();

const keyword = document.getElementById('keyword').value.trim();

if (keyword === '') {

alert('请输入搜索关键字');

return;

}

const formData = new FormData(document.getElementById('search-form'));

const searchParams = new URLSearchParams(formData).toString();

window.location.href = `/search_results?${searchParams}`;

}

function showNewRecordForm() {

document.getElementById('new-record-table').style.display = 'block';

}

function saveNewRecord() {

const record = {};

{% for field in field_names %}

record['{ { field }}'] = document.getElementById('new-{ { field }}').value;

{% endfor %}

fetch('/save_new_record', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({

database: '{ { database }}',

table: '{ { selected_table }}',

record: record

})

})

.then(response => response.json())

.then(data => {

if (data.success) {

alert('数据保存成功');

window.location.href = `/database_home?table={ { selected_table }}`;

} else {

alert('数据保存失败,请检查填写的数据格式或关键字错误');

}

});

}

function goBack() {

window.location.href = '/home';

}

function toggleNewRecordForm() {

button_new_record_activate = !button_new_record_activate;

document.getElementById('new-record-table').style.display = button_new_record_activate ? 'block' : 'none';

document.getElementById('toggle-text').innerText = button_new_record_activate ? '收起添加记录明细' : '添加记录';

}

</script>

</body>

</html>

##############################index.html#################################

<!DOCTYPE html>

<html lang="en">code>

<head>

<meta charset="UTF-8">code>

<meta name="viewport" content="width=device-width, initial-scale=1.0">code>

<title>数据库选择</title>

<style>

body {

display: flex;

justify-content: center;

align-items: center;

height: 100vh;

margin: 0;

background-image: url('/static/background.jpg');

background-size: cover;

background-position: center;

background-repeat: no-repeat;

}

.container {

background-color: rgba(255, 255, 255, 0.8);

padding: 20px;

border-radius: 10px;

box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);

margin: 20px;

width: 50%;

/* 设置容器的宽度为页面宽度的 80% */

}

form {

display: inline-block;

text-align: left;

width: 100%;

}

label {

display: block;

margin-bottom: 5px;

font-weight: bold;

}

input[type="text"],code>

input[type="password"],code>

select {

width: 100%;

padding: 10px;

margin-bottom: 20px;

box-sizing: border-box;

border: 1px solid #ccc;

border-radius: 5px;

background-color: #f8f8f8;

font-size: 16px;

outline: none;

}

.button-container {

display: flex;

justify-content: space-between;

}

button[type="submit"],code>

.logout-button {

padding: 10px 40px;

cursor: pointer;

border: none;

border-radius: 5px;

font-size: 16px;

outline: none;

transition: background-color 0.3s ease;

width: 48%;

/* 设置按钮宽度为48% */

text-align: center;

}

button[type="submit"] {code>

background-color: #007bff;

color: #fff;

}

button[type="submit"]:hover {code>

background-color: #0056b3;

}

.logout-button {

background-color: #dc3545;

color: #fff;

text-decoration: none;

display: inline-block;

line-height: 1.5;

}

.logout-button:hover {

background-color: #c82333;

}

h2 {

margin-bottom: 10px;

color: white;

}

h4 {

margin-bottom: 20px;

font-size: 14px;

text-align: right;

color: white;

}

.footer {

position: fixed;

bottom: 0;

width: 100%;

background-color: #d5dee7;

padding: 10px 0;

text-align: center;

font-size: 14px;

color: #6c757d;

}

</style>

</head>

<body>

<div id="user-info"code>

style="position: absolute; top: 10px; right: 10px; padding: 10px; background-color: #3ec83e; border: 1px solid #007bff; border-radius: 5px;">code>

<span style="color: #0b0808; font-weight: bold;">你好!{ { session['username'] }}</span>code>

</div>

<div class="container">code>

<h2>数据库信息管理系统</h2>

<h4>——buid by 𝓣𝔀𝓲𝓽𝓲𝓰𝓱𝓽@yhy2021_IEE</h4>

<form action="/enter-database" method="post">code>

<label for="db_user">数据库用户:</label>code>

<input type="text" id="db_user" name="db_user" required>code>

<label for="db_password">数据库密码:</label>code>

<input type="password" id="db_password" name="db_password" required>code>

<label for="database">选择数据库:</label>code>

<select id="database" name="database">code>

#############模拟权限管理,这一版已经被淘汰了,这个写法不好################

{% if session['username'] == '旅馆管理系统' %}

<option value="world">world</option>code>

<option value="test_db">test_db</option>code>

{% else %}

{% for database in databases %}

<option value="{ { database }}">{ { database }}</option>code>

{% endfor %}

{% endif %}

</select>

<div class="button-container">code>

<a href="/" class="logout-button">退出登录</a>code>

<button type="submit">进入数据库</button>code>

</div>

</form>

</div>

<div class="footer">code>

Version 1.0.0

</div>

</body>

</html>

#################################login.html#################################

<!DOCTYPE html>

<html lang="en">code>

<head>

<meta charset="UTF-8">code>

<meta name="viewport" content="width=device-width, initial-scale=1.0">code>

<title>Login</title>

<style>

body {

display: flex;

justify-content: center;

align-items: center;

height: 100vh;

margin: 0;

background-image: url('/static/background.jpg');

background-size: cover;

background-position: center;

background-repeat: no-repeat;

}

.login-container {

text-align: center;

position: relative;

border-radius: 20px;

box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);

width: 400px;

}

.gif-background {

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

width: 120%;

height: 150%;

background-image: url('/static/img.gif');

background-size: cover;

/* 自适应拉伸 */

border-radius: 20px;

z-index: -1;

}

h2 {

color: white;

}

form {

display: inline-block;

text-align: left;

position: relative;

z-index: 1;

}

label {

display: block;

margin-bottom: 5px;

font-weight: bold;

color: white;

}

input[type="text"],code>

input[type="password"] {code>

width: 100%;

padding: 10px;

margin-bottom: 20px;

box-sizing: border-box;

border: 1px solid #ccc;

border-radius: 5px;

background-color: #f8f8f8;

font-size: 16px;

color: white;

outline: none;

}

button[type="submit"] {code>

padding: 10px 100px;

cursor: pointer;

border: none;

border-radius: 5px;

background-color: #007bff;

color: #fff;

font-size: 16px;

outline: none;

transition: background-color 0.3s ease;

}

button[type="submit"]:hover {code>

background-color: #0056b3;

}

</style>

</head>

<body>

<div class="login-container">code>

<div class="gif-background"></div>code>

<h2>MySQL信息管理系统统一登录</h2>

<form method="post">code>

<label for="username">信息管理系统账户:</label>code>

<input type="text" id="username" name="username" required><br><br>code>

<label for="password">密码:</label>code>

<input type="password" id="password" name="password" required><br><br>code>

<button type="submit">登录</button>code>

</form>

</div>

</body>

</html>

#################################search_results.html#############################

<!DOCTYPE html>

<html lang="en">code>

<head>

<meta charset="UTF-8">code>

<meta name="viewport" content="width=device-width, initial-scale=1.0">code>

<title>Search Results</title>

<style>

body {

font-family: Arial, sans-serif;

margin: 0;

padding: 0;

background-image: url('/static/background.jpg');

background-size: cover;

background-position: center;

height: 100vh;

overflow: auto;

}

.container {

background-color: rgba(255, 255, 255, 0.8);

padding: 20px;

border-radius: 10px;

box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);

margin: 20px;

}

h1 {

margin-top: 0;

}

button {

padding: 10px 20px;

cursor: pointer;

border: none;

border-radius: 5px;

font-size: 16px;

outline: none;

transition: background-color 0.3s ease;

}

button:hover {

background-color: #0056b3;

color: #fff;

}

table {

width: 100%;

border-collapse: collapse;

margin-top: 20px;

}

th,

td {

border: 1px solid #ccc;

padding: 8px;

text-align: left;

}

th {

background-color: #f2f2f2;

}

.editable {

background-color: #e8f0fe;

}

</style>

</head>

<body>

<div id="user-info"code>

style="position: absolute; top: 10px; right: 10px; padding: 10px; background-color: #3ec83e; border: 1px solid #007bff; border-radius: 5px;">code>

<span style="color: #0b0808; font-weight: bold;">你好!{ { session['username'] }}</span>code>

</div>

<div class="container">code>

<h1>搜索条件 <button class="go-back-button" style="float: right; background-color:#d05d63;"code>

onclick="goBack()">返回上一级</button></h1>code>

<p style="font-size: 18px; font-weight: bold;">搜索关键词: { { keyword }}</p>code>

<p style="font-size: 18px; font-weight: bold;">被搜索数据库: { { database }}</p>code>

<p style="font-size: 18px; font-weight: bold;">被搜索表: { { selected_table }}</p>code>

<form id="search-form" style="text-align: left;" onsubmit="search(event)">code>

<input type="text" id="keyword" name="keyword" placeholder="搜索..."code>

style="width: 50%; padding: 10px; border: 2px solid #ccc; border-radius: 10px; font-size: 16px;">code>

<input type="hidden" name="table" value="{ { selected_table }}">code>

<button type="submit" style="background-color:#a099dd;">搜索</button>code>

</form>

<h2>搜索结果列表:</h2>

<table>

<thead>

<tr>

{% for field in fields %}

<th>{ { field }}</th>

{% endfor %}

<th>修改</th>

<th>删除</th>

</tr>

</thead>

<tbody>

{% for record in records %}

<tr>

{% for field in fields %}

<td contenteditable="true" data-field="{ { field }}">{ { record[field] }}</td>code>

{% endfor %}

<td><button onclick="saveRecord(this)">保存</button></td>code>

<td><button onclick="confirmDelete(this, '{ { record.Name }}')">删除</button></td>code>

</tr>

{% endfor %}

</tbody>

</table>

</div>

<script>

function goBack() {

window.history.back(); // 返回到上一个页面,即database_home.html页面

}

function search(event) {

event.preventDefault(); // 阻止表单默认提交行为

const keyword = document.getElementById('keyword').value.trim();

if (keyword === '') {

alert('请输入搜索关键字');

return;

}

const formData = new FormData(document.getElementById('search-form'));

const searchParams = new URLSearchParams(formData).toString();

window.location.href = `/search_results?${searchParams}`;

}

function saveRecord(button) {

const row = button.closest('tr');

const fields = {};

row.querySelectorAll('td[data-field]').forEach(td => {

const fieldName = td.getAttribute('data-field');

fields[fieldName.toLowerCase()] = td.innerText;

});

fetch('/save_record', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({

database: '{ { database }}',

table: '{ { selected_table }}',

record: fields

})

})

.then(response => response.json())

.then(data => {

if (data.success) {

alert('记录保存成功');

} else {

alert('记录保存失败');

}

});

}

function confirmDelete(button, name) {

if (confirm("确定要删除吗?")) {

deleteRecord(button, name);

} else {

// 用户取消删除操作

}

}

function deleteRecord(button, name) {

const row = button.closest('tr');

fetch('/delete_record', {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify({

database: '{ { database }}',

table: '{ { selected_table }}',

name: name // 将记录的名称作为参数传递

})

})

.then(response => response.json())

.then(data => {

if (data.success) {

alert('记录删除成功');

row.remove();

} else {

alert('记录删除失败');

}

});

}

</script>

</body>

</html>

注,需要把html放到名为templates的文件夹下。

That’s All,THANKS!



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。