db.Model without primary key generates a confusing error message

Issue #2993 invalid
Ling Thio created an issue

When a model definition does not contain a primary key, the following error message appears:

sqlalchemy.exc.InvalidRequestError: Class <class 'XYZ'> does not have a table or tablename specified and does not inherit from an existing table-mapped class.

Example:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)

class Xyz(db.Model):
    name = db.Column(db.String(50))

It would be nice if the error message: a) specifically mentions the missing primary key, or b) prints the current error message, with the addition of the possibility of a missing primary key.

Comments (5)

  1. Mike Bayer repo owner

    can't reproduce - assertions pass in both cases below. Note that for issues specific to flask-sqlalchemy, they should be reported with that project here: https://github.com/mitsuhiko/flask-sqlalchemy/issues

    from sqlalchemy import *
    from sqlalchemy.orm import *
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    try:
        class Xyz(Base):
            name = Column(String(50))
    except Exception as e:
        # Class <class '__main__.Xyz'> does not have a __table__ or __tablename__
        # specified and does not inherit from an existing table-mapped class.
        print(e)
        assert "does not have a __table__ or __tablename__ specified" in str(e)
    
    
    try:
        class Xyz(Base):
            __tablename__ = 'xyz'
            name = Column(String(50))
    except Exception as e:
        # Mapper Mapper|Xyz|xyz could not assemble any primary key columns for mapped table 'xyz'
        # this message is also correct.
        print(e)
        assert "could not assemble any primary key columns" in str(e)
    
  2. Mike Bayer repo owner

    note that it is not reasonable to expect that SQLAlchemy will iterate through the entire mapping process at once and report on all issues at the same time. the mapping process has no option but to halt as soon as it doesn't have enough information to proceed.

  3. Ling Thio reporter

    Thanks @zzzeek for looking into this!

    But you're illustrating the point I'm trying to make:

    class Xyz(Base):
        name = Column(String(50))
    

    Class Xyz does inherit from an existing table-mapped class, and yet it throws this "does not inherit from an existing table-mapped class" error message, which leads developers on the wrong trouble-shooting path. My request is to add the "could not assemble any primary key columns" part to the error message:

    # Class <class '__main__.Xyz'> does not have a __table__ or __tablename__
    # specified and does not inherit from an existing table-mapped class
    # or could not assemble any primary key columns.
    

    Shall I enter this in https://github.com/mitsuhiko/flask-sqlalchemy/issues?

  4. Mike Bayer repo owner

    not in my example above, "Base" is not table-mapped.

    "extends from table-mapped" refers to single table inheritance, which is this:

    class Abc(Base):
        __tablename__ = 'abc'
        id = Column(Integer, primary_key=True)
    
    class Xyz(Abc):
        name = Column(String(50))
    
    # no error!
    
  5. Mike Bayer repo owner

    looks like at best a confusion that arises specific to flask-sqlalchemy, feel free to report over there.

  6. Log in to comment