title: How to update table using sqlalchemy and flask
body: <p>can someone please give me a hand here?
  I am trying to complete a CRUD using Flask and I am having some issues while I am trying to edit a client on the DB. I don't have errors but nothing is update. I am not sure if its some routing thing that I don't have clear.
  I am posting the files I think could help, but let me know if something else is needed.
  Thanks and regards!</p>
  
  <p>app.py</p>
  
  <pre><code>login_manager = LoginManager(app)
  login_manager.login_view = "login"
  db = SQLAlchemy(app)
  
  from models import User, Client
  
  @app.route("/")
  def index():
      user_id = current_user.get_id()
      clients = Client.get_by_user_id(user_id)
      return render_template("index.html", clients=clients)
  
  
  @app.route("/client/&lt;int:id&gt;/", methods=['GET', 'POST'])
  def show_client(id):
  
      client = Client.get_by_id(id)
      form = ClientEditForm(obj=client)
      if client is None:
          abort(404)
      return render_template("client_view.html", client=client, form=form)
  
  @app.route("/admin/client/", methods=['GET', 'POST'], defaults={'client_id': None})
  @app.route("/admin/client/&lt;int:client_id&gt;/", methods=['GET', 'POST'])
  @login_required
  def client_form(client_id):
      form = ClientForm()
      if form.validate_on_submit():
          name = form.name.data
          last_name = form.last_name.data
          cuit = form.cuit.data
          password = form.password.data
          date_from = form.date_from.data
          date_to = form.date_to.data
          category = form.category.data
  
          client = Client(user_id=current_user.id, name=name, last_name=last_name, cuit=cuit, password=password ,date_from=date_from, date_to=date_to, category=category)
          client.save()
  
          return redirect(url_for('index'))
      return render_template("admin/client_form.html", form=form)
  
  #start client edit
  
  @app.route("/clientEdit/", methods=['GET', 'POST'], defaults={'client_id': None})
  @app.route("/clientEdit/&lt;int:client_id&gt;/", methods=['GET', 'POST'])
  @login_required
  def client_edit_form(client_id):
      form = ClientEditForm()
      if form.validate_on_submit():
          name = form.name.data
          last_name = form.last_name.data
          cuit = form.cuit.data
          password = form.password.data
          date_from = form.date_from.data
          date_to = form.date_to.data
          category = form.category.data
          client = Client(user_id=current_user.id, name=name, last_name=last_name, cuit=cuit, password=password ,date_from=date_from, date_to=date_to, category=category)
          client.save()
  
  
          return redirect(url_for('index'))
      return render_template("client_view.html", client=client, form=form)
  
  #end client edit
  
  @app.route("/signup/", methods=["GET", "POST"])
  def show_signup_form():
      if current_user.is_authenticated:
          return redirect(url_for('index'))
      form = SignupForm()
      error = None
      if form.validate_on_submit():
          name = form.name.data
          email = form.email.data
          password = form.password.data
          user = User.get_by_email(email)
          if user is not None:
              error = f'El email {email} ya está siendo utilizado por otro usuario'
          else:
              user = User(name=name, email=email)
              user.set_password(password)
              user.save()
              login_user(user, remember=True)
              next_page = request.args.get('next', None)
              if not next_page or url_parse(next_page).netloc != '':
                  next_page = url_for('index')
              return redirect(next_page)
      return render_template("signup_form.html", form=form, error=error)
  
  @login_manager.user_loader
  def load_user(user_id):
      return User.get_by_id(int(user_id))
  
  @app.route('/login', methods=['GET', 'POST'])
  def login():
      if current_user.is_authenticated:
          return redirect(url_for('index'))
      form = LoginForm()
      if form.validate_on_submit():
          user = User.get_by_email(form.email.data)
          if user is not None and user.check_password(form.password.data):
              login_user(user, remember=form.remember_me.data)
              next_page = request.args.get('next')
              if not next_page or url_parse(next_page).netloc != '':
                  next_page = url_for('index')
              return redirect(next_page)
      return render_template('login_form.html', form=form)
  
  @app.route('/logout')
  def logout():
      logout_user()
      return redirect(url_for('index'))
  </code></pre>
  
  <p>client_view.html</p>
  
  <pre><code>{% extends "base_template.html" %}
  
  {% block title %}{{ client.cuit }}{% endblock %}
  
  {% block content %}
  &lt;h1&gt;{{ client.last_name }}&lt;/h1&gt;
  {{ client.name }}
  {{ client.cuit }}
  
  &lt;form action="" method="post" novalidate&gt;
      {{ form.hidden_tag() }}
      &lt;div&gt;
          {{ form.name.label }}
          {{ form.name(size=60) }}&lt;br&gt;
          {% for error in form.name.errors %}
          &lt;span style="color: red;"&gt;{{ error }}&lt;/span&gt;
          {% endfor %}
      &lt;/div&gt;
      &lt;div&gt;
          {{ form.last_name.label }}
          {{ form.last_name(size=60) }}&lt;br&gt;
          {% for error in form.last_name.errors %}
          &lt;span style="color: red;"&gt;{{ error }}&lt;/span&gt;
          {% endfor %}
      &lt;/div&gt;
      &lt;div&gt;
          {{ form.cuit.label }}
          {{ form.cuit }}&lt;br&gt;
          {% for error in form.cuit.errors %}
          &lt;span style="color: red;"&gt;{{ error }}&lt;/span&gt;
          {% endfor %}
      &lt;/div&gt;
      &lt;div&gt;
          {{ form.password.label }}
          {{ form.password }}&lt;br&gt;
          {% for error in form.password.errors %}
          &lt;span style="color: red;"&gt;{{ error }}&lt;/span&gt;
          {% endfor %}
      &lt;/div&gt;
      &lt;div&gt;
          {{ form.date_from.label }}
          {{ form.date_from }}&lt;br&gt;
          {% for error in form.date_from.errors %}
          &lt;span style="color: red;"&gt;{{ error }}&lt;/span&gt;
          {% endfor %}
      &lt;/div&gt;
      &lt;div&gt;
          {{ form.date_to.label }}
          {{ form.date_to }}&lt;br&gt;
          {% for error in form.date_to.errors %}
          &lt;span style="color: red;"&gt;{{ error }}&lt;/span&gt;
          {% endfor %}
      &lt;/div&gt;
      &lt;div&gt;
          {{ form.category.label }}
          {{ form.category }}&lt;br&gt;
          {% for error in form.category.errors %}
          &lt;span style="color: red;"&gt;{{ error }}&lt;/span&gt;
          {% endfor %}
      &lt;/div&gt;
      &lt;div&gt;
          {{ form.submit() }}
      &lt;/div&gt;
  &lt;/form&gt;
  {% endblock %}
  </code></pre>
  
  <p>forms.py</p>
  
  <pre><code>from flask_wtf import FlaskForm, RecaptchaField
  from wtforms import StringField, SubmitField, PasswordField, TextAreaField, BooleanField
  from wtforms.validators import DataRequired, Email, Length
  
  
  class SignupForm(FlaskForm):
      name = StringField('Nombre', validators=[DataRequired(), Length(max=64)])
      password = PasswordField('Password', validators=[DataRequired()])
      #email = StringField('Email', validators=[DataRequired(), Email()])
      email = StringField('Email', [Email(message=('Not a valid email address!!!.')), DataRequired()])
      #recaptcha = RecaptchaField()
      submit = SubmitField('Registrar')
  
  class ClientForm(FlaskForm):
      name = StringField('Nombre', validators=[DataRequired(), Length(max=25)])
      last_name = StringField('Apellido', validators=[DataRequired(),Length(max=25)])
      cuit = StringField('Cuit', validators=[DataRequired(),Length(max=11)])
      password = PasswordField('Password', validators=[DataRequired()])
      date_from = StringField('Fecha desde', validators=[DataRequired(),Length(max=10)])
      date_to = StringField('Fecha hasta', validators=[DataRequired(),Length(max=10)])
      category = StringField('Categoria', validators=[DataRequired()])
      submit = SubmitField('Enviar')
  
  class LoginForm(FlaskForm):
      email = StringField('Email', validators=[DataRequired()])
      password = PasswordField('Password', validators=[DataRequired()])
      remember_me = BooleanField('Recuérdame')
      submit = SubmitField('Login')
  
  class ClientEditForm(FlaskForm):
      name = StringField('Nombre', validators=[DataRequired(), Length(max=25)])
      last_name = StringField('Apellido', validators=[DataRequired(),Length(max=25)])
      cuit = StringField('Cuit', validators=[DataRequired(),Length(max=11)])
      password = PasswordField('Password', validators=[DataRequired()])
      date_from = StringField('Fecha desde', validators=[DataRequired(),Length(max=10)])
      date_to = StringField('Fecha hasta', validators=[DataRequired(),Length(max=10)])
      category = StringField('Categoria', validators=[DataRequired()])
      submit = SubmitField('Enviar')
  </code></pre>
  
  <p>models.py</p>
  
  <p>from flask import url_for</p>
  
  <pre><code>from flask_login import UserMixin
  from slugify import slugify
  from sqlalchemy.exc import IntegrityError
  from werkzeug.security import generate_password_hash, check_password_hash
  from app import db
  
  
  class User(db.Model, UserMixin):
  
      __tablename__ = 'users'
  
      id = db.Column(db.Integer, primary_key=True)
      name = db.Column(db.String(80), nullable=False)
      email = db.Column(db.String(256), unique=True, nullable=False)
      password = db.Column(db.String(128), nullable=False)
      is_admin = db.Column(db.Boolean, default=False)
  
      def __repr__(self):
          return f'&lt;User {self.email}&gt;'
  
      def set_password(self, password):
          self.password = generate_password_hash(password)
  
      def check_password(self, password):
          return check_password_hash(self.password, password)
  
      def save(self):
          if not self.id:
              db.session.add(self)
          db.session.commit()
  
      @staticmethod
      def get_by_id(id):
          return User.query.get(id)
  
      @staticmethod
      def get_by_email(email):
          return User.query.filter_by(email=email).first()
  
  class Client(db.Model):
      id = db.Column(db.Integer, primary_key=True)
      user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), nullable=False)
      name = db.Column(db.String(25), nullable=False)
      last_name = db.Column(db.String(25), nullable=False)
      cuit = db.Column(db.String(11), nullable=False)
      password = db.Column(db.String(128), nullable=False)
      date_from = db.Column(db.String(10), nullable=False)
      date_to = db.Column(db.String(10), nullable=False)
      category = db.Column(db.String(1), nullable=True)
  
      def __repr__(self):
          return f'&lt;Post {self.last_name}&gt;'
      def save(self):
          if not self.id:
              db.session.add(self)
          saved = False
          count = 0
          while not saved:
              try:
                  print("tero")
                  db.session.commit()
                  saved = True
              except IntegrityError:
                  count += 1
  
      def public_url(self):
          return url_for('show_client', id=self.id)
  
  
      @staticmethod
      def get_by_id(id):
          return Client.query.get(id)
      @staticmethod
      def get_all():
          return Client.query.all()
      @staticmethod
      def get_by_user_id(user_id):
          return Client.query.filter_by(user_id=user_id).all()
  </code></pre>