Repository navigation
Pyright cannot recognize the type of SQLModel.__tablename__ #98
Description
Activity
this is my workaround to silence that type of errors (not my proudest hack but it work)
from sqlmodel import SQLModel from sqlalchemy.orm import declared_attr class User(SQLModel, table=True): name: str @declared_attr def __tablename__(cls): # noqa: N805 return 'users'
inspired by the declared_attr documentation, tested with pyright 1.1.172 (Linux), python 3.9.7, sqlmodel 0.0.4
Reacted by Rob Cannon, Max Sysoev and Christopher Carroll Smith@Chedi Hi, of my own workaround is adding a
# type: ignoreafter__tablename__ = "users".With @Chedi 's workaround, I still get an error on Mypy:
error: Signature of "__tablename__" incompatible with supertype "SQLModel".
Only# type: ignoreworks.another really easy workaround is just specifying the type:
__tablename__: str = 'poop'Reacted by Andrea Parisi, Jacob Linney, Zaffer, Ganesh Rao, Jonas Frei, Joel Ferreira, Stéphane Rabenarisoa, hecarson, Kyrylo Omelchenko, Maksim Kulichenko and 1 moreReacted by Vasilis Totskas, Christopher Carroll Smith, Jonathan Yu, sora and João MorenoReacted by Ben Mares, Ganesh Rao, hecarson, Benjamin Ashbaugh and Mofenganother really easy workaround is just specifying the type:
__tablename__: str = 'poop'Note that Pyright complains at this:
"__tablename__" incorrectly overrides property of same name in class "SQLModel" Pylance(reportIncompatibleMethodOverride)To satisfy the type checker you need to use the declared_attr approach, eg:
class Lineitem(SQLModel, table=True): @declared_attr def __tablename__(cls): return "invoice_lineitems"
This could be mentioned in the docs, and maybe in a future version a more intuitive approach could be used, such as putting it in a
Metaas ormar does:class Lineitem(SQLModel, table=True): class Meta: tablename: str = "invoice_lineitems"
I thought about making a request for this but I'm guessing there's already a lot on the roadmap.
Reacted by M AtheerReacted by Diego VieiraSince I posted #98 (comment), I've started simply doing
__tablename__: str = "invoices_legacy" # type: ignore
I think this is by far the best solution for people still getting the "incorrect override" error for the line without
type: ignore. As I said when I mentioned this in #159,I choose this last method because the others are far too verbose for something as simple as declaring the table name. This may seem hacky, but although I have to tell Pyright to ignore a number of things in sqlmodel, it's not half the file like I have to type: ignore with sqlalchemy.
Reacted by Ben Mares, Zaffer, Sebastian Weigand, Paul T Huntsberger, M Atheer and Ernesto RodriguezIt seems
__tablename__: ClassVar[str] = "users"Solves this for both pyright and mypy
Updated
Works only withbasictype checking mode. Does not work instandardReacted by Vasilis Totskas and zhuxiningI tried all the fixes in this thread, and I'm sorry to report that you'll need
# type: ignoreto fix this with Pylance in "standard" type checking mode, because none of the other suggestions work.Reacted by Benjamin Trom, Hucci, rossbowen, Cédric Bahirwe and zhuxiningReacted by Christian-Manuel ButzkeI use
__tablename__ = typing.cast(declared_attr, "Users")
and be done with it.
Reacted by Christopher Carroll Smith, HT_Ray and Peak ETLIt works on pyright strict mode . But not graceful.
__tablename__: ClassVar[Any] = "my_table"Reacted by Yunice Nicolle Cruz, Abdullah Tahir, Andrew Sansom and Everson Magalhães Cavalcante__tablename__: ClassVar[Any] = "my_table"I can confirm this works for pyright and mypy.
Reacted by 유호건, adi-wan-askui, Abdullah Tahir, Andrew Sansom, zhuxining, Precious and Everson Magalhães Cavalcante- added a commit that references this issue
on Dec 3, 2025 Since I posted #98 (comment), I've started simply doing
__tablename__: str = "invoices_legacy" # type: ignoreI think this is by far the best solution for people still getting the "incorrect override" error for the line without
type: ignore. As I said when I mentioned this in #159,I choose this last method because the others are far too verbose for something as simple as declaring the table name. This may seem hacky, but although I have to tell Pyright to ignore a number of things in sqlmodel, it's not half the file like I have to type: ignore with sqlalchemy.
I can confirm this works.
- added 2 commits that reference this issue
on Jan 11, 2026 - added 4 commits that reference this issue
on Mar 18, 2026 - locked and limited conversation to collaborators
on May 18, 2026 - added a commit that references this issue
on Jun 10, 2026 - added a commit that references this issue
on Sep 21, 2026

First Check
Commit to Help
Example Code
Description
This will cause a type error when you declare
__tablename__with pyright as type checker. Like:Operating System
Linux, macOS
Operating System Details
No response
SQLModel Version
0.0.4
Python Version
3.8.6
Additional Context
No response