海南大学交友平台登录页开发实战day4(解决python传输并读取登录信息的问题)
大家好,欢迎来到海南大学交友平台开发实战系列的第四天!在前三天的开发中,我们已经完成了登录页、注册页的UI布局,以及Python Flask后端的基础搭建,实现了数据库的初始化和核心表结构的创建。今天的核心任务的是打通前端与后端的通信链路,解决"前端页面输入登录/注册信息,通过JS调用Python接口,最终实现数据读写数据库"的核心问题,同时记录开发过程中踩过的坑和对应的解决办法,帮助大家避开同类问题,高效完成开发。
本博文采用"前端HTML+JS + 后端Python Flask + 数据库SQLite"的技术栈,全程实战落地,欢迎大家在评论区交流探讨开发过程中遇到的问题。
一、今日开发核心目标
-
提取前端JS中与接口调用、数据传输相关的核心代码,实现前端与后端的联动;
-
完成本地测试,确保前端输入的登录、注册信息,能通过JS调用Flask接口,成功写入/读取SQLite数据库;
-
解决开发过程中遇到的"接口调用失败""数据库读写异常""数据传输不匹配"等问题;
-
梳理全流程逻辑,帮助大家理解"HTML页面 → JS接口请求 → Python后端处理 → 数据库读写"的完整链路。
二、核心代码梳理(接口相关)
今天的核心是"数据传输",因此重点提取前端JS中接口调用相关代码,以及后端Python中对应的接口实现代码,去掉冗余部分,方便大家直接复用和理解。
2.1 前端JS(接口调用核心代码)
前端核心功能是通过JS的fetch方法,向Flask后端发送POST请求,传递登录、注册信息,并接收后端返回的结果,实现页面的交互反馈。以下是简化后的核心代码,保留了数据传输、接口调用的关键逻辑,去掉了页面切换、表单验证的冗余代码:
javascript
// API基础地址(与Flask后端服务地址保持一致)
const API_BASE = 'http://127.0.0.1:5000';
// 登录按钮点击事件(核心:调用登录接口,传输登录信息)
document.querySelector('#login-page .btn-primary').addEventListener('click', async (e) => {
e.preventDefault();
// 获取前端输入的学号和密码
const studentId = document.getElementById('login-student-id').value;
const password = document.getElementById('login-password').value;
// 简单验证:学号和密码不能为空
if (!studentId || !password) {
alert('请输入学号和密码');
return;
}
try {
// 向后端发送POST请求,传递登录数据
const response = await fetch(`${API_BASE}/api/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json' // 声明数据格式为JSON
},
body: JSON.stringify({
student_id: studentId, // 与后端接口参数名保持一致
password: password
})
});
// 接收后端返回的JSON数据
const data = await response.json();
// 根据后端返回结果,给出前端反馈
if (data.success) {
// 登录成功,跳转到主页
window.location.href = 'home.html';
} else {
// 登录失败,提示错误信息(后端返回的错误提示)
alert(data.message || '账号或密码错误');
}
} catch (error) {
// 捕获请求异常(如后端未启动、接口地址错误)
console.error('登录请求失败:', error);
alert('网络错误,请检查服务器是否运行');
}
});
// 注册表单提交事件(核心:调用注册接口,传输注册信息)
document.getElementById('register-form').addEventListener('submit', async (e) => {
e.preventDefault();
// 密码一致性验证(简化版)
const pwd = document.getElementById('register-password').value;
const confirmPwd = document.getElementById('register-confirm-password').value;
const errorTip = document.getElementById('pwd-error');
if (pwd !== confirmPwd) {
errorTip.style.display = 'block';
return;
}
errorTip.style.display = 'none';
// 获取前端输入的注册信息
const studentId = document.getElementById('register-student-id').value;
const name = document.getElementById('register-name').value;
const wechat = document.getElementById('register-wechat').value;
const qq = document.getElementById('register-qq').value;
const phone = document.getElementById('register-phone').value;
try {
// 向后端发送POST请求,传递注册数据
const response = await fetch(`${API_BASE}/api/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
student_id: studentId,
password: pwd,
name: name,
wechat: wechat,
qq: qq,
phone: phone
})
});
// 接收后端返回的结果
const data = await response.json();
// 前端反馈处理
if (data.success) {
alert('注册成功!请登录');
document.getElementById('register-form').reset(); // 清空表单
switchPage('login-page'); // 跳转到登录页
} else {
alert(data.message || '注册失败');
}
} catch (error) {
console.error('注册请求失败:', error);
alert('网络错误,请检查服务器是否运行');
}
});
2.2 后端Python(接口实现核心代码)
后端Flask的核心是提供登录、注册接口,接收前端JS传递的JSON数据,调用数据库操作函数,完成数据的读写,并返回对应的结果(成功/失败+提示信息)。以下是接口相关的核心代码,保留了关键逻辑:
python
from flask import Flask, request, jsonify
from flask_cors import CORS
import sqlite3
import os
app = Flask(__name__)
CORS(app) # 解决跨域问题(前端调用后端接口必加)
# 数据库配置
DB_FILE = 'hainanu.db'
# 数据库连接函数
def get_db_connection():
conn = sqlite3.connect(DB_FILE)
conn.row_factory = sqlite3.Row
return conn
# 注册接口(接收前端注册信息,写入数据库)
@app.route('/api/register', methods=['POST'])
def register():
data = request.get_json() # 接收前端传递的JSON数据
# 提取前端传递的参数(与JS中body的参数名保持一致)
student_id = data.get('student_id')
password = data.get('password')
name = data.get('name')
wechat = data.get('wechat', '')
qq = data.get('qq', '')
phone = data.get('phone', '')
# 验证必填参数(学号、密码、姓名不能为空)
if not student_id or not password or not name:
return jsonify({'success': False, 'message': '学号、密码和姓名不能为空'}), 400
# 检查学号是否已存在(避免重复注册)
existing_user = get_user_by_student_id(student_id)
if existing_user:
return jsonify({'success': False, 'message': '学号已存在'}), 409
# 调用数据库操作函数,写入注册信息
success, message = create_user(student_id, password, name, wechat, qq, phone)
if success:
return jsonify({'success': True, 'message': message}), 201
else:
return jsonify({'success': False, 'message': message}), 409
# 登录接口(接收前端登录信息,验证数据库)
@app.route('/api/login', methods=['POST'])
def login():
data = request.get_json()
student_id = data.get('student_id')
password = data.get('password')
# 验证必填参数
if not student_id or not password:
return jsonify({'success': False, 'message': '学号和密码不能为空'}), 400
# 从数据库中查询该学号对应的用户信息
user = get_user_by_student_id(student_id)
# 验证密码是否正确(此处为明文验证,后续会优化)
if user and user['password'] == password:
return jsonify({
'success': True,
'message': '登录成功',
'data': {
'id': user['id'],
'student_id': user['student_id'],
'name': user['name']
}
})
else:
return jsonify({'success': False, 'message': '账号或密码错误'}), 401
# 数据库操作辅助函数(简化版)
def get_user_by_student_id(student_id):
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('SELECT * FROM users WHERE student_id = ?', (student_id,))
user = cursor.fetchone()
conn.close()
return user
def create_user(student_id, password, name, wechat=None, qq=None, phone=None):
try:
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute('''
INSERT INTO users (student_id, password, name, wechat, qq, phone)
VALUES (?, ?, ?, ?, ?, ?)
''', (student_id, password, name, wechat, qq, phone))
conn.commit()
conn.close()
return True, "注册成功"
except sqlite3.IntegrityError:
return False, "学号已存在"
# 启动服务
if __name__ == '__main__':
init_db() # 初始化数据库(第一次运行自动创建表)
print("服务器启动成功!访问地址: http://127.0.0.1:5000")
app.run(debug=True, host='127.0.0.1', port=5000)
三、本地测试全流程逻辑(关键步骤)
今天的核心是"打通链路",因此本地测试的每一步都至关重要,以下是完整的测试流程,按照步骤操作,就能确保前端能正常控制Python后端,实现数据库的读写操作,全程无坑:
3.1 测试准备(必做)
-
确保已安装所需依赖:打开PyCharm内置终端,输入命令
pip install flask flask-cors,安装Flask框架和跨域插件(跨域插件必须装,否则前端调用接口会报错); -
确认前端HTML文件、JS文件、后端Python文件(app.py)放在同一目录下,避免路径错误;
-
确保后端Python代码中的数据库路径正确,本文使用相对路径(DB_FILE = 'hainanu.db'),第一次运行会自动生成数据库文件。
3.2 测试步骤(按顺序执行)
步骤1:启动Flask后端服务
打开PyCharm,找到后端Python文件(app.py),右键点击"Run 'app'",启动服务。启动成功后,终端会显示以下信息,说明后端服务正常运行,接口可访问:
bash
数据库初始化完成
==================================================
服务器启动成功!
访问地址: http://127.0.0.1:5000
==================================================
* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
(此处的WARNING是开发服务器提示,不是错误,本地测试可忽略,后续上线再优化)
步骤2:打开前端HTML页面
找到前端登录页HTML文件(如login.html),双击打开,或者用浏览器打开该文件,确保页面能正常显示(登录框、注册框、按钮均可正常点击)。
步骤3:测试注册功能(写入数据)
-
点击登录页的"去注册"按钮,切换到注册页面;
-
输入完整的注册信息(学号、密码、姓名、微信等,学号确保唯一);
-
点击"注册"按钮,若提示"注册成功!请登录",说明前端JS成功调用了后端注册接口,并且数据已成功写入SQLite数据库;
-
此时可在Python文件所在目录找到hainanu.db文件,用SQLite可视化工具(如DB Browser for SQLite)打开,查看users表,能看到刚刚注册的用户信息,说明数据写入成功。

步骤4:测试登录功能(读取数据)
-
注册成功后,自动跳转到登录页面,输入刚刚注册的学号和密码;
-
点击"登录"按钮,若提示"登录成功"并跳转到主页(home.html),说明前端JS成功调用了后端登录接口,并且后端成功从数据库中读取了用户信息,完成了密码验证;
-
若输入错误的学号或密码,会提示"账号或密码错误",说明后端的验证逻辑正常。

步骤5:验证数据库读取结果
登录成功后,后端会从数据库中读取该用户的id、学号、姓名等信息,并返回给前端,前端可根据这些信息进行后续的页面展示(如个人中心)。用SQLite工具查看users表,确认读取的数据与前端输入的一致,整个链路打通。

四、开发踩坑经验与解决办法(重点!)
今天开发过程中,我踩了3个核心坑,花费了不少时间排查,整理出来分享给大家,避免大家重复踩坑,提高开发效率。
坑1:前端调用接口报错"跨域问题"(最常见)
报错现象:前端点击登录/注册按钮,控制台报错"Access to fetch at 'http://127.0.0.1:5000/api/login' from origin 'null' has been blocked by CORS policy",接口调用失败。
原因分析:前端HTML页面是本地打开(协议为file://),而后端服务的协议是http://,不同协议之间的接口调用会被浏览器的跨域政策拦截,导致请求失败。
解决办法:在Flask后端代码中添加CORS配置,允许跨域请求。具体操作就是在创建app实例后,添加一行 CORS(app),如本文后端代码所示。添加后重启后端服务,跨域问题即可解决。
坑2:后端报错"no such column: student_id"(数据库表结构不匹配)
报错现象:前端提交注册信息后,后端终端报错"sqlite3.OperationalError: no such column: student_id",接口返回失败。
原因分析:后端代码中的init_db()函数(初始化数据库、创建表),只有第一次运行时才会执行。如果后续修改了表结构(如添加student_id列),或者复制了代码文件夹,导致数据库文件(hainanu.db)是旧的,旧表中没有student_id列,就会报错。
解决办法:最省事的方式是"重置数据库":① 停止Flask服务(按Ctrl+C);② 找到Python文件所在目录,删除hainanu.db文件;③ 重新运行app.py,代码会自动执行init_db(),创建结构正确的users表,报错即可解决。
坑3:前端传递的数据,后端无法接收(参数名不匹配)
报错现象:前端点击登录/注册,后端终端没有报错,但返回"学号和密码不能为空",即使已经输入了信息。
原因分析:前端JS传递的参数名,与后端接口接收的参数名不一致。比如前端传递的是"studentId",而后端接收的是"student_id",参数名不匹配,后端无法获取到数据,就会判定为"未输入"。
解决办法:确保前端JS中JSON数据的参数名,与后端request.get_json()获取的参数名完全一致。本文中前端传递的是"student_id""password",后端也是用这两个参数名接收,避免大小写、下划线的差异。
坑4:后端服务启动成功,但前端提示"网络错误"
报错现象:后端终端显示启动成功,但前端点击按钮后,提示"网络错误,请检查服务器是否运行"。
原因分析:① 前端JS中的API_BASE地址错误,比如写成了"http://127.0.0.1:5001",与后端服务的端口(5000)不一致;② 后端服务未正常启动,或者启动后被意外关闭;③ 电脑防火墙拦截了本地服务。
解决办法:① 核对API_BASE地址,确保与后端启动的地址(http://127.0.0.1:5000)完全一致;② 检查后端终端,确保服务处于运行状态;③ 临时关闭电脑防火墙,重新测试。
五、今日总结与明日计划
今日顺利打通了前端与后端的通信链路,完成了登录、注册功能的本地测试,实现了"HTML页面 → JS接口请求 → Python后端处理 → SQLite数据库读写"的完整流程,同时解决了开发过程中遇到的跨域、数据库表结构不匹配、参数名不匹配等核心问题,积累了宝贵的实战经验。
通过今天的开发,深刻体会到"前后端参数一致性""数据库表结构同步"的重要性,尤其是新手开发,细节决定成败,一个小小的参数名错误、路径错误,都可能导致整个链路无法打通,耐心排查才能高效解决问题。
明日计划:构建主页UI,和主要功能栏目
如果大家在开发过程中遇到了和我一样的问题,或者有更好的解决办法,欢迎在评论区留言交流;如果觉得本文对你有帮助,别忘了点赞、收藏、关注,后续会持续更新海南大学交友平台的开发实战内容,和大家一起从0到1完成项目开发!