TypeError: missing 1 required positional argument, argument is already defined

Question:

first off if you’re reading this, thank you very much. It’s my first time posting here.

I’m a bit new to Flask and Python as a whole.

I’m trying to create a query to check if the user has reserved or not a class. It’s pretty straight forward, I have an activity table in mySQL DB with things like name, description, etc. And I have a reserves table. This reserves table has the activity id (id_actividad) (I program in spanish so variables and such are in spanish) and user id (id_usuario) as well as it’s own id. Basically, it shows the activities perfectly fine and does the check as well. However, when I try to actually make the reservation, I encounter the following error:

 line 258, in reserva_actividad
if Actividades.is_reservado(id_usuario, id_actividad):
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Actividades.is_reservado() missing 1 required positional argument: 'id_actividad'

So my code itself is broken down into 3 main parts, Actividades.py where I delcare my class and methods, usuario.py (which is where I’m currently executing) and then actividades.html, which is the template for this particular part. I’ve tried making the is_reservado class static, taking off the self (oddly, if self is not defined then it doesn’t get anything from reservas, just actividades table) but ultimately it doesn’t work. I’d appreciate any help or something I’m 100% missing here, I’ll leave the relevant fragments of code down below.

Thank you!

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 %}
`
Asked By: luke.misk

||

Answers:

In usuario.py, in the if condition, you are calling the method in a static contect, meaning you’re not calling it on an object of class Actividades.

When you’re calling the method like Actividades.is_reservado(), you would need to pass the object of type Actividades as a first argument and the id’s as second and third. That’s why the error message says that one parameter is missing. Of course you could just do object.is_reservado() and pass on only the two arguments.

Examples:

obj = Actividades(...)

Actividades.is_reservado(obj, id_usuario, id_actividad)
obj.is_reservado(id_usuario, id_actividad)

However, seeing as the method is_reservado doesn’t use any class properties, it might be a better idea to make it a separate function or just annotate it with @staticmethod and remove the self parameter.

Hope that helped.

Answered By: CClairvoyant
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.