Home > Software engineering >  Flask-SQLAlchemy TypeError: %d format: a number is required, not str when using filter on a string f
Flask-SQLAlchemy TypeError: %d format: a number is required, not str when using filter on a string f

Time:10-21

I really don't have a clue of what is going on that i can't filter this query, tried filter_by() and filter() both return the same error, it is probably a stupid mistake that i'm failing to notice, your help would be really appreciated. The MariaDB(MySQL) table structure is

 -------------- -------------- ------ ----- --------- ---------------- 
| Field        | Type         | Null | Key | Default | Extra          |
 -------------- -------------- ------ ----- --------- ---------------- 
| id           | int(11)      | NO   | PRI | NULL    | auto_increment |
| classe       | int(11)      | NO   |     | NULL    |                |
| nome         | varchar(20)  | NO   |     | NULL    |                |
| sobrenome    | varchar(50)  | NO   |     | NULL    |                |
| razao_social | varchar(255) | YES  |     | NULL    |                |
| cpf_cnpj     | varchar(18)  | NO   | UNI | NULL    |                |
| rg_ie        | varchar(15)  | NO   | UNI | NULL    |                |
| email        | varchar(120) | NO   | UNI | NULL    |                |
| fone         | varchar(11)  | YES  |     | NULL    |                |
| celular      | varchar(14)  | NO   | UNI | NULL    |                |
| password     | varchar(60)  | NO   |     | NULL    |                |
| date_created | datetime     | NO   |     | NULL    |                |
| ip_created   | varchar(45)  | YES  |     | NULL    |                |
| api_token    | varchar(60)  | NO   |     | NULL    |                |
 -------------- -------------- ------ ----- --------- ---------------- 

The exception is

TypeError: %d format: a number is required, not str

when using filter on a string field on line

user = User.query.filter(User.api_token == token).first()

Here is the whole route function

@app.route('/api/login', methods=['GET','POST'])
def api_login():
    if current_user.is_authenticated:
        return "3"
    token = request.args.get('apitoken', '1', type=String)
    ip_ban.add(ip=request.host.split(':')[0],url=url_for('login'))
    user = User.query.filter(User.api_token == token).first()
    if user:
        if current_user.classe == -1 :
            return "-1"
        if current_user.classe == 0 :
            return "0"
        login_user(user)
        loginrec = UserLogins(user_id= user.id, login_ip= request.host.split(':')[0])
        db.session.add(loginrec)
        db.session.commit()
        return "2"
    else:
        return token

As requested: Model of User:

class User(db.Model,UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    classe = db.Column(db.Integer, nullable=False, default=1)
    nome = db.Column(db.String(20), nullable=False)
    sobrenome = db.Column(db.String(50), nullable=False)
    razao_social = db.Column(db.String(255))
    cpf_cnpj = db.Column(db.String(18), unique=True, nullable=False)
    rg_ie = db.Column(db.String(15), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    fone = db.Column(db.String(11))
    celular = db.Column(db.String(14), unique=True, nullable=False)
    password = db.Column(db.String(60), nullable=False)
    date_created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    ip_created = db.Column(db.String(45))
    api_token = db.Column(db.String(60))
    logins = db.relationship('UserLogins', backref='author', lazy=True)
    posts = db.relationship('Post', backref='author', lazy=True)
    tickets = db.relationship('SupportTicket', backref='author', lazy=True)
    produtos = db.relationship('UserProduto', backref='author', lazy=True)
    terminais = db.relationship('Terminal', backref='author', lazy=True)
    ordem_servicos = db.relationship('Ordemservico', backref='author', lazy=True)

    def __repr__(self):
        return f"Usuario('{self.id}', '{self.email}','{self.nome}','{self.sobrenome}','{self.razao_social}','{self.cpf_cnpj}','{self.rg_ie}','{self.fone}','{self.celular}')"

Full traceback

Traceback (most recent call last):
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/flask/app.py", line 2088, in __call__
    return self.wsgi_app(environ, start_response)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/flask/app.py", line 2073, in wsgi_app
    response = self.handle_exception(e)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/flask/app.py", line 2070, in wsgi_app
    response = self.full_dispatch_request()
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/flask/app.py", line 1515, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/flask/app.py", line 1513, in full_dispatch_request
    rv = self.dispatch_request()
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/flask/app.py", line 1499, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/mnt/dados/Documentos/Sources/siteplanos/siteplanos/routes.py", line 615, in api_login
    user = User.query.filter(User.api_token == token).first()
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2762, in first
    return self.limit(1)._iter().first()
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2846, in _iter
    result = self.session.execute(
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 1689, in execute
    result = conn._execute_20(statement, params or {}, execution_options)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1611, in _execute_20
    return meth(self, args_10style, kwargs_10style, execution_options)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
    return connection._execute_clauseelement(
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1478, in _execute_clauseelement
    ret = self._execute_context(
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1842, in _execute_context
    self._handle_dbapi_exception(
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2027, in _handle_dbapi_exception
    util.raise_(exc_info[1], with_traceback=exc_info[2])
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
    raise exception
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1799, in _execute_context
    self.dialect.do_execute(
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 717, in do_execute
    cursor.execute(statement, parameters)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/pymysql/cursors.py", line 146, in execute
    query = self.mogrify(query, args)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/pymysql/cursors.py", line 125, in mogrify
    query = query % self._escape_args(args, conn)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/pymysql/cursors.py", line 109, in _escape_args
    return {key: conn.literal(val) for (key, val) in args.items()}
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/pymysql/cursors.py", line 109, in <dictcomp>
    return {key: conn.literal(val) for (key, val) in args.items()}
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/pymysql/connections.py", line 517, in literal
    return self.escape(obj, self.encoders)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/pymysql/connections.py", line 510, in escape
    return converters.escape_item(obj, self.charset, mapping=mapping)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/pymysql/converters.py", line 25, in escape_item
    val = encoder(val, mapping)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/pymysql/converters.py", line 95, in escape_str
    return "'%s'" % escape_string(str(value), mapping)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/sql/type_api.py", line 705, in __str__
    return str(self.compile())
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/sql/type_api.py", line 692, in compile
    return dialect.type_compiler.process(self)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/sql/compiler.py", line 4844, in process
    return _compiler_dispatch(self, **kw)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/sql/visitors.py", line 82, in _compiler_dispatch
    return meth(self, **kw)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/sql/compiler.py", line 4809, in visit_string
    return self.visit_VARCHAR(type_, **kw)
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/sql/compiler.py", line 4755, in visit_VARCHAR
    return self._render_string_type(type_, "VARCHAR")
  File "/mnt/dados/Documentos/Sources/siteplanos/.venv/lib/python3.8/site-packages/sqlalchemy/sql/compiler.py", line 4743, in _render_string_type
    text  = "(%d)" % type_.length
TypeError: %d format: a number is required, not str

CodePudding user response:

Found the issue, the problem was on line

token = request.args.get('apitoken', '1', type=String)

The correct way is

token = request.args.get('apitoken', '1', type=str)
  • Related