Flask调用Actividades.is_reservado()遇TypeError:缺少必填位置参数
问题:Flask调用Actividades.is_reservado()触发TypeError错误
提交预约时出现以下错误:
line 258, in reserva_actividad if Actividades.is_reservado(id_usuario, id_actividad): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: Actividades.is_reservado() missing 1 required positional argument: 'id_actividad'
我是Flask和Python新手,正在开发用户活动预约查询功能。MySQL数据库包含actividades(活动)和reservas(预约)表,reservas表存了id_actividad、id_usuario及自身ID。当前活动展示和前端预约状态检查正常,但提交预约时触发上述错误。尝试将is_reservado设为静态方法、移除self都没解决问题,相关代码如下:
Actividades.py
class Actividades(UserMixin): def __init__(self, id_actividad, nombre, fecha, hora_inicio, hora_fin, detalles, capacidad) -> None: self.id_actividad = id_actividad self.nombre = nombre self.fecha = fecha self.hora_inicio = hora_inicio self.hora_fin = hora_fin self.detalles = detalles self.capacidad = capacidad def is_reservado(self, id_usuario, id_actividad): try: con = conexion() with con.cursor() as cursor: cursor.execute('SELECT * FROM reservas WHERE id_actividad = %s AND id_usuario = %s', (id_actividad, id_usuario)) reserva = cursor.fetchone() if reserva: return True else: return False except Exception as ex: raise Exception(ex)
usuario.py
@app.route('/reserva_actividad', methods=['POST']) def reserva_actividad(): id_actividad = int(request.form['id_actividad']) print("id_actividad:", id_actividad) # gets it correctly, for example, 3 id_usuario = current_user.get_id() print("id_usuario:", id_usuario) # also gets it correctly, for example, 22 if Actividades.is_reservado(id_usuario, id_actividad): # User already has a reservation for this activity, handle accordingly print("User already has a reservation for this activity") return "You already have a reservation for this activity" Actividades.reserva(id_actividad, id_usuario) return redirect(url_for('actividades'))
actividades.html
{% extends "layouts.html" %} {% block contentD %} <style> .reservado { color: red; } .disponible { color: green; } </style> <h1>Actividades Disponibles</h1> <table class="table"> <thead> <tr> <th>Nombre</th> <th>Fecha</th> <th>Hora de inicio</th> <th>Hora de fin</th> <th>Capacidad</th> <th>Reservada</th> <th>Acción</th> </tr> </thead> <tbody> {% for actividad in actividades %} <tr> <td>{{ actividad.nombre }}</td> <td>{{ actividad.fecha }}</td> <td>{{ actividad.hora_inicio }}</td> <td>{{ actividad.hora_fin }}</td> <td>{{ actividad.capacidad }}</td> {% if actividad.is_reservado(current_user.id, actividad.id_actividad) %} <td class="reservado">Reservado</td> {% else %} <td class="disponible">Disponible</td> {% endif %} <td> {% if not actividad.is_reservado(current_user.id, actividad.id_actividad) %} <form action="/reserva_actividad" method="POST"> <input type="hidden" name="id_actividad" value="{{ actividad.id_actividad }}"> <button type="submit" class="btn btn-primary">Reservar</button> </form> {% else %} <form action="/cancelar_reserva" method="POST"> <input type="hidden" name="id_actividad" value="{{ actividad.id_actividad }}"> <button type="submit" class="btn btn-danger">Cancelar</button> </form> {% endif %} </td> </tr> {% endfor %} </tbody> </table> {% endblock contentD %}
解决方案
核心问题
is_reservado是实例方法,需要通过Actividades类的实例调用,但你在usuario.py中直接用类名调用Actividades.is_reservado(),导致Python将传入的id_usuario当作self参数,原本的id_actividad参数就缺失了,从而触发错误。
修复方案(两种可选)
方案一:将is_reservado改为静态方法(推荐,适配类和实例调用)
修改Actividades.py中的is_reservado方法,添加@staticmethod装饰器,这样既支持类调用(usuario.py代码无需修改),也支持实例调用(前端模板代码可兼容):
class Actividades(UserMixin): # ... __init__方法保持不变 ... @staticmethod def is_reservado(id_usuario, id_actividad): try: con = conexion() with con.cursor() as cursor: cursor.execute('SELECT * FROM reservas WHERE id_actividad = %s AND id_usuario = %s', (id_actividad, id_usuario)) reserva = cursor.fetchone() return reserva is not None # 简化返回逻辑 except Exception as ex: raise Exception(ex)
修改后,usuario.py中的Actividades.is_reservado(id_usuario, id_actividad)即可正常运行,前端模板代码也无需改动。
方案二:保留实例方法,在usuario.py中先获取活动实例
如果更倾向于面向实例的设计,可以先从数据库获取对应活动的实例,再调用方法:
- 实现一个查询活动的辅助方法:
def get_actividad_by_id(id_actividad): con = conexion() with con.cursor() as cursor: cursor.execute('SELECT id_actividad, nombre, fecha, hora_inicio, hora_fin, detalles, capacidad FROM actividades WHERE id_actividad = %s', (id_actividad,)) data = cursor.fetchone() if data: return Actividades(*data) return None
- 修改usuario.py的视图函数:
@app.route('/reserva_actividad', methods=['POST']) def reserva_actividad(): id_actividad = int(request.form['id_actividad']) id_usuario = current_user.get_id() actividad = get_actividad_by_id(id_actividad) if not actividad: return "Activity not found", 404 # 调用实例方法,无需传id_actividad,直接用self.id_actividad if actividad.is_reservado(id_usuario): print("User already has a reservation for this activity") return "You already have a reservation for this activity" Actividades.reserva(id_actividad, id_usuario) return redirect(url_for('actividades'))
- 同步简化Actividades.py的
is_reservado方法:
def is_reservado(self, id_usuario): try: con = conexion() with con.cursor() as cursor: cursor.execute('SELECT * FROM reservas WHERE id_actividad = %s AND id_usuario = %s', (self.id_actividad, id_usuario)) reserva = cursor.fetchone() return reserva is not None except Exception as ex: raise Exception(ex)
- 修改前端模板actividades.html,去掉多余的
id_actividad参数:
{% if actividad.is_reservado(current_user.id) %} <td class="reservado">Reservado</td> {% else %} <td class="disponible">Disponible</td> {% endif %} <!-- 下方判断逻辑同步修改 --> {% if not actividad.is_reservado(current_user.id) %} <!-- 预约表单 --> {% else %} <!-- 取消表单 --> {% endif %}
内容的提问来源于stack exchange,提问作者luke.misk
相关产品推荐
相关产品推荐

