要创建一个宝可梦图鉴网站,使用 Python + MySQL,并实现你描述的功能,以下是完整的代码和操作步骤。
---
### 🧰 技术栈
- **后端**:Python(Flask)
- **数据库**:MySQL
- **前端**:HTML/CSS/JavaScript(Bootstrap)
---
## 1. 数据库设计
### ✅ 创建数据库和表
```sql
-- 创建数据库
CREATE DATABASE pokedex;
-- 使用数据库
USE pokedex;
-- 创建精灵表
CREATE TABLE pokemon (
id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
is_obtained BOOLEAN DEFAULT FALSE,
acquisition_method TEXT,
note TEXT
);
```
---
## 2. 安装依赖
在你的开发环境中运行以下命令:
```bash
pip install flask mysql-connector-python
```
---
## 3. Flask 应用代码
将下面的代码保存为 `app.py`:
```python
from flask import Flask, render_template, request, redirect, url_for
import mysql.connector
import os
app = Flask(__name__)
# 配置数据库连接
db_config = {
'host': 'localhost',
'user': 'root',
'password': 'your_password', # 替换为你的密码
'database': 'pokedex'
}
def get_db_connection():
return mysql.connector.connect(**db_config)
@app.route('/')
def index():
page = int(request.args.get('page', 1))
per_page = 100
offset = (page - 1) * per_page
search_id = request.args.get('search_id')
search_name = request.args.get('search_name')
search_status = request.args.get('search_status')
search_method = request.args.get('search_method')
query = "SELECT * FROM pokemon WHERE 1=1"
params = []
if search_id:
query += " AND id = %s"
params.append(int(search_id))
if search_name:
query += " AND name LIKE %s"
params.append(f"%{search_name}%")
if search_status in ['True', 'False']:
query += " AND is_obtained = %s"
params.append(True if search_status == 'True' else False)
if search_method:
query += " AND acquisition_method LIKE %s"
params.append(f"%{search_method}%")
count_query = "SELECT COUNT(*) FROM pokemon WHERE 1=1"
if params:
count_query += " AND " + " AND ".join([f"{k} = %s" for k in range(len(params))])
conn = get_db_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute(count_query, params)
total_records = cursor.fetchone()['COUNT(*)']
cursor.execute(query + " LIMIT %s OFFSET %s", params + [per_page, offset])
pokemons = cursor.fetchall()
cursor.close()
conn.close()
return render_template('index.html', pokemons=pokemons, page=page, total_records=total_records, per_page=per_page)
@app.route('/edit/<int:pokemon_id>', methods=['GET', 'POST'])
def edit(pokemon_id):
if request.method == 'POST':
name = request.form['name']
is_obtained = 'is_obtained' in request.form
method = request.form['method']
note = request.form['note']
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("""
UPDATE pokemon SET name=%s, is_obtained=%s, acquisition_method=%s, note=%s
WHERE id=%s
""", (name, is_obtained, method, note, pokemon_id))
conn.commit()
cursor.close()
conn.close()
return redirect(url_for('index'))
conn = get_db_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM pokemon WHERE id=%s", (pokemon_id,))
pokemon = cursor.fetchone()
cursor.close()
conn.close()
return render_template('edit.html', pokemon=pokemon)
@app.route('/add', methods=['GET', 'POST'])
def add():
if request.method == 'POST':
id = int(request.form['id'])
name = request.form['name']
is_obtained = 'is_obtained' in request.form
method = request.form['method']
note = request.form['note']
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("""
INSERT INTO pokemon (id, name, is_obtained, acquisition_method, note)
VALUES (%s, %s, %s, %s, %s)
""", (id, name, is_obtained, method, note))
conn.commit()
cursor.close()
conn.close()
return redirect(url_for('index'))
return render_template('add.html')
@app.route('/batch_update', methods=['GET', 'POST'])
def batch_update():
if request.method == 'POST':
data = request.form
ids = data.getlist('ids[]')
names = data.getlist('names[]')
obtained = data.getlist('obtained[]')
methods = data.getlist('methods[]')
notes = data.getlist('notes[]')
conn = get_db_connection()
cursor = conn.cursor()
for i in range(len(ids)):
cursor.execute("""
UPDATE pokemon SET name=%s, is_obtained=%s, acquisition_method=%s, note=%s
WHERE id=%s
""", (names[i], obtained[i] == 'on', methods[i], notes[i], ids[i]))
conn.commit()
cursor.close()
conn.close()
return redirect(url_for('index'))
return render_template('batch_update.html')
if __name__ == '__main__':
app.run(debug=True)
```
---
## 4. HTML 模板
### `templates/index.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>宝可梦图鉴</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h1 class="mb-4">宝可梦图鉴</h1>
<!-- 搜索表单 -->
<form method="get" class="mb-3">
<div class="row g-3">
<div class="col-md-2">
<input type="text" name="search_id" class="form-control" placeholder="ID" value="{{ request.args.search_id }}">
</div>
<div class="col-md-2">
<input type="text" name="search_name" class="form-control" placeholder="名称" value="{{ request.args.search_name }}">
</div>
<div class="col-md-2">
<select name="search_status" class="form-select">
<option value="">获取状态</option>
<option value="True" {% if request.args.search_status == 'True' %} selected {% endif %}>已获取</option>
<option value="False" {% if request.args.search_status == 'False' %} selected {% endif %}>未获取</option>
</select>
</div>
<div class="col-md-2">
<input type="text" name="search_method" class="form-control" placeholder="获取途径" value="{{ request.args.search_method }}">
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-primary">搜索</button>
<a href="/" class="btn btn-secondary">重置</a>
</div>
</div>
</form>
<!-- 显示记录数 -->
<p>共找到 {{ total_records }} 条记录</p>
<!-- 表格展示数据 -->
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>获取状态</th>
<th>获取途径</th>
<th>备注</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for p in pokemons %}
<tr>
<td>{{ p.id }}</td>
<td>{{ p.name }}</td>
<td>{% if p.is_obtained %}✅ 已获取{% else %}❌ 未获取{% endif %}</td>
<td>{{ p.acquisition_method or '-' }}</td>
<td>{{ p.note or '-' }}</td>
<td><a href="/edit/{{ p.id }}" class="btn btn-sm btn-warning">编辑</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- 分页 -->
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
{% if page > 1 %}
<li class="page-item"><a class="page-link" href="?page={{ page - 1 }}">上一页</a></li>
{% else %}
<li class="page-item disabled"><span class="page-link">上一页</span></li>
{% endif %}
<li class="page-item"><span class="page-link">第 {{ page }} 页 / 共 {{ (total_records // 100) + 1 }} 页</span></li>
{% if page < (total_records // 100) + 1 %}
<li class="page-item"><a class="page-link" href="?page={{ page + 1 }}">下一页</a></li>
{% else %}
<li class="page-item disabled"><span class="page-link">下一页</span></li>
{% endif %}
</ul>
</nav>
<!-- 添加按钮 -->
<a href="/add" class="btn btn-success mt-3">添加新精灵</a>
<a href="/batch_update" class="btn btn-info mt-3">批量更新</a>
</div>
</body>
</html>
```
### `templates/edit.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>编辑精灵信息</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h1>编辑精灵信息</h1>
<form method="post">
<div class="mb-3">
<label>ID</label>
<input type="text" name="id" class="form-control" value="{{ pokemon.id }}" readonly>
</div>
<div class="mb-3">
<label>名称</label>
<input type="text" name="name" class="form-control" value="{{ pokemon.name }}">
</div>
<div class="mb-3 form-check">
<input type="checkbox" name="is_obtained" class="form-check-input" {% if pokemon.is_obtained %} checked {% endif %}>
<label class="form-check-label">是否已获取</label>
</div>
<div class="mb-3">
<label>获取途径</label>
<input type="text" name="method" class="form-control" value="{{ pokemon.acquisition_method or '' }}">
</div>
<div class="mb-3">
<label>备注</label>
<textarea name="note" class="form-control">{{ pokemon.note or '' }}</textarea>
</div>
<button type="submit" class="btn btn-primary">保存更改</button>
</form>
</div>
</body>
</html>
```
### `templates/add.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加新精灵</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h1>添加新精灵</h1>
<form method="post">
<div class="mb-3">
<label>ID</label>
<input type="number" name="id" class="form-control" required>
</div>
<div class="mb-3">
<label>名称</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="mb-3 form-check">
<input type="checkbox" name="is_obtained" class="form-check-input">
<label class="form-check-label">是否已获取</label>
</div>
<div class="mb-3">
<label>获取途径</label>
<input type="text" name="method" class="form-control">
</div>
<div class="mb-3">
<label>备注</label>
<textarea name="note" class="form-control"></textarea>
</div>
<button type="submit" class="btn btn-primary">添加精灵</button>
</form>
</div>
</body>
</html>
```
### `templates/batch_update.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>批量更新精灵信息</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h1>批量更新精灵信息</h1>
<form method="post">
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>获取状态</th>
<th>获取途径</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<!-- 示例数据,实际应从数据库中获取并填充 -->
<tr>
<td><input type="text" name="ids[]" class="form-control" value="1"></td>
<td><input type="text" name="names[]" class="form-control" value="皮卡丘"></td>
<td><input type="checkbox" name="obtained[]" class="form-check-input"></td>
<td><input type="text" name="methods[]" class="form-control" value="野生捕捉"></td>
<td><input type="text" name="notes[]" class="form-control" value="电系"></td>
</tr>
<tr>
<td><input type="text" name="ids[]" class="form-control" value="2"></td>
<td><input type="text" name="names[]" class="form-control" value="杰尼龟"></td>
<td><input type="checkbox" name="obtained[]" class="form-check-input"></td>
<td><input type="text" name="methods[]" class="form-control" value="进化获得"></td>
<td><input type="text" name="notes[]" class="form-control" value="水系"></td>
</tr>
</tbody>
</table>
<button type="submit" class="btn btn-primary">批量更新</button>
</form>
</div>
</body>
</html>
```
---
## 5. 部署说明
1. **安装 MySQL**
- Windows: 下载 MySQL 官网安装包。
- Linux: 使用命令 `sudo apt install mysql-server`。
- macOS: 使用 Homebrew `brew install mysql`。
2. **启动 MySQL 服务**
```bash
sudo systemctl start mysql
```
3. **创建用户和权限(可选)**
```sql
CREATE USER 'web_user'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON pokedex.* TO 'web_user'@'localhost';
FLUSH PRIVILEGES;
```
4. **运行 Flask 应用**
```bash
python app.py
```
默认访问地址:`http://127.0.0.1:5000`
---
##