You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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中先获取活动实例

如果更倾向于面向实例的设计,可以先从数据库获取对应活动的实例,再调用方法:

  1. 实现一个查询活动的辅助方法:
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
  1. 修改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'))
  1. 同步简化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)
  1. 修改前端模板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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 05:14:57